diff options
406 files changed, 26656 insertions, 3247 deletions
@@ -158,6 +158,11 @@ LOCAL_SRC_FILES += \ core/java/com/android/internal/os/IResultReceiver.aidl \ core/java/com/android/internal/statusbar/IStatusBar.aidl \ core/java/com/android/internal/statusbar/IStatusBarService.aidl \ + core/java/com/android/internal/textservice/ISpellCheckerService.aidl \ + core/java/com/android/internal/textservice/ISpellCheckerSession.aidl \ + core/java/com/android/internal/textservice/ISpellCheckerSessionListener.aidl \ + core/java/com/android/internal/textservice/ITextServicesManager.aidl \ + core/java/com/android/internal/textservice/ITextServicesSessionListener.aidl \ core/java/com/android/internal/view/IInputContext.aidl \ core/java/com/android/internal/view/IInputContextCallback.aidl \ core/java/com/android/internal/view/IInputMethod.aidl \ @@ -190,6 +195,7 @@ LOCAL_SRC_FILES += \ telephony/java/com/android/internal/telephony/ISms.aidl \ telephony/java/com/android/internal/telephony/IWapPushManager.aidl \ wifi/java/android/net/wifi/IWifiManager.aidl \ + wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl \ telephony/java/com/android/internal/telephony/IExtendedNetworkService.aidl \ voip/java/android/net/sip/ISipSession.aidl \ voip/java/android/net/sip/ISipSessionListener.aidl \ @@ -266,6 +272,11 @@ aidl_files := \ frameworks/base/core/java/android/view/Surface.aidl \ frameworks/base/core/java/android/view/WindowManager.aidl \ frameworks/base/core/java/android/widget/RemoteViews.aidl \ + frameworks/base/core/java/com/android/internal/textservice/ISpellCheckerService.aidl \ + frameworks/base/core/java/com/android/internal/textservice/ISpellCheckerSession.aidl \ + frameworks/base/core/java/com/android/internal/textservice/ISpellCheckerSessionListener.aidl \ + frameworks/base/core/java/com/android/internal/textservice/ITextServicesManager.aidl \ + frameworks/base/core/java/com/android/internal/textservice/ITextServicesSessionListener.aidl \ frameworks/base/core/java/com/android/internal/view/IInputContext.aidl \ frameworks/base/core/java/com/android/internal/view/IInputMethod.aidl \ frameworks/base/core/java/com/android/internal/view/IInputMethodCallback.aidl \ diff --git a/api/current.txt b/api/current.txt index 6984b07..2514efd 100644 --- a/api/current.txt +++ b/api/current.txt @@ -21,6 +21,7 @@ package android { field public static final java.lang.String BIND_DEVICE_ADMIN = "android.permission.BIND_DEVICE_ADMIN"; field public static final java.lang.String BIND_INPUT_METHOD = "android.permission.BIND_INPUT_METHOD"; field public static final java.lang.String BIND_REMOTEVIEWS = "android.permission.BIND_REMOTEVIEWS"; + field public static final java.lang.String BIND_TEXT_SERVICE = "android.permission.BIND_TEXT_SERVICE"; field public static final java.lang.String BIND_WALLPAPER = "android.permission.BIND_WALLPAPER"; field public static final java.lang.String BLUETOOTH = "android.permission.BLUETOOTH"; field public static final java.lang.String BLUETOOTH_ADMIN = "android.permission.BLUETOOTH_ADMIN"; @@ -82,7 +83,6 @@ package android { field public static final java.lang.String READ_SMS = "android.permission.READ_SMS"; field public static final java.lang.String READ_SYNC_SETTINGS = "android.permission.READ_SYNC_SETTINGS"; field public static final java.lang.String READ_SYNC_STATS = "android.permission.READ_SYNC_STATS"; - field public static final java.lang.String READ_WRITE_ALL_VOICEMAIL = "com.android.voicemail.permission.READ_WRITE_ALL_VOICEMAIL"; field public static final java.lang.String READ_WRITE_OWN_VOICEMAIL = "com.android.voicemail.permission.READ_WRITE_OWN_VOICEMAIL"; field public static final java.lang.String REBOOT = "android.permission.REBOOT"; field public static final java.lang.String RECEIVE_BOOT_COMPLETED = "android.permission.RECEIVE_BOOT_COMPLETED"; @@ -185,14 +185,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 = 16843649; // 0x1010381 - field public static final int accessibilityFeedbackType = 16843651; // 0x1010383 - field public static final int accessibilityFlags = 16843653; // 0x1010385 + field public static final int accessibilityEventTypes = 16843647; // 0x101037f + field public static final int accessibilityFeedbackType = 16843649; // 0x1010381 + field public static final int accessibilityFlags = 16843651; // 0x1010383 field public static final int 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 = 16843675; // 0x101039b + field public static final int actionBarSplitStyle = 16843669; // 0x1010395 field public static final int actionBarStyle = 16843470; // 0x10102ce field public static final int actionBarTabBarStyle = 16843508; // 0x10102f4 field public static final int actionBarTabStyle = 16843507; // 0x10102f3 @@ -208,10 +208,10 @@ 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 = 16843647; // 0x101037f - field public static final int actionModeStyle = 16843688; // 0x10103a8 + field public static final int actionModeSelectAllDrawable = 16843645; // 0x101037d + field public static final int actionModeStyle = 16843681; // 0x10103a1 field public static final int actionOverflowButtonStyle = 16843510; // 0x10102f6 - field public static final int actionProviderClass = 16843677; // 0x101039d + field public static final int actionProviderClass = 16843670; // 0x1010396 field public static final int actionViewClass = 16843516; // 0x10102fc field public static final int activatedBackgroundIndicator = 16843517; // 0x10102fd field public static final int activityCloseEnterAnimation = 16842938; // 0x10100ba @@ -223,7 +223,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 = 16843641; // 0x1010379 + field public static final int alignmentMode = 16843639; // 0x1010377 field public static final int allContactsName = 16843468; // 0x10102cc field public static final int allowBackup = 16843392; // 0x1010280 field public static final int allowClearUserData = 16842757; // 0x1010005 @@ -257,8 +257,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 backgroundSplit = 16843672; // 0x1010398 + field public static final int backgroundStacked = 16843671; // 0x1010397 field public static final int backupAgent = 16843391; // 0x101027f field public static final int baseline = 16843548; // 0x101031c field public static final int baselineAlignBottom = 16843042; // 0x1010122 @@ -267,7 +267,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 = 16843660; // 0x101038c + field public static final int bottomChevronDrawable = 16843658; // 0x101038a field public static final int bottomDark = 16842953; // 0x10100c9 field public static final int bottomLeftRadius = 16843179; // 0x10101ab field public static final int bottomMedium = 16842958; // 0x10100ce @@ -286,7 +286,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 = 16843654; // 0x1010386 + field public static final int canRetrieveWindowContent = 16843652; // 0x1010384 field public static final int candidatesTextStyleSpans = 16843312; // 0x1010230 field public static final deprecated int capitalize = 16843113; // 0x1010169 field public static final int centerBright = 16842956; // 0x10100cc @@ -315,18 +315,18 @@ package android { field public static final int codes = 16843330; // 0x1010242 field public static final int collapseColumns = 16843083; // 0x101014b field public static final int color = 16843173; // 0x10101a5 - field public static final int colorActivatedHighlight = 16843684; // 0x10103a4 + field public static final int colorActivatedHighlight = 16843677; // 0x101039d field public static final int colorBackground = 16842801; // 0x1010031 field public static final int colorBackgroundCacheHint = 16843435; // 0x10102ab - field public static final int colorFocusedHighlight = 16843683; // 0x10103a3 + field public static final int colorFocusedHighlight = 16843676; // 0x101039c field public static final int colorForeground = 16842800; // 0x1010030 field public static final int colorForegroundInverse = 16843270; // 0x1010206 - field public static final int colorLongPressedHighlight = 16843682; // 0x10103a2 - field public static final int colorMultiSelectHighlight = 16843685; // 0x10103a5 - field public static final int colorPressedHighlight = 16843681; // 0x10103a1 - field public static final int columnCount = 16843638; // 0x1010376 + field public static final int colorLongPressedHighlight = 16843675; // 0x101039b + field public static final int colorMultiSelectHighlight = 16843678; // 0x101039e + field public static final int colorPressedHighlight = 16843674; // 0x101039a + field public static final int columnCount = 16843636; // 0x1010374 field public static final int columnDelay = 16843215; // 0x10101cf - field public static final int columnOrderPreserved = 16843639; // 0x1010377 + field public static final int columnOrderPreserved = 16843637; // 0x1010375 field public static final int columnWidth = 16843031; // 0x1010117 field public static final int compatibleWidthLimitDp = 16843621; // 0x1010365 field public static final int completionHint = 16843122; // 0x1010172 @@ -380,11 +380,11 @@ package android { field public static final int drawSelectorOnTop = 16843004; // 0x10100fc field public static final int drawable = 16843161; // 0x1010199 field public static final int drawableBottom = 16843118; // 0x101016e - field public static final int drawableEnd = 16843687; // 0x10103a7 + field public static final int drawableEnd = 16843680; // 0x10103a0 field public static final int drawableLeft = 16843119; // 0x101016f field public static final int drawablePadding = 16843121; // 0x1010171 field public static final int drawableRight = 16843120; // 0x1010170 - field public static final int drawableStart = 16843686; // 0x10103a6 + field public static final int drawableStart = 16843679; // 0x101039f field public static final int drawableTop = 16843117; // 0x101016d field public static final int drawingCacheQuality = 16842984; // 0x10100e8 field public static final int dropDownAnchor = 16843363; // 0x1010263 @@ -441,7 +441,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 = 16843666; // 0x1010392 + field public static final int feedbackCount = 16843664; // 0x1010390 field public static final int fillAfter = 16843197; // 0x10101bd field public static final int fillBefore = 16843196; // 0x10101bc field public static final int fillEnabled = 16843343; // 0x101024f @@ -494,7 +494,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 = 16843656; // 0x1010388 + field public static final int handleDrawable = 16843654; // 0x1010386 field public static final int handleProfiling = 16842786; // 0x1010022 field public static final int hapticFeedbackEnabled = 16843358; // 0x101025e field public static final int hardwareAccelerated = 16843475; // 0x10102d3 @@ -503,12 +503,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 = 16843663; // 0x101038f + field public static final int hitRadius = 16843661; // 0x101038d 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 = 16843668; // 0x1010394 + field public static final int horizontalOffset = 16843666; // 0x1010392 field public static final int horizontalScrollViewStyle = 16843603; // 0x1010353 field public static final int horizontalSpacing = 16843028; // 0x1010114 field public static final int host = 16842792; // 0x1010028 @@ -554,7 +554,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 = 16843648; // 0x1010380 + field public static final int isAuxiliary = 16843646; // 0x101037e field public static final int isDefault = 16843297; // 0x1010221 field public static final int isIndicator = 16843079; // 0x1010147 field public static final int isModifier = 16843334; // 0x1010246 @@ -591,7 +591,6 @@ package android { field public static final int layerType = 16843604; // 0x1010354 field public static final int layout = 16842994; // 0x10100f2 field public static final int layoutAnimation = 16842988; // 0x10100ec - field public static final int layoutDirection = 16843634; // 0x1010372 field public static final int layout_above = 16843140; // 0x1010184 field public static final int layout_alignBaseline = 16843142; // 0x1010186 field public static final int layout_alignBottom = 16843146; // 0x101018a @@ -608,20 +607,18 @@ 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_columnFlexibility = 16843646; // 0x101037e - field public static final int layout_columnSpan = 16843645; // 0x101037d + field public static final int layout_columnFlexibility = 16843644; // 0x101037c + field public static final int layout_columnSpan = 16843643; // 0x101037b field public static final int layout_gravity = 16842931; // 0x10100b3 field public static final int layout_height = 16842997; // 0x10100f5 field public static final int layout_margin = 16842998; // 0x10100f6 field public static final int layout_marginBottom = 16843002; // 0x10100fa - 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 = 16843673; // 0x1010399 field public static final int layout_marginTop = 16843000; // 0x10100f8 - field public static final int layout_row = 16843642; // 0x101037a - field public static final int layout_rowFlexibility = 16843644; // 0x101037c - field public static final int layout_rowSpan = 16843643; // 0x101037b + field public static final int layout_row = 16843640; // 0x1010378 + field public static final int layout_rowFlexibility = 16843642; // 0x101037a + field public static final int layout_rowSpan = 16843641; // 0x1010379 field public static final int layout_scale = 16843155; // 0x1010193 field public static final int layout_span = 16843085; // 0x101014d field public static final int layout_toLeftOf = 16843138; // 0x1010182 @@ -631,7 +628,7 @@ package android { 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 = 16843657; // 0x1010389 + field public static final int leftChevronDrawable = 16843655; // 0x1010387 field public static final int lineSpacingExtra = 16843287; // 0x1010217 field public static final int lineSpacingMultiplier = 16843288; // 0x1010218 field public static final int lines = 16843092; // 0x1010154 @@ -643,8 +640,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 = 16843669; // 0x1010395 - field public static final int listPreferredItemHeightSmall = 16843670; // 0x1010396 + field public static final int listPreferredItemHeightLarge = 16843667; // 0x1010393 + field public static final int listPreferredItemHeightSmall = 16843668; // 0x1010394 field public static final int listSelector = 16843003; // 0x10100fb field public static final int listSeparatorTextViewStyle = 16843272; // 0x1010208 field public static final int listViewStyle = 16842868; // 0x1010074 @@ -675,8 +672,8 @@ package android { field public static final int minHeight = 16843072; // 0x1010140 field public static final int minLevel = 16843185; // 0x10101b1 field public static final int minLines = 16843094; // 0x1010156 - field public static final int minResizeHeight = 16843690; // 0x10103aa - field public static final int minResizeWidth = 16843689; // 0x10103a9 + field public static final int minResizeHeight = 16843683; // 0x10103a3 + field public static final int minResizeWidth = 16843682; // 0x10103a2 field public static final int minSdkVersion = 16843276; // 0x101020c field public static final int minWidth = 16843071; // 0x101013f field public static final int mode = 16843134; // 0x101017e @@ -692,7 +689,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 = 16843652; // 0x1010384 + field public static final int notificationTimeout = 16843650; // 0x1010382 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 @@ -706,17 +703,15 @@ 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 = 16843662; // 0x101038e + field public static final int outerRadius = 16843660; // 0x101038c 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 = 16843650; // 0x1010382 + field public static final int packageNames = 16843648; // 0x1010380 field public static final int padding = 16842965; // 0x10100d5 field public static final int paddingBottom = 16842969; // 0x10100d9 - 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 = 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 @@ -797,17 +792,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 = 16843658; // 0x101038a + field public static final int rightChevronDrawable = 16843656; // 0x1010388 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 = 16843636; // 0x1010374 + field public static final int rowCount = 16843634; // 0x1010372 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 = 16843637; // 0x1010375 + field public static final int rowOrderPreserved = 16843635; // 0x1010373 field public static final int saveEnabled = 16842983; // 0x10100e7 field public static final int scaleGravity = 16843262; // 0x10101fe field public static final int scaleHeight = 16843261; // 0x10101fd @@ -873,7 +868,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 = 16843665; // 0x1010391 + field public static final int snapMargin = 16843663; // 0x101038f field public static final int soundEffectsEnabled = 16843285; // 0x1010215 field public static final int spacing = 16843027; // 0x1010113 field public static final int spinnerDropDownItemStyle = 16842887; // 0x1010087 @@ -921,7 +916,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 = 16843635; // 0x1010373 + field public static final int suggestionsEnabled = 16843633; // 0x1010371 field public static final int summary = 16843241; // 0x10101e9 field public static final int summaryColumn = 16843426; // 0x10102a2 field public static final int summaryOff = 16843248; // 0x10101f0 @@ -938,7 +933,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 = 16843655; // 0x1010387 + field public static final int targetDrawables = 16843653; // 0x1010385 field public static final int targetPackage = 16842785; // 0x1010021 field public static final int targetSdkVersion = 16843376; // 0x1010270 field public static final int taskAffinity = 16842770; // 0x1010012 @@ -953,7 +948,7 @@ package android { field public static final int tension = 16843370; // 0x101026a field public static final int testOnly = 16843378; // 0x1010272 field public static final int text = 16843087; // 0x101014f - field public static final int textAllCaps = 16843680; // 0x10103a0 + field public static final int textAllCaps = 16843673; // 0x1010399 field public static final int textAppearance = 16842804; // 0x1010034 field public static final int textAppearanceButton = 16843271; // 0x1010207 field public static final int textAppearanceInverse = 16842805; // 0x1010035 @@ -990,14 +985,12 @@ 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 = 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 field public static final int textEditSidePasteWindowLayout = 16843614; // 0x101035e - field public static final int textEditSuggestionItemLayout = 16843633; // 0x1010371 - field public static final int textEditSuggestionsBottomWindowLayout = 16843631; // 0x101036f - field public static final int textEditSuggestionsTopWindowLayout = 16843632; // 0x1010370 + field public static final int textEditSuggestionItemLayout = 16843632; // 0x1010370 + field public static final int textEditSuggestionsWindowLayout = 16843631; // 0x101036f field public static final int textFilterEnabled = 16843007; // 0x10100ff field public static final int textIsSelectable = 16843542; // 0x1010316 field public static final int textOff = 16843045; // 0x1010125 @@ -1030,7 +1023,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 = 16843659; // 0x101038b + field public static final int topChevronDrawable = 16843657; // 0x1010389 field public static final int topDark = 16842951; // 0x10100c7 field public static final int topLeftRadius = 16843177; // 0x10101a9 field public static final int topOffset = 16843352; // 0x1010258 @@ -1046,7 +1039,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 = 16843640; // 0x1010378 + field public static final int useDefaultMargins = 16843638; // 0x1010376 field public static final int useIntrinsicSizeAsMinimum = 16843536; // 0x1010310 field public static final int useLevel = 16843167; // 0x101019f field public static final int userVisible = 16843409; // 0x1010291 @@ -1060,10 +1053,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 = 16843667; // 0x1010393 + field public static final int verticalOffset = 16843665; // 0x1010391 field public static final int verticalScrollbarPosition = 16843572; // 0x1010334 field public static final int verticalSpacing = 16843029; // 0x1010115 - field public static final int vibrationDuration = 16843664; // 0x1010390 + field public static final int vibrationDuration = 16843662; // 0x101038e field public static final int visibility = 16842972; // 0x10100dc field public static final int visible = 16843156; // 0x1010194 field public static final int vmSafeMode = 16843448; // 0x10102b8 @@ -1080,7 +1073,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 = 16843661; // 0x101038d + field public static final int waveDrawable = 16843659; // 0x101038b field public static final int webTextViewStyle = 16843449; // 0x10102b9 field public static final int webViewStyle = 16842885; // 0x1010085 field public static final int weekDayTextAppearance = 16843592; // 0x1010348 @@ -4791,6 +4784,7 @@ package android.content { field public static final java.lang.String SENSOR_SERVICE = "sensor"; field public static final java.lang.String STORAGE_SERVICE = "storage"; field public static final java.lang.String TELEPHONY_SERVICE = "phone"; + field public static final java.lang.String TEXT_SERVICES_MANAGER_SERVICE = "textservices"; field public static final java.lang.String UI_MODE_SERVICE = "uimode"; field public static final java.lang.String USB_SERVICE = "usb"; field public static final java.lang.String VIBRATOR_SERVICE = "vibrator"; @@ -10412,8 +10406,8 @@ package android.media { method public void setAudioEncodingBitRate(int); method public void setAudioSamplingRate(int); method public void setAudioSource(int) throws java.lang.IllegalStateException; - method public void setAuxiliaryOutputFile(java.io.FileDescriptor); - method public void setAuxiliaryOutputFile(java.lang.String); + method public deprecated void setAuxiliaryOutputFile(java.io.FileDescriptor); + method public deprecated void setAuxiliaryOutputFile(java.lang.String); method public void setCamera(android.hardware.Camera); method public void setCaptureRate(double); method public void setLocation(float, float); @@ -16238,12 +16232,14 @@ package android.provider { } public static final class ContactsContract.StreamItemPhotos implements android.provider.BaseColumns android.provider.ContactsContract.StreamItemPhotosColumns { + field public static final java.lang.String PHOTO = "photo"; } protected static abstract interface ContactsContract.StreamItemPhotosColumns { field public static final java.lang.String ACTION = "action"; field public static final java.lang.String ACTION_URI = "action_uri"; - field public static final java.lang.String PICTURE = "picture"; + field public static final java.lang.String PHOTO_FILE_ID = "photo_file_id"; + field public static final java.lang.String PHOTO_URI = "photo_uri"; field public static final java.lang.String SORT_INDEX = "sort_index"; field public static final java.lang.String STREAM_ITEM_ID = "stream_item_id"; } @@ -16253,7 +16249,6 @@ package android.provider { field public static final android.net.Uri CONTENT_PHOTO_URI; field public static final android.net.Uri CONTENT_URI; field public static final java.lang.String MAX_ITEMS = "max_items"; - field public static final java.lang.String PHOTO_MAX_BYTES = "photo_max_bytes"; } public static final class ContactsContract.StreamItems.StreamItemPhotos implements android.provider.BaseColumns android.provider.ContactsContract.StreamItemPhotosColumns { @@ -16732,18 +16727,18 @@ package android.provider { field public static final java.lang.String WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY = "wifi_networks_available_repeat_delay"; field public static final java.lang.String WIFI_NUM_OPEN_NETWORKS_KEPT = "wifi_num_open_networks_kept"; field public static final java.lang.String WIFI_ON = "wifi_on"; - field public static final java.lang.String WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE = "wifi_watchdog_acceptable_packet_loss_percentage"; - field public static final java.lang.String WIFI_WATCHDOG_AP_COUNT = "wifi_watchdog_ap_count"; - field public static final java.lang.String WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS = "wifi_watchdog_background_check_delay_ms"; - field public static final java.lang.String WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED = "wifi_watchdog_background_check_enabled"; - field public static final java.lang.String WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS = "wifi_watchdog_background_check_timeout_ms"; - field public static final java.lang.String WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT = "wifi_watchdog_initial_ignored_ping_count"; - field public static final java.lang.String WIFI_WATCHDOG_MAX_AP_CHECKS = "wifi_watchdog_max_ap_checks"; + field public static final deprecated java.lang.String WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE = "wifi_watchdog_acceptable_packet_loss_percentage"; + field public static final deprecated java.lang.String WIFI_WATCHDOG_AP_COUNT = "wifi_watchdog_ap_count"; + field public static final deprecated java.lang.String WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS = "wifi_watchdog_background_check_delay_ms"; + field public static final deprecated java.lang.String WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED = "wifi_watchdog_background_check_enabled"; + field public static final deprecated java.lang.String WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS = "wifi_watchdog_background_check_timeout_ms"; + field public static final deprecated java.lang.String WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT = "wifi_watchdog_initial_ignored_ping_count"; + field public static final deprecated java.lang.String WIFI_WATCHDOG_MAX_AP_CHECKS = "wifi_watchdog_max_ap_checks"; field public static final java.lang.String WIFI_WATCHDOG_ON = "wifi_watchdog_on"; - field public static final java.lang.String WIFI_WATCHDOG_PING_COUNT = "wifi_watchdog_ping_count"; - field public static final java.lang.String WIFI_WATCHDOG_PING_DELAY_MS = "wifi_watchdog_ping_delay_ms"; - field public static final java.lang.String WIFI_WATCHDOG_PING_TIMEOUT_MS = "wifi_watchdog_ping_timeout_ms"; - field public static final java.lang.String WIFI_WATCHDOG_WATCH_LIST = "wifi_watchdog_watch_list"; + field public static final deprecated java.lang.String WIFI_WATCHDOG_PING_COUNT = "wifi_watchdog_ping_count"; + field public static final deprecated java.lang.String WIFI_WATCHDOG_PING_DELAY_MS = "wifi_watchdog_ping_delay_ms"; + field public static final deprecated java.lang.String WIFI_WATCHDOG_PING_TIMEOUT_MS = "wifi_watchdog_ping_timeout_ms"; + field public static final deprecated java.lang.String WIFI_WATCHDOG_WATCH_LIST = "wifi_watchdog_watch_list"; } public static class Settings.SettingNotFoundException extends android.util.AndroidException { @@ -17948,6 +17943,31 @@ package android.security { } +package android.service.textservice { + + public abstract class SpellCheckerService extends android.app.Service { + ctor public SpellCheckerService(); + method public void cancel(); + method public abstract android.view.textservice.SuggestionsInfo getSuggestions(android.view.textservice.TextInfo, int, java.lang.String); + method public android.view.textservice.SuggestionsInfo[] getSuggestionsMultiple(android.view.textservice.TextInfo[], java.lang.String, int, boolean); + method public final android.os.IBinder onBind(android.content.Intent); + field public static final java.lang.String SERVICE_INTERFACE; + } + + public class SpellCheckerSession { + method public void close(); + method public android.view.textservice.SpellCheckerInfo getSpellChecker(); + method public void getSuggestions(android.view.textservice.TextInfo, int); + method public void getSuggestions(android.view.textservice.TextInfo[], int, boolean); + method public boolean isSessionDisconnected(); + } + + public static abstract interface SpellCheckerSession.SpellCheckerSessionListener { + method public abstract void onGetSuggestions(android.view.textservice.SuggestionsInfo[]); + } + +} + package android.service.wallpaper { public abstract class WallpaperService extends android.app.Service { @@ -21011,6 +21031,11 @@ package android.view { method public void onPrepareSubMenu(android.view.SubMenu); } + public abstract interface CollapsibleActionView { + method public abstract void onActionViewCollapsed(); + method public abstract void onActionViewExpanded(); + } + public abstract interface ContextMenu implements android.view.Menu { method public abstract void clearHeader(); method public abstract android.view.ContextMenu setHeaderIcon(int); @@ -22721,10 +22746,8 @@ package android.view { ctor public ViewDebug(); method public static void dumpCapturedView(java.lang.String, java.lang.Object); method public static void startHierarchyTracing(java.lang.String, android.view.View); - method public static void startLooperProfiling(java.io.File); method public static void startRecyclerTracing(java.lang.String, android.view.View); method public static void stopHierarchyTracing(); - method public static void stopLooperProfiling(); method public static void stopRecyclerTracing(); method public static void trace(android.view.View, android.view.ViewDebug.RecyclerTraceType, int...); method public static void trace(android.view.View, android.view.ViewDebug.HierarchyTraceType); @@ -24025,6 +24048,52 @@ package android.view.inputmethod { } +package android.view.textservice { + + public final class SpellCheckerInfo implements android.os.Parcelable { + method public int describeContents(); + method public android.content.ComponentName getComponent(); + method public java.lang.String getId(); + method public java.lang.String getPackageName(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + } + + public final class SuggestionsInfo implements android.os.Parcelable { + ctor public SuggestionsInfo(int, java.lang.String[]); + ctor public SuggestionsInfo(int, java.lang.String[], int, int); + ctor public SuggestionsInfo(android.os.Parcel); + method public int describeContents(); + method public int getCookie(); + method public int getSequence(); + method public java.lang.String getSuggestionAt(int); + method public int getSuggestionsAttributes(); + method public int getSuggestionsCount(); + method public void setCookieAndSequence(int, int); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + field public static final int RESULT_ATTR_IN_THE_DICTIONARY = 1; // 0x1 + field public static final int RESULT_ATTR_LOOKS_TYPO = 2; // 0x2 + } + + public final class TextInfo implements android.os.Parcelable { + ctor public TextInfo(java.lang.String); + ctor public TextInfo(java.lang.String, int, int); + ctor public TextInfo(android.os.Parcel); + method public int describeContents(); + method public int getCookie(); + method public int getSequence(); + method public java.lang.String getText(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + } + + public final class TextServicesManager { + method public android.service.textservice.SpellCheckerSession newSpellCheckerSession(java.util.Locale, android.service.textservice.SpellCheckerSession.SpellCheckerSessionListener, boolean); + } + +} + package android.webkit { public final deprecated class CacheManager { @@ -29796,7 +29865,7 @@ package java.lang.ref { ctor public ReferenceQueue(); method public synchronized java.lang.ref.Reference<? extends T> poll(); method public java.lang.ref.Reference<? extends T> remove() throws java.lang.InterruptedException; - method public synchronized java.lang.ref.Reference<? extends T> remove(long) throws java.lang.IllegalArgumentException, java.lang.InterruptedException; + method public synchronized java.lang.ref.Reference<? extends T> remove(long) throws java.lang.InterruptedException; } public class SoftReference extends java.lang.ref.Reference { diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java index 3fb1736..6dfa12b 100644 --- a/cmds/am/src/com/android/commands/am/Am.java +++ b/cmds/am/src/com/android/commands/am/Am.java @@ -468,10 +468,16 @@ public class Am { String profileFile = null; boolean start = false; boolean wall = false; + int profileType = 0; String process = null; String cmd = nextArgRequired(); + if ("looper".equals(cmd)) { + cmd = nextArgRequired(); + profileType = 1; + } + if ("start".equals(cmd)) { start = true; wall = "--wall".equals(nextOption()); @@ -516,7 +522,7 @@ public class Am { } else if (start) { //removeWallOption(); } - if (!mAm.profileControl(process, start, profileFile, fd)) { + if (!mAm.profileControl(process, start, profileFile, fd, profileType)) { wall = false; throw new AndroidException("PROFILE FAILED on process " + process); } @@ -1076,8 +1082,8 @@ public class Am { " am broadcast <INTENT>\n" + " am instrument [-r] [-e <NAME> <VALUE>] [-p] [-w]\n" + " [--no-window-animation] <COMPONENT>\n" + - " am profile start <PROCESS> <FILE>\n" + - " am profile stop <PROCESS>\n" + + " am profile [looper] start <PROCESS> <FILE>\n" + + " am profile [looper] stop <PROCESS>\n" + " am dumpheap [flags] <PROCESS> <FILE>\n" + " am monitor [--gdb <port>]\n" + " am screen-compat [on|off] <PACKAGE>\n" + diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index 2a731a3..b7cd829 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -1104,10 +1104,11 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM data.enforceInterface(IActivityManager.descriptor); String process = data.readString(); boolean start = data.readInt() != 0; + int profileType = data.readInt(); String path = data.readString(); ParcelFileDescriptor fd = data.readInt() != 0 ? data.readFileDescriptor() : null; - boolean res = profileControl(process, start, path, fd); + boolean res = profileControl(process, start, path, fd, profileType); reply.writeNoException(); reply.writeInt(res ? 1 : 0); return true; @@ -2888,13 +2889,14 @@ class ActivityManagerProxy implements IActivityManager } public boolean profileControl(String process, boolean start, - String path, ParcelFileDescriptor fd) throws RemoteException + String path, ParcelFileDescriptor fd, int profileType) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeString(process); data.writeInt(start ? 1 : 0); + data.writeInt(profileType); data.writeString(path); if (fd != null) { data.writeInt(1); diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index f6cd866..9bbbd6c 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -676,11 +676,12 @@ public final class ActivityThread { queueOrSendMessage(H.ACTIVITY_CONFIGURATION_CHANGED, token); } - public void profilerControl(boolean start, String path, ParcelFileDescriptor fd) { + public void profilerControl(boolean start, String path, ParcelFileDescriptor fd, + int profileType) { ProfilerControlData pcd = new ProfilerControlData(); pcd.path = path; pcd.fd = fd; - queueOrSendMessage(H.PROFILER_CONTROL, pcd, start ? 1 : 0); + queueOrSendMessage(H.PROFILER_CONTROL, pcd, start ? 1 : 0, profileType); } public void dumpHeap(boolean managed, String path, ParcelFileDescriptor fd) { @@ -954,7 +955,7 @@ public final class ActivityThread { } public void scheduleTrimMemory(int level) { - queueOrSendMessage(H.TRIM_MEMORY, level); + queueOrSendMessage(H.TRIM_MEMORY, null, level); } } @@ -1148,7 +1149,7 @@ public final class ActivityThread { handleActivityConfigurationChanged((IBinder)msg.obj); break; case PROFILER_CONTROL: - handleProfilerControl(msg.arg1 != 0, (ProfilerControlData)msg.obj); + handleProfilerControl(msg.arg1 != 0, (ProfilerControlData)msg.obj, msg.arg2); break; case CREATE_BACKUP_AGENT: handleCreateBackupAgent((CreateBackupAgentData)msg.obj); @@ -1184,8 +1185,10 @@ public final class ActivityThread { break; case UPDATE_PACKAGE_COMPATIBILITY_INFO: handleUpdatePackageCompatibilityInfo((UpdateCompatibilityData)msg.obj); + break; case TRIM_MEMORY: handleTrimMemory(msg.arg1); + break; } if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + msg.what); } @@ -3469,11 +3472,18 @@ public final class ActivityThread { performConfigurationChanged(r.activity, mCompatConfiguration); } - final void handleProfilerControl(boolean start, ProfilerControlData pcd) { + final void handleProfilerControl(boolean start, ProfilerControlData pcd, int profileType) { if (start) { try { - Debug.startMethodTracing(pcd.path, pcd.fd.getFileDescriptor(), - 8 * 1024 * 1024, 0); + switch (profileType) { + case 1: + ViewDebug.startLooperProfiling(pcd.path, pcd.fd.getFileDescriptor()); + break; + default: + Debug.startMethodTracing(pcd.path, pcd.fd.getFileDescriptor(), + 8 * 1024 * 1024, 0); + break; + } } catch (RuntimeException e) { Slog.w(TAG, "Profiling failed on path " + pcd.path + " -- can the process access this path?"); @@ -3485,7 +3495,15 @@ public final class ActivityThread { } } } else { - Debug.stopMethodTracing(); + switch (profileType) { + case 1: + ViewDebug.stopLooperProfiling(); + break; + default: + Debug.stopMethodTracing(); + break; + + } } } diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java index 942f245..9a5b527 100644 --- a/core/java/android/app/ApplicationThreadNative.java +++ b/core/java/android/app/ApplicationThreadNative.java @@ -376,10 +376,11 @@ public abstract class ApplicationThreadNative extends Binder { data.enforceInterface(IApplicationThread.descriptor); boolean start = data.readInt() != 0; + int profileType = data.readInt(); String path = data.readString(); ParcelFileDescriptor fd = data.readInt() != 0 ? data.readFileDescriptor() : null; - profilerControl(start, path, fd); + profilerControl(start, path, fd, profileType); return true; } @@ -936,10 +937,11 @@ class ApplicationThreadProxy implements IApplicationThread { } public void profilerControl(boolean start, String path, - ParcelFileDescriptor fd) throws RemoteException { + ParcelFileDescriptor fd, int profileType) throws RemoteException { Parcel data = Parcel.obtain(); data.writeInterfaceToken(IApplicationThread.descriptor); data.writeInt(start ? 1 : 0); + data.writeInt(profileType); data.writeString(path); if (fd != null) { data.writeInt(1); diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index d2323e7..a99cec2 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -59,6 +59,8 @@ import android.net.IThrottleManager; import android.net.Uri; import android.net.wifi.IWifiManager; import android.net.wifi.WifiManager; +import android.net.wifi.p2p.IWifiP2pManager; +import android.net.wifi.p2p.WifiP2pManager; import android.nfc.NfcManager; import android.os.Binder; import android.os.Bundle; @@ -83,6 +85,7 @@ import android.view.ContextThemeWrapper; import android.view.WindowManagerImpl; import android.view.accessibility.AccessibilityManager; import android.view.inputmethod.InputMethodManager; +import android.view.textservice.TextServicesManager; import android.accounts.AccountManager; import android.accounts.IAccountManager; import android.app.admin.DevicePolicyManager; @@ -320,6 +323,11 @@ class ContextImpl extends Context { return InputMethodManager.getInstance(ctx); }}); + registerService(TEXT_SERVICES_MANAGER_SERVICE, new ServiceFetcher() { + public Object createService(ContextImpl ctx) { + return TextServicesManager.getInstance(); + }}); + registerService(KEYGUARD_SERVICE, new ServiceFetcher() { public Object getService(ContextImpl ctx) { // TODO: why isn't this caching it? It wasn't @@ -432,6 +440,13 @@ class ContextImpl extends Context { return new WifiManager(service, ctx.mMainThread.getHandler()); }}); + registerService(WIFI_P2P_SERVICE, new ServiceFetcher() { + public Object createService(ContextImpl ctx) { + IBinder b = ServiceManager.getService(WIFI_P2P_SERVICE); + IWifiP2pManager service = IWifiP2pManager.Stub.asInterface(b); + return new WifiP2pManager(service); + }}); + registerService(WINDOW_SERVICE, new ServiceFetcher() { public Object getService(ContextImpl ctx) { return WindowManagerImpl.getDefault(ctx.mPackageInfo.mCompatibilityInfo); diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java index c82c9ec..789d3a6 100644 --- a/core/java/android/app/FragmentManager.java +++ b/core/java/android/app/FragmentManager.java @@ -1695,6 +1695,7 @@ final class FragmentManagerImpl extends FragmentManager { public void dispatchDestroy() { mDestroyed = true; + execPendingActions(); moveToState(Fragment.INITIALIZING, false); mActivity = null; } diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index 93c821c..64d77e8 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -284,7 +284,7 @@ public interface IActivityManager extends IInterface { // Turn on/off profiling in a particular process. public boolean profileControl(String process, boolean start, - String path, ParcelFileDescriptor fd) throws RemoteException; + String path, ParcelFileDescriptor fd, int profileType) throws RemoteException; public boolean shutdown(int timeout) throws RemoteException; diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java index 9de0bf4..d0607d0 100644 --- a/core/java/android/app/IApplicationThread.java +++ b/core/java/android/app/IApplicationThread.java @@ -105,7 +105,7 @@ public interface IApplicationThread extends IInterface { throws RemoteException; void scheduleLowMemory() throws RemoteException; void scheduleActivityConfigurationChanged(IBinder token) throws RemoteException; - void profilerControl(boolean start, String path, ParcelFileDescriptor fd) + void profilerControl(boolean start, String path, ParcelFileDescriptor fd, int profileType) throws RemoteException; void dumpHeap(boolean managed, String path, ParcelFileDescriptor fd) throws RemoteException; diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java index 2952e6b..f99b420 100644 --- a/core/java/android/app/Instrumentation.java +++ b/core/java/android/app/Instrumentation.java @@ -536,9 +536,11 @@ public class Instrumentation { */ public final Activity waitForActivityWithTimeout(long timeOut) { synchronized (this) { - try { - wait(timeOut); - } catch (InterruptedException e) { + if (mLastActivity == null) { + try { + wait(timeOut); + } catch (InterruptedException e) { + } } if (mLastActivity == null) { return null; diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java index 1af0983..ca64c88 100644 --- a/core/java/android/app/StatusBarManager.java +++ b/core/java/android/app/StatusBarManager.java @@ -97,9 +97,10 @@ public class StatusBarManager { } } - public void setIcon(String slot, int iconId, int iconLevel) { + public void setIcon(String slot, int iconId, int iconLevel, String contentDescription) { try { - mService.setIcon(slot, mContext.getPackageName(), iconId, iconLevel); + mService.setIcon(slot, mContext.getPackageName(), iconId, iconLevel, + contentDescription); } catch (RemoteException ex) { // system process is dead anyway. throw new RuntimeException(ex); diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java index 019652c..1ef99a1 100644 --- a/core/java/android/appwidget/AppWidgetManager.java +++ b/core/java/android/appwidget/AppWidgetManager.java @@ -388,6 +388,10 @@ public class AppWidgetManager { TypedValue.complexToDimensionPixelSize(info.minWidth, mDisplayMetrics); info.minHeight = TypedValue.complexToDimensionPixelSize(info.minHeight, mDisplayMetrics); + info.minResizeWidth = + TypedValue.complexToDimensionPixelSize(info.minResizeWidth, mDisplayMetrics); + info.minResizeHeight = + TypedValue.complexToDimensionPixelSize(info.minResizeHeight, mDisplayMetrics); } return providers; } @@ -411,6 +415,10 @@ public class AppWidgetManager { TypedValue.complexToDimensionPixelSize(info.minWidth, mDisplayMetrics); info.minHeight = TypedValue.complexToDimensionPixelSize(info.minHeight, mDisplayMetrics); + info.minResizeWidth = + TypedValue.complexToDimensionPixelSize(info.minResizeWidth, mDisplayMetrics); + info.minResizeHeight = + TypedValue.complexToDimensionPixelSize(info.minResizeHeight, mDisplayMetrics); } return info; } diff --git a/core/java/android/appwidget/AppWidgetProviderInfo.java b/core/java/android/appwidget/AppWidgetProviderInfo.java index b8c5b02..9c352d5 100644 --- a/core/java/android/appwidget/AppWidgetProviderInfo.java +++ b/core/java/android/appwidget/AppWidgetProviderInfo.java @@ -187,6 +187,8 @@ public class AppWidgetProviderInfo implements Parcelable { } this.minWidth = in.readInt(); this.minHeight = in.readInt(); + this.minResizeWidth = in.readInt(); + this.minResizeHeight = in.readInt(); this.updatePeriodMillis = in.readInt(); this.initialLayout = in.readInt(); if (0 != in.readInt()) { @@ -208,6 +210,8 @@ public class AppWidgetProviderInfo implements Parcelable { } out.writeInt(this.minWidth); out.writeInt(this.minHeight); + out.writeInt(this.minResizeWidth); + out.writeInt(this.minResizeHeight); out.writeInt(this.updatePeriodMillis); out.writeInt(this.initialLayout); if (this.configure != null) { diff --git a/core/java/android/bluetooth/BluetoothDeviceProfileState.java b/core/java/android/bluetooth/BluetoothDeviceProfileState.java index ab3a426..095cd11 100644 --- a/core/java/android/bluetooth/BluetoothDeviceProfileState.java +++ b/core/java/android/bluetooth/BluetoothDeviceProfileState.java @@ -120,6 +120,7 @@ public final class BluetoothDeviceProfileState extends StateMachine { private Pair<Integer, String> mIncomingConnections; private PowerManager.WakeLock mWakeLock; private PowerManager mPowerManager; + private boolean mPairingRequestRcvd = false; private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { @Override @@ -187,27 +188,38 @@ public final class BluetoothDeviceProfileState extends StateMachine { Message msg = obtainMessage(CONNECTION_ACCESS_REQUEST_REPLY); msg.arg1 = val; sendMessage(msg); + } else if (action.equals(BluetoothDevice.ACTION_PAIRING_REQUEST)) { + mPairingRequestRcvd = true; + } else if (action.equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)) { + int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, + BluetoothDevice.ERROR); + if (state == BluetoothDevice.BOND_BONDED && mPairingRequestRcvd) { + setTrust(BluetoothDevice.CONNECTION_ACCESS_YES); + mPairingRequestRcvd = false; + } else if (state == BluetoothDevice.BOND_NONE) { + mPairingRequestRcvd = false; + } } } }; private boolean isPhoneDocked(BluetoothDevice autoConnectDevice) { - // This works only because these broadcast intents are "sticky" - Intent i = mContext.registerReceiver(null, new IntentFilter(Intent.ACTION_DOCK_EVENT)); - if (i != null) { - int state = i.getIntExtra(Intent.EXTRA_DOCK_STATE, Intent.EXTRA_DOCK_STATE_UNDOCKED); - if (state != Intent.EXTRA_DOCK_STATE_UNDOCKED) { - BluetoothDevice device = i.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); - if (device != null && autoConnectDevice.equals(device)) { - return true; - } - } - } - return false; - } + // This works only because these broadcast intents are "sticky" + Intent i = mContext.registerReceiver(null, new IntentFilter(Intent.ACTION_DOCK_EVENT)); + if (i != null) { + int state = i.getIntExtra(Intent.EXTRA_DOCK_STATE, Intent.EXTRA_DOCK_STATE_UNDOCKED); + if (state != Intent.EXTRA_DOCK_STATE_UNDOCKED) { + BluetoothDevice device = i.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); + if (device != null && autoConnectDevice.equals(device)) { + return true; + } + } + } + return false; + } public BluetoothDeviceProfileState(Context context, String address, - BluetoothService service, BluetoothA2dpService a2dpService) { + BluetoothService service, BluetoothA2dpService a2dpService, boolean setTrust) { super(address); mContext = context; mDevice = new BluetoothDevice(address); @@ -231,6 +243,8 @@ public final class BluetoothDeviceProfileState extends StateMachine { filter.addAction(BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED); filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED); filter.addAction(BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY); + filter.addAction(BluetoothDevice.ACTION_PAIRING_REQUEST); + filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED); mContext.registerReceiver(mBroadcastReceiver, filter); @@ -247,6 +261,10 @@ public final class BluetoothDeviceProfileState extends StateMachine { PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.ON_AFTER_RELEASE, TAG); mWakeLock.setReferenceCounted(false); + + if (setTrust) { + setTrust(BluetoothDevice.CONNECTION_ACCESS_YES); + } } private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener = diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java index 3284361..8f2b3d8 100644 --- a/core/java/android/bluetooth/BluetoothHeadset.java +++ b/core/java/android/bluetooth/BluetoothHeadset.java @@ -661,7 +661,7 @@ public final class BluetoothHeadset implements BluetoothProfile { */ public boolean disconnectHeadsetInternal(BluetoothDevice device) { if (DBG) log("disconnectHeadsetInternal"); - if (mService != null && isEnabled()) { + if (mService != null && !isDisabled()) { try { return mService.disconnectHeadsetInternal(device); } catch (RemoteException e) {Log.e(TAG, e.toString());} diff --git a/core/java/android/content/ComponentCallbacks.java b/core/java/android/content/ComponentCallbacks.java index 92b98fd..37cc141 100644 --- a/core/java/android/content/ComponentCallbacks.java +++ b/core/java/android/content/ComponentCallbacks.java @@ -56,11 +56,8 @@ public interface ComponentCallbacks { static final int TRIM_MEMORY_COMPLETE = 80; /** @hide */ - static final int TRIM_MEMORY_MODERATE = 60; + static final int TRIM_MEMORY_MODERATE = 50; /** @hide */ - static final int TRIM_MEMORY_BACKGROUND = 40; - - /** @hide */ - static final int TRIM_MEMORY_INVISIBLE = 20; + static final int TRIM_MEMORY_BACKGROUND = 20; } diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index fed6d81..cdda910 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -1572,6 +1572,17 @@ public abstract class Context { public static final String WIFI_SERVICE = "wifi"; /** + * Use with {@link #getSystemService} to retrieve a {@link + * android.net.wifi.p2p.WifiP2pManager} for handling management of + * Wi-Fi p2p. + * + * @see #getSystemService + * @see android.net.wifi.p2p.WifiP2pManager + * @hide + */ + public static final String WIFI_P2P_SERVICE = "wifip2p"; + + /** * Use with {@link #getSystemService} to retrieve a * {@link android.media.AudioManager} for handling management of volume, * ringer modes and audio routing. @@ -1612,6 +1623,15 @@ public abstract class Context { /** * Use with {@link #getSystemService} to retrieve a + * {@link android.view.textservice.TextServicesManager} for accessing + * text services. + * + * @see #getSystemService + */ + public static final String TEXT_SERVICES_MANAGER_SERVICE = "textservices"; + + /** + * Use with {@link #getSystemService} to retrieve a * {@link android.appwidget.AppWidgetManager} for accessing AppWidgets. * * @hide diff --git a/core/java/android/inputmethodservice/ExtractEditLayout.java b/core/java/android/inputmethodservice/ExtractEditLayout.java index eafff49..5cfa998 100644 --- a/core/java/android/inputmethodservice/ExtractEditLayout.java +++ b/core/java/android/inputmethodservice/ExtractEditLayout.java @@ -172,7 +172,10 @@ public class ExtractEditLayout extends LinearLayout { @Override public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) { - return mCallback.onActionItemClicked(this, item); + if (mCallback != null) { + return mCallback.onActionItemClicked(this, item); + } + return false; } @Override diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index ce6f697..a564d97 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -653,6 +653,17 @@ public class ConnectivityManager { } } + /** + * {@hide} + */ + public int setUsbTethering(boolean enable) { + try { + return mService.setUsbTethering(enable); + } catch (RemoteException e) { + return TETHER_ERROR_SERVICE_UNAVAIL; + } + } + /** {@hide} */ public static final int TETHER_ERROR_NO_ERROR = 0; /** {@hide} */ diff --git a/core/java/android/net/EthernetDataTracker.java b/core/java/android/net/EthernetDataTracker.java index a866436..b035c51 100644 --- a/core/java/android/net/EthernetDataTracker.java +++ b/core/java/android/net/EthernetDataTracker.java @@ -103,6 +103,10 @@ public class EthernetDataTracker implements NetworkStateTracker { public void interfaceRemoved(String iface) { mTracker.interfaceRemoved(iface); } + + public void limitReached(String limitName, String iface) { + // Ignored. + } } private EthernetDataTracker() { diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl index d95fc8d..b1d99a4 100644 --- a/core/java/android/net/IConnectivityManager.aidl +++ b/core/java/android/net/IConnectivityManager.aidl @@ -88,6 +88,8 @@ interface IConnectivityManager String[] getTetherableBluetoothRegexs(); + int setUsbTethering(boolean enable); + void requestNetworkTransitionWakelock(in String forWhom); void reportInetCondition(int networkType, int percentage); diff --git a/core/java/android/net/INetworkManagementEventObserver.aidl b/core/java/android/net/INetworkManagementEventObserver.aidl index 4436e6e..a97f203 100644 --- a/core/java/android/net/INetworkManagementEventObserver.aidl +++ b/core/java/android/net/INetworkManagementEventObserver.aidl @@ -52,4 +52,14 @@ interface INetworkManagementEventObserver { * @param iface The interface. */ void interfaceRemoved(String iface); + + /** + * A networking quota limit has been reached. The quota might not + * be specific to an interface. + * + * @param limitName The name of the limit that triggered. + * @param iface The interface on which the limit was detected. + */ + void limitReached(String limitName, String iface); + } diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java index 9826bec..132f3ba 100644 --- a/core/java/android/net/LinkProperties.java +++ b/core/java/android/net/LinkProperties.java @@ -58,8 +58,8 @@ public class LinkProperties implements Parcelable { private ProxyProperties mHttpProxy; public static class CompareResult<T> { - public ArrayList<T> removed = new ArrayList<T>(); - public ArrayList<T> added = new ArrayList<T>(); + public Collection<T> removed = new ArrayList<T>(); + public Collection<T> added = new ArrayList<T>(); @Override public String toString() { diff --git a/core/java/android/net/VpnBuilder.java b/core/java/android/net/VpnBuilder.java new file mode 100644 index 0000000..4582523 --- /dev/null +++ b/core/java/android/net/VpnBuilder.java @@ -0,0 +1,413 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.app.Activity; +import android.app.PendingIntent; +import android.content.Context; +import android.content.Intent; +import android.os.ParcelFileDescriptor; +import android.os.RemoteException; +import android.os.ServiceManager; + +import com.android.internal.net.VpnConfig; + +import java.net.InetAddress; +import java.net.Inet4Address; +import java.net.Inet6Address; +import java.net.DatagramSocket; +import java.net.Socket; +import java.util.ArrayList; + +/** + * VpnBuilder is a framework which enables applications to build their + * own VPN solutions. In general, it creates a virtual network interface, + * configures addresses and routing rules, and returns a file descriptor + * to the application. Each read from the descriptor retrieves an outgoing + * packet which was routed to the interface. Each write to the descriptor + * injects an incoming packet just like it was received from the interface. + * The framework is running on Internet Protocol (IP), so packets are + * always started with IP headers. The application then completes a VPN + * connection by processing and exchanging packets with a remote server + * over a secured tunnel. + * + * <p>Letting applications intercept packets raises huge security concerns. + * Besides, a VPN application can easily break the network, and two of them + * may conflict with each other. The framework takes several actions to + * address these issues. Here are some key points: + * <ul> + * <li>User action is required to create a VPN connection.</li> + * <li>There can be only one VPN connection running at the same time. The + * existing interface is deactivated when a new one is created.</li> + * <li>A system-managed notification is shown during the lifetime of a + * VPN connection.</li> + * <li>A system-managed dialog gives the information of the current VPN + * connection. It also provides a button to disconnect.</li> + * <li>The network is restored automatically when the file descriptor is + * closed. It also covers the cases when a VPN application is crashed + * or killed by the system.</li> + * </ul> + * + * <p>There are two primary methods in this class: {@link #prepare} and + * {@link #establish}. The former deals with the user action and stops + * the existing VPN connection created by another application. The latter + * creates a VPN interface using the parameters supplied to this builder. + * An application must call {@link #prepare} to grant the right to create + * an interface, and it can be revoked at any time by another application. + * The application got revoked is notified by an {@link #ACTION_VPN_REVOKED} + * broadcast. Here are the general steps to create a VPN connection: + * <ol> + * <li>When the user press the button to connect, call {@link #prepare} + * and launch the intent if necessary.</li> + * <li>Register a receiver for {@link #ACTION_VPN_REVOKED} broadcasts. + * <li>Connect to the remote server and negotiate the network parameters + * of the VPN connection.</li> + * <li>Use those parameters to configure a VpnBuilder and create a VPN + * interface by calling {@link #establish}.</li> + * <li>Start processing packets between the returned file descriptor and + * the VPN tunnel.</li> + * <li>When an {@link #ACTION_VPN_REVOKED} broadcast is received, the + * interface is already deactivated by the framework. Close the file + * descriptor and shut down the VPN tunnel gracefully. + * </ol> + * Methods in this class can be used in activities and services. However, + * the intent returned from {@link #prepare} must be launched from an + * activity. The broadcast receiver can be registered at any time, but doing + * it before calling {@link #establish} effectively avoids race conditions. + * + * <p class="note">Using this class requires + * {@link android.Manifest.permission#VPN} permission. + * @hide + */ +public class VpnBuilder { + + /** + * Broadcast intent action indicating that the VPN application has been + * revoked. This can be only received by the target application on the + * receiver explicitly registered using {@link Context#registerReceiver}. + * + * <p>This is a protected intent that can only be sent by the system. + */ + public static final String ACTION_VPN_REVOKED = VpnConfig.ACTION_VPN_REVOKED; + + /** + * Use IConnectivityManager instead since those methods are hidden and + * not available in ConnectivityManager. + */ + private static IConnectivityManager getService() { + return IConnectivityManager.Stub.asInterface( + ServiceManager.getService(Context.CONNECTIVITY_SERVICE)); + } + + /** + * Prepare to establish a VPN connection. This method returns {@code null} + * if the VPN application is already prepared. Otherwise, it returns an + * {@link Intent} to a system activity. The application should launch the + * activity using {@link Activity#startActivityForResult} to get itself + * prepared. The activity may pop up a dialog to require user action, and + * the result will come back to the application through its + * {@link Activity#onActivityResult}. The application becomes prepared if + * the result is {@link Activity#RESULT_OK}, and it is granted to create a + * VPN interface by calling {@link #establish}. + * + * <p>Only one application can be granted at the same time. The right + * is revoked when another application is granted. The application + * losing the right will be notified by an {@link #ACTION_VPN_REVOKED} + * broadcast, and its VPN interface will be deactivated by the system. + * The application should then notify the remote server and disconnect + * gracefully. Unless the application becomes prepared again, subsequent + * calls to {@link #establish} will return {@code null}. + * + * @see #establish + * @see #ACTION_VPN_REVOKED + */ + public static Intent prepare(Context context) { + try { + if (getService().prepareVpn(context.getPackageName(), null)) { + return null; + } + } catch (RemoteException e) { + // ignore + } + return VpnConfig.getIntentForConfirmation(); + } + + private VpnConfig mConfig = new VpnConfig(); + private StringBuilder mAddresses = new StringBuilder(); + private StringBuilder mRoutes = new StringBuilder(); + + /** + * Set the name of this session. It will be displayed in system-managed + * dialogs and notifications. This is recommended not required. + */ + public VpnBuilder setSession(String session) { + mConfig.session = session; + return this; + } + + /** + * Set the {@link PendingIntent} to an activity for users to configure + * the VPN connection. If it is not set, the button to configure will + * not be shown in system-managed dialogs. + */ + public VpnBuilder setConfigureIntent(PendingIntent intent) { + mConfig.configureIntent = intent; + return this; + } + + /** + * Set the maximum transmission unit (MTU) of the VPN interface. If it + * is not set, the default value in the operating system will be used. + * + * @throws IllegalArgumentException if the value is not positive. + */ + public VpnBuilder setMtu(int mtu) { + if (mtu <= 0) { + throw new IllegalArgumentException("Bad mtu"); + } + mConfig.mtu = mtu; + return this; + } + + /** + * Private method to validate address and prefixLength. + */ + private static void check(InetAddress address, int prefixLength) { + if (address.isLoopbackAddress()) { + throw new IllegalArgumentException("Bad address"); + } + if (address instanceof Inet4Address) { + if (prefixLength < 0 || prefixLength > 32) { + throw new IllegalArgumentException("Bad prefixLength"); + } + } else if (address instanceof Inet6Address) { + if (prefixLength < 0 || prefixLength > 128) { + throw new IllegalArgumentException("Bad prefixLength"); + } + } else { + throw new IllegalArgumentException("Unsupported family"); + } + } + + /** + * Convenience method to add a network address to the VPN interface + * using a numeric address string. See {@link InetAddress} for the + * definitions of numeric address formats. + * + * @throws IllegalArgumentException if the address is invalid. + * @see #addAddress(InetAddress, int) + */ + public VpnBuilder addAddress(String address, int prefixLength) { + return addAddress(InetAddress.parseNumericAddress(address), prefixLength); + } + + /** + * Add a network address to the VPN interface. Both IPv4 and IPv6 + * addresses are supported. At least one address must be set before + * calling {@link #establish}. + * + * @throws IllegalArgumentException if the address is invalid. + */ + public VpnBuilder addAddress(InetAddress address, int prefixLength) { + check(address, prefixLength); + + if (address.isAnyLocalAddress()) { + throw new IllegalArgumentException("Bad address"); + } + + mAddresses.append(String.format(" %s/%d", address.getHostAddress(), prefixLength)); + return this; + } + + /** + * Convenience method to add a network route to the VPN interface + * using a numeric address string. See {@link InetAddress} for the + * definitions of numeric address formats. + * + * @see #addRoute(InetAddress, int) + * @throws IllegalArgumentException if the route is invalid. + */ + public VpnBuilder addRoute(String address, int prefixLength) { + return addRoute(InetAddress.parseNumericAddress(address), prefixLength); + } + + /** + * Add a network route to the VPN interface. Both IPv4 and IPv6 + * routes are supported. + * + * @throws IllegalArgumentException if the route is invalid. + */ + public VpnBuilder addRoute(InetAddress address, int prefixLength) { + check(address, prefixLength); + + int offset = prefixLength / 8; + byte[] bytes = address.getAddress(); + if (offset < bytes.length) { + if ((byte)(bytes[offset] << (prefixLength % 8)) != 0) { + throw new IllegalArgumentException("Bad address"); + } + while (++offset < bytes.length) { + if (bytes[offset] != 0) { + throw new IllegalArgumentException("Bad address"); + } + } + } + + mRoutes.append(String.format(" %s/%d", address.getHostAddress(), prefixLength)); + return this; + } + + /** + * Convenience method to add a DNS server to the VPN connection + * using a numeric address string. See {@link InetAddress} for the + * definitions of numeric address formats. + * + * @throws IllegalArgumentException if the address is invalid. + * @see #addDnsServer(InetAddress) + */ + public VpnBuilder addDnsServer(String address) { + return addDnsServer(InetAddress.parseNumericAddress(address)); + } + + /** + * Add a DNS server to the VPN connection. Both IPv4 and IPv6 + * addresses are supported. If none is set, the DNS servers of + * the default network will be used. + * + * @throws IllegalArgumentException if the address is invalid. + */ + public VpnBuilder addDnsServer(InetAddress address) { + if (address.isLoopbackAddress() || address.isAnyLocalAddress()) { + throw new IllegalArgumentException("Bad address"); + } + if (mConfig.dnsServers == null) { + mConfig.dnsServers = new ArrayList<String>(); + } + mConfig.dnsServers.add(address.getHostAddress()); + return this; + } + + /** + * Add a search domain to the DNS resolver. + */ + public VpnBuilder addSearchDomain(String domain) { + if (mConfig.searchDomains == null) { + mConfig.searchDomains = new ArrayList<String>(); + } + mConfig.searchDomains.add(domain); + return this; + } + + /** + * Create a VPN interface using the parameters supplied to this builder. + * The interface works on IP packets, and a file descriptor is returned + * for the application to access them. Each read retrieves an outgoing + * packet which was routed to the interface. Each write injects an + * incoming packet just like it was received from the interface. The file + * descriptor is put into non-blocking mode by default to avoid blocking + * Java threads. To use the file descriptor completely in native space, + * see {@link ParcelFileDescriptor#detachFd()}. The application MUST + * close the file descriptor when the VPN connection is terminated. The + * VPN interface will be removed and the network will be restored by the + * framework automatically. + * + * <p>To avoid conflicts, there can be only one active VPN interface at + * the same time. Usually network parameters are never changed during the + * lifetime of a VPN connection. It is also common for an application to + * create a new file descriptor after closing the previous one. However, + * it is rare but not impossible to have two interfaces while performing a + * seamless handover. In this case, the old interface will be deactivated + * when the new one is configured successfully. Both file descriptors are + * valid but now outgoing packets will be routed to the new interface. + * Therefore, after draining the old file descriptor, the application MUST + * close it and start using the new file descriptor. If the new interface + * cannot be created, the existing interface and its file descriptor remain + * untouched. + * + * <p>An exception will be thrown if the interface cannot be created for + * any reason. However, this method returns {@code null} if the application + * is not prepared or is revoked by another application. This helps solve + * possible race conditions while handling {@link #ACTION_VPN_REVOKED} + * broadcasts. + * + * @return {@link ParcelFileDescriptor} of the VPN interface, or + * {@code null} if the application is not prepared. + * @throws IllegalArgumentException if a parameter is not accepted by the + * operating system. + * @throws IllegalStateException if a parameter cannot be applied by the + * operating system. + * @see #prepare + */ + public ParcelFileDescriptor establish() { + mConfig.addresses = mAddresses.toString(); + mConfig.routes = mRoutes.toString(); + + try { + return getService().establishVpn(mConfig); + } catch (RemoteException e) { + throw new IllegalStateException(e); + } + } + + /** + * Protect a socket from VPN connections. The socket will be bound to the + * current default network interface, so its traffic will not be forwarded + * through VPN. This method is useful if some connections need to be kept + * outside of VPN. For example, a VPN tunnel should protect itself if its + * destination is covered by VPN routes. Otherwise its outgoing packets + * will be sent back to the VPN interface and cause an infinite loop. + * + * <p>The socket is NOT closed by this method. + * + * @return {@code true} on success. + */ + public static boolean protect(int socket) { + ParcelFileDescriptor dup = null; + try { + dup = ParcelFileDescriptor.fromFd(socket); + return getService().protectVpn(dup); + } catch (Exception e) { + return false; + } finally { + try { + dup.close(); + } catch (Exception e) { + // ignore + } + } + } + + /** + * Protect a {@link Socket} from VPN connections. + * + * @return {@code true} on success. + * @see #protect(int) + */ + public static boolean protect(Socket socket) { + return protect(socket.getFileDescriptor$().getInt$()); + } + + /** + * Protect a {@link DatagramSocket} from VPN connections. + * + * @return {@code true} on success. + * @see #protect(int) + */ + public static boolean protect(DatagramSocket socket) { + return protect(socket.getFileDescriptor$().getInt$()); + } +} diff --git a/core/java/android/nfc/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl index dcbe9da..2ed6619 100644 --- a/core/java/android/nfc/INfcAdapter.aidl +++ b/core/java/android/nfc/INfcAdapter.aidl @@ -46,8 +46,6 @@ interface INfcAdapter // NfcAdapter-class related methods boolean isEnabled(); - NdefMessage localGet(); - void localSet(in NdefMessage message); void enableForegroundDispatch(in ComponentName activity, in PendingIntent intent, in IntentFilter[] filters, in TechListParcel techLists); void disableForegroundDispatch(in ComponentName activity); @@ -62,4 +60,7 @@ interface INfcAdapter int createLlcpSocket(int sap, int miu, int rw, int linearBufferLength); boolean disable(); boolean enable(); + boolean enableZeroClick(); + boolean disableZeroClick(); + boolean zeroClickEnabled(); } diff --git a/core/java/android/nfc/INfcTag.aidl b/core/java/android/nfc/INfcTag.aidl index aa5937e..7bdefe7 100644 --- a/core/java/android/nfc/INfcTag.aidl +++ b/core/java/android/nfc/INfcTag.aidl @@ -44,5 +44,6 @@ interface INfcTag Tag rediscover(int nativehandle); int setTimeout(int technology, int timeout); + int getTimeout(int technology); void resetTimeouts(); } diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java index 738e75f..4d04027 100644 --- a/core/java/android/nfc/NfcAdapter.java +++ b/core/java/android/nfc/NfcAdapter.java @@ -684,44 +684,45 @@ public final class NfcAdapter { } /** - * Set the NDEF Message that this NFC adapter should appear as to Tag - * readers. - * <p> - * Any Tag reader can read the contents of the local tag when it is in - * proximity, without any further user confirmation. - * <p> - * The implementation of this method must either - * <ul> - * <li>act as a passive tag containing this NDEF message - * <li>provide the NDEF message on over LLCP to peer NFC adapters - * </ul> - * The NDEF message is preserved across reboot. - * <p>Requires {@link android.Manifest.permission#NFC} permission. - * - * @param message NDEF message to make public + * Enable zero-click sharing. + * * @hide */ - public void setLocalNdefMessage(NdefMessage message) { + public boolean enableZeroClick() { try { - sService.localSet(message); + return sService.enableZeroClick(); } catch (RemoteException e) { attemptDeadServiceRecovery(e); + return false; } } /** - * Get the NDEF Message that this adapter appears as to Tag readers. - * <p>Requires {@link android.Manifest.permission#NFC} permission. + * Disable zero-click sharing. * - * @return NDEF Message that is publicly readable * @hide */ - public NdefMessage getLocalNdefMessage() { + public boolean disableZeroClick() { try { - return sService.localGet(); + return sService.disableZeroClick(); } catch (RemoteException e) { attemptDeadServiceRecovery(e); - return null; + return false; + } + } + + /** + * Return true if zero-click sharing is enabled. + * + * @return true if zero-click sharing is enabled + * @hide + */ + public boolean zeroClickEnabled() { + try { + return sService.zeroClickEnabled(); + } catch (RemoteException e) { + attemptDeadServiceRecovery(e); + return false; } } diff --git a/core/java/android/nfc/tech/IsoDep.java b/core/java/android/nfc/tech/IsoDep.java index d02086f..0672a4e 100644 --- a/core/java/android/nfc/tech/IsoDep.java +++ b/core/java/android/nfc/tech/IsoDep.java @@ -101,6 +101,24 @@ public final class IsoDep extends BasicTagTechnology { } /** + * Gets the currently set timeout of {@link #transceive} in milliseconds. + * + * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. + * + * @return timeout value in milliseconds + * @hide + */ + // TODO Unhide for ICS + public int getTimeout() { + try { + return mTag.getTagService().getTimeout(TagTechnology.ISO_DEP); + } catch (RemoteException e) { + Log.e(TAG, "NFC service dead", e); + return 0; + } + } + + /** * Return the ISO-DEP historical bytes for {@link NfcA} tags. * <p>Does not cause any RF activity and does not block. * <p>The historical bytes can be used to help identify a tag. They are present diff --git a/core/java/android/nfc/tech/MifareClassic.java b/core/java/android/nfc/tech/MifareClassic.java index 5cafe5b..93e7cbd 100644 --- a/core/java/android/nfc/tech/MifareClassic.java +++ b/core/java/android/nfc/tech/MifareClassic.java @@ -597,6 +597,24 @@ public final class MifareClassic extends BasicTagTechnology { } } + /** + * Gets the currently set timeout of {@link #transceive} in milliseconds. + * + * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. + * + * @return timeout value in milliseconds + * @hide + */ + // TODO Unhide for ICS + public int getTimeout() { + try { + return mTag.getTagService().getTimeout(TagTechnology.MIFARE_CLASSIC); + } catch (RemoteException e) { + Log.e(TAG, "NFC service dead", e); + return 0; + } + } + private static void validateSector(int sector) { // Do not be too strict on upper bounds checking, since some cards // have more addressable memory than they report. For example, diff --git a/core/java/android/nfc/tech/MifareUltralight.java b/core/java/android/nfc/tech/MifareUltralight.java index 3d4cdd1..ca74ebe 100644 --- a/core/java/android/nfc/tech/MifareUltralight.java +++ b/core/java/android/nfc/tech/MifareUltralight.java @@ -238,6 +238,24 @@ public final class MifareUltralight extends BasicTagTechnology { } } + /** + * Gets the currently set timeout of {@link #transceive} in milliseconds. + * + * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. + * + * @return timeout value in milliseconds + * @hide + */ + // TODO Unhide for ICS + public int getTimeout() { + try { + return mTag.getTagService().getTimeout(TagTechnology.MIFARE_ULTRALIGHT); + } catch (RemoteException e) { + Log.e(TAG, "NFC service dead", e); + return 0; + } + } + private static void validatePageIndex(int pageIndex) { // Do not be too strict on upper bounds checking, since some cards // may have more addressable memory than they report. diff --git a/core/java/android/nfc/tech/NfcA.java b/core/java/android/nfc/tech/NfcA.java index 08095e6..bd1f95a 100644 --- a/core/java/android/nfc/tech/NfcA.java +++ b/core/java/android/nfc/tech/NfcA.java @@ -141,4 +141,22 @@ public final class NfcA extends BasicTagTechnology { Log.e(TAG, "NFC service dead", e); } } + + /** + * Gets the currently set timeout of {@link #transceive} in milliseconds. + * + * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. + * + * @return timeout value in milliseconds + * @hide + */ + // TODO Unhide for ICS + public int getTimeout() { + try { + return mTag.getTagService().getTimeout(TagTechnology.NFC_A); + } catch (RemoteException e) { + Log.e(TAG, "NFC service dead", e); + return 0; + } + } } diff --git a/core/java/android/nfc/tech/NfcF.java b/core/java/android/nfc/tech/NfcF.java index 85abf89..7b25a72 100644 --- a/core/java/android/nfc/tech/NfcF.java +++ b/core/java/android/nfc/tech/NfcF.java @@ -140,4 +140,22 @@ public final class NfcF extends BasicTagTechnology { Log.e(TAG, "NFC service dead", e); } } + + /** + * Gets the currently set timeout of {@link #transceive} in milliseconds. + * + * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. + * + * @return timeout value in milliseconds + * @hide + */ + // TODO Unhide for ICS + public int getTimeout() { + try { + return mTag.getTagService().getTimeout(TagTechnology.NFC_F); + } catch (RemoteException e) { + Log.e(TAG, "NFC service dead", e); + return 0; + } + } } diff --git a/core/java/android/os/Handler.java b/core/java/android/os/Handler.java index cd39d5c..bc37244 100644 --- a/core/java/android/os/Handler.java +++ b/core/java/android/os/Handler.java @@ -361,7 +361,8 @@ public class Handler { /** * Remove any pending posts of Runnable <var>r</var> with Object - * <var>token</var> that are in the message queue. + * <var>token</var> that are in the message queue. If <var>token</var> is null, + * all callbacks will be removed. */ public final void removeCallbacks(Runnable r, Object token) { @@ -517,7 +518,8 @@ public class Handler { /** * Remove any pending posts of messages with code 'what' and whose obj is - * 'object' that are in the message queue. + * 'object' that are in the message queue. If <var>token</var> is null, + * all messages will be removed. */ public final void removeMessages(int what, Object object) { mQueue.removeMessages(this, what, object, true); @@ -525,7 +527,8 @@ public class Handler { /** * Remove any pending posts of callbacks and sent messages whose - * <var>obj</var> is <var>token</var>. + * <var>obj</var> is <var>token</var>. If <var>token</var> is null, + * all callbacks and messages will be removed. */ public final void removeCallbacksAndMessages(Object token) { mQueue.removeCallbacksAndMessages(this, token); diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl index f230526..1174e3b 100644 --- a/core/java/android/os/INetworkManagementService.aidl +++ b/core/java/android/os/INetworkManagementService.aidl @@ -180,7 +180,7 @@ interface INetworkManagementService /** * Stop Wifi Access Point */ - void stopAccessPoint(); + void stopAccessPoint(String wlanIface); /** * Set Access Point config diff --git a/core/java/android/os/Looper.java b/core/java/android/os/Looper.java index 720e802b..c61f28a 100644 --- a/core/java/android/os/Looper.java +++ b/core/java/android/os/Looper.java @@ -130,19 +130,20 @@ public class Looper { if (logging != null) { logging.println(">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what); - wallStart = System.currentTimeMillis(); - threadStart = SystemClock.currentThreadTimeMillis(); + wallStart = SystemClock.currentTimeMicro(); + threadStart = SystemClock.currentThreadTimeMicro(); } msg.target.dispatchMessage(msg); if (logging != null) { - long wallTime = System.currentTimeMillis() - wallStart; - long threadTime = SystemClock.currentThreadTimeMillis() - threadStart; + long wallTime = SystemClock.currentTimeMicro() - wallStart; + long threadTime = SystemClock.currentThreadTimeMicro() - threadStart; logging.println("<<<<< Finished to " + msg.target + " " + msg.callback); if (logging instanceof Profiler) { - ((Profiler) logging).profile(msg, wallStart, wallTime, threadTime); + ((Profiler) logging).profile(msg, wallStart, wallTime, + threadStart, threadTime); } } @@ -247,6 +248,7 @@ public class Looper { * @hide */ public static interface Profiler { - void profile(Message message, long wallStart, long wallTime, long threadTime); + void profile(Message message, long wallStart, long wallTime, + long threadStart, long threadTime); } } diff --git a/core/java/android/os/SystemClock.java b/core/java/android/os/SystemClock.java index 2dd6749..7291739 100644 --- a/core/java/android/os/SystemClock.java +++ b/core/java/android/os/SystemClock.java @@ -157,4 +157,22 @@ public final class SystemClock { * @return elapsed milliseconds in the thread */ public static native long currentThreadTimeMillis(); + + /** + * Returns microseconds running in the current thread. + * + * @return elapsed microseconds in the thread + * + * @hide + */ + public static native long currentThreadTimeMicro(); + + /** + * Returns current wall time in microseconds. + * + * @return elapsed microseconds in wall time + * + * @hide + */ + public static native long currentTimeMicro(); } diff --git a/core/java/android/preference/CheckBoxPreference.java b/core/java/android/preference/CheckBoxPreference.java index 437e553..166b21b 100644 --- a/core/java/android/preference/CheckBoxPreference.java +++ b/core/java/android/preference/CheckBoxPreference.java @@ -61,8 +61,8 @@ public class CheckBoxPreference extends TwoStatePreference { View checkboxView = view.findViewById(com.android.internal.R.id.checkbox); if (checkboxView != null && checkboxView instanceof Checkable) { ((Checkable) checkboxView).setChecked(mChecked); - - sendAccessibilityEventForView(checkboxView); + // Post this so this view is bound and attached when firing the event. + postSendAccessibilityEventForView(checkboxView); } syncSummaryView(view); diff --git a/core/java/android/preference/PreferenceActivity.java b/core/java/android/preference/PreferenceActivity.java index c90de17..78c9010 100644 --- a/core/java/android/preference/PreferenceActivity.java +++ b/core/java/android/preference/PreferenceActivity.java @@ -563,6 +563,12 @@ public abstract class PreferenceActivity extends ListActivity implements // Single pane, showing just a prefs fragment. findViewById(com.android.internal.R.id.headers).setVisibility(View.GONE); mPrefsContainer.setVisibility(View.VISIBLE); + if (initialTitle != 0) { + CharSequence initialTitleStr = getText(initialTitle); + CharSequence initialShortTitleStr = initialShortTitle != 0 + ? getText(initialShortTitle) : null; + showBreadCrumbs(initialTitleStr, initialShortTitleStr); + } } else if (mHeaders.size() > 0) { setListAdapter(new HeaderAdapter(this, mHeaders)); if (!mSinglePane) { @@ -1093,6 +1099,10 @@ public abstract class PreferenceActivity extends ListActivity implements } else { getListView().clearChoices(); } + showBreadCrumbs(header); + } + + void showBreadCrumbs(Header header) { if (header != null) { CharSequence title = header.getBreadCrumbTitle(getResources()); if (title == null) title = header.getTitle(getResources()); diff --git a/core/java/android/preference/SwitchPreference.java b/core/java/android/preference/SwitchPreference.java index f681526..3dbd522 100644 --- a/core/java/android/preference/SwitchPreference.java +++ b/core/java/android/preference/SwitchPreference.java @@ -102,8 +102,8 @@ public class SwitchPreference extends TwoStatePreference { View checkableView = view.findViewById(com.android.internal.R.id.switchWidget); if (checkableView != null && checkableView instanceof Checkable) { ((Checkable) checkableView).setChecked(mChecked); - - sendAccessibilityEventForView(checkableView); + // Post this so this view is bound and attached when firing the event. + postSendAccessibilityEventForView(checkableView); if (checkableView instanceof Switch) { final Switch switchView = (Switch) checkableView; diff --git a/core/java/android/preference/TwoStatePreference.java b/core/java/android/preference/TwoStatePreference.java index 8e21c4c..55ef108 100644 --- a/core/java/android/preference/TwoStatePreference.java +++ b/core/java/android/preference/TwoStatePreference.java @@ -16,7 +16,6 @@ package android.preference; -import android.app.Service; import android.content.Context; import android.content.SharedPreferences; import android.content.res.TypedArray; @@ -39,28 +38,20 @@ public abstract class TwoStatePreference extends Preference { private CharSequence mSummaryOff; boolean mChecked; private boolean mSendAccessibilityEventViewClickedType; - private AccessibilityManager mAccessibilityManager; private boolean mDisableDependentsState; + private SendAccessibilityEventTypeViewClicked mSendAccessibilityEventTypeViewClicked; + public TwoStatePreference(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); - - mAccessibilityManager = - (AccessibilityManager) getContext().getSystemService(Service.ACCESSIBILITY_SERVICE); } public TwoStatePreference(Context context, AttributeSet attrs) { - super(context, attrs); - - mAccessibilityManager = - (AccessibilityManager) getContext().getSystemService(Service.ACCESSIBILITY_SERVICE); + this(context, attrs, 0); } public TwoStatePreference(Context context) { - super(context); - - mAccessibilityManager = - (AccessibilityManager) getContext().getSystemService(Service.ACCESSIBILITY_SERVICE); + this(context, null); } @Override @@ -198,20 +189,23 @@ public abstract class TwoStatePreference extends Preference { } /** - * Send an accessibility event for the given view if appropriate + * Post send an accessibility event for the given view if appropriate. + * * @param view View that should send the event */ - void sendAccessibilityEventForView(View view) { + void postSendAccessibilityEventForView(View view) { // send an event to announce the value change of the state. It is done here // because clicking a preference does not immediately change the checked state // for example when enabling the WiFi - if (mSendAccessibilityEventViewClickedType && - mAccessibilityManager.isEnabled() && - view.isEnabled()) { + if (mSendAccessibilityEventViewClickedType + && AccessibilityManager.getInstance(getContext()).isEnabled() + && view.isEnabled()) { mSendAccessibilityEventViewClickedType = false; - - int eventType = AccessibilityEvent.TYPE_VIEW_CLICKED; - view.sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType)); + if (mSendAccessibilityEventTypeViewClicked == null) { + mSendAccessibilityEventTypeViewClicked = new SendAccessibilityEventTypeViewClicked(); + } + mSendAccessibilityEventTypeViewClicked.mView = view; + view.post(mSendAccessibilityEventTypeViewClicked); } } @@ -306,4 +300,13 @@ public abstract class TwoStatePreference extends Preference { } }; } + + private final class SendAccessibilityEventTypeViewClicked implements Runnable { + private View mView; + + @Override + public void run() { + mView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED); + } + } } diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java index 76f198c..4a719ec 100644 --- a/core/java/android/provider/ContactsContract.java +++ b/core/java/android/provider/ContactsContract.java @@ -1439,6 +1439,13 @@ public final class ContactsContract { CONTENT_URI, "strequent"); /** + * The content:// style URI for showing frequently contacted person listing. + * @hide + */ + public static final Uri CONTENT_FREQUENT_URI = Uri.withAppendedPath( + CONTENT_URI, "frequent"); + + /** * The content:// style URI used for "type-to-filter" functionality on the * {@link #CONTENT_STREQUENT_URI} URI. The filter string will be used to match * various parts of the contact name. The filter argument should be passed @@ -1747,9 +1754,9 @@ public final class ContactsContract { * Uri displayPhotoUri = Uri.withAppendedPath(contactUri, Contacts.Photo.DISPLAY_PHOTO); * try { * AssetFileDescriptor fd = - * getContentResolver().openAssetFile(displayPhotoUri, "r"); + * getContentResolver().openAssetFileDescriptor(displayPhotoUri, "r"); * return fd.createInputStream(); - * } catch (FileNotFoundException e) { + * } catch (IOException e) { * return null; * } * } @@ -2586,7 +2593,7 @@ public final class ContactsContract { * display photo. To access this directory append * {@link RawContacts.DisplayPhoto#CONTENT_DIRECTORY} to the raw contact URI. * The resulting URI represents an image file, and should be interacted with - * using ContentProvider.openAssetFile. + * using ContentResolver.openAssetFileDescriptor. * <p> * <p> * Note that this sub-directory also supports opening the photo as an asset file @@ -2605,7 +2612,7 @@ public final class ContactsContract { * RawContacts.DisplayPhoto.CONTENT_DIRECTORY); * try { * AssetFileDescriptor fd = - * getContentResolver().openAssetFile(rawContactPhotoUri, "rw"); + * getContentResolver().openAssetFileDescriptor(rawContactPhotoUri, "rw"); * OutputStream os = fd.createOutputStream(); * os.write(photo); * os.close(); @@ -2804,7 +2811,7 @@ public final class ContactsContract { /** * The package containing resources for this status: label and icon. - * <p>Type: NUMBER</p> + * <p>Type: TEXT</p> */ public static final String STATUS_RES_PACKAGE = "status_res_package"; @@ -2872,7 +2879,7 @@ public final class ContactsContract { * ContentValues values = new ContentValues(); * values.put(StreamItems.TEXT, "Breakfasted at Tiffanys"); * values.put(StreamItems.TIMESTAMP, timestamp); - * values.put(StreamItems.COMMENT, "3 people reshared this"); + * values.put(StreamItems.COMMENTS, "3 people reshared this"); * values.put(StreamItems.ACTION, action); * values.put(StreamItems.ACTION_URI, actionUri); * Uri streamItemUri = getContentResolver().insert( @@ -2887,7 +2894,7 @@ public final class ContactsContract { * values.put(StreamItems.RAW_CONTACT_ID, rawContactId); * values.put(StreamItems.TEXT, "Breakfasted at Tiffanys"); * values.put(StreamItems.TIMESTAMP, timestamp); - * values.put(StreamItems.COMMENT, "3 people reshared this"); + * values.put(StreamItems.COMMENTS, "3 people reshared this"); * values.put(StreamItems.ACTION, action); * values.put(StreamItems.ACTION_URI, actionUri); * Uri streamItemUri = getContentResolver().insert(StreamItems.CONTENT_URI, values); @@ -2906,7 +2913,7 @@ public final class ContactsContract { * <pre> * values.clear(); * values.put(StreamItemPhotos.SORT_INDEX, 1); - * values.put(StreamItemPhotos.PICTURE, photoData); + * values.put(StreamItemPhotos.PHOTO, photoData); * values.put(StreamItemPhotos.ACTION, action); * values.put(StreamItemPhotos.ACTION_URI, actionUri); * getContentResolver().insert(Uri.withAppendedPath( @@ -2920,7 +2927,7 @@ public final class ContactsContract { * values.clear(); * values.put(StreamItemPhotos.STREAM_ITEM_ID, streamItemId); * values.put(StreamItemPhotos.SORT_INDEX, 1); - * values.put(StreamItemPhotos.PICTURE, photoData); + * values.put(StreamItemPhotos.PHOTO, photoData); * values.put(StreamItemPhotos.ACTION, action); * values.put(StreamItemPhotos.ACTION_URI, actionUri); * getContentResolver().insert(StreamItems.CONTENT_PHOTO_URI, values); @@ -3008,8 +3015,7 @@ public final class ContactsContract { /** * This URI allows the caller to query for the maximum number of stream items - * that will be stored under any single raw contact, as well as the maximum - * photo size (in bytes) accepted in stream item photos. + * that will be stored under any single raw contact. */ public static final Uri CONTENT_LIMIT_URI = Uri.withAppendedPath(AUTHORITY_URI, "stream_items_limit"); @@ -3022,13 +3028,6 @@ public final class ContactsContract { public static final String MAX_ITEMS = "max_items"; /** - * Queries to {@link ContactsContract.StreamItems#CONTENT_LIMIT_URI} will - * contain this column, with the value indicating the byte limit for - * individual photos. - */ - public static final String PHOTO_MAX_BYTES = "photo_max_bytes"; - - /** * <p> * A sub-directory of a single stream item entry that contains all of its * photo rows. To access this @@ -3067,7 +3066,7 @@ public final class ContactsContract { * The package name to use when creating {@link Resources} objects for * this stream item. This value is only designed for use when building * user interfaces, and should not be used to infer the owner. - * <P>Type: NUMBER</P> + * <P>Type: TEXT</P> */ public static final String RES_PACKAGE = "res_package"; @@ -3161,7 +3160,7 @@ public final class ContactsContract { * <pre> * ContentValues values = new ContentValues(); * values.put(StreamItemPhotos.SORT_INDEX, 1); - * values.put(StreamItemPhotos.PICTURE, photoData); + * values.put(StreamItemPhotos.PHOTO, photoData); * values.put(StreamItemPhotos.ACTION, action); * values.put(StreamItemPhotos.ACTION_URI, actionUri); * Uri photoUri = getContentResolver().insert(Uri.withAppendedPath( @@ -3176,7 +3175,7 @@ public final class ContactsContract { * ContentValues values = new ContentValues(); * values.put(StreamItemPhotos.STREAM_ITEM_ID, streamItemId); * values.put(StreamItemPhotos.SORT_INDEX, 1); - * values.put(StreamItemPhotos.PICTURE, photoData); + * values.put(StreamItemPhotos.PHOTO, photoData); * values.put(StreamItemPhotos.ACTION, action); * values.put(StreamItemPhotos.ACTION_URI, actionUri); * Uri photoUri = getContentResolver().insert(StreamItems.CONTENT_PHOTO_URI, values); @@ -3198,7 +3197,7 @@ public final class ContactsContract { * <dd> * <pre> * ContentValues values = new ContentValues(); - * values.put(StreamItemPhotos.PICTURE, newPhotoData); + * values.put(StreamItemPhotos.PHOTO, newPhotoData); * getContentResolver().update( * ContentUris.withAppendedId( * Uri.withAppendedPath( @@ -3212,7 +3211,7 @@ public final class ContactsContract { * <pre> * ContentValues values = new ContentValues(); * values.put(StreamItemPhotos.STREAM_ITEM_ID, streamItemId); - * values.put(StreamItemPhotos.PICTURE, newPhotoData); + * values.put(StreamItemPhotos.PHOTO, newPhotoData); * getContentResolver().update(StreamItems.CONTENT_PHOTO_URI, values); * </pre> * </dd> @@ -3271,6 +3270,21 @@ public final class ContactsContract { * null, null, null, StreamItemPhotos.SORT_INDEX); * </pre> * </dl> + * The record will contain both a {@link StreamItemPhotos#PHOTO_FILE_ID} and a + * {@link StreamItemPhotos#PHOTO_URI}. The {@link StreamItemPhotos#PHOTO_FILE_ID} + * can be used in conjunction with the {@link ContactsContract.DisplayPhoto} API to + * retrieve photo content, or you can open the {@link StreamItemPhotos#PHOTO_URI} as + * an asset file, as follows: + * <pre> + * public InputStream openDisplayPhoto(String photoUri) { + * try { + * AssetFileDescriptor fd = getContentResolver().openAssetFileDescriptor(photoUri, "r"); + * return fd.createInputStream(); + * } catch (IOException e) { + * return null; + * } + * } + * <pre> * </dd> * </dl> */ @@ -3280,6 +3294,20 @@ public final class ContactsContract { */ private StreamItemPhotos() { } + + /** + * <p> + * The binary representation of the photo. Any size photo can be inserted; + * the provider will resize it appropriately for storage and display. + * </p> + * <p> + * This is only intended for use when inserting or updating a stream item photo. + * To retrieve the photo that was stored, open {@link StreamItemPhotos#PHOTO_URI} + * as an asset file. + * </p> + * <P>Type: BLOB</P> + */ + public static final String PHOTO = "photo"; } /** @@ -3302,13 +3330,18 @@ public final class ContactsContract { public static final String SORT_INDEX = "sort_index"; /** - * The binary representation of the picture. Pictures larger than - * {@link ContactsContract.StreamItems#PHOTO_MAX_BYTES} bytes in size (as - * queryable from {@link ContactsContract.StreamItems#CONTENT_LIMIT_URI}) - * will be rejected. - * <P>Type: BLOB</P> + * Photo file ID for the photo. + * See {@link ContactsContract.DisplayPhoto}. + * <P>Type: NUMBER</P> */ - public static final String PICTURE = "picture"; + public static final String PHOTO_FILE_ID = "photo_file_id"; + + /** + * URI for retrieving the photo content, automatically populated. Callers + * may retrieve the photo content by opening this URI as an asset file. + * <P>Type: TEXT</P> + */ + public static final String PHOTO_URI = "photo_uri"; /** * The activity action to execute when the photo is tapped. @@ -7273,9 +7306,10 @@ public final class ContactsContract { * public InputStream openDisplayPhoto(long photoFileId) { * Uri displayPhotoUri = ContentUris.withAppendedId(DisplayPhoto.CONTENT_URI, photoKey); * try { - * AssetFileDescriptor fd = getContentResolver().openAssetFile(displayPhotoUri, "r"); + * AssetFileDescriptor fd = getContentResolver().openAssetFileDescriptor( + * displayPhotoUri, "r"); * return fd.createInputStream(); - * } catch (FileNotFoundException e) { + * } catch (IOException e) { * return null; * } * } diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java index f3bcedb..f799af3 100644 --- a/core/java/android/provider/MediaStore.java +++ b/core/java/android/provider/MediaStore.java @@ -283,13 +283,6 @@ public final class MediaStore { */ public static final String IS_DRM = "is_drm"; - /** - * Used by the media scanner to suppress files from being processed as media files. - * - * <P>Type: INTEGER (boolean)</P> - * @hide - */ - public static final String NO_MEDIA = "no_media"; } /** diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index ad32047..1cd46de 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -16,8 +16,6 @@ package android.provider; - - import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.app.SearchManager; @@ -48,7 +46,6 @@ import java.net.URISyntaxException; import java.util.HashMap; import java.util.HashSet; - /** * The Settings provider contains global system-level device preferences. */ @@ -2877,6 +2874,7 @@ public final class Settings { * The acceptable packet loss percentage (range 0 - 100) before trying * another AP on the same network. */ + @Deprecated public static final String WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE = "wifi_watchdog_acceptable_packet_loss_percentage"; @@ -2884,11 +2882,13 @@ public final class Settings { * The number of access points required for a network in order for the * watchdog to monitor it. */ + @Deprecated public static final String WIFI_WATCHDOG_AP_COUNT = "wifi_watchdog_ap_count"; /** * The delay between background checks. */ + @Deprecated public static final String WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS = "wifi_watchdog_background_check_delay_ms"; @@ -2896,12 +2896,14 @@ public final class Settings { * Whether the Wi-Fi watchdog is enabled for background checking even * after it thinks the user has connected to a good access point. */ + @Deprecated public static final String WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED = "wifi_watchdog_background_check_enabled"; /** * The timeout for a background ping */ + @Deprecated public static final String WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS = "wifi_watchdog_background_check_timeout_ms"; @@ -2911,6 +2913,7 @@ public final class Settings { * calculation. For example, one network always seemed to time out for * the first couple pings, so this is set to 3 by default. */ + @Deprecated public static final String WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT = "wifi_watchdog_initial_ignored_ping_count"; @@ -2920,6 +2923,7 @@ public final class Settings { * initial connection state for the network. This is a safeguard for * networks containing multiple APs whose DNS does not respond to pings. */ + @Deprecated public static final String WIFI_WATCHDOG_MAX_AP_CHECKS = "wifi_watchdog_max_ap_checks"; /** @@ -2930,24 +2934,85 @@ public final class Settings { /** * A comma-separated list of SSIDs for which the Wi-Fi watchdog should be enabled. */ + @Deprecated public static final String WIFI_WATCHDOG_WATCH_LIST = "wifi_watchdog_watch_list"; /** * The number of pings to test if an access point is a good connection. */ + @Deprecated public static final String WIFI_WATCHDOG_PING_COUNT = "wifi_watchdog_ping_count"; /** * The delay between pings. */ + @Deprecated public static final String WIFI_WATCHDOG_PING_DELAY_MS = "wifi_watchdog_ping_delay_ms"; /** * The timeout per ping. */ + @Deprecated public static final String WIFI_WATCHDOG_PING_TIMEOUT_MS = "wifi_watchdog_ping_timeout_ms"; /** + * ms delay before rechecking an 'online' wifi connection when it is thought to be unstable. + * @hide + */ + public static final String WIFI_WATCHDOG_DNS_CHECK_SHORT_INTERVAL_MS = + "wifi_watchdog_dns_check_short_interval_ms"; + + /** + * ms delay before rechecking an 'online' wifi connection when it is thought to be stable. + * @hide + */ + public static final String WIFI_WATCHDOG_DNS_CHECK_LONG_INTERVAL_MS = + "wifi_watchdog_dns_check_long_interval_ms"; + + /** + * ms delay before rechecking a connect SSID for walled garden with a http download. + * @hide + */ + public static final String WIFI_WATCHDOG_WALLED_GARDEN_INTERVAL_MS = + "wifi_watchdog_walled_garden_interval_ms"; + + /** + * max blacklist calls on an SSID before full dns check failures disable the network. + * @hide + */ + public static final String WIFI_WATCHDOG_MAX_SSID_BLACKLISTS = + "wifi_watchdog_max_ssid_blacklists"; + + /** + * Number of dns pings per check. + * @hide + */ + public static final String WIFI_WATCHDOG_NUM_DNS_PINGS = "wifi_watchdog_num_dns_pings"; + + /** + * Minimum number of responses to the dns pings to consider the test 'successful'. + * @hide + */ + public static final String WIFI_WATCHDOG_MIN_DNS_RESPONSES = + "wifi_watchdog_min_dns_responses"; + + /** + * Timeout on dns pings + * @hide + */ + public static final String WIFI_WATCHDOG_DNS_PING_TIMEOUT_MS = + "wifi_watchdog_dns_ping_timeout_ms"; + + /** + * We consider action from a 'blacklist' call to have finished by the end of + * this interval. If we are connected to the same AP with no network connection, + * we are likely stuck on an SSID with no external connectivity. + * @hide + */ + public static final String WIFI_WATCHDOG_BLACKLIST_FOLLOWUP_INTERVAL_MS = + "wifi_watchdog_blacklist_followup_interval_ms"; + + /** * Setting to turn off walled garden test on Wi-Fi. Feature is enabled by default and * the setting needs to be set to 0 to disable it. * @hide @@ -2972,6 +3037,14 @@ public final class Settings { "wifi_watchdog_walled_garden_pattern"; /** + * Boolean to determine whether to notify on disabling a network. Secure setting used + * to notify user only once. This setting is not monitored continuously. + * @hide + */ + public static final String WIFI_WATCHDOG_SHOW_DISABLED_NETWORK_POPUP = + "wifi_watchdog_show_disabled_network_popup"; + + /** * The maximum number of times we will retry a connection to an access * point for which we have failed in acquiring an IP address from DHCP. * A value of N means that we will make N+1 connection attempts in all. @@ -3661,6 +3734,15 @@ public final class Settings { */ public static final String VOICE_RECOGNITION_SERVICE = "voice_recognition_service"; + + /** + * The {@link ComponentName} string of the service to be used as the spell checker + * service which is one of the services managed by the text service manager. + * + * @hide + */ + public static final String SPELL_CHECKER_SERVICE = "spell_checker_service"; + /** * What happens when the user presses the Power button while in-call * and the screen is on.<br/> diff --git a/core/java/android/server/BluetoothBondState.java b/core/java/android/server/BluetoothBondState.java index 75f38f9..30a8b2a 100644 --- a/core/java/android/server/BluetoothBondState.java +++ b/core/java/android/server/BluetoothBondState.java @@ -21,8 +21,13 @@ import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothA2dp; import android.bluetooth.BluetoothHeadset; +import android.content.BroadcastReceiver; +import android.content.ContentResolver; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; +import android.content.SharedPreferences; +import android.provider.Settings; import android.util.Log; import java.io.BufferedReader; @@ -74,11 +79,17 @@ class BluetoothBondState { private BluetoothA2dp mA2dpProxy; private BluetoothHeadset mHeadsetProxy; + private ArrayList<String> mPairingRequestRcvd = new ArrayList<String>(); + BluetoothBondState(Context context, BluetoothService service) { mContext = context; mService = service; mBluetoothInputProfileHandler = BluetoothInputProfileHandler.getInstance(mContext, mService); + + IntentFilter filter = new IntentFilter(); + filter.addAction(BluetoothDevice.ACTION_PAIRING_REQUEST); + mContext.registerReceiver(mReceiver, filter); } synchronized void setPendingOutgoingBonding(String address) { @@ -137,11 +148,18 @@ class BluetoothBondState { } if (state == BluetoothDevice.BOND_BONDED) { - mService.addProfileState(address); + boolean setTrust = false; + if (mPairingRequestRcvd.contains(address)) setTrust = true; + + mService.addProfileState(address, setTrust); + mPairingRequestRcvd.remove(address); + } else if (state == BluetoothDevice.BOND_BONDING) { if (mA2dpProxy == null || mHeadsetProxy == null) { getProfileProxy(); } + } else if (state == BluetoothDevice.BOND_NONE) { + mPairingRequestRcvd.remove(address); } setProfilePriorities(address, state); @@ -452,4 +470,17 @@ class BluetoothBondState { } } + private final BroadcastReceiver mReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (intent == null) return; + + String action = intent.getAction(); + if (action.equals(BluetoothDevice.ACTION_PAIRING_REQUEST)) { + BluetoothDevice dev = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); + String address = dev.getAddress(); + mPairingRequestRcvd.add(address); + } + } + }; } diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java index ff16c18..d68d8ba 100755 --- a/core/java/android/server/BluetoothService.java +++ b/core/java/android/server/BluetoothService.java @@ -527,10 +527,19 @@ public class BluetoothService extends IBluetooth.Stub { break; case MESSAGE_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY: address = (String)msg.obj; - if (address != null) { + if (address == null) return; + int attempt = mBondState.getAttempt(address); + + // Try only if attemps are in progress and cap it 2 attempts + // The 2 attempts cap is a fail safe if the stack returns + // an incorrect error code for bonding failures and if the pin + // is entered wrongly twice we should abort. + if (attempt > 0 && attempt <= 2) { + mBondState.attempt(address); createBond(address); return; } + if (attempt > 0) mBondState.clearPinAttempts(address); break; } } @@ -741,7 +750,6 @@ public class BluetoothService extends IBluetooth.Stub { BluetoothDevice.BOND_NONE, result); return; } - mBondState.attempt(address); } /*package*/ BluetoothDevice getRemoteDevice(String address) { @@ -2277,11 +2285,11 @@ public class BluetoothService extends IBluetooth.Stub { return false; } - BluetoothDeviceProfileState addProfileState(String address) { + BluetoothDeviceProfileState addProfileState(String address, boolean setTrust) { BluetoothDeviceProfileState state = mDeviceProfileState.get(address); if (state != null) return state; - state = new BluetoothDeviceProfileState(mContext, address, this, mA2dpService); + state = new BluetoothDeviceProfileState(mContext, address, this, mA2dpService, setTrust); mDeviceProfileState.put(address, state); state.start(); return state; @@ -2311,7 +2319,7 @@ public class BluetoothService extends IBluetooth.Stub { } for (String path : bonds) { String address = getAddressFromObjectPath(path); - BluetoothDeviceProfileState state = addProfileState(address); + BluetoothDeviceProfileState state = addProfileState(address, false); } } diff --git a/core/java/android/service/textservice/SpellCheckerService.java b/core/java/android/service/textservice/SpellCheckerService.java new file mode 100644 index 0000000..6ac99ca --- /dev/null +++ b/core/java/android/service/textservice/SpellCheckerService.java @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package android.service.textservice; + +import com.android.internal.textservice.ISpellCheckerService; +import com.android.internal.textservice.ISpellCheckerSession; +import com.android.internal.textservice.ISpellCheckerSessionListener; + +import android.app.Service; +import android.content.Intent; +import android.os.IBinder; +import android.os.RemoteException; +import android.view.textservice.SuggestionsInfo; +import android.view.textservice.TextInfo; + +import java.lang.ref.WeakReference; + +/** + * SpellCheckerService provides an abstract base class for a spell checker. + * This class combines a service to the system with the spell checker service interface that + * spell checker must implement. + */ +public abstract class SpellCheckerService extends Service { + private static final String TAG = SpellCheckerService.class.getSimpleName(); + public static final String SERVICE_INTERFACE = SpellCheckerService.class.getName(); + + private final SpellCheckerServiceBinder mBinder = new SpellCheckerServiceBinder(this); + + /** + * Get suggestions for specified text in TextInfo. + * This function will run on the incoming IPC thread. So, this is not called on the main thread, + * but will be called in series on another thread. + * @param textInfo the text metadata + * @param suggestionsLimit the number of limit of suggestions returned + * @param locale the locale for getting suggestions + * @return SuggestionInfo which contains suggestions for textInfo + */ + public abstract SuggestionsInfo getSuggestions( + TextInfo textInfo, int suggestionsLimit, String locale); + + /** + * A batch process of onGetSuggestions. + * This function will run on the incoming IPC thread. So, this is not called on the main thread, + * but will be called in series on another thread. + * @param textInfos an array of the text metadata + * @param locale the locale for getting suggestions + * @param suggestionsLimit the number of limit of suggestions returned + * @param sequentialWords true if textInfos can be treated as sequential words. + * @return an array of SuggestionInfo of onGetSuggestions + */ + public SuggestionsInfo[] getSuggestionsMultiple( + TextInfo[] textInfos, String locale, int suggestionsLimit, boolean sequentialWords) { + final int length = textInfos.length; + final SuggestionsInfo[] retval = new SuggestionsInfo[length]; + for (int i = 0; i < length; ++i) { + retval[i] = getSuggestions(textInfos[i], suggestionsLimit, locale); + retval[i].setCookieAndSequence(textInfos[i].getCookie(), textInfos[i].getSequence()); + } + return retval; + } + + /** + * Request to abort all tasks executed in SpellChecker. + * This function will run on the incoming IPC thread. So, this is not called on the main thread, + * but will be called in series on another thread. + */ + public void cancel() {} + + /** + * Implement to return the implementation of the internal spell checker + * service interface. Subclasses should not override. + */ + @Override + public final IBinder onBind(final Intent intent) { + return mBinder; + } + + private static class SpellCheckerSessionImpl extends ISpellCheckerSession.Stub { + private final WeakReference<SpellCheckerService> mInternalServiceRef; + private final String mLocale; + private final ISpellCheckerSessionListener mListener; + + public SpellCheckerSessionImpl( + SpellCheckerService service, String locale, ISpellCheckerSessionListener listener) { + mInternalServiceRef = new WeakReference<SpellCheckerService>(service); + mLocale = locale; + mListener = listener; + } + + @Override + public void getSuggestionsMultiple( + TextInfo[] textInfos, int suggestionsLimit, boolean sequentialWords) { + final SpellCheckerService service = mInternalServiceRef.get(); + if (service == null) return; + try { + mListener.onGetSuggestions( + service.getSuggestionsMultiple(textInfos, mLocale, + suggestionsLimit, sequentialWords)); + } catch (RemoteException e) { + } + } + + @Override + public void cancel() { + final SpellCheckerService service = mInternalServiceRef.get(); + if (service == null) return; + service.cancel(); + } + } + + private static class SpellCheckerServiceBinder extends ISpellCheckerService.Stub { + private final WeakReference<SpellCheckerService> mInternalServiceRef; + + public SpellCheckerServiceBinder(SpellCheckerService service) { + mInternalServiceRef = new WeakReference<SpellCheckerService>(service); + } + + @Override + public ISpellCheckerSession getISpellCheckerSession( + String locale, ISpellCheckerSessionListener listener) { + final SpellCheckerService service = mInternalServiceRef.get(); + if (service == null) return null; + return new SpellCheckerSessionImpl(service, locale, listener); + } + } +} diff --git a/core/java/android/service/textservice/SpellCheckerSession.java b/core/java/android/service/textservice/SpellCheckerSession.java new file mode 100644 index 0000000..400454d --- /dev/null +++ b/core/java/android/service/textservice/SpellCheckerSession.java @@ -0,0 +1,284 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.service.textservice; + +import com.android.internal.textservice.ISpellCheckerSession; +import com.android.internal.textservice.ISpellCheckerSessionListener; +import com.android.internal.textservice.ITextServicesManager; +import com.android.internal.textservice.ITextServicesSessionListener; + +import android.os.Handler; +import android.os.Message; +import android.os.RemoteException; +import android.util.Log; +import android.view.textservice.SpellCheckerInfo; +import android.view.textservice.SuggestionsInfo; +import android.view.textservice.TextInfo; + +import java.util.LinkedList; +import java.util.Locale; +import java.util.Queue; + +/** + * The SpellCheckerSession interface provides the per client functionality of SpellCheckerService. + */ +public class SpellCheckerSession { + private static final String TAG = SpellCheckerSession.class.getSimpleName(); + private static final boolean DBG = false; + + private static final int MSG_ON_GET_SUGGESTION_MULTIPLE = 1; + + private final InternalListener mInternalListener; + private final ITextServicesManager mTextServicesManager; + private final SpellCheckerInfo mSpellCheckerInfo; + private final SpellCheckerSessionListenerImpl mSpellCheckerSessionListenerImpl; + + private boolean mIsUsed; + private SpellCheckerSessionListener mSpellCheckerSessionListener; + + /** Handler that will execute the main tasks */ + private final Handler mHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_ON_GET_SUGGESTION_MULTIPLE: + handleOnGetSuggestionsMultiple((SuggestionsInfo[]) msg.obj); + break; + } + } + }; + + /** + * Constructor + * @hide + */ + public SpellCheckerSession( + SpellCheckerInfo info, ITextServicesManager tsm, SpellCheckerSessionListener listener) { + if (info == null || listener == null || tsm == null) { + throw new NullPointerException(); + } + mSpellCheckerInfo = info; + mSpellCheckerSessionListenerImpl = new SpellCheckerSessionListenerImpl(mHandler); + mInternalListener = new InternalListener(); + mTextServicesManager = tsm; + mIsUsed = true; + mSpellCheckerSessionListener = listener; + } + + /** + * @return true if the connection to a text service of this session is disconnected and not + * alive. + */ + public boolean isSessionDisconnected() { + return mSpellCheckerSessionListenerImpl.isDisconnected(); + } + + /** + * Get the spell checker service info this spell checker session has. + * @return SpellCheckerInfo for the specified locale. + */ + public SpellCheckerInfo getSpellChecker() { + return mSpellCheckerInfo; + } + + /** + * Finish this session and allow TextServicesManagerService to disconnect the bound spell + * checker. + */ + public void close() { + mIsUsed = false; + try { + mTextServicesManager.finishSpellCheckerService(mSpellCheckerSessionListenerImpl); + } catch (RemoteException e) { + // do nothing + } + } + + /** + * Get candidate strings for a substring of the specified text. + * @param textInfo text metadata for a spell checker + * @param suggestionsLimit the number of limit of suggestions returned + */ + public void getSuggestions(TextInfo textInfo, int suggestionsLimit) { + getSuggestions(new TextInfo[] {textInfo}, suggestionsLimit, false); + } + + /** + * A batch process of getSuggestions + * @param textInfos an array of text metadata for a spell checker + * @param suggestionsLimit the number of limit of suggestions returned + * @param sequentialWords true if textInfos can be treated as sequential words. + */ + public void getSuggestions( + TextInfo[] textInfos, int suggestionsLimit, boolean sequentialWords) { + // TODO: Handle multiple words suggestions by using WordBreakIterator + mSpellCheckerSessionListenerImpl.getSuggestionsMultiple( + textInfos, suggestionsLimit, sequentialWords); + } + + private void handleOnGetSuggestionsMultiple(SuggestionsInfo[] suggestionInfos) { + mSpellCheckerSessionListener.onGetSuggestions(suggestionInfos); + } + + private static class SpellCheckerSessionListenerImpl extends ISpellCheckerSessionListener.Stub { + private static final int TASK_CANCEL = 1; + private static final int TASK_GET_SUGGESTIONS_MULTIPLE = 2; + private final Queue<SpellCheckerParams> mPendingTasks = + new LinkedList<SpellCheckerParams>(); + private final Handler mHandler; + + private boolean mOpened; + private ISpellCheckerSession mISpellCheckerSession; + + public SpellCheckerSessionListenerImpl(Handler handler) { + mOpened = false; + mHandler = handler; + } + + private static class SpellCheckerParams { + public final int mWhat; + public final TextInfo[] mTextInfos; + public final int mSuggestionsLimit; + public final boolean mSequentialWords; + public SpellCheckerParams(int what, TextInfo[] textInfos, int suggestionsLimit, + boolean sequentialWords) { + mWhat = what; + mTextInfos = textInfos; + mSuggestionsLimit = suggestionsLimit; + mSequentialWords = sequentialWords; + } + } + + private void processTask(SpellCheckerParams scp) { + switch (scp.mWhat) { + case TASK_CANCEL: + processCancel(); + break; + case TASK_GET_SUGGESTIONS_MULTIPLE: + processGetSuggestionsMultiple(scp); + break; + } + } + + public synchronized void onServiceConnected(ISpellCheckerSession session) { + mISpellCheckerSession = session; + mOpened = true; + if (DBG) + Log.d(TAG, "onServiceConnected - Success"); + while (!mPendingTasks.isEmpty()) { + processTask(mPendingTasks.poll()); + } + } + + public void getSuggestionsMultiple( + TextInfo[] textInfos, int suggestionsLimit, boolean sequentialWords) { + processOrEnqueueTask( + new SpellCheckerParams(TASK_GET_SUGGESTIONS_MULTIPLE, textInfos, + suggestionsLimit, sequentialWords)); + } + + public boolean isDisconnected() { + return mOpened && mISpellCheckerSession == null; + } + + public boolean checkOpenConnection() { + if (mISpellCheckerSession != null) { + return true; + } + Log.e(TAG, "not connected to the spellchecker service."); + return false; + } + + private void processOrEnqueueTask(SpellCheckerParams scp) { + if (mISpellCheckerSession == null) { + mPendingTasks.offer(scp); + } else { + processTask(scp); + } + } + + private void processCancel() { + if (!checkOpenConnection()) { + return; + } + try { + mISpellCheckerSession.cancel(); + } catch (RemoteException e) { + Log.e(TAG, "Failed to cancel " + e); + } + } + + private void processGetSuggestionsMultiple(SpellCheckerParams scp) { + if (!checkOpenConnection()) { + return; + } + try { + mISpellCheckerSession.getSuggestionsMultiple( + scp.mTextInfos, scp.mSuggestionsLimit, scp.mSequentialWords); + } catch (RemoteException e) { + Log.e(TAG, "Failed to get suggestions " + e); + } + } + + @Override + public void onGetSuggestions(SuggestionsInfo[] results) { + mHandler.sendMessage(Message.obtain(mHandler, MSG_ON_GET_SUGGESTION_MULTIPLE, results)); + } + } + + /** + * Callback for getting results from text services + */ + public interface SpellCheckerSessionListener { + /** + * Callback for "getSuggestions" + * @param results an array of results of getSuggestions + */ + public void onGetSuggestions(SuggestionsInfo[] results); + } + + private class InternalListener extends ITextServicesSessionListener.Stub { + @Override + public void onServiceConnected(ISpellCheckerSession session) { + mSpellCheckerSessionListenerImpl.onServiceConnected(session); + } + } + + @Override + protected void finalize() throws Throwable { + super.finalize(); + if (mIsUsed) { + Log.e(TAG, "SpellCheckerSession was not finished properly." + + "You should call finishShession() when you finished to use a spell checker."); + close(); + } + } + + /** + * @hide + */ + public ITextServicesSessionListener getTextServicesSessionListener() { + return mInternalListener; + } + + /** + * @hide + */ + public ISpellCheckerSessionListener getSpellCheckerSessionListener() { + return mSpellCheckerSessionListenerImpl; + } +} diff --git a/core/java/android/speech/tts/AudioPlaybackHandler.java b/core/java/android/speech/tts/AudioPlaybackHandler.java index 255b333..89b6f32 100644 --- a/core/java/android/speech/tts/AudioPlaybackHandler.java +++ b/core/java/android/speech/tts/AudioPlaybackHandler.java @@ -356,9 +356,7 @@ class AudioPlaybackHandler { mLastSynthesisRequest = param; // Create the audio track. - final AudioTrack audioTrack = createStreamingAudioTrack( - param.mStreamType, param.mSampleRateInHz, param.mAudioFormat, - param.mChannelCount, param.mVolume, param.mPan); + final AudioTrack audioTrack = createStreamingAudioTrack(param); if (DBG) Log.d(TAG, "Created audio track [" + audioTrack.hashCode() + "]"); @@ -405,16 +403,10 @@ class AudioPlaybackHandler { param.mLogger.onPlaybackStart(); } + // Wait for the audio track to stop playing, and then release its resources. private void handleSynthesisDone(MessageParams msg) { final SynthesisMessageParams params = (SynthesisMessageParams) msg; - handleSynthesisDone(params); - // This call is delayed more than it should be, but we are - // certain at this point that we have all the data we want. - params.mLogger.onWriteData(); - } - // Wait for the audio track to stop playing, and then release it's resources. - private void handleSynthesisDone(SynthesisMessageParams params) { if (DBG) Log.d(TAG, "handleSynthesisDone()"); final AudioTrack audioTrack = params.getAudioTrack(); @@ -422,6 +414,10 @@ class AudioPlaybackHandler { return; } + if (params.mBytesWritten < params.mAudioBufferSize) { + audioTrack.stop(); + } + if (DBG) Log.d(TAG, "Waiting for audio track to complete : " + audioTrack.hashCode()); blockUntilDone(params); @@ -442,8 +438,15 @@ class AudioPlaybackHandler { } params.getDispatcher().dispatchUtteranceCompleted(); mLastSynthesisRequest = null; + params.mLogger.onWriteData(); } + /** + * The minimum increment of time to wait for an audiotrack to finish + * playing. + */ + private static final long MIN_SLEEP_TIME_MS = 20; + private static void blockUntilDone(SynthesisMessageParams params) { if (params.mAudioTrack == null || params.mBytesWritten <= 0) { return; @@ -460,36 +463,41 @@ class AudioPlaybackHandler { break; } - long estimatedTimeMs = ((lengthInFrames - currentPosition) * 1000) / + final long estimatedTimeMs = ((lengthInFrames - currentPosition) * 1000) / audioTrack.getSampleRate(); - if (DBG) Log.d(TAG, "About to sleep for : " + estimatedTimeMs + " ms," + - " Playback position : " + currentPosition); + final long sleepTimeMs = Math.max(estimatedTimeMs, MIN_SLEEP_TIME_MS); + + if (DBG) Log.d(TAG, "About to sleep for : " + sleepTimeMs + " ms," + + " Playback position : " + currentPosition + ", Length in frames : " + + lengthInFrames); try { - Thread.sleep(estimatedTimeMs); + Thread.sleep(sleepTimeMs); } catch (InterruptedException ie) { break; } } } - private static AudioTrack createStreamingAudioTrack(int streamType, int sampleRateInHz, - int audioFormat, int channelCount, float volume, float pan) { - int channelConfig = getChannelConfig(channelCount); + private static AudioTrack createStreamingAudioTrack(SynthesisMessageParams params) { + final int channelConfig = getChannelConfig(params.mChannelCount); + final int sampleRateInHz = params.mSampleRateInHz; + final int audioFormat = params.mAudioFormat; int minBufferSizeInBytes = AudioTrack.getMinBufferSize(sampleRateInHz, channelConfig, audioFormat); int bufferSizeInBytes = Math.max(MIN_AUDIO_BUFFER_SIZE, minBufferSizeInBytes); - AudioTrack audioTrack = new AudioTrack(streamType, sampleRateInHz, channelConfig, + AudioTrack audioTrack = new AudioTrack(params.mStreamType, sampleRateInHz, channelConfig, audioFormat, bufferSizeInBytes, AudioTrack.MODE_STREAM); if (audioTrack.getState() != AudioTrack.STATE_INITIALIZED) { Log.w(TAG, "Unable to create audio track."); audioTrack.release(); return null; } + params.mAudioBufferSize = bufferSizeInBytes; - setupVolume(audioTrack, volume, pan); + setupVolume(audioTrack, params.mVolume, params.mPan); return audioTrack; } diff --git a/core/java/android/speech/tts/SynthesisMessageParams.java b/core/java/android/speech/tts/SynthesisMessageParams.java index ffe70e2..7da5daa 100644 --- a/core/java/android/speech/tts/SynthesisMessageParams.java +++ b/core/java/android/speech/tts/SynthesisMessageParams.java @@ -35,6 +35,7 @@ final class SynthesisMessageParams extends MessageParams { volatile AudioTrack mAudioTrack; // Not volatile, accessed only from the synthesis thread. int mBytesWritten; + int mAudioBufferSize; private final LinkedList<ListEntry> mDataBufferList = new LinkedList<ListEntry>(); @@ -55,6 +56,7 @@ final class SynthesisMessageParams extends MessageParams { // initially null. mAudioTrack = null; mBytesWritten = 0; + mAudioBufferSize = 0; } @Override diff --git a/core/java/android/util/JsonReader.java b/core/java/android/util/JsonReader.java index 09ce8e4..f2a86c9 100644 --- a/core/java/android/util/JsonReader.java +++ b/core/java/android/util/JsonReader.java @@ -738,6 +738,14 @@ public final class JsonReader implements Closeable { int total; while ((total = in.read(buffer, limit, buffer.length - limit)) != -1) { limit += total; + + // if this is the first read, consume an optional byte order mark (BOM) if it exists + if (bufferStartLine == 1 && bufferStartColumn == 1 + && limit > 0 && buffer[0] == '\ufeff') { + pos++; + bufferStartColumn--; + } + if (limit >= minimum) { return true; } @@ -844,7 +852,7 @@ public final class JsonReader implements Closeable { private boolean skipTo(String toFind) throws IOException { outer: - for (; pos + toFind.length() < limit || fillBuffer(toFind.length()); pos++) { + for (; pos + toFind.length() <= limit || fillBuffer(toFind.length()); pos++) { for (int c = 0; c < toFind.length(); c++) { if (buffer[pos + c] != toFind.charAt(c)) { continue outer; diff --git a/core/java/android/view/CollapsibleActionView.java b/core/java/android/view/CollapsibleActionView.java new file mode 100644 index 0000000..ab2365e --- /dev/null +++ b/core/java/android/view/CollapsibleActionView.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.view; + +import android.view.MenuItem.OnActionExpandListener; + +/** + * When a {@link View} implements this interface it will receive callbacks + * when expanded or collapsed as an action view alongside the optional, + * app-specified callbacks to {@link OnActionExpandListener}. + * + * <p>See {@link MenuItem} for more information about action views. + * See {@link android.app.ActionBar} for more information about the action bar. + */ +public interface CollapsibleActionView { + /** + * Called when this view is expanded as an action view. + * See {@link MenuItem#expandActionView()}. + */ + public void onActionViewExpanded(); + + /** + * Called when this view is collapsed as an action view. + * See {@link MenuItem#collapseActionView()}. + */ + public void onActionViewCollapsed(); +} diff --git a/core/java/android/view/DisplayList.java b/core/java/android/view/DisplayList.java index 4484d59..f4c0249 100644 --- a/core/java/android/view/DisplayList.java +++ b/core/java/android/view/DisplayList.java @@ -41,15 +41,6 @@ public abstract class DisplayList { abstract void end(); /** - * Indicates whether this display list can be replayed or not. - * - * @return True if the display list can be replayed, false otherwise. - * - * @see android.view.HardwareCanvas#drawDisplayList(DisplayList) - */ - abstract boolean isReady(); - - /** * Invalidates the display list, indicating that it should be repopulated * with new drawing commands prior to being used again. Calling this method * causes calls to {@link #isValid()} to return <code>false</code>. diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java index 80244bb..d22fa6e 100644 --- a/core/java/android/view/GLES20Canvas.java +++ b/core/java/android/view/GLES20Canvas.java @@ -51,6 +51,7 @@ class GLES20Canvas extends HardwareCanvas { // The native renderer will be destroyed when this object dies. // DO NOT overwrite this reference once it is set. + @SuppressWarnings("unused") private CanvasFinalizer mFinalizer; private int mWidth; @@ -97,12 +98,8 @@ class GLES20Canvas extends HardwareCanvas { protected GLES20Canvas(boolean record, boolean translucent) { mOpaque = !translucent; - setupRenderer(record); - } - - protected void setupRenderer(boolean record) { if (record) { - mRenderer = nGetDisplayListRenderer(mRenderer); + mRenderer = nCreateDisplayListRenderer(); } else { mRenderer = nCreateRenderer(); } @@ -114,43 +111,31 @@ class GLES20Canvas extends HardwareCanvas { if (mRenderer == 0) { throw new IllegalStateException("Could not create GLES20Canvas renderer"); } else { - mFinalizer = CanvasFinalizer.getFinalizer(mFinalizer, mRenderer); + mFinalizer = new CanvasFinalizer(mRenderer); } } + protected void resetDisplayListRenderer() { + nResetDisplayListRenderer(mRenderer); + } + private static native int nCreateRenderer(); private static native int nCreateLayerRenderer(int layer); - private static native int nGetDisplayListRenderer(int renderer); + private static native int nCreateDisplayListRenderer(); + private static native void nResetDisplayListRenderer(int renderer); private static native void nDestroyRenderer(int renderer); - private static class CanvasFinalizer { - int mRenderer; - - // Factory method returns new instance if old one is null, or old instance - // otherwise, destroying native renderer along the way as necessary - static CanvasFinalizer getFinalizer(CanvasFinalizer oldFinalizer, int renderer) { - if (oldFinalizer == null) { - return new CanvasFinalizer(renderer); - } - oldFinalizer.replaceNativeObject(renderer); - return oldFinalizer; - } + private static final class CanvasFinalizer { + private final int mRenderer; - private CanvasFinalizer(int renderer) { + public CanvasFinalizer(int renderer) { mRenderer = renderer; } - private void replaceNativeObject(int newRenderer) { - if (mRenderer != 0 && newRenderer != mRenderer) { - nDestroyRenderer(mRenderer); - } - mRenderer = newRenderer; - } - @Override protected void finalize() throws Throwable { try { - replaceNativeObject(0); + nDestroyRenderer(mRenderer); } finally { super.finalize(); } @@ -322,11 +307,11 @@ class GLES20Canvas extends HardwareCanvas { // Display list /////////////////////////////////////////////////////////////////////////// - int getDisplayList() { - return nGetDisplayList(mRenderer); + int getDisplayList(int displayList) { + return nGetDisplayList(mRenderer, displayList); } - private static native int nGetDisplayList(int renderer); + private static native int nGetDisplayList(int renderer, int displayList); static void destroyDisplayList(int displayList) { nDestroyDisplayList(displayList); @@ -337,7 +322,7 @@ class GLES20Canvas extends HardwareCanvas { @Override public boolean drawDisplayList(DisplayList displayList, int width, int height, Rect dirty) { return nDrawDisplayList(mRenderer, - ((GLES20DisplayList) displayList).mNativeDisplayList, width, height, dirty); + ((GLES20DisplayList) displayList).getNativeDisplayList(), width, height, dirty); } private static native boolean nDrawDisplayList(int renderer, int displayList, @@ -345,7 +330,7 @@ class GLES20Canvas extends HardwareCanvas { @Override void outputDisplayList(DisplayList displayList) { - nOutputDisplayList(mRenderer, ((GLES20DisplayList) displayList).mNativeDisplayList); + nOutputDisplayList(mRenderer, ((GLES20DisplayList) displayList).getNativeDisplayList()); } private static native void nOutputDisplayList(int renderer, int displayList); diff --git a/core/java/android/view/GLES20DisplayList.java b/core/java/android/view/GLES20DisplayList.java index aeff31f..9e649ce 100644 --- a/core/java/android/view/GLES20DisplayList.java +++ b/core/java/android/view/GLES20DisplayList.java @@ -16,52 +16,50 @@ package android.view; -import java.lang.ref.WeakReference; +import android.graphics.Bitmap; + +import java.util.ArrayList; /** * An implementation of display list for OpenGL ES 2.0. */ class GLES20DisplayList extends DisplayList { - private GLES20Canvas mCanvas; - - private boolean mStarted = false; - private boolean mRecorded = false; - private boolean mValid = false; + // These lists ensure that any Bitmaps recorded by a DisplayList are kept alive as long + // as the DisplayList is alive. The Bitmaps are populated by the GLES20RecordingCanvas. + final ArrayList<Bitmap> mBitmaps = new ArrayList<Bitmap>(5); - int mNativeDisplayList; - WeakReference<View> hostView; + private GLES20RecordingCanvas mCanvas; + private boolean mValid; // The native display list will be destroyed when this object dies. // DO NOT overwrite this reference once it is set. - @SuppressWarnings("unused") private DisplayListFinalizer mFinalizer; - public GLES20DisplayList(View view) { - hostView = new WeakReference<View>(view); + int getNativeDisplayList() { + if (!mValid || mFinalizer == null) { + throw new IllegalStateException("The display list is not valid."); + } + return mFinalizer.mNativeDisplayList; } @Override HardwareCanvas start() { - if (mStarted) { - throw new IllegalStateException("Recording has already started"); - } - if (mCanvas != null) { - ((GLES20RecordingCanvas) mCanvas).reset(); - } else { - mCanvas = new GLES20RecordingCanvas(true); + throw new IllegalStateException("Recording has already started"); } - mStarted = true; - mRecorded = false; - mValid = true; + mValid = false; + mCanvas = GLES20RecordingCanvas.obtain(this); + mCanvas.start(); return mCanvas; } @Override void invalidate() { - mStarted = false; - mRecorded = false; + if (mCanvas != null) { + mCanvas.recycle(); + mCanvas = null; + } mValid = false; } @@ -73,48 +71,28 @@ class GLES20DisplayList extends DisplayList { @Override void end() { if (mCanvas != null) { - mStarted = false; - mRecorded = true; - - mNativeDisplayList = mCanvas.getDisplayList(); - mFinalizer = DisplayListFinalizer.getFinalizer(mFinalizer, mNativeDisplayList); + if (mFinalizer != null) { + mCanvas.end(mFinalizer.mNativeDisplayList); + } else { + mFinalizer = new DisplayListFinalizer(mCanvas.end(0)); + } + mCanvas.recycle(); + mCanvas = null; + mValid = true; } } - @Override - boolean isReady() { - return !mStarted && mRecorded; - } - private static class DisplayListFinalizer { - int mNativeDisplayList; - - // Factory method returns new instance if old one is null, or old instance - // otherwise, destroying native display list along the way as necessary - static DisplayListFinalizer getFinalizer(DisplayListFinalizer oldFinalizer, - int nativeDisplayList) { - if (oldFinalizer == null) { - return new DisplayListFinalizer(nativeDisplayList); - } - oldFinalizer.replaceNativeObject(nativeDisplayList); - return oldFinalizer; - } + final int mNativeDisplayList; - private DisplayListFinalizer(int nativeDisplayList) { + public DisplayListFinalizer(int nativeDisplayList) { mNativeDisplayList = nativeDisplayList; } - private void replaceNativeObject(int newNativeDisplayList) { - if (mNativeDisplayList != 0 && mNativeDisplayList != newNativeDisplayList) { - GLES20Canvas.destroyDisplayList(mNativeDisplayList); - } - mNativeDisplayList = newNativeDisplayList; - } - @Override protected void finalize() throws Throwable { try { - replaceNativeObject(0); + GLES20Canvas.destroyDisplayList(mNativeDisplayList); } finally { super.finalize(); } diff --git a/core/java/android/view/GLES20RecordingCanvas.java b/core/java/android/view/GLES20RecordingCanvas.java index ec94fe7..078222b 100644 --- a/core/java/android/view/GLES20RecordingCanvas.java +++ b/core/java/android/view/GLES20RecordingCanvas.java @@ -24,8 +24,10 @@ import android.graphics.Path; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Shader; - -import java.util.ArrayList; +import android.util.Pool; +import android.util.Poolable; +import android.util.PoolableManager; +import android.util.Pools; /** * An implementation of a GL canvas that records drawing operations. @@ -33,62 +35,94 @@ import java.util.ArrayList; * Bitmap objects that it draws, preventing the backing memory of Bitmaps from being freed while * the DisplayList is still holding a native reference to the memory. */ -class GLES20RecordingCanvas extends GLES20Canvas { - // These lists ensure that any Bitmaps recorded by a DisplayList are kept alive as long - // as the DisplayList is alive. - @SuppressWarnings({"MismatchedQueryAndUpdateOfCollection"}) - private final ArrayList<Bitmap> mBitmaps = new ArrayList<Bitmap>(5); +class GLES20RecordingCanvas extends GLES20Canvas implements Poolable<GLES20RecordingCanvas> { + // The recording canvas pool should be large enough to handle a deeply nested + // view hierarchy because display lists are generated recursively. + private static final int POOL_LIMIT = 50; + + private static final Pool<GLES20RecordingCanvas> sPool = Pools.synchronizedPool( + Pools.finitePool(new PoolableManager<GLES20RecordingCanvas>() { + public GLES20RecordingCanvas newInstance() { + return new GLES20RecordingCanvas(); + } + @Override + public void onAcquired(GLES20RecordingCanvas element) { + } + @Override + public void onReleased(GLES20RecordingCanvas element) { + } + }, POOL_LIMIT)); + + private GLES20RecordingCanvas mNextPoolable; + private boolean mIsPooled; + + private GLES20DisplayList mDisplayList; - GLES20RecordingCanvas(boolean translucent) { - super(true, translucent); + private GLES20RecordingCanvas() { + super(true /*record*/, true /*translucent*/); + } + + static GLES20RecordingCanvas obtain(GLES20DisplayList displayList) { + GLES20RecordingCanvas canvas = sPool.acquire(); + canvas.mDisplayList = displayList; + return canvas; + } + + void recycle() { + mDisplayList = null; + resetDisplayListRenderer(); + sPool.release(this); + } + + void start() { + mDisplayList.mBitmaps.clear(); + } + + int end(int nativeDisplayList) { + return getDisplayList(nativeDisplayList); } private void recordShaderBitmap(Paint paint) { if (paint != null) { final Shader shader = paint.getShader(); if (shader instanceof BitmapShader) { - mBitmaps.add(((BitmapShader) shader).mBitmap); + mDisplayList.mBitmaps.add(((BitmapShader) shader).mBitmap); } } } - void reset() { - mBitmaps.clear(); - setupRenderer(true); - } - @Override public void drawPatch(Bitmap bitmap, byte[] chunks, RectF dst, Paint paint) { super.drawPatch(bitmap, chunks, dst, paint); - mBitmaps.add(bitmap); + mDisplayList.mBitmaps.add(bitmap); // Shaders in the Paint are ignored when drawing a Bitmap } @Override public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) { super.drawBitmap(bitmap, left, top, paint); - mBitmaps.add(bitmap); + mDisplayList.mBitmaps.add(bitmap); // Shaders in the Paint are ignored when drawing a Bitmap } @Override public void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint) { super.drawBitmap(bitmap, matrix, paint); - mBitmaps.add(bitmap); + mDisplayList.mBitmaps.add(bitmap); // Shaders in the Paint are ignored when drawing a Bitmap } @Override public void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) { super.drawBitmap(bitmap, src, dst, paint); - mBitmaps.add(bitmap); + mDisplayList.mBitmaps.add(bitmap); // Shaders in the Paint are ignored when drawing a Bitmap } @Override public void drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint) { super.drawBitmap(bitmap, src, dst, paint); - mBitmaps.add(bitmap); + mDisplayList.mBitmaps.add(bitmap); // Shaders in the Paint are ignored when drawing a Bitmap } @@ -111,7 +145,7 @@ class GLES20RecordingCanvas extends GLES20Canvas { int vertOffset, int[] colors, int colorOffset, Paint paint) { super.drawBitmapMesh(bitmap, meshWidth, meshHeight, verts, vertOffset, colors, colorOffset, paint); - mBitmaps.add(bitmap); + mDisplayList.mBitmaps.add(bitmap); // Shaders in the Paint are ignored when drawing a Bitmap } @@ -270,4 +304,24 @@ class GLES20RecordingCanvas extends GLES20Canvas { colorOffset, indices, indexOffset, indexCount, paint); recordShaderBitmap(paint); } + + @Override + public GLES20RecordingCanvas getNextPoolable() { + return mNextPoolable; + } + + @Override + public void setNextPoolable(GLES20RecordingCanvas element) { + mNextPoolable = element; + } + + @Override + public boolean isPooled() { + return mIsPooled; + } + + @Override + public void setPooled(boolean isPooled) { + mIsPooled = isPooled; + } } diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java index b865b50..503b54b 100644 --- a/core/java/android/view/HardwareRenderer.java +++ b/core/java/android/view/HardwareRenderer.java @@ -189,7 +189,7 @@ public abstract class HardwareRenderer { * * @return A new display list. */ - abstract DisplayList createDisplayList(View v); + abstract DisplayList createDisplayList(); /** * Creates a new hardware layer. A hardware layer built by calling this @@ -852,8 +852,8 @@ public abstract class HardwareRenderer { } @Override - DisplayList createDisplayList(View v) { - return new GLES20DisplayList(v); + DisplayList createDisplayList() { + return new GLES20DisplayList(); } @Override diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index ff5fa7f..c68b01c 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -607,8 +607,6 @@ import java.util.concurrent.CopyOnWriteArrayList; * @attr ref android.R.styleable#View_paddingLeft * @attr ref android.R.styleable#View_paddingRight * @attr ref android.R.styleable#View_paddingTop - * @attr ref android.R.styleable#View_paddingStart - * @attr ref android.R.styleable#View_paddingEnd * @attr ref android.R.styleable#View_saveEnabled * @attr ref android.R.styleable#View_rotation * @attr ref android.R.styleable#View_rotationX @@ -9101,7 +9099,10 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED; } - private void resolvePadding() { + /** + * @hide + */ + protected void resolvePadding() { // If the user specified the absolute padding (either with android:padding or // android:paddingLeft/Top/Right/Bottom), use this padding, otherwise // use the default padding or the padding from the background drawable @@ -9832,7 +9833,7 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit // we copy in child display lists into ours in drawChild() mRecreateDisplayList = true; if (mDisplayList == null) { - mDisplayList = mAttachInfo.mHardwareRenderer.createDisplayList(this); + mDisplayList = mAttachInfo.mHardwareRenderer.createDisplayList(); // If we're creating a new display list, make sure our parent gets invalidated // since they will need to recreate their display list to account for this // new child display list. @@ -12027,12 +12028,13 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit mPrivateFlags |= FORCE_LAYOUT; mPrivateFlags |= INVALIDATED; - if (mLayoutParams != null && mParent != null) { - mLayoutParams.resolveWithDirection(getResolvedLayoutDirection()); - } - - if (mParent != null && !mParent.isLayoutRequested()) { - mParent.requestLayout(); + if (mParent != null) { + if (mLayoutParams != null) { + mLayoutParams.resolveWithDirection(getResolvedLayoutDirection()); + } + if (!mParent.isLayoutRequested()) { + mParent.requestLayout(); + } } } diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java index b85159b..4acf48c 100644 --- a/core/java/android/view/ViewDebug.java +++ b/core/java/android/view/ViewDebug.java @@ -25,7 +25,9 @@ import android.os.Debug; import android.os.Environment; import android.os.Looper; import android.os.Message; +import android.os.ParcelFileDescriptor; import android.os.RemoteException; +import android.os.SystemClock; import android.util.DisplayMetrics; import android.util.Log; import android.util.Printer; @@ -35,7 +37,7 @@ import java.io.BufferedWriter; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.File; -import java.io.FileNotFoundException; +import java.io.FileDescriptor; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; @@ -49,10 +51,14 @@ import java.lang.reflect.AccessibleObject; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.channels.FileChannel; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; import java.util.List; +import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -424,22 +430,22 @@ public class ViewDebug { * and obtain the traces. Both methods must be invoked on the * same thread. * - * @param traceFile The path where to write the looper traces - * - * @see #stopLooperProfiling() + * @hide */ - public static void startLooperProfiling(File traceFile) { + public static void startLooperProfiling(String path, FileDescriptor fileDescriptor) { if (sLooperProfilerStorage.get() == null) { - LooperProfiler profiler = new LooperProfiler(traceFile); + LooperProfiler profiler = new LooperProfiler(path, fileDescriptor); sLooperProfilerStorage.set(profiler); Looper.myLooper().setMessageLogging(profiler); } - } + } /** * Stops profiling the looper associated with the current thread. * - * @see #startLooperProfiling(java.io.File) + * @see #startLooperProfiling(String, java.io.FileDescriptor) + * + * @hide */ public static void stopLooperProfiling() { LooperProfiler profiler = sLooperProfilerStorage.get(); @@ -451,15 +457,35 @@ public class ViewDebug { } private static class LooperProfiler implements Looper.Profiler, Printer { - private static final int LOOPER_PROFILER_VERSION = 1; - private static final String LOG_TAG = "LooperProfiler"; + private static final int TRACE_VERSION_NUMBER = 3; + private static final int ACTION_EXIT_METHOD = 0x1; + private static final int HEADER_SIZE = 32; + private static final String HEADER_MAGIC = "SLOW"; + private static final short HEADER_RECORD_SIZE = (short) 14; + + private final long mTraceWallStart; + private final long mTraceThreadStart; + private final ArrayList<Entry> mTraces = new ArrayList<Entry>(512); - private final File mTraceFile; - public LooperProfiler(File traceFile) { - mTraceFile = traceFile; + private final HashMap<String, Integer> mTraceNames = new HashMap<String, Integer>(32); + private int mTraceId = 0; + + private final String mPath; + private ParcelFileDescriptor mFileDescriptor; + + LooperProfiler(String path, FileDescriptor fileDescriptor) { + mPath = path; + try { + mFileDescriptor = ParcelFileDescriptor.dup(fileDescriptor); + } catch (IOException e) { + Log.e(LOG_TAG, "Could not write trace file " + mPath, e); + throw new RuntimeException(e); + } + mTraceWallStart = SystemClock.currentTimeMicro(); + mTraceThreadStart = SystemClock.currentThreadTimeMicro(); } @Override @@ -468,17 +494,28 @@ public class ViewDebug { } @Override - public void profile(Message message, long wallStart, long wallTime, long threadTime) { + public void profile(Message message, long wallStart, long wallTime, + long threadStart, long threadTime) { Entry entry = new Entry(); - entry.messageId = message.what; - entry.name = message.getTarget().getMessageName(message); + entry.traceId = getTraceId(message); entry.wallStart = wallStart; entry.wallTime = wallTime; + entry.threadStart = threadStart; entry.threadTime = threadTime; mTraces.add(entry); } + private int getTraceId(Message message) { + String name = message.getTarget().getMessageName(message); + Integer traceId = mTraceNames.get(name); + if (traceId == null) { + traceId = mTraceId++ << 4; + mTraceNames.put(name, traceId); + } + return traceId; + } + void save() { // Don't block the UI thread new Thread(new Runnable() { @@ -486,52 +523,138 @@ public class ViewDebug { public void run() { saveTraces(); } - }, "LooperProfiler[" + mTraceFile + "]").start(); + }, "LooperProfiler[" + mPath + "]").start(); } private void saveTraces() { - FileOutputStream fos; - try { - fos = new FileOutputStream(mTraceFile); - } catch (FileNotFoundException e) { - Log.e(LOG_TAG, "Could not open trace file: " + mTraceFile); - return; - } - + FileOutputStream fos = new FileOutputStream(mFileDescriptor.getFileDescriptor()); DataOutputStream out = new DataOutputStream(new BufferedOutputStream(fos)); try { - out.writeInt(LOOPER_PROFILER_VERSION); - out.writeInt(mTraces.size()); - for (Entry entry : mTraces) { - saveTrace(entry, out); - } + writeHeader(out, mTraceWallStart, mTraceNames, mTraces); + out.flush(); - Log.d(LOG_TAG, "Looper traces ready: " + mTraceFile); + writeTraces(fos, out.size(), mTraceWallStart, mTraceThreadStart, mTraces); + + Log.d(LOG_TAG, "Looper traces ready: " + mPath); } catch (IOException e) { - Log.e(LOG_TAG, "Could not write trace file: ", e); + Log.e(LOG_TAG, "Could not write trace file " + mPath, e); } finally { try { out.close(); } catch (IOException e) { - // Ignore + Log.e(LOG_TAG, "Could not write trace file " + mPath, e); + } + try { + mFileDescriptor.close(); + } catch (IOException e) { + Log.e(LOG_TAG, "Could not write trace file " + mPath, e); } } } + + private static void writeTraces(FileOutputStream out, long offset, long wallStart, + long threadStart, ArrayList<Entry> entries) throws IOException { + + FileChannel channel = out.getChannel(); + + // Header + ByteBuffer buffer = ByteBuffer.allocateDirect(HEADER_SIZE); + buffer.put(HEADER_MAGIC.getBytes()); + buffer = buffer.order(ByteOrder.LITTLE_ENDIAN); + buffer.putShort((short) TRACE_VERSION_NUMBER); // version + buffer.putShort((short) HEADER_SIZE); // offset to data + buffer.putLong(wallStart); // start time in usec + buffer.putShort(HEADER_RECORD_SIZE); // size of a record in bytes + // padding to 32 bytes + for (int i = 0; i < HEADER_SIZE - 18; i++) { + buffer.put((byte) 0); + } + + buffer.flip(); + channel.position(offset).write(buffer); + + buffer = ByteBuffer.allocateDirect(14).order(ByteOrder.LITTLE_ENDIAN); + for (Entry entry : entries) { + buffer.putShort((short) 1); // we simulate only one thread + buffer.putInt(entry.traceId); // entering method + buffer.putInt((int) (entry.threadStart - threadStart)); + buffer.putInt((int) (entry.wallStart - wallStart)); + + buffer.flip(); + channel.write(buffer); + buffer.clear(); + + buffer.putShort((short) 1); + buffer.putInt(entry.traceId | ACTION_EXIT_METHOD); // exiting method + buffer.putInt((int) (entry.threadStart + entry.threadTime - threadStart)); + buffer.putInt((int) (entry.wallStart + entry.wallTime - wallStart)); + + buffer.flip(); + channel.write(buffer); + buffer.clear(); + } + + channel.close(); + } + + private static void writeHeader(DataOutputStream out, long start, + HashMap<String, Integer> names, ArrayList<Entry> entries) throws IOException { + + Entry last = entries.get(entries.size() - 1); + long wallTotal = (last.wallStart + last.wallTime) - start; + + startSection("version", out); + addValue(null, Integer.toString(TRACE_VERSION_NUMBER), out); + addValue("data-file-overflow", "false", out); + addValue("clock", "dual", out); + addValue("elapsed-time-usec", Long.toString(wallTotal), out); + addValue("num-method-calls", Integer.toString(entries.size()), out); + addValue("clock-call-overhead-nsec", "1", out); + addValue("vm", "dalvik", out); + + startSection("threads", out); + addThreadId(1, "main", out); + + startSection("methods", out); + addMethods(names, out); + + startSection("end", out); + } + + private static void addMethods(HashMap<String, Integer> names, DataOutputStream out) + throws IOException { + + for (Map.Entry<String, Integer> name : names.entrySet()) { + out.writeBytes(String.format("0x%08x\tEventQueue\t%s\t()V\tLooper\t-2\n", + name.getValue(), name.getKey())); + } + } + + private static void addThreadId(int id, String name, DataOutputStream out) + throws IOException { - private void saveTrace(Entry entry, DataOutputStream out) throws IOException { - out.writeInt(entry.messageId); - out.writeUTF(entry.name); - out.writeLong(entry.wallStart); - out.writeLong(entry.wallTime); - out.writeLong(entry.threadTime); + out.writeBytes(Integer.toString(id) + '\t' + name + '\n'); + } + + private static void addValue(String name, String value, DataOutputStream out) + throws IOException { + + if (name != null) { + out.writeBytes(name + "="); + } + out.writeBytes(value + '\n'); + } + + private static void startSection(String name, DataOutputStream out) throws IOException { + out.writeBytes("*" + name + '\n'); } static class Entry { - int messageId; - String name; + int traceId; long wallStart; long wallTime; + long threadStart; long threadTime; } } diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index 54fee3c..6f90971 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -2148,9 +2148,12 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager onPopulateAccessibilityEvent(event); // Let our children have a shot in populating the event. for (int i = 0, count = getChildCount(); i < count; i++) { - boolean handled = getChildAt(i).dispatchPopulateAccessibilityEvent(event); - if (handled) { - return handled; + View child = getChildAt(i); + if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) { + boolean handled = getChildAt(i).dispatchPopulateAccessibilityEvent(event); + if (handled) { + return handled; + } } } return false; @@ -2851,7 +2854,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager // display lists to render, force an invalidate to allow the animation to // continue drawing another frame invalidate(true); - if (a instanceof AlphaAnimation) { + if (a.hasAlpha()) { // alpha animations should cause the child to recreate its display list child.invalidate(true); } diff --git a/core/java/android/view/animation/AlphaAnimation.java b/core/java/android/view/animation/AlphaAnimation.java index 651fe45..c4d9afc 100644 --- a/core/java/android/view/animation/AlphaAnimation.java +++ b/core/java/android/view/animation/AlphaAnimation.java @@ -78,4 +78,12 @@ public class AlphaAnimation extends Animation { public boolean willChangeBounds() { return false; } + + /** + * @hide + */ + @Override + public boolean hasAlpha() { + return true; + } } diff --git a/core/java/android/view/animation/Animation.java b/core/java/android/view/animation/Animation.java index 87c759c..b7dfabc 100644 --- a/core/java/android/view/animation/Animation.java +++ b/core/java/android/view/animation/Animation.java @@ -1001,6 +1001,15 @@ public abstract class Animation implements Cloneable { } /** + * Return true if this animation changes the view's alpha property. + * + * @hide + */ + public boolean hasAlpha() { + return false; + } + + /** * Utility class to parse a string description of a size. */ protected static class Description { diff --git a/core/java/android/view/animation/AnimationSet.java b/core/java/android/view/animation/AnimationSet.java index 873ce53..4f2542b 100644 --- a/core/java/android/view/animation/AnimationSet.java +++ b/core/java/android/view/animation/AnimationSet.java @@ -43,6 +43,8 @@ public class AnimationSet extends Animation { private static final int PROPERTY_CHANGE_BOUNDS_MASK = 0x80; private int mFlags = 0; + private boolean mDirty; + private boolean mHasAlpha; private ArrayList<Animation> mAnimations = new ArrayList<Animation>(); @@ -138,6 +140,28 @@ public class AnimationSet extends Animation { } /** + * @hide + */ + @Override + public boolean hasAlpha() { + if (mDirty) { + mDirty = mHasAlpha = false; + + final int count = mAnimations.size(); + final ArrayList<Animation> animations = mAnimations; + + for (int i = 0; i < count; i++) { + if (animations.get(i).hasAlpha()) { + mHasAlpha = true; + break; + } + } + } + + return mHasAlpha; + } + + /** * <p>Sets the duration of every child animation.</p> * * @param durationMillis the duration of the animation, in milliseconds, for @@ -175,6 +199,8 @@ public class AnimationSet extends Animation { mLastEnd = Math.max(mLastEnd, a.getStartOffset() + a.getDuration()); mDuration = mLastEnd - mStartOffset; } + + mDirty = true; } /** diff --git a/core/java/android/view/textservice/SpellCheckerInfo.aidl b/core/java/android/view/textservice/SpellCheckerInfo.aidl new file mode 100644 index 0000000..eb5dfcc --- /dev/null +++ b/core/java/android/view/textservice/SpellCheckerInfo.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.view.textservice; + +parcelable SpellCheckerInfo; diff --git a/core/java/android/view/textservice/SpellCheckerInfo.java b/core/java/android/view/textservice/SpellCheckerInfo.java new file mode 100644 index 0000000..1205adf --- /dev/null +++ b/core/java/android/view/textservice/SpellCheckerInfo.java @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package android.view.textservice; + +import android.content.ComponentName; +import android.content.Context; +import android.content.pm.ResolveInfo; +import android.content.pm.ServiceInfo; +import android.os.Parcel; +import android.os.Parcelable; + +/** + * This class is used to specify meta information of an spell checker. + */ +public final class SpellCheckerInfo implements Parcelable { + private final ResolveInfo mService; + private final String mId; + + /** + * Constructor. + * @hide + */ + public SpellCheckerInfo(Context context, ResolveInfo service) { + mService = service; + ServiceInfo si = service.serviceInfo; + mId = new ComponentName(si.packageName, si.name).flattenToShortString(); + } + + /** + * Constructor. + * @hide + */ + public SpellCheckerInfo(Parcel source) { + mId = source.readString(); + mService = ResolveInfo.CREATOR.createFromParcel(source); + } + + /** + * Return a unique ID for this spell checker. The ID is generated from + * the package and class name implementing the method. + */ + public String getId() { + return mId; + } + + + /** + * Return the component of the service that implements. + */ + public ComponentName getComponent() { + return new ComponentName( + mService.serviceInfo.packageName, mService.serviceInfo.name); + } + + /** + * Return the .apk package that implements this input method. + */ + public String getPackageName() { + return mService.serviceInfo.packageName; + } + + /** + * Used to package this object into a {@link Parcel}. + * + * @param dest The {@link Parcel} to be written. + * @param flags The flags used for parceling. + */ + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(mId); + mService.writeToParcel(dest, flags); + } + + + /** + * Used to make this class parcelable. + */ + public static final Parcelable.Creator<SpellCheckerInfo> CREATOR + = new Parcelable.Creator<SpellCheckerInfo>() { + @Override + public SpellCheckerInfo createFromParcel(Parcel source) { + return new SpellCheckerInfo(source); + } + + @Override + public SpellCheckerInfo[] newArray(int size) { + return new SpellCheckerInfo[size]; + } + }; + + /** + * Used to make this class parcelable. + */ + @Override + public int describeContents() { + return 0; + } +} diff --git a/core/java/android/view/textservice/SuggestionsInfo.aidl b/core/java/android/view/textservice/SuggestionsInfo.aidl new file mode 100644 index 0000000..66e20d2 --- /dev/null +++ b/core/java/android/view/textservice/SuggestionsInfo.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.view.textservice; + +parcelable SuggestionsInfo; diff --git a/core/java/android/view/textservice/SuggestionsInfo.java b/core/java/android/view/textservice/SuggestionsInfo.java new file mode 100644 index 0000000..3332f1e --- /dev/null +++ b/core/java/android/view/textservice/SuggestionsInfo.java @@ -0,0 +1,186 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package android.view.textservice; + +import android.os.Parcel; +import android.os.Parcelable; + +/** + * This class contains a metadata of suggestions from the text service + */ +public final class SuggestionsInfo implements Parcelable { + private static final String[] EMPTY = new String[0]; + + /** + * Flag of the attributes of the suggestions that can be obtained by + * {@link #getSuggestionsAttributes}: this tells that the requested word was found + * in the dictionary in the text service. + */ + public static final int RESULT_ATTR_IN_THE_DICTIONARY = 0x0001; + /** + * Flag of the attributes of the suggestions that can be obtained by + * {@link #getSuggestionsAttributes}: this tells that the text service thinks the requested + * word looks a typo. + */ + public static final int RESULT_ATTR_LOOKS_TYPO = 0x0002; + private final int mSuggestionsAttributes; + private final String[] mSuggestions; + private final boolean mSuggestionsAvailable; + private int mCookie; + private int mSequence; + + /** + * Constructor. + * @param suggestionsAttributes from the text service + * @param suggestions from the text service + */ + public SuggestionsInfo(int suggestionsAttributes, String[] suggestions) { + mSuggestionsAttributes = suggestionsAttributes; + if (suggestions == null) { + mSuggestions = EMPTY; + mSuggestionsAvailable = false; + } else { + mSuggestions = suggestions; + mSuggestionsAvailable = true; + } + mCookie = 0; + mSequence = 0; + } + + /** + * Constructor. + * @param suggestionsAttributes from the text service + * @param suggestions from the text service + * @param cookie the cookie of the input TextInfo + * @param sequence the cookie of the input TextInfo + */ + public SuggestionsInfo( + int suggestionsAttributes, String[] suggestions, int cookie, int sequence) { + if (suggestions == null) { + mSuggestions = EMPTY; + mSuggestionsAvailable = false; + } else { + mSuggestions = suggestions; + mSuggestionsAvailable = true; + } + mSuggestionsAttributes = suggestionsAttributes; + mCookie = cookie; + mSequence = sequence; + } + + public SuggestionsInfo(Parcel source) { + mSuggestionsAttributes = source.readInt(); + mSuggestions = source.readStringArray(); + mCookie = source.readInt(); + mSequence = source.readInt(); + mSuggestionsAvailable = source.readInt() == 1; + } + + /** + * Used to package this object into a {@link Parcel}. + * + * @param dest The {@link Parcel} to be written. + * @param flags The flags used for parceling. + */ + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mSuggestionsAttributes); + dest.writeStringArray(mSuggestions); + dest.writeInt(mCookie); + dest.writeInt(mSequence); + dest.writeInt(mSuggestionsAvailable ? 1 : 0); + } + + /** + * Set the cookie and the sequence of SuggestionsInfo which are set to TextInfo from a client + * application + * @param cookie the cookie of an input TextInfo + * @param sequence the cookie of an input TextInfo + */ + public void setCookieAndSequence(int cookie, int sequence) { + mCookie = cookie; + mSequence = sequence; + } + + /** + * @return the cookie which may be set by a client application + */ + public int getCookie() { + return mCookie; + } + + /** + * @return the sequence which may be set by a client application + */ + public int getSequence() { + return mSequence; + } + + /** + * @return the attributes of suggestions. This includes whether the spell checker has the word + * in its dictionary or not and whether the spell checker has confident suggestions for the + * word or not. + */ + public int getSuggestionsAttributes() { + return mSuggestionsAttributes; + } + + /** + * @return the count of the suggestions. If there's no suggestions at all, this method returns + * -1. Even if this method returns 0, it doesn't necessarily mean that there are no suggestions + * for the requested word. For instance, the caller could have been asked to limit the maximum + * number of suggestions returned. + */ + public int getSuggestionsCount() { + if (!mSuggestionsAvailable) { + return -1; + } + return mSuggestions.length; + } + + /** + * @param i the id of suggestions + * @return the suggestion at the specified id + */ + public String getSuggestionAt(int i) { + return mSuggestions[i]; + } + + /** + * Used to make this class parcelable. + */ + public static final Parcelable.Creator<SuggestionsInfo> CREATOR + = new Parcelable.Creator<SuggestionsInfo>() { + @Override + public SuggestionsInfo createFromParcel(Parcel source) { + return new SuggestionsInfo(source); + } + + @Override + public SuggestionsInfo[] newArray(int size) { + return new SuggestionsInfo[size]; + } + }; + + /** + * Used to make this class parcelable. + */ + @Override + public int describeContents() { + return 0; + } +} diff --git a/core/java/android/view/textservice/TextInfo.aidl b/core/java/android/view/textservice/TextInfo.aidl new file mode 100644 index 0000000..d231d76 --- /dev/null +++ b/core/java/android/view/textservice/TextInfo.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.view.textservice; + +parcelable TextInfo; diff --git a/core/java/android/view/textservice/TextInfo.java b/core/java/android/view/textservice/TextInfo.java new file mode 100644 index 0000000..b534eb0 --- /dev/null +++ b/core/java/android/view/textservice/TextInfo.java @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package android.view.textservice; + +import android.os.Parcel; +import android.os.Parcelable; +import android.text.TextUtils; + +/** + * This class contains a metadata of the input of TextService + */ +public final class TextInfo implements Parcelable { + private final String mText; + private final int mCookie; + private final int mSequence; + + /** + * Constructor. + * @param text the text which will be input to TextService + */ + public TextInfo(String text) { + this(text, 0, 0); + } + + /** + * Constructor. + * @param text the text which will be input to TextService + * @param cookie the cookie for this TextInfo + * @param sequence the sequence number for this TextInfo + */ + public TextInfo(String text, int cookie, int sequence) { + if (TextUtils.isEmpty(text)) { + throw new IllegalArgumentException(text); + } + mText = text; + mCookie = cookie; + mSequence = sequence; + } + + public TextInfo(Parcel source) { + mText = source.readString(); + mCookie = source.readInt(); + mSequence = source.readInt(); + } + + /** + * Used to package this object into a {@link Parcel}. + * + * @param dest The {@link Parcel} to be written. + * @param flags The flags used for parceling. + */ + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(mText); + dest.writeInt(mCookie); + dest.writeInt(mSequence); + } + + /** + * @return the text which is an input of a text service + */ + public String getText() { + return mText; + } + + /** + * @return the cookie of TextInfo + */ + public int getCookie() { + return mCookie; + } + + /** + * @return the sequence of TextInfo + */ + public int getSequence() { + return mSequence; + } + + /** + * Used to make this class parcelable. + */ + public static final Parcelable.Creator<TextInfo> CREATOR + = new Parcelable.Creator<TextInfo>() { + @Override + public TextInfo createFromParcel(Parcel source) { + return new TextInfo(source); + } + + @Override + public TextInfo[] newArray(int size) { + return new TextInfo[size]; + } + }; + + /** + * Used to make this class parcelable. + */ + @Override + public int describeContents() { + return 0; + } +} diff --git a/core/java/android/view/textservice/TextServicesManager.java b/core/java/android/view/textservice/TextServicesManager.java new file mode 100644 index 0000000..9749416 --- /dev/null +++ b/core/java/android/view/textservice/TextServicesManager.java @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package android.view.textservice; + +import com.android.internal.textservice.ITextServicesManager; + +import android.content.Context; +import android.os.IBinder; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.view.textservice.SpellCheckerInfo; +import android.service.textservice.SpellCheckerSession; +import android.service.textservice.SpellCheckerSession.SpellCheckerSessionListener; + +import java.util.Locale; + +/** + * System API to the overall text services, which arbitrates interaction between applications + * and text services. You can retrieve an instance of this interface with + * {@link Context#getSystemService(String) Context.getSystemService()}. + * + * The user can change the current text services in Settings. And also applications can specify + * the target text services. + */ +public final class TextServicesManager { + private static final String TAG = TextServicesManager.class.getSimpleName(); + + private static TextServicesManager sInstance; + private static ITextServicesManager sService; + + private TextServicesManager() { + if (sService == null) { + IBinder b = ServiceManager.getService(Context.TEXT_SERVICES_MANAGER_SERVICE); + sService = ITextServicesManager.Stub.asInterface(b); + } + } + + /** + * Retrieve the global TextServicesManager instance, creating it if it doesn't already exist. + * @hide + */ + public static TextServicesManager getInstance() { + synchronized (TextServicesManager.class) { + if (sInstance != null) { + return sInstance; + } + sInstance = new TextServicesManager(); + } + return sInstance; + } + + /** + * Get a spell checker session for the specified spell checker + * @param locale the locale for the spell checker + * @param listener a spell checker session lister for getting results from a spell checker. + * @param referToSpellCheckerLanguageSettings if true, the session for one of enabled + * languages in settings will be returned. + * @return the spell checker session of the spell checker + */ + // TODO: Add a method to get enabled spell checkers. + // TODO: Handle referToSpellCheckerLanguageSettings + public SpellCheckerSession newSpellCheckerSession(Locale locale, + SpellCheckerSessionListener listener, boolean referToSpellCheckerLanguageSettings) { + if (locale == null || listener == null) { + throw new NullPointerException(); + } + final SpellCheckerInfo info; + try { + info = sService.getCurrentSpellChecker(locale.toString()); + } catch (RemoteException e) { + return null; + } + if (info == null) { + return null; + } + final SpellCheckerSession session = new SpellCheckerSession(info, sService, listener); + try { + sService.getSpellCheckerService( + info, locale.toString(), session.getTextServicesSessionListener(), + session.getSpellCheckerSessionListener()); + } catch (RemoteException e) { + return null; + } + return session; + } +} diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index b22c57b..6a3b2ff 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -6330,8 +6330,8 @@ public class WebView extends AbsoluteLayout if (action == MotionEvent.ACTION_POINTER_DOWN) { cancelTouch(); action = MotionEvent.ACTION_DOWN; - } else if (action == MotionEvent.ACTION_POINTER_UP && ev.getPointerCount() == 2) { - // set mLastTouchX/Y to the remaining point + } else if (action == MotionEvent.ACTION_POINTER_UP && ev.getPointerCount() >= 2) { + // set mLastTouchX/Y to the remaining points for multi-touch. mLastTouchX = Math.round(x); mLastTouchY = Math.round(y); } else if (action == MotionEvent.ACTION_MOVE) { @@ -9119,20 +9119,12 @@ public class WebView extends AbsoluteLayout return nativeTileProfilingNumTilesInFrame(frame); } /** @hide only used by profiling tests */ - public int tileProfilingGetX(int frame, int tile) { - return nativeTileProfilingGetX(frame, tile); + public int tileProfilingGetInt(int frame, int tile, String key) { + return nativeTileProfilingGetInt(frame, tile, key); } /** @hide only used by profiling tests */ - public int tileProfilingGetY(int frame, int tile) { - return nativeTileProfilingGetY(frame, tile); - } - /** @hide only used by profiling tests */ - public boolean tileProfilingGetReady(int frame, int tile) { - return nativeTileProfilingGetReady(frame, tile); - } - /** @hide only used by profiling tests */ - public int tileProfilingGetLevel(int frame, int tile) { - return nativeTileProfilingGetLevel(frame, tile); + public float tileProfilingGetFloat(int frame, int tile, String key) { + return nativeTileProfilingGetFloat(frame, tile, key); } private native int nativeCacheHitFramePointer(); @@ -9262,10 +9254,8 @@ public class WebView extends AbsoluteLayout private native void nativeTileProfilingClear(); private native int nativeTileProfilingNumFrames(); private native int nativeTileProfilingNumTilesInFrame(int frame); - private native int nativeTileProfilingGetX(int frame, int tile); - private native int nativeTileProfilingGetY(int frame, int tile); - private native boolean nativeTileProfilingGetReady(int frame, int tile); - private native int nativeTileProfilingGetLevel(int frame, int tile); + private native int nativeTileProfilingGetInt(int frame, int tile, String key); + private native float nativeTileProfilingGetFloat(int frame, int tile, String key); // Never call this version except by updateCachedTextfield(String) - // we always want to pass in our generation number. private native void nativeUpdateCachedTextfield(String updatedText, diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java index d7a2526..8d8023b 100644 --- a/core/java/android/webkit/WebViewCore.java +++ b/core/java/android/webkit/WebViewCore.java @@ -1069,6 +1069,15 @@ public final class WebViewCore { + " arg1=" + msg.arg1 + " arg2=" + msg.arg2 + " obj=" + msg.obj); } + if (mWebView == null + && msg.what != EventHub.RESUME_TIMERS + && msg.what != EventHub.PAUSE_TIMERS) { + if (DebugFlags.WEB_VIEW_CORE) { + Log.v(LOGTAG, "Rejecting message " + msg.what + + " because we are destroyed"); + } + return; + } switch (msg.what) { case WEBKIT_DRAW: webkitDraw(); @@ -1757,30 +1766,17 @@ public final class WebViewCore { } /** - * Removes pending messages and trigger a DESTROY message to send to - * WebCore. + * Sends a DESTROY message to WebCore. * Called from UI thread. */ void destroy() { - // We don't want anyone to post a message between removing pending - // messages and sending the destroy message. synchronized (mEventHub) { - // RESUME_TIMERS and PAUSE_TIMERS are per process base. They need to - // be preserved even the WebView is destroyed. - // Note: we should not have more than one RESUME_TIMERS/PAUSE_TIMERS - boolean hasResume = mEventHub.hasMessages(EventHub.RESUME_TIMERS); - boolean hasPause = mEventHub.hasMessages(EventHub.PAUSE_TIMERS); - mEventHub.removeMessages(); + // Do not call removeMessages as then we risk removing PAUSE_TIMERS + // or RESUME_TIMERS messages, which we must still handle as they + // are per process. DESTROY will instead trigger a white list in + // mEventHub, skipping any remaining messages in the queue mEventHub.sendMessageAtFrontOfQueue( Message.obtain(null, EventHub.DESTROY)); - if (hasPause) { - mEventHub.sendMessageAtFrontOfQueue( - Message.obtain(null, EventHub.PAUSE_TIMERS)); - } - if (hasResume) { - mEventHub.sendMessageAtFrontOfQueue( - Message.obtain(null, EventHub.RESUME_TIMERS)); - } mEventHub.blockMessages(); } } @@ -2113,13 +2109,17 @@ public final class WebViewCore { // called from JNI or WebView thread /* package */ void contentDraw() { - // don't update the Picture until we have an initial width and finish - // the first layout - if (mCurrentViewWidth == 0 || !mBrowserFrame.firstLayoutDone()) { - return; - } - // only fire an event if this is our first request synchronized (this) { + if (mWebView == null || mBrowserFrame == null) { + // We were destroyed + return; + } + // don't update the Picture until we have an initial width and finish + // the first layout + if (mCurrentViewWidth == 0 || !mBrowserFrame.firstLayoutDone()) { + return; + } + // only fire an event if this is our first request if (mDrawIsScheduled) return; mDrawIsScheduled = true; if (mDrawIsPaused) return; diff --git a/core/java/android/webkit/ZoomManager.java b/core/java/android/webkit/ZoomManager.java index 49ea944..70e48ad 100644 --- a/core/java/android/webkit/ZoomManager.java +++ b/core/java/android/webkit/ZoomManager.java @@ -794,6 +794,8 @@ class ZoomManager { mInitialZoomOverview = false; dismissZoomPicker(); mFocusMovementQueue.clear(); + mFocusX = detector.getFocusX(); + mFocusY = detector.getFocusY(); mWebView.mViewManager.startZoom(); mWebView.onPinchToZoomAnimationStart(); mAccumulatedSpan = 0; diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index 8f8c1d0..b7c1687 100644 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -4638,9 +4638,6 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te childrenTop += getVerticalFadingEdgeLength(); } } - // Don't ever focus a disabled item. - if (!mAdapter.isEnabled(i)) continue; - if (top >= childrenTop) { // Found a view whose top is fully visisble selectedPos = firstPosition + i; diff --git a/core/java/android/widget/ActivityChooserModel.java b/core/java/android/widget/ActivityChooserModel.java index d7429b3..4b0a6da 100644 --- a/core/java/android/widget/ActivityChooserModel.java +++ b/core/java/android/widget/ActivityChooserModel.java @@ -317,6 +317,7 @@ public class ActivityChooserModel extends DataSetObservable { dataModel = new ActivityChooserModel(context, historyFileName); sDataModelRegistry.put(historyFileName, dataModel); } + dataModel.readHistoricalData(); return dataModel; } } @@ -505,7 +506,7 @@ public class ActivityChooserModel extends DataSetObservable { * data is read until this method is invoked. * <p> */ - public void readHistoricalData() { + private void readHistoricalData() { synchronized (mInstanceLock) { if (!mCanReadHistoricalData || !mHistoricalRecordsChanged) { return; @@ -527,7 +528,7 @@ public class ActivityChooserModel extends DataSetObservable { * @throws IllegalStateException If this method is called before a call to * {@link #readHistoricalData()}. */ - public void persistHistoricalData() { + private void persistHistoricalData() { synchronized (mInstanceLock) { if (!mReadShareHistoryCalled) { throw new IllegalStateException("No preceding call to #readHistoricalData"); @@ -629,6 +630,7 @@ public class ActivityChooserModel extends DataSetObservable { if (added) { mHistoricalRecordsChanged = true; pruneExcessiveHistoricalRecordsLocked(); + persistHistoricalData(); sortActivities(); } return added; diff --git a/core/java/android/widget/ActivityChooserView.java b/core/java/android/widget/ActivityChooserView.java index 5b69aa8..d85f8a4 100644 --- a/core/java/android/widget/ActivityChooserView.java +++ b/core/java/android/widget/ActivityChooserView.java @@ -307,7 +307,6 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod ActivityChooserModel dataModel = mAdapter.getDataModel(); if (dataModel != null) { dataModel.registerObserver(mModelDataSetOberver); - dataModel.readHistoricalData(); } mIsAttachedToWindow = true; } @@ -318,7 +317,6 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod ActivityChooserModel dataModel = mAdapter.getDataModel(); if (dataModel != null) { dataModel.unregisterObserver(mModelDataSetOberver); - dataModel.persistHistoricalData(); } mIsAttachedToWindow = false; } diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java index 755d4e0..00c75a9 100644 --- a/core/java/android/widget/AdapterView.java +++ b/core/java/android/widget/AdapterView.java @@ -902,15 +902,16 @@ public abstract class AdapterView<T extends Adapter> extends ViewGroup { @Override public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) { - // Add a record for ourselves as well. - AccessibilityEvent record = AccessibilityEvent.obtain(); - record.setSource(this); - // Set the class since it is not populated in #dispatchPopulateAccessibilityEvent - record.setClassName(getClass().getName()); - child.onInitializeAccessibilityEvent(record); - child.dispatchPopulateAccessibilityEvent(record); - event.appendRecord(record); - return true; + if (super.onRequestSendAccessibilityEvent(child, event)) { + // Add a record for ourselves as well. + AccessibilityEvent record = AccessibilityEvent.obtain(); + onInitializeAccessibilityEvent(record); + // Populate with the text of the requesting child. + child.dispatchPopulateAccessibilityEvent(record); + event.appendRecord(record); + return true; + } + return false; } @Override diff --git a/core/java/android/widget/CheckedTextView.java b/core/java/android/widget/CheckedTextView.java index 49616cc..f3a6da7 100644 --- a/core/java/android/widget/CheckedTextView.java +++ b/core/java/android/widget/CheckedTextView.java @@ -39,8 +39,9 @@ public class CheckedTextView extends TextView implements Checkable { private boolean mChecked; private int mCheckMarkResource; private Drawable mCheckMarkDrawable; - private int mBasePaddingRight; + private int mBasePadding; private int mCheckMarkWidth; + private boolean mNeedRequestlayout; private static final int[] CHECKED_STATE_SET = { R.attr.state_checked @@ -123,6 +124,7 @@ public class CheckedTextView extends TextView implements Checkable { mCheckMarkDrawable.setCallback(null); unscheduleDrawable(mCheckMarkDrawable); } + mNeedRequestlayout = (d != mCheckMarkDrawable); if (d != null) { d.setCallback(this); d.setVisible(getVisibility() == VISIBLE, false); @@ -130,19 +132,35 @@ public class CheckedTextView extends TextView implements Checkable { setMinHeight(d.getIntrinsicHeight()); mCheckMarkWidth = d.getIntrinsicWidth(); - mUserPaddingRight = mCheckMarkWidth + mBasePaddingRight; d.setState(getDrawableState()); } else { - mUserPaddingRight = mBasePaddingRight; + mCheckMarkWidth = 0; } mCheckMarkDrawable = d; - requestLayout(); + // Do padding resolution. This will call setPadding() and do a requestLayout() if needed. + resolvePadding(); + } + + /** + * @hide + */ + @Override + protected void resolvePadding() { + super.resolvePadding(); + int newPadding = (mCheckMarkDrawable != null) ? + mCheckMarkWidth + mBasePadding : mBasePadding; + mNeedRequestlayout |= (mPaddingRight != newPadding); + mPaddingRight = newPadding; + if (mNeedRequestlayout) { + requestLayout(); + mNeedRequestlayout = false; + } } @Override public void setPadding(int left, int top, int right, int bottom) { super.setPadding(left, top, right, bottom); - mBasePaddingRight = mUserPaddingRight; + mBasePadding = mPaddingRight; } @Override @@ -167,9 +185,9 @@ public class CheckedTextView extends TextView implements Checkable { int right = getWidth(); checkMarkDrawable.setBounds( - right - mUserPaddingRight, + right - mPaddingRight, y, - right - mUserPaddingRight + mCheckMarkWidth, + right - mPaddingRight + mCheckMarkWidth, y + height); checkMarkDrawable.draw(canvas); } diff --git a/core/java/android/widget/GridLayout.java b/core/java/android/widget/GridLayout.java index 5747fd3..3bd7fab 100644 --- a/core/java/android/widget/GridLayout.java +++ b/core/java/android/widget/GridLayout.java @@ -596,7 +596,6 @@ public class GridLayout extends ViewGroup { int col = 0; for (int i = 0, N = getChildCount(); i < N; i++) { View c = getChildAt(i); - if (isGone(c)) continue; LayoutParams lp = getLayoutParams1(c); final Spec colSpec = lp.columnSpec; @@ -1002,7 +1001,6 @@ public class GridLayout extends ViewGroup { int count = -1; for (int i = 0, N = getChildCount(); i < N; i++) { View c = getChildAt(i); - if (isGone(c)) continue; LayoutParams params = getLayoutParams(c); Spec spec = horizontal ? params.columnSpec : params.rowSpec; count = max(count, spec.span.min); diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java index 161b404..299e1ff 100644 --- a/core/java/android/widget/ImageView.java +++ b/core/java/android/widget/ImageView.java @@ -30,14 +30,15 @@ import android.graphics.RectF; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.net.Uri; +import android.text.TextUtils; import android.util.AttributeSet; import android.util.Log; import android.view.RemotableViewMethod; import android.view.View; import android.view.ViewDebug; +import android.view.accessibility.AccessibilityEvent; import android.widget.RemoteViews.RemoteView; - /** * Displays an arbitrary image, such as an icon. The ImageView class * can load images from various sources (such as resources or content @@ -208,7 +209,15 @@ public class ImageView extends View { } return false; } - + + @Override + public void onPopulateAccessibilityEvent(AccessibilityEvent event) { + CharSequence contentDescription = getContentDescription(); + if (!TextUtils.isEmpty(contentDescription)) { + event.getText().add(contentDescription); + } + } + /** * Set this to true if you want the ImageView to adjust its bounds * to preserve the aspect ratio of its drawable. diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index b116f0f..a7324b0 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -16,11 +16,6 @@ package android.widget; -import com.android.internal.util.FastMath; -import com.android.internal.widget.EditableInputConnection; - -import org.xmlpull.v1.XmlPullParserException; - import android.R; import android.content.ClipData; import android.content.ClipData.Item; @@ -139,6 +134,11 @@ import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputMethodManager; import android.widget.RemoteViews.RemoteView; +import com.android.internal.util.FastMath; +import com.android.internal.widget.EditableInputConnection; + +import org.xmlpull.v1.XmlPullParserException; + import java.io.IOException; import java.lang.ref.WeakReference; import java.text.BreakIterator; @@ -329,7 +329,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener private int mTextEditPasteWindowLayout, mTextEditSidePasteWindowLayout; private int mTextEditNoPasteWindowLayout, mTextEditSideNoPasteWindowLayout; - private int mTextEditSuggestionsBottomWindowLayout, mTextEditSuggestionsTopWindowLayout; + private int mTextEditSuggestionsWindowLayout; private int mTextEditSuggestionItemLayout; private SuggestionsPopupWindow mSuggestionsPopupWindow; private SuggestionRangeSpan mSuggestionRangeSpan; @@ -830,12 +830,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener mTextEditSideNoPasteWindowLayout = a.getResourceId(attr, 0); break; - case com.android.internal.R.styleable.TextView_textEditSuggestionsBottomWindowLayout: - mTextEditSuggestionsBottomWindowLayout = a.getResourceId(attr, 0); - break; - - case com.android.internal.R.styleable.TextView_textEditSuggestionsTopWindowLayout: - mTextEditSuggestionsTopWindowLayout = a.getResourceId(attr, 0); + case com.android.internal.R.styleable.TextView_textEditSuggestionsWindowLayout: + mTextEditSuggestionsWindowLayout = a.getResourceId(attr, 0); break; case com.android.internal.R.styleable.TextView_textEditSuggestionItemLayout: @@ -5090,6 +5086,40 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } @Override + public boolean onKeyPreIme(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK) { + boolean areSuggestionsShown = areSuggestionsShown(); + boolean isInSelectionMode = mSelectionActionMode != null; + + if (areSuggestionsShown || isInSelectionMode) { + if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) { + KeyEvent.DispatcherState state = getKeyDispatcherState(); + if (state != null) { + state.startTracking(event, this); + } + return true; + } else if (event.getAction() == KeyEvent.ACTION_UP) { + KeyEvent.DispatcherState state = getKeyDispatcherState(); + if (state != null) { + state.handleUpEvent(event); + } + if (event.isTracking() && !event.isCanceled()) { + if (areSuggestionsShown) { + hideSuggestions(); + return true; + } + if (isInSelectionMode) { + stopSelectionActionMode(); + return true; + } + } + } + } + } + return super.onKeyPreIme(keyCode, event); + } + + @Override public boolean onKeyDown(int keyCode, KeyEvent event) { int which = doKeyDown(keyCode, event, null); if (which == 0) { @@ -5241,6 +5271,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener // Has to be done on key down (and not on key up) to correctly be intercepted. case KeyEvent.KEYCODE_BACK: + if (areSuggestionsShown()) { + hideSuggestions(); + return -1; + } if (mSelectionActionMode != null) { stopSelectionActionMode(); return -1; @@ -7617,7 +7651,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener // Because of View recycling in ListView, there is no easy way to know when a TextView with // selection becomes visible again. Until a better solution is found, stop text selection // mode (if any) as soon as this TextView is recycled. - stopSelectionActionMode(); + hideControllers(); } @Override @@ -7889,8 +7923,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (!selectAllGotFocus && hasSelection()) { startSelectionActionMode(); } else { - stopSelectionActionMode(); - hideSuggestions(); + hideControllers(); if (hasInsertionController() && !selectAllGotFocus && mText.length() > 0) { getInsertionController().show(); } @@ -8748,9 +8781,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener private static final int MAX_NUMBER_SUGGESTIONS = 5; private static final int NO_SUGGESTIONS = -1; private final PopupWindow mContainer; - private final ViewGroup[] mSuggestionViews = new ViewGroup[2]; - private final int[] mSuggestionViewLayouts = new int[] { - mTextEditSuggestionsBottomWindowLayout, mTextEditSuggestionsTopWindowLayout}; + private ViewGroup mSuggestionViewGroup; private WordIterator mSuggestionWordIterator; private TextAppearanceSpan[] mHighlightSpans = new TextAppearanceSpan[0]; @@ -8772,12 +8803,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener int suggestionIndex; // the index of the suggestion inside suggestionSpan } - private ViewGroup getViewGroup(boolean under) { - final int viewIndex = under ? 0 : 1; - ViewGroup viewGroup = mSuggestionViews[viewIndex]; - - if (viewGroup == null) { - final int layout = mSuggestionViewLayouts[viewIndex]; + private void initSuggestionViewGroup() { + if (mSuggestionViewGroup == null) { LayoutInflater inflater = (LayoutInflater) TextView.this.mContext. getSystemService(Context.LAYOUT_INFLATER_SERVICE); @@ -8786,19 +8813,19 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener "Unable to create TextEdit suggestion window inflater"); } - View view = inflater.inflate(layout, null); + View view = inflater.inflate(mTextEditSuggestionsWindowLayout, null); if (! (view instanceof ViewGroup)) { throw new IllegalArgumentException( "Inflated TextEdit suggestion window is not a ViewGroup: " + view); } - viewGroup = (ViewGroup) view; + mSuggestionViewGroup = (ViewGroup) view; // Inflate the suggestion items once and for all. for (int i = 0; i < MAX_NUMBER_SUGGESTIONS; i++) { - View childView = inflater.inflate(mTextEditSuggestionItemLayout, viewGroup, - false); + View childView = inflater.inflate(mTextEditSuggestionItemLayout, + mSuggestionViewGroup, false); if (! (childView instanceof TextView)) { throw new IllegalArgumentException( @@ -8806,14 +8833,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } childView.setTag(new SuggestionInfo()); - viewGroup.addView(childView); + mSuggestionViewGroup.addView(childView); childView.setOnClickListener(this); } - mSuggestionViews[viewIndex] = viewGroup; + mContainer.setContentView(mSuggestionViewGroup); } - - return viewGroup; } public void show() { @@ -8824,8 +8849,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener SuggestionSpan[] suggestionSpans = spannable.getSpans(pos, pos, SuggestionSpan.class); final int nbSpans = suggestionSpans.length; - ViewGroup viewGroup = getViewGroup(true); - mContainer.setContentView(viewGroup); + initSuggestionViewGroup(); int totalNbSuggestions = 0; int spanUnionStart = mText.length(); @@ -8841,7 +8865,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener String[] suggestions = suggestionSpan.getSuggestions(); int nbSuggestions = suggestions.length; for (int suggestionIndex = 0; suggestionIndex < nbSuggestions; suggestionIndex++) { - TextView textView = (TextView) viewGroup.getChildAt(totalNbSuggestions); + TextView textView = (TextView) mSuggestionViewGroup.getChildAt( + totalNbSuggestions); textView.setText(suggestions[suggestionIndex]); SuggestionInfo suggestionInfo = (SuggestionInfo) textView.getTag(); suggestionInfo.spanStart = spanStart; @@ -8860,7 +8885,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (totalNbSuggestions == 0) { // TODO Replace by final text, use a dedicated layout, add a fade out timer... - TextView textView = (TextView) viewGroup.getChildAt(0); + TextView textView = (TextView) mSuggestionViewGroup.getChildAt(0); textView.setText("No suggestions available"); SuggestionInfo suggestionInfo = (SuggestionInfo) textView.getTag(); suggestionInfo.spanStart = NO_SUGGESTIONS; @@ -8871,17 +8896,24 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); for (int i = 0; i < totalNbSuggestions; i++) { - final TextView textView = (TextView) viewGroup.getChildAt(i); + final TextView textView = (TextView) mSuggestionViewGroup.getChildAt(i); highlightTextDifferences(textView, spanUnionStart, spanUnionEnd); } } - for (int i = 0; i < MAX_NUMBER_SUGGESTIONS; i++) { - viewGroup.getChildAt(i).setVisibility(i < totalNbSuggestions ? VISIBLE : GONE); + for (int i = 0; i < totalNbSuggestions; i++) { + mSuggestionViewGroup.getChildAt(i).setVisibility(VISIBLE); + } + for (int i = totalNbSuggestions; i < MAX_NUMBER_SUGGESTIONS; i++) { + mSuggestionViewGroup.getChildAt(i).setVisibility(GONE); } - final int size = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); - viewGroup.measure(size, size); + final DisplayMetrics displayMetrics = mContext.getResources().getDisplayMetrics(); + final int screenWidth = displayMetrics.widthPixels; + final int screenHeight = displayMetrics.heightPixels; + mSuggestionViewGroup.measure( + View.MeasureSpec.makeMeasureSpec(screenWidth, View.MeasureSpec.AT_MOST), + View.MeasureSpec.makeMeasureSpec(screenHeight, View.MeasureSpec.AT_MOST)); positionAtCursor(); } @@ -9042,6 +9074,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener mContainer.dismiss(); } + public boolean isShowing() { + return mContainer.isShowing(); + } + @Override public void onClick(View view) { if (view instanceof TextView) { @@ -9130,23 +9166,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener // Vertical clipping if (coords[1] + height > screenHeight) { - // Try to position above current line instead - // TODO use top layout instead, reverse suggestion order, - // try full screen vertical down if it still does not fit. TBD with designers. - - // Update dimensions from new view - contentView = mContainer.getContentView(); - width = contentView.getMeasuredWidth(); - height = contentView.getMeasuredHeight(); - - final int lineTop = mLayout.getLineTop(line); - final int lineHeight = lineBottom - lineTop; - coords[1] -= height + lineHeight; + coords[1] = screenHeight - height; } // Horizontal clipping - coords[0] = Math.max(0, coords[0]); coords[0] = Math.min(displayMetrics.widthPixels - width, coords[0]); + coords[0] = Math.max(0, coords[0]); mContainer.showAtLocation(TextView.this, Gravity.NO_GRAVITY, coords[0], coords[1]); } @@ -9168,6 +9193,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } } + boolean areSuggestionsShown() { + return mSuggestionsPopupWindow != null && mSuggestionsPopupWindow.isShowing(); + } + /** * Some parts of the text can have alternate suggestion text attached. This is typically done by * the IME by adding {@link SuggestionSpan}s to the text. diff --git a/core/java/com/android/internal/app/AlertController.java b/core/java/com/android/internal/app/AlertController.java index 8d6caa1..2061c90 100644 --- a/core/java/com/android/internal/app/AlertController.java +++ b/core/java/com/android/internal/app/AlertController.java @@ -438,7 +438,7 @@ public class AlertController { LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); - topPanel.addView(mCustomTitleView, lp); + topPanel.addView(mCustomTitleView, 0, lp); // Hide the title template View titleTemplate = mWindow.findViewById(R.id.title_template); diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl index a9e5057..07430e7 100644 --- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl @@ -27,7 +27,7 @@ interface IStatusBarService void expand(); void collapse(); void disable(int what, IBinder token, String pkg); - void setIcon(String slot, String iconPackage, int iconId, int iconLevel); + void setIcon(String slot, String iconPackage, int iconId, int iconLevel, String contentDescription); void setIconVisibility(String slot, boolean visible); void removeIcon(String slot); void topAppWindowChanged(boolean menuVisible); diff --git a/core/java/com/android/internal/statusbar/StatusBarIcon.java b/core/java/com/android/internal/statusbar/StatusBarIcon.java index ae2cac2..3333c82 100644 --- a/core/java/com/android/internal/statusbar/StatusBarIcon.java +++ b/core/java/com/android/internal/statusbar/StatusBarIcon.java @@ -19,42 +19,35 @@ package com.android.internal.statusbar; import android.os.Parcel; import android.os.Parcelable; -/** - * @hide - */ public class StatusBarIcon implements Parcelable { public String iconPackage; public int iconId; public int iconLevel; public boolean visible = true; public int number; + public CharSequence contentDescription; - private StatusBarIcon() { - } - - public StatusBarIcon(String iconPackage, int iconId, int iconLevel) { - this.iconPackage = iconPackage; - this.iconId = iconId; - this.iconLevel = iconLevel; - } - - public StatusBarIcon(String iconPackage, int iconId, int iconLevel, int number) { + public StatusBarIcon(String iconPackage, int iconId, int iconLevel, int number, + CharSequence contentDescription) { this.iconPackage = iconPackage; this.iconId = iconId; this.iconLevel = iconLevel; this.number = number; + this.contentDescription = contentDescription; } + @Override public String toString() { return "StatusBarIcon(pkg=" + this.iconPackage + " id=0x" + Integer.toHexString(this.iconId) + " level=" + this.iconLevel + " visible=" + visible + " num=" + this.number + " )"; } + @Override public StatusBarIcon clone() { - StatusBarIcon that = new StatusBarIcon(this.iconPackage, this.iconId, this.iconLevel); + StatusBarIcon that = new StatusBarIcon(this.iconPackage, this.iconId, this.iconLevel, + this.number, this.contentDescription); that.visible = this.visible; - that.number = this.number; return that; } @@ -71,6 +64,7 @@ public class StatusBarIcon implements Parcelable { this.iconLevel = in.readInt(); this.visible = in.readInt() != 0; this.number = in.readInt(); + this.contentDescription = in.readCharSequence(); } public void writeToParcel(Parcel out, int flags) { @@ -79,6 +73,7 @@ public class StatusBarIcon implements Parcelable { out.writeInt(this.iconLevel); out.writeInt(this.visible ? 1 : 0); out.writeInt(this.number); + out.writeCharSequence(this.contentDescription); } public int describeContents() { diff --git a/core/java/com/android/internal/textservice/ISpellCheckerService.aidl b/core/java/com/android/internal/textservice/ISpellCheckerService.aidl new file mode 100644 index 0000000..ff00492 --- /dev/null +++ b/core/java/com/android/internal/textservice/ISpellCheckerService.aidl @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.textservice; + +import com.android.internal.textservice.ISpellCheckerSession; +import com.android.internal.textservice.ISpellCheckerSessionListener; + +/** + * Public interface to the global spell checker. + * @hide + */ +interface ISpellCheckerService { + ISpellCheckerSession getISpellCheckerSession( + String locale, ISpellCheckerSessionListener listener); +} diff --git a/core/java/com/android/internal/textservice/ISpellCheckerSession.aidl b/core/java/com/android/internal/textservice/ISpellCheckerSession.aidl new file mode 100644 index 0000000..79e43510c0 --- /dev/null +++ b/core/java/com/android/internal/textservice/ISpellCheckerSession.aidl @@ -0,0 +1,28 @@ +/* + * 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.textservice; + +import android.view.textservice.TextInfo; + +/** + * @hide + */ +oneway interface ISpellCheckerSession { + void getSuggestionsMultiple( + in TextInfo[] textInfos, int suggestionsLimit, boolean multipleWords); + void cancel(); +} diff --git a/core/java/com/android/internal/textservice/ISpellCheckerSessionListener.aidl b/core/java/com/android/internal/textservice/ISpellCheckerSessionListener.aidl new file mode 100644 index 0000000..796b06e --- /dev/null +++ b/core/java/com/android/internal/textservice/ISpellCheckerSessionListener.aidl @@ -0,0 +1,26 @@ +/* + * 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.textservice; + +import android.view.textservice.SuggestionsInfo; + +/** + * @hide + */ +oneway interface ISpellCheckerSessionListener { + void onGetSuggestions(in SuggestionsInfo[] results); +} diff --git a/core/java/com/android/internal/textservice/ITextServicesManager.aidl b/core/java/com/android/internal/textservice/ITextServicesManager.aidl new file mode 100644 index 0000000..ad0c1ff --- /dev/null +++ b/core/java/com/android/internal/textservice/ITextServicesManager.aidl @@ -0,0 +1,35 @@ +/* + * 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.textservice; + +import com.android.internal.textservice.ISpellCheckerSessionListener; +import com.android.internal.textservice.ITextServicesSessionListener; + +import android.content.ComponentName; +import android.view.textservice.SpellCheckerInfo; + +/** + * Interface to the text service manager. + * @hide + */ +interface ITextServicesManager { + SpellCheckerInfo getCurrentSpellChecker(String locale); + oneway void getSpellCheckerService(in SpellCheckerInfo info, in String locale, + in ITextServicesSessionListener tsListener, + in ISpellCheckerSessionListener scListener); + oneway void finishSpellCheckerService(in ISpellCheckerSessionListener listener); +} diff --git a/core/java/com/android/internal/textservice/ITextServicesSessionListener.aidl b/core/java/com/android/internal/textservice/ITextServicesSessionListener.aidl new file mode 100644 index 0000000..ecb6cd0 --- /dev/null +++ b/core/java/com/android/internal/textservice/ITextServicesSessionListener.aidl @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.textservice; + +import com.android.internal.textservice.ISpellCheckerSession; + +import android.view.textservice.SpellCheckerInfo; + +/** + * Interface to the text service session. + * @hide + */ +interface ITextServicesSessionListener { + oneway void onServiceConnected(in ISpellCheckerSession spellCheckerSession); +} diff --git a/core/java/com/android/internal/util/Protocol.java b/core/java/com/android/internal/util/Protocol.java index 69b80d9..9ecd29f 100644 --- a/core/java/com/android/internal/util/Protocol.java +++ b/core/java/com/android/internal/util/Protocol.java @@ -41,6 +41,9 @@ public class Protocol { /** Non system protocols */ public static final int BASE_WIFI = 0x00020000; public static final int BASE_WIFI_WATCHDOG = 0x00021000; + public static final int BASE_WIFI_P2P_MANAGER = 0x00022000; + public static final int BASE_WIFI_P2P_SERVICE = 0x00023000; + public static final int BASE_WIFI_MONITOR = 0x00024000; public static final int BASE_DHCP = 0x00030000; public static final int BASE_DATA_CONNECTION = 0x00040000; public static final int BASE_DATA_CONNECTION_AC = 0x00041000; diff --git a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java index 80f68ac..06f753f 100644 --- a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java +++ b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java @@ -48,6 +48,7 @@ public class ActionMenuPresenter extends BaseMenuPresenter { private boolean mMaxItemsSet; private boolean mStrictWidthLimit; private boolean mWidthLimitSet; + private boolean mExpandedActionViewsExclusive; private int mMinCellSize; @@ -124,6 +125,10 @@ public class ActionMenuPresenter extends BaseMenuPresenter { mMaxItemsSet = true; } + public void setExpandedActionViewsExclusive(boolean isExclusive) { + mExpandedActionViewsExclusive = isExclusive; + } + @Override public MenuView getMenuView(ViewGroup root) { MenuView result = super.getMenuView(root); @@ -326,6 +331,11 @@ public class ActionMenuPresenter extends BaseMenuPresenter { } else { hasOverflow = true; } + if (mExpandedActionViewsExclusive && item.isActionViewExpanded()) { + // Overflow everything if we have an expanded action view and we're + // space constrained. + maxActions = 0; + } } // Reserve a spot for the overflow item if needed. diff --git a/core/java/com/android/internal/view/menu/MenuBuilder.java b/core/java/com/android/internal/view/menu/MenuBuilder.java index 164d581..159b3da 100644 --- a/core/java/com/android/internal/view/menu/MenuBuilder.java +++ b/core/java/com/android/internal/view/menu/MenuBuilder.java @@ -50,6 +50,8 @@ public class MenuBuilder implements Menu { private static final String LOGTAG = "MenuBuilder"; private static final String PRESENTER_KEY = "android:menu:presenters"; + private static final String ACTION_VIEW_STATES_KEY = "android:menu:actionviewstates"; + private static final String EXPANDED_ACTION_VIEW_ID = "android:menu:expandedactionview"; private static final int[] sCategoryToOrder = new int[] { 1, /* No category */ @@ -308,6 +310,67 @@ public class MenuBuilder implements Menu { dispatchRestoreInstanceState(state); } + public void saveActionViewStates(Bundle outStates) { + SparseArray<Parcelable> viewStates = null; + + final int itemCount = size(); + for (int i = 0; i < itemCount; i++) { + final MenuItem item = getItem(i); + final View v = item.getActionView(); + if (v != null && v.getId() != View.NO_ID) { + if (viewStates == null) { + viewStates = new SparseArray<Parcelable>(); + } + v.saveHierarchyState(viewStates); + if (item.isActionViewExpanded()) { + outStates.putInt(EXPANDED_ACTION_VIEW_ID, item.getItemId()); + } + } + if (item.hasSubMenu()) { + final SubMenuBuilder subMenu = (SubMenuBuilder) item.getSubMenu(); + subMenu.saveActionViewStates(outStates); + } + } + + if (viewStates != null) { + outStates.putSparseParcelableArray(getActionViewStatesKey(), viewStates); + } + } + + public void restoreActionViewStates(Bundle states) { + if (states == null) { + return; + } + + SparseArray<Parcelable> viewStates = states.getSparseParcelableArray( + getActionViewStatesKey()); + + final int itemCount = size(); + for (int i = 0; i < itemCount; i++) { + final MenuItem item = getItem(i); + final View v = item.getActionView(); + if (v != null && v.getId() != View.NO_ID) { + v.restoreHierarchyState(viewStates); + } + if (item.hasSubMenu()) { + final SubMenuBuilder subMenu = (SubMenuBuilder) item.getSubMenu(); + subMenu.restoreActionViewStates(states); + } + } + + final int expandedId = states.getInt(EXPANDED_ACTION_VIEW_ID); + if (expandedId > 0) { + MenuItem itemToExpand = findItem(expandedId); + if (itemToExpand != null) { + itemToExpand.expandActionView(); + } + } + } + + protected String getActionViewStatesKey() { + return ACTION_VIEW_STATES_KEY; + } + public void setCallback(Callback cb) { mCallback = cb; } diff --git a/core/java/com/android/internal/view/menu/MenuItemImpl.java b/core/java/com/android/internal/view/menu/MenuItemImpl.java index 541d101..b0a002d 100644 --- a/core/java/com/android/internal/view/menu/MenuItemImpl.java +++ b/core/java/com/android/internal/view/menu/MenuItemImpl.java @@ -553,6 +553,9 @@ public final class MenuItemImpl implements MenuItem { public MenuItem setActionView(View view) { mActionView = view; mActionProvider = null; + if (view != null && view.getId() == View.NO_ID && mId > 0) { + view.setId(mId); + } mMenu.onItemActionRequestChanged(this); return this; } diff --git a/core/java/com/android/internal/view/menu/SubMenuBuilder.java b/core/java/com/android/internal/view/menu/SubMenuBuilder.java index fb1cd5e..92acf8c 100644 --- a/core/java/com/android/internal/view/menu/SubMenuBuilder.java +++ b/core/java/com/android/internal/view/menu/SubMenuBuilder.java @@ -121,4 +121,13 @@ public class SubMenuBuilder extends MenuBuilder implements SubMenu { public boolean collapseItemActionView(MenuItemImpl item) { return mParentMenu.collapseItemActionView(item); } + + @Override + public String getActionViewStatesKey() { + final int itemId = mItem != null ? mItem.getItemId() : 0; + if (itemId == 0) { + return null; + } + return super.getActionViewStatesKey() + ":" + itemId; + } } diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java index 678751c..09262e0 100644 --- a/core/java/com/android/internal/widget/ActionBarView.java +++ b/core/java/com/android/internal/widget/ActionBarView.java @@ -42,6 +42,7 @@ import android.text.TextUtils; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.Log; +import android.view.CollapsibleActionView; import android.view.Gravity; import android.view.LayoutInflater; import android.view.Menu; @@ -285,8 +286,11 @@ public class ActionBarView extends AbsActionBarView { public void setSplitActionBar(boolean splitActionBar) { if (mSplitActionBar != splitActionBar) { if (mMenuView != null) { + final ViewGroup oldParent = (ViewGroup) mMenuView.getParent(); + if (oldParent != null) { + oldParent.removeView(mMenuView); + } if (splitActionBar) { - removeView(mMenuView); if (mSplitView != null) { mSplitView.addView(mMenuView); } @@ -332,7 +336,10 @@ public class ActionBarView extends AbsActionBarView { MenuBuilder builder = (MenuBuilder) menu; mOptionsMenu = builder; if (mMenuView != null) { - removeView(mMenuView); + final ViewGroup oldParent = (ViewGroup) mMenuView.getParent(); + if (oldParent != null) { + oldParent.removeView(mMenuView); + } } if (mActionMenuPresenter == null) { mActionMenuPresenter = new ActionMenuPresenter(); @@ -345,11 +352,19 @@ public class ActionBarView extends AbsActionBarView { final LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT); if (!mSplitActionBar) { + mActionMenuPresenter.setExpandedActionViewsExclusive( + getResources().getBoolean( + com.android.internal.R.bool.action_bar_expanded_action_views_exclusive)); builder.addMenuPresenter(mActionMenuPresenter); builder.addMenuPresenter(mExpandedMenuPresenter); menuView = (ActionMenuView) mActionMenuPresenter.getMenuView(this); + final ViewGroup oldParent = (ViewGroup) menuView.getParent(); + if (oldParent != null && oldParent != this) { + oldParent.removeView(menuView); + } addView(menuView, layoutParams); } else { + mActionMenuPresenter.setExpandedActionViewsExclusive(false); // Allow full screen width in split mode. mActionMenuPresenter.setWidthLimit( getContext().getResources().getDisplayMetrics().widthPixels, true); @@ -361,6 +376,10 @@ public class ActionBarView extends AbsActionBarView { builder.addMenuPresenter(mExpandedMenuPresenter); menuView = (ActionMenuView) mActionMenuPresenter.getMenuView(this); if (mSplitView != null) { + final ViewGroup oldParent = (ViewGroup) menuView.getParent(); + if (oldParent != null && oldParent != mSplitView) { + oldParent.removeView(menuView); + } mSplitView.addView(menuView, layoutParams); } else { // We'll add this later if we missed it this time. @@ -1300,6 +1319,10 @@ public class ActionBarView extends AbsActionBarView { if (mCustomNavView != null) mCustomNavView.setVisibility(GONE); requestLayout(); item.setActionViewExpanded(true); + + if (mExpandedActionView instanceof CollapsibleActionView) { + ((CollapsibleActionView) mExpandedActionView).onActionViewExpanded(); + } return true; } @@ -1326,11 +1349,16 @@ public class ActionBarView extends AbsActionBarView { if (mCustomNavView != null && (mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0) { mCustomNavView.setVisibility(VISIBLE); } + View collapsedView = mExpandedActionView; mExpandedActionView = null; mExpandedHomeLayout.setIcon(null); mCurrentExpandedItem = null; requestLayout(); item.setActionViewExpanded(false); + + if (collapsedView instanceof CollapsibleActionView) { + ((CollapsibleActionView) collapsedView).onActionViewCollapsed(); + } return true; } diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp index 50d9ca1..9be3779 100644 --- a/core/jni/android_media_AudioRecord.cpp +++ b/core/jni/android_media_AudioRecord.cpp @@ -127,7 +127,7 @@ static void recorderCallback(int event, void* user, void *info) { static int android_media_AudioRecord_setup(JNIEnv *env, jobject thiz, jobject weak_this, jint source, jint sampleRateInHertz, jint channels, - jint audioFormat, jint buffSizeInBytes) + jint audioFormat, jint buffSizeInBytes, jintArray jSession) { //LOGV(">> Entering android_media_AudioRecord_setup"); //LOGV("sampleRate=%d, audioFormat=%d, channels=%x, buffSizeInBytes=%d", @@ -162,6 +162,20 @@ android_media_AudioRecord_setup(JNIEnv *env, jobject thiz, jobject weak_this, return AUDIORECORD_ERROR_SETUP_INVALIDSOURCE; } + if (jSession == NULL) { + LOGE("Error creating AudioRecord: invalid session ID pointer"); + return AUDIORECORD_ERROR; + } + + jint* nSession = (jint *) env->GetPrimitiveArrayCritical(jSession, NULL); + if (nSession == NULL) { + LOGE("Error creating AudioRecord: Error retrieving session id pointer"); + return AUDIORECORD_ERROR; + } + int sessionId = nSession[0]; + env->ReleasePrimitiveArrayCritical(jSession, nSession, 0); + nSession = NULL; + audiorecord_callback_cookie *lpCallbackData = NULL; AudioRecord* lpRecorder = NULL; @@ -193,13 +207,24 @@ android_media_AudioRecord_setup(JNIEnv *env, jobject thiz, jobject weak_this, recorderCallback,// callback_t lpCallbackData,// void* user 0, // notificationFrames, - true); // threadCanCallJava) + true, // threadCanCallJava) + sessionId); if(lpRecorder->initCheck() != NO_ERROR) { LOGE("Error creating AudioRecord instance: initialization check failed."); goto native_init_failure; } + nSession = (jint *) env->GetPrimitiveArrayCritical(jSession, NULL); + if (nSession == NULL) { + LOGE("Error creating AudioRecord: Error retrieving session id pointer"); + goto native_init_failure; + } + // read the audio session ID back from AudioTrack in case a new session was created during set() + nSession[0] = lpRecorder->getSessionId(); + env->ReleasePrimitiveArrayCritical(jSession, nSession, 0); + nSession = NULL; + // save our newly created C++ AudioRecord in the "nativeRecorderInJavaObj" field // of the Java object env->SetIntField(thiz, javaAudioRecordFields.nativeRecorderInJavaObj, (int)lpRecorder); @@ -485,7 +510,7 @@ static JNINativeMethod gMethods[] = { // name, signature, funcPtr {"native_start", "()I", (void *)android_media_AudioRecord_start}, {"native_stop", "()V", (void *)android_media_AudioRecord_stop}, - {"native_setup", "(Ljava/lang/Object;IIIII)I", + {"native_setup", "(Ljava/lang/Object;IIIII[I)I", (void *)android_media_AudioRecord_setup}, {"native_finalize", "()V", (void *)android_media_AudioRecord_finalize}, {"native_release", "()V", (void *)android_media_AudioRecord_release}, diff --git a/core/jni/android_net_wifi_Wifi.cpp b/core/jni/android_net_wifi_Wifi.cpp index e930c5c..3cbd912 100644 --- a/core/jni/android_net_wifi_Wifi.cpp +++ b/core/jni/android_net_wifi_Wifi.cpp @@ -28,6 +28,9 @@ #define WIFI_PKG_NAME "android/net/wifi/WifiNative" #define BUF_SIZE 256 +//TODO: This file can be refactored to push a lot of the functionality to java +//with just a few JNI calls - doBoolean/doInt/doString + namespace android { static jboolean sScanModeActive = false; @@ -315,26 +318,56 @@ static jboolean android_net_wifi_stopDriverCommand(JNIEnv* env, jobject) return doBooleanCommand("OK", "DRIVER STOP"); } -static jboolean android_net_wifi_startPacketFiltering(JNIEnv* env, jobject) +/* + Multicast filtering rules work as follows: + + The driver can filter multicast (v4 and/or v6) and broadcast packets when in + a power optimized mode (typically when screen goes off). + + In order to prevent the driver from filtering the multicast/broadcast packets, we have to + add a DRIVER RXFILTER-ADD rule followed by DRIVER RXFILTER-START to make the rule effective + + DRIVER RXFILTER-ADD Num + where Num = 0 - Unicast, 1 - Broadcast, 2 - Mutil4 or 3 - Multi6 + + and DRIVER RXFILTER-START + + In order to stop the usage of these rules, we do + + DRIVER RXFILTER-STOP + DRIVER RXFILTER-REMOVE Num + where Num is as described for RXFILTER-ADD + + The SETSUSPENDOPT driver command overrides the filtering rules +*/ + +static jboolean android_net_wifi_startMultiV4Filtering(JNIEnv* env, jobject) { - return doBooleanCommand("OK", "DRIVER RXFILTER-ADD 0") - && doBooleanCommand("OK", "DRIVER RXFILTER-ADD 1") - && doBooleanCommand("OK", "DRIVER RXFILTER-ADD 3") + return doBooleanCommand("OK", "DRIVER RXFILTER-STOP") + && doBooleanCommand("OK", "DRIVER RXFILTER-REMOVE 2") && doBooleanCommand("OK", "DRIVER RXFILTER-START"); } -static jboolean android_net_wifi_stopPacketFiltering(JNIEnv* env, jobject) +static jboolean android_net_wifi_stopMultiV4Filtering(JNIEnv* env, jobject) { - jboolean result = doBooleanCommand("OK", "DRIVER RXFILTER-STOP"); - if (result) { - (void)doBooleanCommand("OK", "DRIVER RXFILTER-REMOVE 3"); - (void)doBooleanCommand("OK", "DRIVER RXFILTER-REMOVE 1"); - (void)doBooleanCommand("OK", "DRIVER RXFILTER-REMOVE 0"); - } + return doBooleanCommand("OK", "DRIVER RXFILTER-ADD 2") + && doBooleanCommand("OK", "DRIVER RXFILTER-START"); +} - return result; +static jboolean android_net_wifi_startMultiV6Filtering(JNIEnv* env, jobject) +{ + return doBooleanCommand("OK", "DRIVER RXFILTER-STOP") + && doBooleanCommand("OK", "DRIVER RXFILTER-REMOVE 3") + && doBooleanCommand("OK", "DRIVER RXFILTER-START"); +} + +static jboolean android_net_wifi_stopMultiV6Filtering(JNIEnv* env, jobject) +{ + return doBooleanCommand("OK", "DRIVER RXFILTER-ADD 3") + && doBooleanCommand("OK", "DRIVER RXFILTER-START"); } + static jint android_net_wifi_getRssiHelper(const char *cmd) { char reply[BUF_SIZE]; @@ -507,6 +540,35 @@ static void android_net_wifi_setScanIntervalCommand(JNIEnv* env, jobject, jint s } +static jboolean android_net_wifi_doBooleanCommand(JNIEnv* env, jobject, jstring javaCommand) +{ + ScopedUtfChars command(env, javaCommand); + if (command.c_str() == NULL) { + return JNI_FALSE; + } + return doBooleanCommand("OK", "%s", command.c_str()); +} + +static jint android_net_wifi_doIntCommand(JNIEnv* env, jobject, jstring javaCommand) +{ + ScopedUtfChars command(env, javaCommand); + if (command.c_str() == NULL) { + return -1; + } + return doIntCommand("%s", command.c_str()); +} + +static jstring android_net_wifi_doStringCommand(JNIEnv* env, jobject, jstring javaCommand) +{ + ScopedUtfChars command(env, javaCommand); + if (command.c_str() == NULL) { + return NULL; + } + return doStringCommand(env, "%s", command.c_str()); +} + + + // ---------------------------------------------------------------------------- /* @@ -545,8 +607,10 @@ static JNINativeMethod gWifiMethods[] = { { "setScanModeCommand", "(Z)Z", (void*) android_net_wifi_setScanModeCommand }, { "startDriverCommand", "()Z", (void*) android_net_wifi_startDriverCommand }, { "stopDriverCommand", "()Z", (void*) android_net_wifi_stopDriverCommand }, - { "startPacketFiltering", "()Z", (void*) android_net_wifi_startPacketFiltering }, - { "stopPacketFiltering", "()Z", (void*) android_net_wifi_stopPacketFiltering }, + { "startFilteringMulticastV4Packets", "()Z", (void*) android_net_wifi_startMultiV4Filtering}, + { "stopFilteringMulticastV4Packets", "()Z", (void*) android_net_wifi_stopMultiV4Filtering}, + { "startFilteringMulticastV6Packets", "()Z", (void*) android_net_wifi_startMultiV6Filtering}, + { "stopFilteringMulticastV6Packets", "()Z", (void*) android_net_wifi_stopMultiV6Filtering}, { "setPowerModeCommand", "(I)Z", (void*) android_net_wifi_setPowerModeCommand }, { "getPowerModeCommand", "()I", (void*) android_net_wifi_getPowerModeCommand }, { "setBandCommand", "(I)Z", (void*) android_net_wifi_setBandCommand}, @@ -576,6 +640,9 @@ static JNINativeMethod gWifiMethods[] = { (void*) android_net_wifi_setCountryCodeCommand}, { "enableBackgroundScanCommand", "(Z)V", (void*) android_net_wifi_enableBackgroundScanCommand}, { "setScanIntervalCommand", "(I)V", (void*) android_net_wifi_setScanIntervalCommand}, + { "doBooleanCommand", "(Ljava/lang/String;)Z", (void*) android_net_wifi_doBooleanCommand}, + { "doIntCommand", "(Ljava/lang/String;)I", (void*) android_net_wifi_doIntCommand}, + { "doStringCommand", "(Ljava/lang/String;)Ljava/lang/String;", (void*) android_net_wifi_doStringCommand}, }; int register_android_net_wifi_WifiManager(JNIEnv* env) diff --git a/core/jni/android_os_SystemClock.cpp b/core/jni/android_os_SystemClock.cpp index ffd0c1e..66d58cd 100644 --- a/core/jni/android_os_SystemClock.cpp +++ b/core/jni/android_os_SystemClock.cpp @@ -80,6 +80,38 @@ static jlong android_os_SystemClock_currentThreadTimeMillis(JNIEnv* env, } /* + * native public static long currentThreadTimeMicro(); + */ +static jlong android_os_SystemClock_currentThreadTimeMicro(JNIEnv* env, + jobject clazz) +{ +#if defined(HAVE_POSIX_CLOCKS) + struct timespec tm; + + clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tm); + + return tm.tv_sec * 1000000LL + tm.tv_nsec / 1000; +#else + struct timeval tv; + + gettimeofday(&tv, NULL); + return tv.tv_sec * 1000000LL + tv.tv_nsec / 1000; +#endif +} + +/* + * native public static long currentTimeMicro(); + */ +static jlong android_os_SystemClock_currentTimeMicro(JNIEnv* env, + jobject clazz) +{ + struct timeval tv; + + gettimeofday(&tv, NULL); + return tv.tv_sec * 1000000LL + tv.tv_usec; +} + +/* * JNI registration. */ static JNINativeMethod gMethods[] = { @@ -92,6 +124,10 @@ static JNINativeMethod gMethods[] = { (void*) android_os_SystemClock_elapsedRealtime }, { "currentThreadTimeMillis", "()J", (void*) android_os_SystemClock_currentThreadTimeMillis }, + { "currentThreadTimeMicro", "()J", + (void*) android_os_SystemClock_currentThreadTimeMicro }, + { "currentTimeMicro", "()J", + (void*) android_os_SystemClock_currentTimeMicro }, }; int register_android_os_SystemClock(JNIEnv* env) { diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp index b0c2f2c..b06de9d 100644 --- a/core/jni/android_view_GLES20Canvas.cpp +++ b/core/jni/android_view_GLES20Canvas.cpp @@ -576,18 +576,18 @@ static void android_view_GLES20Canvas_drawTextRun(JNIEnv* env, jobject clazz, // ---------------------------------------------------------------------------- static DisplayList* android_view_GLES20Canvas_getDisplayList(JNIEnv* env, - jobject clazz, DisplayListRenderer* renderer) { - return renderer->getDisplayList(); + jobject clazz, DisplayListRenderer* renderer, DisplayList* displayList) { + return renderer->getDisplayList(displayList); +} + +static OpenGLRenderer* android_view_GLES20Canvas_createDisplayListRenderer(JNIEnv* env, + jobject clazz) { + return new DisplayListRenderer; } -static OpenGLRenderer* android_view_GLES20Canvas_getDisplayListRenderer(JNIEnv* env, +static void android_view_GLES20Canvas_resetDisplayListRenderer(JNIEnv* env, jobject clazz, DisplayListRenderer* renderer) { - if (renderer == NULL) { - renderer = new DisplayListRenderer; - } else { - renderer->reset(); - } - return renderer; + renderer->reset(); } static void android_view_GLES20Canvas_destroyDisplayList(JNIEnv* env, @@ -812,9 +812,10 @@ static JNINativeMethod gMethods[] = { { "nGetClipBounds", "(ILandroid/graphics/Rect;)Z", (void*) android_view_GLES20Canvas_getClipBounds }, - { "nGetDisplayList", "(I)I", (void*) android_view_GLES20Canvas_getDisplayList }, + { "nGetDisplayList", "(II)I", (void*) android_view_GLES20Canvas_getDisplayList }, { "nDestroyDisplayList", "(I)V", (void*) android_view_GLES20Canvas_destroyDisplayList }, - { "nGetDisplayListRenderer", "(I)I", (void*) android_view_GLES20Canvas_getDisplayListRenderer }, + { "nCreateDisplayListRenderer", "()I", (void*) android_view_GLES20Canvas_createDisplayListRenderer }, + { "nResetDisplayListRenderer", "(I)V", (void*) android_view_GLES20Canvas_resetDisplayListRenderer }, { "nDrawDisplayList", "(IIIILandroid/graphics/Rect;)Z", (void*) android_view_GLES20Canvas_drawDisplayList }, { "nOutputDisplayList", "(II)V", (void*) android_view_GLES20Canvas_outputDisplayList }, diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 290f049..91003d1 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -300,15 +300,6 @@ android:label="@string/permlab_readWriteOwnVoicemail" android:description="@string/permdesc_readWriteOwnVoicemail" /> - <!-- Allows an application to read/write all voicemails. In order to be able - access all voicemails, this permission is needed in *addition* to - READ_WRITE_OWN_VOICEMAIL. --> - <permission android:name="com.android.voicemail.permission.READ_WRITE_ALL_VOICEMAIL" - android:permissionGroup="android.permission-group.PERSONAL_INFO" - android:protectionLevel="signature" - android:label="@string/permlab_readWriteAllVoicemail" - android:description="@string/permdesc_readWriteAllVoicemail" /> - <!-- ======================================= --> <!-- Permissions for accessing location info --> <!-- ======================================= --> @@ -1129,6 +1120,13 @@ android:description="@string/permdesc_bindInputMethod" android:protectionLevel="signature" /> + <!-- Must be required by a TextService (e.g. SpellCheckerService) + to ensure that only the system can bind to it. --> + <permission android:name="android.permission.BIND_TEXT_SERVICE" + android:label="@string/permlab_bindTextService" + android:description="@string/permdesc_bindTextService" + android:protectionLevel="signature" /> + <!-- Must be required by a {@link android.service.wallpaper.WallpaperService}, to ensure that only the system can bind to it. --> <permission android:name="android.permission.BIND_WALLPAPER" @@ -1206,7 +1204,7 @@ <permission android:name="android.permission.READ_FRAME_BUFFER" android:label="@string/permlab_readFrameBuffer" android:description="@string/permdesc_readFrameBuffer" - android:protectionLevel="signature" /> + android:protectionLevel="signatureOrSystem" /> <!-- Required to be able to disable the device (very dangerous!). --> <permission android:name="android.permission.BRICK" diff --git a/core/res/res/anim/screen_rotate_minus_90_enter.xml b/core/res/res/anim/screen_rotate_minus_90_enter.xml index 30518e0..61aa72a 100644 --- a/core/res/res/anim/screen_rotate_minus_90_enter.xml +++ b/core/res/res/anim/screen_rotate_minus_90_enter.xml @@ -19,11 +19,6 @@ <set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false"> - <scale android:fromXScale="100%p" android:toXScale="100%" - android:fromYScale="100%p" android:toYScale="100%" - android:pivotX="50%" android:pivotY="50%" - android:interpolator="@interpolator/decelerate_quint" - android:duration="@android:integer/config_mediumAnimTime" /> <rotate android:fromDegrees="-90" android:toDegrees="0" android:pivotX="50%" android:pivotY="50%" android:interpolator="@interpolator/decelerate_quint" diff --git a/core/res/res/anim/screen_rotate_plus_90_enter.xml b/core/res/res/anim/screen_rotate_plus_90_enter.xml index 20943c8..53b0ccd 100644 --- a/core/res/res/anim/screen_rotate_plus_90_enter.xml +++ b/core/res/res/anim/screen_rotate_plus_90_enter.xml @@ -19,11 +19,6 @@ <set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false"> - <scale android:fromXScale="100%p" android:toXScale="100%" - android:fromYScale="100%p" android:toYScale="100%" - android:pivotX="50%" android:pivotY="50%" - android:interpolator="@interpolator/decelerate_quint" - android:duration="@android:integer/config_mediumAnimTime" /> <rotate android:fromDegrees="90" android:toDegrees="0" android:pivotX="50%" android:pivotY="50%" android:interpolator="@interpolator/decelerate_quint" diff --git a/core/res/res/drawable-hdpi/text_edit_suggestions_top_window.9.png b/core/res/res/drawable-hdpi/text_edit_suggestions_top_window.9.png Binary files differdeleted file mode 100644 index ff6b34a..0000000 --- a/core/res/res/drawable-hdpi/text_edit_suggestions_top_window.9.png +++ /dev/null diff --git a/core/res/res/drawable-hdpi/text_edit_suggestions_bottom_window.9.png b/core/res/res/drawable-hdpi/text_edit_suggestions_window.9.png Binary files differindex c97514f..c97514f 100644 --- a/core/res/res/drawable-hdpi/text_edit_suggestions_bottom_window.9.png +++ b/core/res/res/drawable-hdpi/text_edit_suggestions_window.9.png diff --git a/core/res/res/drawable-mdpi/text_edit_suggestions_top_window.9.png b/core/res/res/drawable-mdpi/text_edit_suggestions_top_window.9.png Binary files differdeleted file mode 100644 index 41886eb..0000000 --- a/core/res/res/drawable-mdpi/text_edit_suggestions_top_window.9.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/text_edit_suggestions_bottom_window.9.png b/core/res/res/drawable-mdpi/text_edit_suggestions_window.9.png Binary files differindex 88be6e1..88be6e1 100644 --- a/core/res/res/drawable-mdpi/text_edit_suggestions_bottom_window.9.png +++ b/core/res/res/drawable-mdpi/text_edit_suggestions_window.9.png diff --git a/core/res/res/layout/text_edit_suggestion_item.xml b/core/res/res/layout/text_edit_suggestion_item.xml index ef537d9..082c5ec 100644 --- a/core/res/res/layout/text_edit_suggestion_item.xml +++ b/core/res/res/layout/text_edit_suggestion_item.xml @@ -22,6 +22,8 @@ android:paddingTop="8dip" android:paddingBottom="8dip" android:layout_gravity="left|center_vertical" + android:singleLine="true" + android:ellipsize="marquee" android:textAppearance="?android:attr/textAppearanceMedium" android:textColor="@android:color/dim_foreground_light" /> diff --git a/core/res/res/layout/text_edit_suggestions_top_window.xml b/core/res/res/layout/text_edit_suggestions_window.xml index 67faa37..824025e 100644 --- a/core/res/res/layout/text_edit_suggestions_top_window.xml +++ b/core/res/res/layout/text_edit_suggestions_window.xml @@ -18,6 +18,6 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" - android:background="@android:drawable/text_edit_suggestions_top_window"> + android:background="@android:drawable/text_edit_suggestions_window"> </LinearLayout> diff --git a/core/res/res/layout/text_edit_suggestions_bottom_window.xml b/core/res/res/layout/wifi_p2p_go_negotiation_request_alert.xml index 588bfbd..41ca657 100644 --- a/core/res/res/layout/text_edit_suggestions_bottom_window.xml +++ b/core/res/res/layout/wifi_p2p_go_negotiation_request_alert.xml @@ -4,9 +4,9 @@ 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. @@ -16,8 +16,11 @@ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:orientation="vertical" - android:background="@android:drawable/text_edit_suggestions_bottom_window"> + android:layout_height="wrap_content"> + <EditText android:id="@+id/wifi_p2p_wps_pin" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:inputType="textPassword" + /> </LinearLayout> diff --git a/core/res/res/values-sw600dp/bools.xml b/core/res/res/values-sw600dp/bools.xml index d73ff99..a453ac1 100644 --- a/core/res/res/values-sw600dp/bools.xml +++ b/core/res/res/values-sw600dp/bools.xml @@ -17,4 +17,5 @@ <resources> <bool name="preferences_prefer_dual_pane">true</bool> <bool name="show_ongoing_ime_switcher">false</bool> + <bool name="action_bar_expanded_action_views_exclusive">false</bool> </resources> diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 082284a..7d7aea9 100755 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -713,10 +713,7 @@ <!-- Layout of a the view that is used to create the text suggestions popup window in an EditText. This window will be displayed below the text line. --> - <attr name="textEditSuggestionsBottomWindowLayout" format="reference" /> - <!-- Same as textEditSuggestionsBottomWindowLayout, but used when the popup is displayed - above the current line of text instead of below. --> - <attr name="textEditSuggestionsTopWindowLayout" format="reference" /> + <attr name="textEditSuggestionsWindowLayout" format="reference" /> <!-- Layout of the TextView item that will populate the suggestion popup window. --> <attr name="textEditSuggestionItemLayout" format="reference" /> @@ -3082,10 +3079,7 @@ <!-- Layout of a the view that is used to create the text suggestions popup window in an EditText. This window will be displayed below the text line. --> - <attr name="textEditSuggestionsBottomWindowLayout" /> - <!-- Same as textEditSuggestionsBottomWindowLayout, but used when the popup is displayed - above the current line of text instead of below. --> - <attr name="textEditSuggestionsTopWindowLayout" /> + <attr name="textEditSuggestionsWindowLayout" /> <!-- Layout of the TextView item that will populate the suggestion popup window. --> <attr name="textEditSuggestionItemLayout" /> diff --git a/core/res/res/values/bools.xml b/core/res/res/values/bools.xml index e51fc66..6e4db5e 100644 --- a/core/res/res/values/bools.xml +++ b/core/res/res/values/bools.xml @@ -19,4 +19,5 @@ <bool name="split_action_bar_is_narrow">true</bool> <bool name="preferences_prefer_dual_pane">false</bool> <bool name="show_ongoing_ime_switcher">true</bool> + <bool name="action_bar_expanded_action_views_exclusive">true</bool> </resources> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 215700c..2b2f356 100755 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -182,6 +182,9 @@ <!-- Boolean indicating whether the wifi chipset has dual frequency band support --> <bool translatable="false" name="config_wifi_dual_band_support">false</bool> + <!-- Boolean indicating whether the wifi chipset has p2p support --> + <bool translatable="false" name="config_wifi_p2p_support">false</bool> + <!-- Boolean indicating whether the wifi chipset supports background scanning mechanism. This mechanism allows the host to remain in suspend state and the dongle to actively scan and wake the host when a configured SSID is detected by the dongle. This chipset diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index ba2a036..b2b7025 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -1715,12 +1715,9 @@ <public type="attr" name="switchPreferenceStyle" /> <public type="attr" name="textSuggestionsWindowStyle" /> - <public type="attr" name="textEditSuggestionsBottomWindowLayout" /> - <public type="attr" name="textEditSuggestionsTopWindowLayout" /> + <public type="attr" name="textEditSuggestionsWindowLayout" /> <public type="attr" name="textEditSuggestionItemLayout" /> - <public type="attr" name="layoutDirection" /> - <public type="attr" name="suggestionsEnabled" /> <public type="attr" name="rowCount" /> @@ -1765,15 +1762,8 @@ <public type="attr" name="listPreferredItemHeightLarge" /> <public type="attr" name="listPreferredItemHeightSmall" /> - <public type="attr" name="paddingStart"/> - <public type="attr" name="paddingEnd"/> - <public type="attr" name="layout_marginStart"/> - <public type="attr" name="layout_marginEnd"/> - <public type="attr" name="actionBarSplitStyle" /> - <public type="attr" name="textDirection"/> - <public type="attr" name="actionProviderClass" /> <public type="attr" name="backgroundStacked" /> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 64f7316..e1a31f4 100755 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -705,6 +705,12 @@ interface of an input method. Should never be needed for normal applications.</string> <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> + <string name="permlab_bindTextService">bind to a text service</string> + <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> + <string name="permdesc_bindTextService">Allows the holder to bind to the top-level + interface of a text service(e.g. SpellCheckerService). Should never be needed for normal applications.</string> + + <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permlab_bindWallpaper">bind to a wallpaper</string> <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permdesc_bindWallpaper">Allows the holder to bind to the top-level @@ -2160,14 +2166,6 @@ voicemails that its associated service can access.</string> <!-- Title of an application permission, listed so the user can choose whether - they want to allow the application to do this. [CHAR LIMIT=NONE] --> - <string name="permlab_readWriteAllVoicemail">Access all voicemails</string> - <!-- Description of an application permission, listed so the user can choose whether - they want to allow the application to do this. [CHAR LIMIT=NONE] --> - <string name="permdesc_readWriteAllVoicemail">Allows the application to store and retrieve all - voicemails that this device can access.</string> - - <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permlab_writeGeolocationPermissions">Modify Browser geolocation permissions</string> <!-- Description of an application permission, listed so the user can choose whether @@ -2576,9 +2574,23 @@ <item quantity="one">Open Wi-Fi network available</item> <item quantity="other">Open Wi-Fi networks available</item> </plurals> + + <!-- A notification is shown the first time a wireless network is disabled due to bad connectivity. This is the notification's title / ticker. --> + <string name="wifi_watchdog_network_disabled">A Wi-Fi network was disabled</string> + <!-- A notification is shown the first time a wireless network is disabled due to bad connectivity. This is the notification's message which leads to the settings pane --> + <string name="wifi_watchdog_network_disabled_detailed">A Wi-Fi network was temporarily disabled due to bad connectivity.</string> + <!-- Do not translate. Default access point SSID used for tethering --> <string name="wifi_tether_configure_ssid_default" translatable="false">AndroidAP</string> + <!-- Wi-Fi p2p dialog title--> + <string name="wifi_p2p_dialog_title">Wi-Fi Direct</string> + <string name="wifi_p2p_turnon_message">Start Wi-Fi Direct operation. This will turn off Wi-Fi client/hotspot operation.</string> + <string name="wifi_p2p_failed_message">Failed to start Wi-Fi Direct</string> + <string name="wifi_p2p_pbc_go_negotiation_request_message">Wi-Fi Direct connection setup request from <xliff:g id="p2p_device_address">%1$s</xliff:g>. Click OK to accept. </string> + <string name="wifi_p2p_pin_go_negotiation_request_message">Wi-Fi Direct connection setup request from <xliff:g id="p2p_device_address">%1$s</xliff:g>. Enter pin to proceed. </string> + <string name="wifi_p2p_pin_display_message">WPS pin <xliff:g id="p2p_wps_pin">%1$s</xliff:g> needs to be entered on the peer device <xliff:g id="p2p_client_address">%2$s</xliff:g> for connection setup to proceed </string> + <!-- Name of the dialog that lets the user choose an accented character to insert --> <string name="select_character">Insert character</string> @@ -2677,12 +2689,14 @@ <!-- USB_STORAGE_ERROR dialog ok button--> <string name="dlg_ok">OK</string> - <!-- USB_PREFERENCES: Notification for wehen the user connects the phone to a computer via USB in MTP mode. This is the title --> + <!-- USB_PREFERENCES: Notification for when the user connects the phone to a computer via USB in MTP mode. This is the title --> <string name="usb_mtp_notification_title">Connected as a media device</string> - <!-- USB_PREFERENCES: Notification for wehen the user connects the phone to a computer via USB in PTP mode. This is the title --> + <!-- USB_PREFERENCES: Notification for when the user connects the phone to a computer via USB in PTP mode. This is the title --> <string name="usb_ptp_notification_title">Connected as a camera</string> - <!-- USB_PREFERENCES: Notification for wehen the user connects the phone to a computer via USB in mass storage mode (for installer CD image). This is the title --> + <!-- USB_PREFERENCES: Notification for when the user connects the phone to a computer via USB in mass storage mode (for installer CD image). This is the title --> <string name="usb_cd_installer_notification_title">Connected as an installer</string> + <!-- USB_PREFERENCES: Notification for when a USB accessory is attached. This is the title --> + <string name="usb_accessory_notification_title">Connected to a USB accessory</string> <!-- See USB_PREFERENCES. This is the message. --> <string name="usb_notification_message">Touch for other USB options</string> @@ -3058,4 +3072,9 @@ <!-- Title for a dialog showing possible activities for sharing in ShareActionProvider [CHAR LIMIT=25] --> <string name="share_action_provider_share_with">Share with...</string> + <!-- Status Bar icon descriptions --> + + <!-- Description of for the status bar's icon that the device is locked for accessibility. [CHAR LIMIT=NONE] --> + <string name="status_bar_device_locked">Device locked.</string> + </resources> diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml index d647467..9b6c442 100644 --- a/core/res/res/values/styles.xml +++ b/core/res/res/values/styles.xml @@ -423,8 +423,7 @@ <item name="android:textEditNoPasteWindowLayout">?android:attr/textEditNoPasteWindowLayout</item> <item name="android:textEditSidePasteWindowLayout">?android:attr/textEditSidePasteWindowLayout</item> <item name="android:textEditSideNoPasteWindowLayout">?android:attr/textEditSideNoPasteWindowLayout</item> - <item name="android:textEditSuggestionsBottomWindowLayout">?android:attr/textEditSuggestionsBottomWindowLayout</item> - <item name="android:textEditSuggestionsTopWindowLayout">?android:attr/textEditSuggestionsTopWindowLayout</item> + <item name="android:textEditSuggestionsWindowLayout">?android:attr/textEditSuggestionsWindowLayout</item> <item name="android:textEditSuggestionItemLayout">?android:attr/textEditSuggestionItemLayout</item> <item name="android:textCursorDrawable">?android:attr/textCursorDrawable</item> </style> diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml index 90f3602..93ccfe3 100644 --- a/core/res/res/values/themes.xml +++ b/core/res/res/values/themes.xml @@ -190,8 +190,7 @@ <item name="textEditSidePasteWindowLayout">@android:layout/text_edit_side_paste_window</item> <item name="textEditSideNoPasteWindowLayout">@android:layout/text_edit_side_no_paste_window</item> <item name="textSuggestionsWindowStyle">@android:style/Widget.TextSuggestions</item> - <item name="textEditSuggestionsBottomWindowLayout">@android:layout/text_edit_suggestions_bottom_window</item> - <item name="textEditSuggestionsTopWindowLayout">@android:layout/text_edit_suggestions_top_window</item> + <item name="textEditSuggestionsWindowLayout">@android:layout/text_edit_suggestions_window</item> <item name="textEditSuggestionItemLayout">@android:layout/text_edit_suggestion_item</item> <item name="textCursorDrawable">@null</item> diff --git a/core/tests/coretests/src/android/util/JsonReaderTest.java b/core/tests/coretests/src/android/util/JsonReaderTest.java index 0b50af3..42b7640 100644 --- a/core/tests/coretests/src/android/util/JsonReaderTest.java +++ b/core/tests/coretests/src/android/util/JsonReaderTest.java @@ -857,11 +857,32 @@ public final class JsonReaderTest extends TestCase { } } + public void testBomIgnoredAsFirstCharacterOfDocument() throws IOException { + JsonReader reader = new JsonReader(new StringReader("\ufeff[]")); + reader.beginArray(); + reader.endArray(); + } + + public void testBomForbiddenAsOtherCharacterInDocument() throws IOException { + JsonReader reader = new JsonReader(new StringReader("[\ufeff]")); + reader.beginArray(); + try { + reader.endArray(); + fail(); + } catch (IOException expected) { + } + } + public void testFailWithPosition() throws IOException { testFailWithPosition("Expected literal value at line 6 column 3", "[\n\n\n\n\n0,}]"); } + public void testFailWithPositionIsOffsetByBom() throws IOException { + testFailWithPosition("Expected literal value at line 1 column 4", + "\ufeff[0,}]"); + } + public void testFailWithPositionGreaterThanBufferSize() throws IOException { String spaces = repeat(' ', 8192); testFailWithPosition("Expected literal value at line 6 column 3", diff --git a/docs/html/guide/appendix/api-levels.jd b/docs/html/guide/appendix/api-levels.jd index 5c18a83..7a0e17f 100644 --- a/docs/html/guide/appendix/api-levels.jd +++ b/docs/html/guide/appendix/api-levels.jd @@ -82,20 +82,71 @@ API Level 1 and subsequent releases have incremented the API Level.</p> Android platform.</p> <table> - <tr><th>Platform Version</th><th>API Level</th></tr> - <tr><td>Android 3.1</td><td>12</td></tr> - <tr><td>Android 3.0</td><td>11</td></tr> - <tr><td>Android 2.3.4</td><td rowspan="2">10</td></tr> - <tr><td>Android 2.3.3</td></tr> - <tr><td>Android 2.3</td><td>9</td></tr> - <tr><td>Android 2.2</td><td>8</td></tr> - <tr><td>Android 2.1</td><td>7</td></tr> - <tr><td>Android 2.0.1</td><td>6</td></tr> - <tr><td>Android 2.0</td><td>5</td></tr> - <tr><td>Android 1.6</td><td>4</td></tr> - <tr><td>Android 1.5</td><td>3</td></tr> - <tr><td>Android 1.1</td><td>2</td></tr> - <tr><td>Android 1.0</td><td>1</td></tr> + <tr><th>Platform Version</th><th>API Level</th><th>VERSION_CODE</th><th>Notes</th></tr> + + <tr><td><a href="{@docRoot}sdk/android-3.2.html">Android 3.2</a></td> + <td><a href="{@docRoot}sdk/api_diff/13/changes.html" title="Diff Report">13</a></td> + <td>{@link android.os.Build.VERSION_CODES#HONEYCOMB_MR2}</td> + <td><!-- <a href="{@docRoot}sdk/android-3.2-highlights.html">Platform Highlights</a>--></td></tr> + + <tr><td><a href="{@docRoot}sdk/android-3.1.html">Android 3.1.x</a></td> + <td><a href="{@docRoot}sdk/api_diff/12/changes.html" title="Diff Report">12</a></td> + <td>{@link android.os.Build.VERSION_CODES#HONEYCOMB_MR1}</td> + <td><a href="{@docRoot}sdk/android-3.1-highlights.html">Platform Highlights</a></td></tr> + + <tr><td><a href="{@docRoot}sdk/android-3.0.html">Android 3.0.x</td> + <td><a href="{@docRoot}sdk/api_diff/11/changes.html" title="Diff Report">11</a></td> + <td>{@link android.os.Build.VERSION_CODES#HONEYCOMB}</td> + <td><a href="{@docRoot}sdk/android-3.0-highlights.html">Platform Highlights</a></td></tr> + + <tr><td><a href="{@docRoot}sdk/android-2.3.3.html">Android 2.3.4<br>Android 2.3.3</td> + <td><a href="{@docRoot}sdk/api_diff/10/changes.html" title="Diff Report">10</a></td> + <td>{@link android.os.Build.VERSION_CODES#GINGERBREAD_MR1}</td> + <td rowspan="2"><a href="{@docRoot}sdk/android-2.3-highlights.html">Platform Highlights</a></td></tr> + + <tr><td><a href="{@docRoot}sdk/android-2.3.html">Android 2.3.2<br>Android 2.3.1<br>Android 2.3</td> + <td><a href="{@docRoot}sdk/api_diff/9/changes.html" title="Diff Report">9</a></td> + <td>{@link android.os.Build.VERSION_CODES#GINGERBREAD}</td> + </tr> + + <tr><td><a href="{@docRoot}sdk/android-2.2.html">Android 2.2.x</td> + <td ><a href="{@docRoot}sdk/api_diff/8/changes.html" title="Diff Report">8</a></td> + <td>{@link android.os.Build.VERSION_CODES#FROYO}</td> + <td><a href="{@docRoot}sdk/android-2.2-highlights.html">Platform Highlights</a></td></tr> + + <tr><td><a href="{@docRoot}sdk/android-2.1.html">Android 2.1.x</td> + <td><a href="{@docRoot}sdk/api_diff/7/changes.html" title="Diff Report">7</a></td> + <td>{@link android.os.Build.VERSION_CODES#ECLAIR_MR1}</td> + <td rowspan="3" ><a href="{@docRoot}sdk/android-2.0-highlights.html">Platform Highlights</a></td></tr> + + <tr><td><a href="{@docRoot}sdk/android-2.0.1.html">Android 2.0.1</td> + <td><a href="{@docRoot}sdk/api_diff/6/changes.html" title="Diff Report">6</a></td> + <td>{@link android.os.Build.VERSION_CODES#ECLAIR_0_1}</td> + </tr> + + <tr><td><a href="{@docRoot}sdk/android-2.0.html">Android 2.0</td> + <td><a href="{@docRoot}sdk/api_diff/5/changes.html" title="Diff Report">5</a></td> + <td>{@link android.os.Build.VERSION_CODES#ECLAIR}</td> + </tr> + + <tr><td><a href="{@docRoot}sdk/android-1.6.html">Android 1.6</td> + <td><a href="{@docRoot}sdk/api_diff/4/changes.html" title="Diff Report">4</a></td> + <td>{@link android.os.Build.VERSION_CODES#DONUT}</td> + <td><a href="{@docRoot}sdk/android-1.6-highlights.html">Platform Highlights</a></td></tr> + + <tr><td><a href="{@docRoot}sdk/android-1.5.html">Android 1.5</td> + <td><a href="{@docRoot}sdk/api_diff/3/changes.html" title="Diff Report">3</a></td> + <td>{@link android.os.Build.VERSION_CODES#CUPCAKE}</td> + <td><a href="{@docRoot}sdk/android-1.5-highlights.html">Platform Highlights</a></td></tr> + + <tr><td><a href="{@docRoot}sdk/android-1.1.html">Android 1.1</td> + <td>2</td> + <td>{@link android.os.Build.VERSION_CODES#BASE_1_1}</td><td></td></tr> + + <tr><td><a href="{@docRoot}sdk/android-1.0.html">Android 1.0</td> + <td>1</td> + <td>{@link android.os.Build.VERSION_CODES#BASE}</td> + <td></td></tr> </table> diff --git a/docs/html/guide/developing/tools/adb.jd b/docs/html/guide/developing/tools/adb.jd index 78d12ef..d32cf66 100644 --- a/docs/html/guide/developing/tools/adb.jd +++ b/docs/html/guide/developing/tools/adb.jd @@ -280,7 +280,7 @@ instance, see <a href="{@docRoot}guide/developing/building/index.html">Building <td>Run PPP over USB. <ul> <li><code><tty></code> — the tty for PPP stream. For example <code>dev:/dev/omap_csmi_ttyl</code>. </li> -<li><code>[parm]... </code> &mdash zero or more PPP/PPPD options, such as <code>defaultroute</code>, <code>local</code>, <code>notty</code>, etc.</li></ul> +<li><code>[parm]... </code> — zero or more PPP/PPPD options, such as <code>defaultroute</code>, <code>local</code>, <code>notty</code>, etc.</li></ul> <p>Note that you should not automatically start a PPP connection. </p></td> <td></td> diff --git a/docs/html/guide/topics/intents/intents-filters.jd b/docs/html/guide/topics/intents/intents-filters.jd index 5905214..3f94553 100644 --- a/docs/html/guide/topics/intents/intents-filters.jd +++ b/docs/html/guide/topics/intents/intents-filters.jd @@ -927,7 +927,7 @@ as described by its two intent filters: <p> The first, primary, purpose of this activity is to enable the user to -interact with a single note &mdash to either {@code VIEW} the note or +interact with a single note — to either {@code VIEW} the note or {@code EDIT} it. (The {@code EDIT_NOTE} category is a synonym for {@code EDIT}.) The intent would contain the URI for data matching the MIME type <code>vnd.android.cursor.item/vnd.google.note</code> — diff --git a/docs/html/guide/topics/manifest/activity-element.jd b/docs/html/guide/topics/manifest/activity-element.jd index 3486212..743832c 100644 --- a/docs/html/guide/topics/manifest/activity-element.jd +++ b/docs/html/guide/topics/manifest/activity-element.jd @@ -710,7 +710,7 @@ the soft keyboard.</li> The setting must be one of the values listed in the following table, or a combination of one "{@code state...}" value plus one "{@code adjust...}" value. Setting multiple values in either group — multiple -"{@code state...}" values, for example &mdash has undefined results. +"{@code state...}" values, for example — has undefined results. Individual values are separated by a vertical bar ({@code |}). For example: </p> @@ -801,4 +801,4 @@ Level 3.</dd> <dt>see also:</dt> <dd><code><a href="{@docRoot}guide/topics/manifest/application-element.html"><application></a></code> <br/><code><a href="{@docRoot}guide/topics/manifest/activity-alias-element.html"><activity-alias></a></code></dd> -</dl>
\ No newline at end of file +</dl> diff --git a/docs/html/guide/topics/providers/content-providers.jd b/docs/html/guide/topics/providers/content-providers.jd index 2a84c26..513886a 100644 --- a/docs/html/guide/topics/providers/content-providers.jd +++ b/docs/html/guide/topics/providers/content-providers.jd @@ -277,7 +277,7 @@ are returned. All the content providers that come with the platform define constants for their columns. For example, the {@link android.provider.Contacts.Phones android.provider.Contacts.Phones} class defines constants for the names of the columns in the phone table illustrated -earlier &mdash {@code _ID}, {@code NUMBER}, {@code NUMBER_KEY}, {@code NAME}, +earlier — {@code _ID}, {@code NUMBER}, {@code NUMBER_KEY}, {@code NAME}, and so on.</li> <li><p>A filter detailing which rows to return, formatted as an SQL {@code WHERE} diff --git a/docs/html/sdk/android-3.1.jd b/docs/html/sdk/android-3.1.jd index 992b7d1..1614722 100644 --- a/docs/html/sdk/android-3.1.jd +++ b/docs/html/sdk/android-3.1.jd @@ -19,14 +19,14 @@ sdk.platform.apiLevel=12 <h2>Reference</h2> <ol> <li><a -href="{@docRoot}sdk/api_diff/11/changes.html">API +href="{@docRoot}sdk/api_diff/12/changes.html">API Differences Report »</a> </li> </ol> <h2>See Also</h2> <ol> <li><a href="{@docRoot}guide/practices/optimizing-for-3.0.html">Optimizing -Apps for Android 3.0</a></li> +Apps for Android 3.x</a></li> </ol> </div> @@ -765,7 +765,7 @@ was upgraded while it was in started state (not in a stopped state).</p></li> </ul> -<h3 if="other">Core utilities</h3> +<h3 id="other">Core utilities</h3> <ul> <li>LRU cache diff --git a/docs/html/sdk/android-3.2.jd b/docs/html/sdk/android-3.2.jd new file mode 100644 index 0000000..5618eae --- /dev/null +++ b/docs/html/sdk/android-3.2.jd @@ -0,0 +1,737 @@ +page.title=Android 3.2 Platform +sdk.platform.version=3.2 +sdk.platform.apiLevel=13 +@jd:body + +<div id="qv-wrapper"> +<div id="qv"> + +<h2>In this document</h2> +<ol> + <li><a href="#relnotes">Revisions</a></li> + <li><a href="#highlights">Highlights</a></li> + <li><a href="#api">API Overview</a></li> + <li><a href="#api-level">API Level</a></li> + <li><a href="#apps">Built-in Applications</a></li> + <li><a href="#locs">Locales</a></li> + <li><a href="#skins">Emulator Skins</a></li> +</ol> + +<h2>Reference</h2> +<ol> +<li><a +href="{@docRoot}sdk/api_diff/13/changes.html">API +Differences Report »</a> </li> +</ol> + +<h2>See Also</h2> +<ol> + <li><a href="{@docRoot}guide/practices/screens_support.html">Supporting + Multiple Screens</a></li> + <li><a href="{@docRoot}guide/practices/optimizing-for-3.0.html">Optimizing +Apps for Android 3.x</a></li> +</ol> + +</div> +</div> + + +<p><em>API Level:</em> <strong>{@sdkPlatformApiLevel}</strong></p> + +<p>Welcome to Android 3.2!</p> + +<p>Android 3.2 is an incremental platform release that adds new +capabilities for users and developers. The sections below provide an overview +of the new features and developer APIs.</p> + +<p>For developers, the Android {@sdkPlatformVersion} platform is available as a +downloadable component for the Android SDK. The downloadable platform includes +an Android library and system image, as well as a set of emulator skins and +more. The downloadable platform includes no external libraries.</p> + +<p>To get started developing or testing against Android {@sdkPlatformVersion}, +use the Android SDK Manager to download the platform into your SDK. For more +information, see <a href="{@docRoot}sdk/adding-components.html">Adding SDK +Components</a>. If you are new to Android, <a +href="{@docRoot}sdk/index.html">download the SDK Starter Package</a> first.</p> + +<p class="note"><strong>Reminder:</strong> If you've already published an +Android application, please test and optimize your application on Android 3.2 as +soon as possible. You should do so to be sure your application provides the best +experience possible on the latest Android-powered devices. For information about +what you can do, read <a +href="{@docRoot}guide/practices/optimizing-for-3.0.html">Optimizing Apps for +Android 3.x</a>.</p> + + +<h2 id="relnotes">Revisions</h2> + +<p>To determine what revision of the Android {@sdkPlatformVersion} platform you +have installed, refer to the "Installed Packages" listing in the Android SDK and +AVD Manager.</p> + + +<div class="toggle-content opened" style="padding-left:1em;"> + + <p><a href="#" onclick="return toggleContent(this)"> + <img src="{@docRoot}assets/images/triangle-opened.png" +class="toggle-content-img" alt="" /> + Android {@sdkPlatformVersion}, Revision 1</a> <em>(July 2011)</em> + </a></p> + + <div class="toggle-content-toggleme" style="padding-left:2em;"> + +<dl> +<dt>Initial release. SDK Tools r12 or higher is recommended.</dt> +</dl> + + </div> +</div> + +<h2 id="highlights" style="margin-top:1.5em;">Platform Highlights</h2> + +<h3>New user features</h3> + +<ul> +<li><strong>Optimizations for a wider range of tablets</strong> + +<p>Android 3.2 includes a variety of optimizations across the system +to ensure a great user experience on a wider range of tablet devices.</p></li> + +<li><strong>Compatibility zoom for fixed-sized apps</strong> + +<p>Android 3.2 introduces a new <em>compatibility zoom</em> mode that gives +users a new way to view fixed-sized apps on larger devices. The new mode provides a +pixel-scaled alternative to the standard UI stretching for apps that are not +designed to run on larger screen sizes, such as on tablets. The new mode is +accessible to users from a menu icon in the system bar, for apps that need +compatibility support.</p></li> + +<li><strong>Media sync from SD card</strong> +<p>On devices that support an SD card, users can now load media files directly +from the SD card to apps that use them. A system facility makes the files +accessible to apps from the system media store.</p></li> +</ul> + + +<h3>New developer features</h3> + +<ul> +<li><strong>Extended API for managing screens support</strong> + +<p>Android 3.2 introduces extensions to the platform's screen support API to +give developers additional ways to manage application UI across the range of +Android-powered devices. The API includes new resource qualifiers and new +manifest attributes that give you more precise control over how your +apps are displayed on different sizes, rather than relying on generalized +size categories.</p> + +<p>To ensure the best possible display for fixed-sized apps and apps with limited +support for various screen sizes, the platform also provides a new zoom +compatibility mode that renders the UI on a smaller screen area, then scales it +up to fill the space available on the display. For more information about the +screen support API and the controls it provides, see the sections below. </p></li> +</ul> + + +<h2 id="api">API Overview</h2> + +<h3 id="usb">Screens Support APIs</h3> + +<p>Android 3.2 introduces new screens support APIs that give you more +control over how their applications are displayed across different screen sizes. +The API builds on the existing screens-support API, including the platform's +generalized screen density model, but extends it with the ability to precisely +target specific screen ranges by their dimensions, measured in +density-independent pixel units (such as 600dp or 720dp wide), rather than +by their generalized screen sizes (such as large or xlarge)</p> + +<p>When designing an application's UI, you can still rely on the platform to +provide density abstraction, which means that applications do not need to +compensate for the differences in actual pixel density across devices. You +can design the application UI according to the amount of horizontal or vertical +space available. The platform expresses the amount of space available using three new +characteristics: <em>smallestWidth</em>, <em>width</em>, and +<em>height</em>.</p> + +<ul> +<li>A screen's <em>smallestWidth</em> is its fundamental minimum size, +measured in density-independent pixel ("dp") units. Of the screen's height or +width, it is the shorter of the two. For a screen in portrait orientation, the +smallestWidth is normally based on its width, while in landscape orientation it is based +on its height. In all cases, the smallestWidth is derived from a fixed characteristic of the +screen and the value does not change, regardless of orientation. The smallestWidth +is important for applications because it represents the shortest possible width +in which the application UI will need to be drawn, not including screen areas +reserved by the system. +</li> + +<li>In constrast, a screen's <em>width</em> and <em>height</em> represent the +current horizontal or vertical space available for application layout, measured +in "dp" units, not including screen areas reserved by the system. The width and +height of a screen change when the user switches orientation between landscape +and portrait. </li> + +</ul> + +<p>The new screens support API is designed to let you manage application UI +according to the smallestWidth of the current screen. You can also manage the +UI according to current width or height, as needed. For those purposes, the API +provides these tools:</p> + +<ul> +<li>New resource qualifiers for targeting layouts and other resources to a +minimum smallestWidth, width, or height, and</li> +<li>New manifest attributes, for specifying the app's maximum +screen compatibility range</li> +</ul> + +<p>Additionally, applications can still query the system and manage UI and +resource loading at runtime, as in the previous versions of the platform.</p> + +<p>Since the new API lets you target screens more directly through smallestWidth, +width, and height, it's helpful to understand the typical +characteristics of the different screen types. The table below provides some +examples, measured in "dp" units. </p> + +<p class="caption"><strong>Table 1.</strong> Typical devices, with density +and size in dp.</p> + +<table> +<tr> +<th>Type</th> +<th>Density (generalized)</th> +<th>Dimensions (dp)</th> +<th>smallestWidth (dp)</th> +</tr> +<tr> +<td>Baseline phone</td> +<td>mdpi</td> +<td>320x480</td> +<td>320</td> +</td> +<tr> +<td>Small tablet/large phone</td> +<td>mdpi</td> +<td>480x800</td> +<td>480</td> +</tr> +<tr> +<td>7-inch tablet</td> +<td>mdpi</td> +<td>600x1024</td> +<td>600</td> +</tr> +<tr> +<td>10-inch tablet</td> +<td>mdpi</td> +<td>800x1280</td> +<td>800</td> +</tr> +</table> + +<p>The sections below provide more information about the new screen qualifiers +and manifest attributes. For complete information about how to use the screen +support API, see <a +href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple +Screens</a>.</p> + +<h4>New resource qualifiers for screens support</h4> + +<p>The new resource qualifiers in Android 3.2 let you better target your layouts +for ranges of screen sizes. Using the qualifiers, you can create resource +configurations designed for a specific minimum smallestWidth, current width, or +current height, measured in density-independent pixels.</p> + +<p>The new qualifiers are:</p> +<ul> +<li><code>swNNNdp</code> — Specifies the minimum smallestWidth on which +the resource should be used, measured in "dp" units. As mentioned above, a +screen's smallestWidth is constant, regardless of orientation. Examples: +<code>sw320dp</code>, <code>sw720dp</code>, <code>sw720dp</code>.</li> + +<li><code>wNNNdp</code> and <code>hNNNdp</code> — Specifies the minimum +width or height on which the resource should be used, measured in "dp" units. As +mentioned above, a screen's width and height are relative to the orientation of +the screen and change whenever the orientation changes. Examples: +<code>w320dp</code>, <code>w720dp</code>, <code>h1024dp</code>.</p></li> +</ul> + +<p>You can also create multiple overlapping resource configurations if needed. +For example, you could tag some resources for use on any screen wider than 480 +dp, others for wider than 600 dp, and others for wider than 720 dp. When +multiple resource configurations are qualified for a given screen, the system +selects the configuration that is the closest match. For precise control over +which resources are loaded on a given screen, you can tag resources with one +qualifier or combine several new or existing qualifiers. + +<p>Based on the typical dimensions listed earlier, here are some examples of how +you could use the new qualifiers:</p> + +<pre class="classic prettyprint">res/layout/main_activity.xml # For phones +res/layout-sw600dp/main_activity.xml # For 7” tablets +res/layout-sw720dp/main_activity.xml # For 10” tablets +res/layout-w600dp/main_activity.xml # Multi-pane when enough width +res/layout-sw600dp-w720dp/main_activity.xml # For large width</pre> + +<p>Older versions of the platform will ignore the new qualifiers, so you can +mix them as needed to ensure that your app looks great on any device. Here +are some examples:</p> + +<pre class="classic prettyprint">res/layout/main_activity.xml # For phones +res/layout-xlarge/main_activity.xml # For pre-3.2 tablets +res/layout-sw600dp/main_activity.xml # For 3.2 and up tablets</pre> + +<p>For complete information about how to use the new qualifiers, see <a href="{@docRoot}guide/practices/screens_support.html#NewQualifiers">Using new +size qualifiers</a>.</p> + +<h4>New manifest attributes for screen-size compatibility</h4> + +<p>The framework offers a new set of <a +href="{@docRoot}"><code><supports-screens></code></a> manifest attributes that let +you manage your app's support for different screen sizess. +Specifically, you can specify the largest and smallest screens on which your app +is designed to run, as well as the largest screen on which it is designed run +without needing the system's new <a href="{@docRoot}guide/practices/screen-compat-mode.html">screen +compatibility mode</a>. Like the resource qualifiers described above, the new +manifest attributes specify the range of screens that the application supports, +as specified by the smallestWidth. </p> + +<p>The new manifest attributes for screen support are: </p> + +<ul> +<li><code>android:compatibleWidthLimitDp="<em>numDp"</em></code> — This +attribute lets you specify the maximum smallestWidth on which the application +can run without needing compatibility mode. If the current screen is larger than +the value specified, the system displays the application in normal mode but +allows the user to optionally switch to compatibility mode through a setting in +the system bar.</li> + +<li><code>android:largestWidthLimitDp="<em>numDp</em>"</code> — This +attribute lets you specify the maximum smallestWidth on which the application +is designed to run. If the current screen is larger than the value specified, +the system forces the application into screen compatibility mode, to ensure best +display on the current screen.</li> + +<li><code>android:smallestWidthLimitDp="<em>numDp"</em></code> — This +attribute lets you specify the minimum smallestWidth on which the application +can run. If the current screen is smaller than the value specified, the system +considers the application incompatible with the device, but does not prevent it +from being installed and run.</li> +</ul> + +<p class="note"><strong>Note:</strong> Android Market does not currently filter +apps based on any of the attributes above. Support for filtering will be +added in a later platform release. Applications that require +filtering based on screen size can use the existing <code><supports-screens></code> +attributes.</p> + +<p>For complete information about how to use the new attributes, see <a href="{@docRoot}guide/practices/screens_support.html#DeclaringScreenSizeSupport">Declaring +screen size support</a>.</p> + +<h4>Screen compatibility mode</h4> + +<p>Android 3.2 provides a new screen compatibility mode for applications +explicitly declaring that they do not support screens as large as the one on +which they are running. This new "zoom" mode is a pixel-scaled — it +renders the application in a smaller screen area and then scales the pixels to +fill the current screen.</p> + +<p>By default, the system offers screen compatibility mode as an user option, for apps +that require it. Users can turn the zoom mode on and off using a control available +in the system bar. </p> + +<p>Because the new screen compatibility mode may not be appropriate for all +applications, the platform allows the application to disable it using manifest +attributes. When disabled by the app, the system does not offer "zoom" compatibility +mode as an option for users when the app is running.</p> + +<p class="note"><strong>Note:</strong> For important information about how +to control compatibility mode in your applications, please review the <a +href="http://android-developers.blogspot.com/2011/07/new-mode-for-apps-on-large- +screens.html">New Mode for Apps on Large Screens</a> article on the Android +Developers Blog. </p> + +<h4>New screen density for 720p televisions and similar devices</h4> + +<p>To meet the needs of applications running on 720p televisions or similar with +moderate density screens, Android 3.2 introduces a new generalized density, +<code>tvdpi</code>, with an approximate dpi of 213. Applications can query for +the new density in {@link android.util.DisplayMetrics#densityDpi} and can use +the new <code>tvdpi</code> qualifier to tag resources for televisions and +similar devices. For example:</p> + +<pre class="classic prettyprint">res/drawable-tvdpi/my_icon.png # Bitmap for tv density</pre> + +<p>In general, applications should not need to work with this density. For situations +where output is needed for a 720p screen, the UI elements can be scaled +automatically by the platform.</p> + + +<h3 id="ui" style="margin-top:1.25em;">UI framework</h3> +<ul> +<li>Fragments + <ul> + <li>New {@link android.app.Fragment.SavedState} class holds the state + information retrieved from a fragment instance through + {@link android.app.FragmentManager#saveFragmentInstanceState(android.app.Fragment) saveFragmentInstanceState()}.</li> + <li>New method {@link android.app.FragmentManager#saveFragmentInstanceState(android.app.Fragment) saveFragmentInstanceState()} + saves the current instance state of + the given Fragment. The state can be used later when creating a new instance + of the Fragment that matches the current state.</li> + <li>New method {@link android.app.Fragment#setInitialSavedState(SavedState) setInitialSavedState()} + sets the initial saved state for a Fragment when first constructed.</li> + <li>New {@link android.app.Fragment#onViewCreated(android.view.View, android.os.Bundle) + onViewCreated()} callback method notifies the Fragment that + {@link android.app.Fragment#onCreateView(LayoutInflater, ViewGroup, Bundle) onCreateView()} + has returned, but before any saved state has been restored in to the View.</li> + <li>{@link android.app.Fragment#isDetached()} method determines whether + the Fragment has been explicitly detached from the UI.</li> + <li>New {@link android.app.FragmentTransaction#attach(android.app.Fragment) attach()} + and {@link android.app.FragmentTransaction#detach(android.app.Fragment) detach()} + methods let an application re-attach or detach fragments in the UI.</li> + <li>A new {@link android.app.FragmentTransaction#setCustomAnimations(int, int, int, int) + setCustomAnimations()} overload method lets you set specific animation + resources to run for enter/exit operations and specifically when + popping the back stack. The existing implementation does not account + for the different behavior of fragments when popping the back stack.</li> + </ul> +</li> +<li>Screen size information in ActivityInfo and ApplicationInfo + <ul> + <li>{@link android.content.pm.ActivityInfo} adds {@link android.content.pm.ActivityInfo#CONFIG_SCREEN_SIZE} + and {@link android.content.pm.ActivityInfo#CONFIG_SMALLEST_SCREEN_SIZE} as bit masks + in {@link android.R.attr#configChanges}. The bits indicate whether an Activity can + itself handle the screen size and smallest screen size.</li> + <li>{@link android.content.pm.ApplicationInfo} adds + {@link android.content.pm.ApplicationInfo#largestWidthLimitDp}, {@link android.content.pm.ApplicationInfo#compatibleWidthLimitDp}, + and {@link android.content.pm.ApplicationInfo#requiresSmallestWidthDp} fields, + derived from the corresponding <code><supports-screens></code> attributes + in the application manifest file.</li> + </ul> +</li> +<li>Helpers for getting display size from WindowManager + <ul> + <li>New methods {@link android.view.Display#getSize(android.graphics.Point) + getSize()} and {@link android.view.Display#getRectSize(android.graphics.Rect) + getRectSize()} let applications get the raw size of the display.</li> + </ul> +</li> +<li>New public "holographic" styles + <ul> + <li>The platform now exposes a variety of public "holographic" styles + for text, actionbar widgets and tabs, and more. See + {@link android.R.style} for a full list.</li> + </ul> +</li> +<li>{@link android.app.LocalActivityManager}, {@link android.app.ActivityGroup}, and + {@link android.app.LocalActivityManager} are now deprecated + <ul> + <li>New applications should use Fragments instead of these classes. To + continue to run on older versions of the platform, you can use the v4 Support + Library (compatibility library), available in the Android SDK. The v4 Support + Library provides a version of the Fragment API that is compatible down to + Android 1.6 (API level 4). + <li>For apps developing against Android 3.0 (API level + 11) or higher, tabs are typically presented in the UI using the new + {@link android.app.ActionBar#newTab() ActionBar.newTab()} and related APIs + for placing tabs within their action bar area.</p></li> + </ul> +</li> +</ul> + +<h3 id="media" style="margin-top:1em;">Media framework</h3> +<ul> + <li>Applications that use the platform's media provider ({@link + android.provider.MediaStore}) can now read media data directly from the + removeable SD card, where supported by the device. Applications can also + interact with the SD card files directly, using the MTP API. </li> + +</ul> +<h3 id="graphics" style="margin-top:1.25em;">Graphics</h3> +<ul> +<li>Parcelable utilities in Point and PointF + <ul> + <li>{@link android.graphics.Point} and {@link android.graphics.PointF} + classes now include the {@link android.os.Parcelable} interface and utility methods {@link + android.graphics.Point#describeContents()}, {@link + android.graphics.Point#readFromParcel(android.os.Parcel) readFromParcel()}, and {@link + android.graphics.Point#writeToParcel(android.os.Parcel, int) writeToParcel()}.</li> + </ul> +</li> +</ul> + + +<h3 id="ime" style="margin-top:1.25em;">IME framework</h3> +<ul> + <li>New {@link android.view.KeyEvent#getModifiers()} method for + retrieving the current state of the modifier keys.</li> +</ul> + + +<h3 id="usb" style="margin-top:1.25em;">USB framework</h3> +<ul> + <li>New {@link + android.hardware.usb.UsbDeviceConnection#getRawDescriptors()} method for + retrieving the raw USB descriptors for the device. You can use the + method to access descriptors not supported directly via the higher + level APIs.</li> +</ul> + + +<h3 id="network" style="margin-top:1.25em;">Network</h3> +<ul> +<li>Network type constants + <ul> + <li>{@link android.net.ConnectivityManager} adds the constants {@link + android.net.ConnectivityManager#TYPE_ETHERNET} and {@link + android.net.ConnectivityManager#TYPE_BLUETOOTH}.</li> + </ul> +</li> +</ul> + + +<h3 id="telephony" style="margin-top:1.25em;">Telephony</h3> +<ul> + <li>New {@link android.telephony.TelephonyManager#NETWORK_TYPE_HSPAP} network type constant.</li> +</ul> + +<h3 id="other" style="margin-top:1.25em;">Core utilities</h3> +<ul> +<li>Parcelable utilities + <ul> + <li>New interface {@link android.os.Parcelable.ClassLoaderCreator} allows + the application to receive the ClassLoader in which the object is being created.</li> + <li>New {@link android.os.ParcelFileDescriptor#adoptFd(int) adoptFd}, {@link + android.os.ParcelFileDescriptor#dup(java.io.FileDescriptor) dup()}, and {@link + android.os.ParcelFileDescriptor#fromFd(int) fromFd()} for managing + {@link android.os.ParcelFileDescriptor} objects.</li> + </ul> +</li> +<li>Binder and IBinder + <ul> + <li>New method {@link android.os.Binder#dumpAsync(java.io.FileDescriptor, java.lang.String[]) dumpAsync()} + in {@link android.os.Binder} and {@link android.os.IBinder} let applications + dump to a specified file, ensuring that the target executes asynchronously.</li> + <li>New {@link android.os.IBinder} protocol transaction code {@link + android.os.IBinder#TWEET_TRANSACTION} lets applications send a tweet + to the target object.</li> + </ul> +</li> +</ul> + + + + +<h3 id="features">New feature constants</h3> + +<p>The platform adds new hardware feature constants that you can declare +in their application manifests, to inform external entities such as Android +Market of required hardware and software capabilities. You declare these +and other feature constants in <a +href="{@docRoot}guide/topics/manifest/uses-feature-element.html">{@code +<uses-feature>}</a> manifest elements. + +<p>Android Market filters applications based on their <code><uses-feature></code> attributes, to ensure that they are available only to devices on which their requirements are met. </p> + +<ul> +<li>Feature constants for landscape or portrait requirements + +<p>Android 3.2 introduces new feature constants that let applications specify whether they require display in landscape orientation, portrait orientation, or both. Declaring these constants indicates that the application must not be installed on a device that doesn't offer the associated orientation. Conversely, if one or both of the constants are not declared, it indicates that the application does not have a preference for the undeclared orientations and may be installed on a device that doesn't offer them. </p> + +<ul> + <li>{@link android.content.pm.PackageManager#FEATURE_SCREEN_LANDSCAPE +android.hardware.screen.landscape} — The application requires display in +landscape orientation.</li> + <li>{@link android.content.pm.PackageManager#FEATURE_SCREEN_PORTRAIT +android.hardware.screen.portrait} — The application requires display in +portrait orientation.</li> +</ul> + +<p>A typical application that functions properly in both landscape and portrait orientations would not normally need to declare an orientation requirement. Rather, an application designed primarily for one orientation, such as an app designed for a television, could declare one of the constants to ensure that it isn't available to devices that don't provide that orientation.</p> + +<p>If the application is targeting API level 12 or lower, the platform assumes that if app has not specified whether it requires portrait or landscape, both orientations are required.</p> +</li> +<li>Other feature constants + +<ul> + <li>{@link android.content.pm.PackageManager#FEATURE_FAKETOUCH_MULTITOUCH_DISTINCT +android.hardware.faketouch.multitouch.distinct} — The application requires support for emulated mulitouch input with distinct tracking of two or more points.</li> + + <li>{@link android.content.pm.PackageManager#FEATURE_FAKETOUCH_MULTITOUCH_JAZZHAND +android.hardware.faketouch.multitouch.jazzhand} — The application requires support for emulated mulitouch input with distinct tracking of five or more points.</li> +</ul> + +</li> +</ul> + + +<h3 id="api-diff">API Differences Report</h3> + +<p>For a detailed view of all API changes in Android {@sdkPlatformVersion} (API +Level +{@sdkPlatformApiLevel}), see the <a +href="{@docRoot}sdk/api_diff/{@sdkPlatformApiLevel}/changes.html">API +Differences Report</a>.</p> + + + + + +<h2 id="api-level">API Level</h2> + +<p>The Android {@sdkPlatformVersion} platform delivers an updated version of +the framework API. The Android {@sdkPlatformVersion} API +is assigned an integer identifier — +<strong>{@sdkPlatformApiLevel}</strong> — that is +stored in the system itself. This identifier, called the "API Level", allows the +system to correctly determine whether an application is compatible with +the system, prior to installing the application. </p> + +<p>To use APIs introduced in Android {@sdkPlatformVersion} in your application, +you need compile the application against the Android library that is provided in +the Android {@sdkPlatformVersion} SDK platform. Depending on your needs, you +might +also need to add an <code>android:minSdkVersion="{@sdkPlatformApiLevel}"</code> +attribute to the <code><uses-sdk></code> element in the application's +manifest.</p> + +<p>For more information about how to use API Level, see the <a +href="{@docRoot}guide/appendix/api-levels.html">API Levels</a> document. </p> + + +<h2 id="apps">Built-in Applications</h2> + +<p>The system image included in the downloadable platform provides these +built-in applications:</p> + +<table style="border:0;padding-bottom:0;margin-bottom:0;"> +<tr> +<td style="border:0;padding-bottom:0;margin-bottom:0;"> +<ul> +<li>API Demos</li> +<li>Browser</li> +<li>Calculator</li> +<li>Camera</li> +<li>Clock</li> +<li>Contacts</li> +<li>Custom Locale</li> +<li>Dev Tools</li> +<li>Downloads</li> +<li>Email</li> +</ul> +</td> +<td style="border:0;padding-bottom:0;margin-bottom:0;padding-left:5em;"> +<ul> +<li>Gallery</li> +<li>Gestures Builder</li> +<li>Messaging</li> +<li>Music</li> +<li>Search</li> +<li>Settings</li> +<li>Spare Parts</li> +<li>Speech Recorder</li> +<li>Widget Preview</li> +</ul> +</td> +</tr> +</table> + + +<h2 id="locs" style="margin-top:.75em;">Locales</h2> + +<p>The system image included in the downloadable SDK platform provides a variety +of +built-in locales. In some cases, region-specific strings are available for the +locales. In other cases, a default version of the language is used. The +languages that are available in the Android 3.0 system +image are listed below (with <em>language</em>_<em>country/region</em> locale +descriptor).</p> + +<table style="border:0;padding-bottom:0;margin-bottom:0;"> +<tr> +<td style="border:0;padding-bottom:0;margin-bottom:0;"> +<ul> +<li>Arabic, Egypt (ar_EG)</li> +<li>Arabic, Israel (ar_IL)</li> +<li>Bulgarian, Bulgaria (bg_BG)</li> +<li>Catalan, Spain (ca_ES)</li> +<li>Czech, Czech Republic (cs_CZ)</li> +<li>Danish, Denmark(da_DK)</li> +<li>German, Austria (de_AT)</li> +<li>German, Switzerland (de_CH)</li> +<li>German, Germany (de_DE)</li> +<li>German, Liechtenstein (de_LI)</li> +<li>Greek, Greece (el_GR)</li> +<li>English, Australia (en_AU)</li> +<li>English, Canada (en_CA)</li> +<li>English, Britain (en_GB)</li> +<li>English, Ireland (en_IE)</li> +<li>English, India (en_IN)</li> +<li>English, New Zealand (en_NZ)</li> +<li>English, Singapore(en_SG)</li> +<li>English, US (en_US)</li> +<li>English, Zimbabwe (en_ZA)</li> +<li>Spanish (es_ES)</li> +<li>Spanish, US (es_US)</li> +<li>Finnish, Finland (fi_FI)</li> +<li>French, Belgium (fr_BE)</li> +<li>French, Canada (fr_CA)</li> +<li>French, Switzerland (fr_CH)</li> +<li>French, France (fr_FR)</li> +<li>Hebrew, Israel (he_IL)</li> +<li>Hindi, India (hi_IN)</li> +</ul> +</td> +<td style="border:0;padding-bottom:0;margin-bottom:0;padding-left:5em;"> +<li>Croatian, Croatia (hr_HR)</li> +<li>Hungarian, Hungary (hu_HU)</li> +<li>Indonesian, Indonesia (id_ID)</li> +<li>Italian, Switzerland (it_CH)</li> +<li>Italian, Italy (it_IT)</li> +<li>Japanese (ja_JP)</li> +<li>Korean (ko_KR)</li> +<li>Lithuanian, Lithuania (lt_LT)</li> +<li>Latvian, Latvia (lv_LV)</li> +<li>Norwegian bokmål, Norway (nb_NO)</li> +<li>Dutch, Belgium (nl_BE)</li> +<li>Dutch, Netherlands (nl_NL)</li> +<li>Polish (pl_PL)</li> +<li>Portuguese, Brazil (pt_BR)</li> +<li>Portuguese, Portugal (pt_PT)</li> +<li>Romanian, Romania (ro_RO)</li> +<li>Russian (ru_RU)</li></li> +<li>Slovak, Slovakia (sk_SK)</li> +<li>Slovenian, Slovenia (sl_SI)</li> +<li>Serbian (sr_RS)</li> +<li>Swedish, Sweden (sv_SE)</li> +<li>Thai, Thailand (th_TH)</li> +<li>Tagalog, Philippines (tl_PH)</li> +<li>Turkish, Turkey (tr_TR)</li> +<li>Ukrainian, Ukraine (uk_UA)</li> +<li>Vietnamese, Vietnam (vi_VN)</li> +<li>Chinese, PRC (zh_CN)</li> +<li>Chinese, Taiwan (zh_TW)</li> +</td> +</tr> +</table> + +<p class="note"><strong>Note:</strong> The Android platform may support more +locales than are included in the SDK system image. All of the supported locales +are available in the <a href="http://source.android.com/">Android Open Source +Project</a>.</p> + +<h2 id="skins">Emulator Skins</h2> + +<p>The downloadable platform includes the following emulator skin:</p> + +<ul> + <li> + WXGA (1280x800, medium density, xlarge screen) + </li> +</ul> + +<p>For more information about how to develop an application that displays +and functions properly on all Android-powered devices, see <a +href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple +Screens</a>.</p> diff --git a/docs/html/sdk/api_diff/13/changes.html b/docs/html/sdk/api_diff/13/changes.html new file mode 100644 index 0000000..0a25fca --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes.html @@ -0,0 +1,45 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<!-- on Wed Jun 29 10:50:35 PDT 2011 --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +API Differences between 12 and 13 +</TITLE> +<link href="../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</head> +<frameset cols="242,**" framespacing="1" frameborder="yes" border="1" bordercolor="#e9e9e9"> +<frameset rows="174,**" framespacing="1" frameborder="yes" border="1" bordercolor="#e9e9e9"> + <frame src="changes/jdiff_topleftframe.html" scrolling="no" name="topleftframe" frameborder="1"> + <frame src="changes/alldiffs_index_all.html" scrolling="auto" name="bottomleftframe" frameborder="1"> + </frameset> + <frame src="changes/changes-summary.html" scrolling="auto" name="rightframe" frameborder="1"> +</frameset> +<noframes> +<h2> +Frame Alert +</h2> + +<p> +This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client. +<br> +Link to <a href="changes/changes-summary.html" target="_top">Non-frame version.</A> +</noframes> +</html> diff --git a/docs/html/sdk/api_diff/13/changes/alldiffs_index_additions.html b/docs/html/sdk/api_diff/13/changes/alldiffs_index_additions.html new file mode 100644 index 0000000..1d53429 --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/alldiffs_index_additions.html @@ -0,0 +1,663 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +All Additions Index +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY class="gc-documentation" style="padding:12px;"> +<a NAME="topheader"></a> +<table summary="Index for All Differences" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;"> + <tr> + <th class="indexHeader"> + Filter the Index: + </th> + </tr> + <tr> + <td class="indexText" style="line-height:1.3em;padding-left:2em;"> +<a href="alldiffs_index_all.html" xclass="hiddenlink">All Differences</a> + <br> +<font color="#999999">Removals</font> + <br> +<b>Additions</b> + <br> +<A HREF="alldiffs_index_changes.html"xclass="hiddenlink">Changes</A> + </td> + </tr> +</table> +<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;"> +Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font> +</div> +<!-- Method adoptFd --> +<A NAME="A"></A> +<br><font size="+2">A</font> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.os.ParcelFileDescriptor.html#android.os.ParcelFileDescriptor.adoptFd_added(int)" class="hiddenlink" target="rightframe"><b>adoptFd</b> +(<code>int</code>)</A></nobr><br> +<!-- Method attach --> +<nobr><A HREF="android.app.FragmentTransaction.html#android.app.FragmentTransaction.attach_added(android.app.Fragment)" class="hiddenlink" target="rightframe"><b>attach</b> +(<code>Fragment</code>)</A></nobr><br> +<!-- Field compatibleWidthLimitDp --> +<A NAME="C"></A> +<br><font size="+2">C</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<i>compatibleWidthLimitDp</i><br> +<nobr> in +<A HREF="android.R.attr.html#android.R.attr.compatibleWidthLimitDp" class="hiddenlink" target="rightframe">android.R.attr</A> +</nobr><br> +<!-- Field compatibleWidthLimitDp --> +<nobr> in +<A HREF="android.content.pm.ApplicationInfo.html#android.content.pm.ApplicationInfo.compatibleWidthLimitDp" class="hiddenlink" target="rightframe">android.content.pm.ApplicationInfo</A> +</nobr><br> +<!-- Field CONFIG_SCREEN_SIZE --> +<nobr><A HREF="android.content.pm.ActivityInfo.html#android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE" class="hiddenlink" target="rightframe">CONFIG_SCREEN_SIZE</A> +</nobr><br> +<!-- Field CONFIG_SMALLEST_SCREEN_SIZE --> +<nobr><A HREF="android.content.pm.ActivityInfo.html#android.content.pm.ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE" class="hiddenlink" target="rightframe">CONFIG_SMALLEST_SCREEN_SIZE</A> +</nobr><br> +<!-- Field CREATOR --> +<i>CREATOR</i><br> +<nobr> in +<A HREF="android.graphics.Point.html#android.graphics.Point.CREATOR" class="hiddenlink" target="rightframe">android.graphics.Point</A> +</nobr><br> +<!-- Field CREATOR --> +<nobr> in +<A HREF="android.graphics.PointF.html#android.graphics.PointF.CREATOR" class="hiddenlink" target="rightframe">android.graphics.PointF</A> +</nobr><br> +<!-- Field DENSITY_TV --> +<A NAME="D"></A> +<br><font size="+2">D</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.util.DisplayMetrics.html#android.util.DisplayMetrics.DENSITY_TV" class="hiddenlink" target="rightframe">DENSITY_TV</A> +</nobr><br> +<!-- Method describeContents --> +<i>describeContents</i><br> + <nobr><A HREF="android.graphics.Point.html#android.graphics.Point.describeContents_added()" class="hiddenlink" target="rightframe">type <b> +()</b> in android.graphics.Point +</A></nobr><br> +<!-- Method describeContents --> + <nobr><A HREF="android.graphics.PointF.html#android.graphics.PointF.describeContents_added()" class="hiddenlink" target="rightframe">type <b> +()</b> in android.graphics.PointF +</A></nobr><br> +<!-- Method detach --> +<nobr><A HREF="android.app.FragmentTransaction.html#android.app.FragmentTransaction.detach_added(android.app.Fragment)" class="hiddenlink" target="rightframe"><b>detach</b> +(<code>Fragment</code>)</A></nobr><br> +<!-- Method dumpAsync --> +<i>dumpAsync</i><br> + <nobr><A HREF="android.os.Binder.html#android.os.Binder.dumpAsync_added(java.io.FileDescriptor, java.lang.String[])" class="hiddenlink" target="rightframe">type <b> +(<code>FileDescriptor, String[]</code>)</b> in android.os.Binder +</A></nobr><br> +<!-- Method dumpAsync --> + <nobr><A HREF="android.os.IBinder.html#android.os.IBinder.dumpAsync_added(java.io.FileDescriptor, java.lang.String[])" class="hiddenlink" target="rightframe">type <b> +(<code>FileDescriptor, String[]</code>)</b> in android.os.IBinder +</A></nobr><br> +<!-- Method dup --> +<nobr><A HREF="android.os.ParcelFileDescriptor.html#android.os.ParcelFileDescriptor.dup_added(java.io.FileDescriptor)" class="hiddenlink" target="rightframe"><b>dup</b> +(<code>FileDescriptor</code>)</A></nobr><br> +<!-- Field FEATURE_FAKETOUCH_MULTITOUCH_DISTINCT --> +<A NAME="F"></A> +<br><font size="+2">F</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.content.pm.PackageManager.html#android.content.pm.PackageManager.FEATURE_FAKETOUCH_MULTITOUCH_DISTINCT" class="hiddenlink" target="rightframe">FEATURE_FAKETOUCH_MULTITOUCH_DISTINCT</A> +</nobr><br> +<!-- Field FEATURE_FAKETOUCH_MULTITOUCH_JAZZHAND --> +<nobr><A HREF="android.content.pm.PackageManager.html#android.content.pm.PackageManager.FEATURE_FAKETOUCH_MULTITOUCH_JAZZHAND" class="hiddenlink" target="rightframe">FEATURE_FAKETOUCH_MULTITOUCH_JAZZHAND</A> +</nobr><br> +<!-- Field FEATURE_SCREEN_LANDSCAPE --> +<nobr><A HREF="android.content.pm.PackageManager.html#android.content.pm.PackageManager.FEATURE_SCREEN_LANDSCAPE" class="hiddenlink" target="rightframe">FEATURE_SCREEN_LANDSCAPE</A> +</nobr><br> +<!-- Field FEATURE_SCREEN_PORTRAIT --> +<nobr><A HREF="android.content.pm.PackageManager.html#android.content.pm.PackageManager.FEATURE_SCREEN_PORTRAIT" class="hiddenlink" target="rightframe">FEATURE_SCREEN_PORTRAIT</A> +</nobr><br> +<!-- Class Fragment.SavedState --> +<A HREF="pkg_android.app.html#Fragment.SavedState" class="hiddenlink" target="rightframe"><b>Fragment.SavedState</b></A><br> +<!-- Method fromFd --> +<nobr><A HREF="android.os.ParcelFileDescriptor.html#android.os.ParcelFileDescriptor.fromFd_added(int)" class="hiddenlink" target="rightframe"><b>fromFd</b> +(<code>int</code>)</A></nobr><br> +<!-- Method getModifiers --> +<A NAME="G"></A> +<br><font size="+2">G</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.view.KeyEvent.html#android.view.KeyEvent.getModifiers_added()" class="hiddenlink" target="rightframe"><b>getModifiers</b> +()</A></nobr><br> +<!-- Method getRawDescriptors --> +<nobr><A HREF="android.hardware.usb.UsbDeviceConnection.html#android.hardware.usb.UsbDeviceConnection.getRawDescriptors_added()" class="hiddenlink" target="rightframe"><b>getRawDescriptors</b> +()</A></nobr><br> +<!-- Method getRectSize --> +<nobr><A HREF="android.view.Display.html#android.view.Display.getRectSize_added(android.graphics.Rect)" class="hiddenlink" target="rightframe"><b>getRectSize</b> +(<code>Rect</code>)</A></nobr><br> +<!-- Method getSize --> +<nobr><A HREF="android.view.Display.html#android.view.Display.getSize_added(android.graphics.Point)" class="hiddenlink" target="rightframe"><b>getSize</b> +(<code>Point</code>)</A></nobr><br> +<!-- Field HONEYCOMB_MR2 --> +<A NAME="H"></A> +<br><font size="+2">H</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.os.Build.VERSION_CODES.html#android.os.Build.VERSION_CODES.HONEYCOMB_MR2" class="hiddenlink" target="rightframe">HONEYCOMB_MR2</A> +</nobr><br> +<!-- Method isDetached --> +<A NAME="I"></A> +<br><font size="+2">I</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.app.Fragment.html#android.app.Fragment.isDetached_added()" class="hiddenlink" target="rightframe"><b>isDetached</b> +()</A></nobr><br> +<!-- Field largestWidthLimitDp --> +<A NAME="L"></A> +<br><font size="+2">L</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<i>largestWidthLimitDp</i><br> +<nobr> in +<A HREF="android.R.attr.html#android.R.attr.largestWidthLimitDp" class="hiddenlink" target="rightframe">android.R.attr</A> +</nobr><br> +<!-- Field largestWidthLimitDp --> +<nobr> in +<A HREF="android.content.pm.ApplicationInfo.html#android.content.pm.ApplicationInfo.largestWidthLimitDp" class="hiddenlink" target="rightframe">android.content.pm.ApplicationInfo</A> +</nobr><br> +<!-- Field NETWORK_TYPE_HSPAP --> +<A NAME="N"></A> +<br><font size="+2">N</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.telephony.TelephonyManager.html#android.telephony.TelephonyManager.NETWORK_TYPE_HSPAP" class="hiddenlink" target="rightframe">NETWORK_TYPE_HSPAP</A> +</nobr><br> +<!-- Method onViewCreated --> +<A NAME="O"></A> +<br><font size="+2">O</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.app.Fragment.html#android.app.Fragment.onViewCreated_added(android.view.View, android.os.Bundle)" class="hiddenlink" target="rightframe"><b>onViewCreated</b> +(<code>View, Bundle</code>)</A></nobr><br> +<!-- Class Parcelable.ClassLoaderCreator --> +<A NAME="P"></A> +<br><font size="+2">P</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<A HREF="pkg_android.os.html#Parcelable.ClassLoaderCreator" class="hiddenlink" target="rightframe"><b><i>Parcelable.ClassLoaderCreator</i></b></A><br> +<!-- Method readFromParcel --> +<A NAME="R"></A> +<br><font size="+2">R</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<i>readFromParcel</i><br> + <nobr><A HREF="android.graphics.Point.html#android.graphics.Point.readFromParcel_added(android.os.Parcel)" class="hiddenlink" target="rightframe">type <b> +(<code>Parcel</code>)</b> in android.graphics.Point +</A></nobr><br> +<!-- Method readFromParcel --> + <nobr><A HREF="android.graphics.PointF.html#android.graphics.PointF.readFromParcel_added(android.os.Parcel)" class="hiddenlink" target="rightframe">type <b> +(<code>Parcel</code>)</b> in android.graphics.PointF +</A></nobr><br> +<!-- Field requiresSmallestWidthDp --> +<i>requiresSmallestWidthDp</i><br> +<nobr> in +<A HREF="android.R.attr.html#android.R.attr.requiresSmallestWidthDp" class="hiddenlink" target="rightframe">android.R.attr</A> +</nobr><br> +<!-- Field requiresSmallestWidthDp --> +<nobr> in +<A HREF="android.content.pm.ApplicationInfo.html#android.content.pm.ApplicationInfo.requiresSmallestWidthDp" class="hiddenlink" target="rightframe">android.content.pm.ApplicationInfo</A> +</nobr><br> +<!-- Method saveFragmentInstanceState --> +<A NAME="S"></A> +<br><font size="+2">S</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.app.FragmentManager.html#android.app.FragmentManager.saveFragmentInstanceState_added(android.app.Fragment)" class="hiddenlink" target="rightframe"><b>saveFragmentInstanceState</b> +(<code>Fragment</code>)</A></nobr><br> +<!-- Field SCREEN_HEIGHT_DP_UNDEFINED --> +<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.SCREEN_HEIGHT_DP_UNDEFINED" class="hiddenlink" target="rightframe">SCREEN_HEIGHT_DP_UNDEFINED</A> +</nobr><br> +<!-- Field SCREEN_WIDTH_DP_UNDEFINED --> +<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.SCREEN_WIDTH_DP_UNDEFINED" class="hiddenlink" target="rightframe">SCREEN_WIDTH_DP_UNDEFINED</A> +</nobr><br> +<!-- Field screenHeightDp --> +<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.screenHeightDp" class="hiddenlink" target="rightframe">screenHeightDp</A> +</nobr><br> +<!-- Field screenWidthDp --> +<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.screenWidthDp" class="hiddenlink" target="rightframe">screenWidthDp</A> +</nobr><br> +<!-- Field SET_POINTER_SPEED --> +<nobr><A HREF="android.Manifest.permission.html#android.Manifest.permission.SET_POINTER_SPEED" class="hiddenlink" target="rightframe">SET_POINTER_SPEED</A> +</nobr><br> +<!-- Method setCustomAnimations --> +<nobr><A HREF="android.app.FragmentTransaction.html#android.app.FragmentTransaction.setCustomAnimations_added(int, int, int, int)" class="hiddenlink" target="rightframe"><b>setCustomAnimations</b> +(<code>int, int, int, int</code>)</A></nobr><br> +<!-- Method setInitialSavedState --> +<nobr><A HREF="android.app.Fragment.html#android.app.Fragment.setInitialSavedState_added(android.app.Fragment.SavedState)" class="hiddenlink" target="rightframe"><b>setInitialSavedState</b> +(<code>SavedState</code>)</A></nobr><br> +<!-- Field SMALLEST_SCREEN_WIDTH_DP_UNDEFINED --> +<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED" class="hiddenlink" target="rightframe">SMALLEST_SCREEN_WIDTH_DP_UNDEFINED</A> +</nobr><br> +<!-- Field smallestScreenWidthDp --> +<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.smallestScreenWidthDp" class="hiddenlink" target="rightframe">smallestScreenWidthDp</A> +</nobr><br> +<!-- Field TextAppearance_Holo --> +<A NAME="T"></A> +<br><font size="+2">T</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo" class="hiddenlink" target="rightframe">TextAppearance_Holo</A> +</nobr><br> +<!-- Field TextAppearance_Holo_DialogWindowTitle --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_DialogWindowTitle" class="hiddenlink" target="rightframe">TextAppearance_Holo_DialogWindowTitle</A> +</nobr><br> +<!-- Field TextAppearance_Holo_Inverse --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Inverse" class="hiddenlink" target="rightframe">TextAppearance_Holo_Inverse</A> +</nobr><br> +<!-- Field TextAppearance_Holo_Large --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Large" class="hiddenlink" target="rightframe">TextAppearance_Holo_Large</A> +</nobr><br> +<!-- Field TextAppearance_Holo_Large_Inverse --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Large_Inverse" class="hiddenlink" target="rightframe">TextAppearance_Holo_Large_Inverse</A> +</nobr><br> +<!-- Field TextAppearance_Holo_Medium --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Medium" class="hiddenlink" target="rightframe">TextAppearance_Holo_Medium</A> +</nobr><br> +<!-- Field TextAppearance_Holo_Medium_Inverse --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Medium_Inverse" class="hiddenlink" target="rightframe">TextAppearance_Holo_Medium_Inverse</A> +</nobr><br> +<!-- Field TextAppearance_Holo_SearchResult_Subtitle --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_SearchResult_Subtitle" class="hiddenlink" target="rightframe">TextAppearance_Holo_SearchResult_Subtitle</A> +</nobr><br> +<!-- Field TextAppearance_Holo_SearchResult_Title --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_SearchResult_Title" class="hiddenlink" target="rightframe">TextAppearance_Holo_SearchResult_Title</A> +</nobr><br> +<!-- Field TextAppearance_Holo_Small --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Small" class="hiddenlink" target="rightframe">TextAppearance_Holo_Small</A> +</nobr><br> +<!-- Field TextAppearance_Holo_Small_Inverse --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Small_Inverse" class="hiddenlink" target="rightframe">TextAppearance_Holo_Small_Inverse</A> +</nobr><br> +<!-- Field TextAppearance_Holo_Widget --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget</A> +</nobr><br> +<!-- Field TextAppearance_Holo_Widget_ActionBar_Subtitle --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_ActionBar_Subtitle" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_ActionBar_Subtitle</A> +</nobr><br> +<!-- Field TextAppearance_Holo_Widget_ActionBar_Title --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_ActionBar_Title" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_ActionBar_Title</A> +</nobr><br> +<!-- Field TextAppearance_Holo_Widget_ActionMode_Subtitle --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_ActionMode_Subtitle" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_ActionMode_Subtitle</A> +</nobr><br> +<!-- Field TextAppearance_Holo_Widget_ActionMode_Title --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_ActionMode_Title" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_ActionMode_Title</A> +</nobr><br> +<!-- Field TextAppearance_Holo_Widget_Button --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_Button" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_Button</A> +</nobr><br> +<!-- Field TextAppearance_Holo_Widget_DropDownHint --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_DropDownHint" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_DropDownHint</A> +</nobr><br> +<!-- Field TextAppearance_Holo_Widget_DropDownItem --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_DropDownItem" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_DropDownItem</A> +</nobr><br> +<!-- Field TextAppearance_Holo_Widget_EditText --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_EditText" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_EditText</A> +</nobr><br> +<!-- Field TextAppearance_Holo_Widget_IconMenu_Item --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_IconMenu_Item" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_IconMenu_Item</A> +</nobr><br> +<!-- Field TextAppearance_Holo_Widget_PopupMenu --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_PopupMenu" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_PopupMenu</A> +</nobr><br> +<!-- Field TextAppearance_Holo_Widget_PopupMenu_Large --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_PopupMenu_Large" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_PopupMenu_Large</A> +</nobr><br> +<!-- Field TextAppearance_Holo_Widget_PopupMenu_Small --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_PopupMenu_Small" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_PopupMenu_Small</A> +</nobr><br> +<!-- Field TextAppearance_Holo_Widget_TabWidget --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_TabWidget" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_TabWidget</A> +</nobr><br> +<!-- Field TextAppearance_Holo_Widget_TextView --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_TextView" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_TextView</A> +</nobr><br> +<!-- Field TextAppearance_Holo_Widget_TextView_PopupMenu --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_TextView_PopupMenu" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_TextView_PopupMenu</A> +</nobr><br> +<!-- Field TextAppearance_Holo_Widget_TextView_SpinnerItem --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_TextView_SpinnerItem" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_TextView_SpinnerItem</A> +</nobr><br> +<!-- Field TextAppearance_Holo_WindowTitle --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_WindowTitle" class="hiddenlink" target="rightframe">TextAppearance_Holo_WindowTitle</A> +</nobr><br> +<!-- Field Theme_Holo_Light_NoActionBar --> +<nobr><A HREF="android.R.style.html#android.R.style.Theme_Holo_Light_NoActionBar" class="hiddenlink" target="rightframe">Theme_Holo_Light_NoActionBar</A> +</nobr><br> +<!-- Field Theme_Holo_Light_NoActionBar_Fullscreen --> +<nobr><A HREF="android.R.style.html#android.R.style.Theme_Holo_Light_NoActionBar_Fullscreen" class="hiddenlink" target="rightframe">Theme_Holo_Light_NoActionBar_Fullscreen</A> +</nobr><br> +<!-- Field TWEET_TRANSACTION --> +<nobr><A HREF="android.os.IBinder.html#android.os.IBinder.TWEET_TRANSACTION" class="hiddenlink" target="rightframe">TWEET_TRANSACTION</A> +</nobr><br> +<!-- Field TYPE_BLUETOOTH --> +<nobr><A HREF="android.net.ConnectivityManager.html#android.net.ConnectivityManager.TYPE_BLUETOOTH" class="hiddenlink" target="rightframe">TYPE_BLUETOOTH</A> +</nobr><br> +<!-- Field TYPE_ETHERNET --> +<nobr><A HREF="android.net.ConnectivityManager.html#android.net.ConnectivityManager.TYPE_ETHERNET" class="hiddenlink" target="rightframe">TYPE_ETHERNET</A> +</nobr><br> +<!-- Field UI_MODE_TYPE_TELEVISION --> +<A NAME="U"></A> +<br><font size="+2">U</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.UI_MODE_TYPE_TELEVISION" class="hiddenlink" target="rightframe">UI_MODE_TYPE_TELEVISION</A> +</nobr><br> +<!-- Field Widget_ActionBar_TabBar --> +<A NAME="W"></A> +<br><font size="+2">W</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.R.style.html#android.R.style.Widget_ActionBar_TabBar" class="hiddenlink" target="rightframe">Widget_ActionBar_TabBar</A> +</nobr><br> +<!-- Field Widget_ActionBar_TabText --> +<nobr><A HREF="android.R.style.html#android.R.style.Widget_ActionBar_TabText" class="hiddenlink" target="rightframe">Widget_ActionBar_TabText</A> +</nobr><br> +<!-- Field Widget_ActionBar_TabView --> +<nobr><A HREF="android.R.style.html#android.R.style.Widget_ActionBar_TabView" class="hiddenlink" target="rightframe">Widget_ActionBar_TabView</A> +</nobr><br> +<!-- Field Widget_Holo_ActionBar_TabBar --> +<nobr><A HREF="android.R.style.html#android.R.style.Widget_Holo_ActionBar_TabBar" class="hiddenlink" target="rightframe">Widget_Holo_ActionBar_TabBar</A> +</nobr><br> +<!-- Field Widget_Holo_ActionBar_TabText --> +<nobr><A HREF="android.R.style.html#android.R.style.Widget_Holo_ActionBar_TabText" class="hiddenlink" target="rightframe">Widget_Holo_ActionBar_TabText</A> +</nobr><br> +<!-- Field Widget_Holo_ActionBar_TabView --> +<nobr><A HREF="android.R.style.html#android.R.style.Widget_Holo_ActionBar_TabView" class="hiddenlink" target="rightframe">Widget_Holo_ActionBar_TabView</A> +</nobr><br> +<!-- Field Widget_Holo_Light_ActionBar_TabBar --> +<nobr><A HREF="android.R.style.html#android.R.style.Widget_Holo_Light_ActionBar_TabBar" class="hiddenlink" target="rightframe">Widget_Holo_Light_ActionBar_TabBar</A> +</nobr><br> +<!-- Field Widget_Holo_Light_ActionBar_TabText --> +<nobr><A HREF="android.R.style.html#android.R.style.Widget_Holo_Light_ActionBar_TabText" class="hiddenlink" target="rightframe">Widget_Holo_Light_ActionBar_TabText</A> +</nobr><br> +<!-- Field Widget_Holo_Light_ActionBar_TabView --> +<nobr><A HREF="android.R.style.html#android.R.style.Widget_Holo_Light_ActionBar_TabView" class="hiddenlink" target="rightframe">Widget_Holo_Light_ActionBar_TabView</A> +</nobr><br> +<!-- Method writeToParcel --> +<i>writeToParcel</i><br> + <nobr><A HREF="android.graphics.Point.html#android.graphics.Point.writeToParcel_added(android.os.Parcel, int)" class="hiddenlink" target="rightframe">type <b> +(<code>Parcel, int</code>)</b> in android.graphics.Point +</A></nobr><br> +<!-- Method writeToParcel --> + <nobr><A HREF="android.graphics.PointF.html#android.graphics.PointF.writeToParcel_added(android.os.Parcel, int)" class="hiddenlink" target="rightframe">type <b> +(<code>Parcel, int</code>)</b> in android.graphics.PointF +</A></nobr><br> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/alldiffs_index_all.html b/docs/html/sdk/api_diff/13/changes/alldiffs_index_all.html new file mode 100644 index 0000000..a4e428e --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/alldiffs_index_all.html @@ -0,0 +1,941 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +All Differences Index +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY class="gc-documentation" style="padding:12px;"> +<a NAME="topheader"></a> +<table summary="Index for All Differences" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;"> + <tr> + <th class="indexHeader"> + Filter the Index: + </th> + </tr> + <tr> + <td class="indexText" style="line-height:1.3em;padding-left:2em;"> +<b>All Differences</b> + <br> +<font color="#999999">Removals</font> + <br> +<A HREF="alldiffs_index_additions.html"xclass="hiddenlink">Additions</A> + <br> +<A HREF="alldiffs_index_changes.html"xclass="hiddenlink">Changes</A> + </td> + </tr> +</table> +<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;"> +Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font> +</div> +<!-- Class Activity --> +<A NAME="A"></A> +<br><font size="+2">A</font> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<A HREF="android.app.Activity.html" class="hiddenlink" target="rightframe">Activity</A><br> +<!-- Class ActivityGroup --> +<A HREF="android.app.ActivityGroup.html" class="hiddenlink" target="rightframe">ActivityGroup</A><br> +<!-- Class ActivityInfo --> +<A HREF="android.content.pm.ActivityInfo.html" class="hiddenlink" target="rightframe">ActivityInfo</A><br> +<!-- Method adoptFd --> +<nobr><A HREF="android.os.ParcelFileDescriptor.html#android.os.ParcelFileDescriptor.adoptFd_added(int)" class="hiddenlink" target="rightframe"><b>adoptFd</b> +(<code>int</code>)</A></nobr><br> +<!-- Package android --> +<A HREF="pkg_android.html" class="hiddenlink" target="rightframe">android</A><br> +<!-- Package android.app --> +<A HREF="pkg_android.app.html" class="hiddenlink" target="rightframe">android.app</A><br> +<!-- Package android.content.pm --> +<A HREF="pkg_android.content.pm.html" class="hiddenlink" target="rightframe">android.content.pm</A><br> +<!-- Package android.content.res --> +<A HREF="pkg_android.content.res.html" class="hiddenlink" target="rightframe">android.content.res</A><br> +<!-- Package android.graphics --> +<A HREF="pkg_android.graphics.html" class="hiddenlink" target="rightframe">android.graphics</A><br> +<!-- Package android.hardware.usb --> +<A HREF="pkg_android.hardware.usb.html" class="hiddenlink" target="rightframe">android.hardware.usb</A><br> +<!-- Package android.net --> +<A HREF="pkg_android.net.html" class="hiddenlink" target="rightframe">android.net</A><br> +<!-- Package android.os --> +<A HREF="pkg_android.os.html" class="hiddenlink" target="rightframe">android.os</A><br> +<!-- Package android.telephony --> +<A HREF="pkg_android.telephony.html" class="hiddenlink" target="rightframe">android.telephony</A><br> +<!-- Package android.util --> +<A HREF="pkg_android.util.html" class="hiddenlink" target="rightframe">android.util</A><br> +<!-- Package android.view --> +<A HREF="pkg_android.view.html" class="hiddenlink" target="rightframe">android.view</A><br> +<!-- Class ApplicationInfo --> +<A HREF="android.content.pm.ApplicationInfo.html" class="hiddenlink" target="rightframe">ApplicationInfo</A><br> +<!-- Method attach --> +<nobr><A HREF="android.app.FragmentTransaction.html#android.app.FragmentTransaction.attach_added(android.app.Fragment)" class="hiddenlink" target="rightframe"><b>attach</b> +(<code>Fragment</code>)</A></nobr><br> +<!-- Class Binder --> +<A NAME="B"></A> +<br><font size="+2">B</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<A HREF="android.os.Binder.html" class="hiddenlink" target="rightframe">Binder</A><br> +<!-- Class Build.VERSION_CODES --> +<A HREF="android.os.Build.VERSION_CODES.html" class="hiddenlink" target="rightframe">Build.VERSION_CODES</A><br> +<!-- Field compatibleWidthLimitDp --> +<A NAME="C"></A> +<br><font size="+2">C</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<i>compatibleWidthLimitDp</i><br> +<nobr> in +<A HREF="android.R.attr.html#android.R.attr.compatibleWidthLimitDp" class="hiddenlink" target="rightframe">android.R.attr</A> +</nobr><br> +<!-- Field compatibleWidthLimitDp --> +<nobr> in +<A HREF="android.content.pm.ApplicationInfo.html#android.content.pm.ApplicationInfo.compatibleWidthLimitDp" class="hiddenlink" target="rightframe">android.content.pm.ApplicationInfo</A> +</nobr><br> +<!-- Field CONFIG_SCREEN_SIZE --> +<nobr><A HREF="android.content.pm.ActivityInfo.html#android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE" class="hiddenlink" target="rightframe">CONFIG_SCREEN_SIZE</A> +</nobr><br> +<!-- Field CONFIG_SMALLEST_SCREEN_SIZE --> +<nobr><A HREF="android.content.pm.ActivityInfo.html#android.content.pm.ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE" class="hiddenlink" target="rightframe">CONFIG_SMALLEST_SCREEN_SIZE</A> +</nobr><br> +<!-- Class Configuration --> +<A HREF="android.content.res.Configuration.html" class="hiddenlink" target="rightframe">Configuration</A><br> +<!-- Class ConnectivityManager --> +<A HREF="android.net.ConnectivityManager.html" class="hiddenlink" target="rightframe">ConnectivityManager</A><br> +<!-- Field CREATOR --> +<i>CREATOR</i><br> +<nobr> in +<A HREF="android.graphics.Point.html#android.graphics.Point.CREATOR" class="hiddenlink" target="rightframe">android.graphics.Point</A> +</nobr><br> +<!-- Field CREATOR --> +<nobr> in +<A HREF="android.graphics.PointF.html#android.graphics.PointF.CREATOR" class="hiddenlink" target="rightframe">android.graphics.PointF</A> +</nobr><br> +<!-- Field DENSITY_TV --> +<A NAME="D"></A> +<br><font size="+2">D</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.util.DisplayMetrics.html#android.util.DisplayMetrics.DENSITY_TV" class="hiddenlink" target="rightframe">DENSITY_TV</A> +</nobr><br> +<!-- Method describeContents --> +<i>describeContents</i><br> + <nobr><A HREF="android.graphics.Point.html#android.graphics.Point.describeContents_added()" class="hiddenlink" target="rightframe">type <b> +()</b> in android.graphics.Point +</A></nobr><br> +<!-- Method describeContents --> + <nobr><A HREF="android.graphics.PointF.html#android.graphics.PointF.describeContents_added()" class="hiddenlink" target="rightframe">type <b> +()</b> in android.graphics.PointF +</A></nobr><br> +<!-- Method detach --> +<nobr><A HREF="android.app.FragmentTransaction.html#android.app.FragmentTransaction.detach_added(android.app.Fragment)" class="hiddenlink" target="rightframe"><b>detach</b> +(<code>Fragment</code>)</A></nobr><br> +<!-- Method dismissDialog --> +<nobr><A HREF="android.app.Activity.html#android.app.Activity.dismissDialog_changed(int)" class="hiddenlink" target="rightframe">dismissDialog +(<code>int</code>)</A></nobr><br> +<!-- Class Display --> +<A HREF="android.view.Display.html" class="hiddenlink" target="rightframe">Display</A><br> +<!-- Class DisplayMetrics --> +<A HREF="android.util.DisplayMetrics.html" class="hiddenlink" target="rightframe">DisplayMetrics</A><br> +<!-- Method dumpAsync --> +<i>dumpAsync</i><br> + <nobr><A HREF="android.os.Binder.html#android.os.Binder.dumpAsync_added(java.io.FileDescriptor, java.lang.String[])" class="hiddenlink" target="rightframe">type <b> +(<code>FileDescriptor, String[]</code>)</b> in android.os.Binder +</A></nobr><br> +<!-- Method dumpAsync --> + <nobr><A HREF="android.os.IBinder.html#android.os.IBinder.dumpAsync_added(java.io.FileDescriptor, java.lang.String[])" class="hiddenlink" target="rightframe">type <b> +(<code>FileDescriptor, String[]</code>)</b> in android.os.IBinder +</A></nobr><br> +<!-- Method dup --> +<nobr><A HREF="android.os.ParcelFileDescriptor.html#android.os.ParcelFileDescriptor.dup_added(java.io.FileDescriptor)" class="hiddenlink" target="rightframe"><b>dup</b> +(<code>FileDescriptor</code>)</A></nobr><br> +<!-- Method exitKeyguardSecurely --> +<A NAME="E"></A> +<br><font size="+2">E</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.app.KeyguardManager.html#android.app.KeyguardManager.exitKeyguardSecurely_changed(android.app.KeyguardManager.OnKeyguardExitResult)" class="hiddenlink" target="rightframe">exitKeyguardSecurely +(<code>OnKeyguardExitResult</code>)</A></nobr><br> +<!-- Field FEATURE_FAKETOUCH_MULTITOUCH_DISTINCT --> +<A NAME="F"></A> +<br><font size="+2">F</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.content.pm.PackageManager.html#android.content.pm.PackageManager.FEATURE_FAKETOUCH_MULTITOUCH_DISTINCT" class="hiddenlink" target="rightframe">FEATURE_FAKETOUCH_MULTITOUCH_DISTINCT</A> +</nobr><br> +<!-- Field FEATURE_FAKETOUCH_MULTITOUCH_JAZZHAND --> +<nobr><A HREF="android.content.pm.PackageManager.html#android.content.pm.PackageManager.FEATURE_FAKETOUCH_MULTITOUCH_JAZZHAND" class="hiddenlink" target="rightframe">FEATURE_FAKETOUCH_MULTITOUCH_JAZZHAND</A> +</nobr><br> +<!-- Field FEATURE_SCREEN_LANDSCAPE --> +<nobr><A HREF="android.content.pm.PackageManager.html#android.content.pm.PackageManager.FEATURE_SCREEN_LANDSCAPE" class="hiddenlink" target="rightframe">FEATURE_SCREEN_LANDSCAPE</A> +</nobr><br> +<!-- Field FEATURE_SCREEN_PORTRAIT --> +<nobr><A HREF="android.content.pm.PackageManager.html#android.content.pm.PackageManager.FEATURE_SCREEN_PORTRAIT" class="hiddenlink" target="rightframe">FEATURE_SCREEN_PORTRAIT</A> +</nobr><br> +<!-- Class Fragment --> +<A HREF="android.app.Fragment.html" class="hiddenlink" target="rightframe">Fragment</A><br> +<!-- Class Fragment.SavedState --> +<A HREF="pkg_android.app.html#Fragment.SavedState" class="hiddenlink" target="rightframe"><b>Fragment.SavedState</b></A><br> +<!-- Class FragmentManager --> +<A HREF="android.app.FragmentManager.html" class="hiddenlink" target="rightframe">FragmentManager</A><br> +<!-- Class FragmentTransaction --> +<A HREF="android.app.FragmentTransaction.html" class="hiddenlink" target="rightframe">FragmentTransaction</A><br> +<!-- Method fromFd --> +<nobr><A HREF="android.os.ParcelFileDescriptor.html#android.os.ParcelFileDescriptor.fromFd_added(int)" class="hiddenlink" target="rightframe"><b>fromFd</b> +(<code>int</code>)</A></nobr><br> +<!-- Method getHeight --> +<A NAME="G"></A> +<br><font size="+2">G</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.view.Display.html#android.view.Display.getHeight_changed()" class="hiddenlink" target="rightframe">getHeight +()</A></nobr><br> +<!-- Method getLastNonConfigurationInstance --> +<nobr><A HREF="android.app.Activity.html#android.app.Activity.getLastNonConfigurationInstance_changed()" class="hiddenlink" target="rightframe">getLastNonConfigurationInstance +()</A></nobr><br> +<!-- Method getModifiers --> +<nobr><A HREF="android.view.KeyEvent.html#android.view.KeyEvent.getModifiers_added()" class="hiddenlink" target="rightframe"><b>getModifiers</b> +()</A></nobr><br> +<!-- Method getRawDescriptors --> +<nobr><A HREF="android.hardware.usb.UsbDeviceConnection.html#android.hardware.usb.UsbDeviceConnection.getRawDescriptors_added()" class="hiddenlink" target="rightframe"><b>getRawDescriptors</b> +()</A></nobr><br> +<!-- Method getRectSize --> +<nobr><A HREF="android.view.Display.html#android.view.Display.getRectSize_added(android.graphics.Rect)" class="hiddenlink" target="rightframe"><b>getRectSize</b> +(<code>Rect</code>)</A></nobr><br> +<!-- Method getSize --> +<nobr><A HREF="android.view.Display.html#android.view.Display.getSize_added(android.graphics.Point)" class="hiddenlink" target="rightframe"><b>getSize</b> +(<code>Point</code>)</A></nobr><br> +<!-- Method getWidth --> +<nobr><A HREF="android.view.Display.html#android.view.Display.getWidth_changed()" class="hiddenlink" target="rightframe">getWidth +()</A></nobr><br> +<!-- Field HONEYCOMB_MR2 --> +<A NAME="H"></A> +<br><font size="+2">H</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.os.Build.VERSION_CODES.html#android.os.Build.VERSION_CODES.HONEYCOMB_MR2" class="hiddenlink" target="rightframe">HONEYCOMB_MR2</A> +</nobr><br> +<!-- Class IBinder --> +<A NAME="I"></A> +<br><font size="+2">I</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<A HREF="android.os.IBinder.html" class="hiddenlink" target="rightframe"><i>IBinder</i></A><br> +<!-- Method isDetached --> +<nobr><A HREF="android.app.Fragment.html#android.app.Fragment.isDetached_added()" class="hiddenlink" target="rightframe"><b>isDetached</b> +()</A></nobr><br> +<!-- Class KeyEvent --> +<A NAME="K"></A> +<br><font size="+2">K</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<A HREF="android.view.KeyEvent.html" class="hiddenlink" target="rightframe">KeyEvent</A><br> +<!-- Class KeyguardManager --> +<A HREF="android.app.KeyguardManager.html" class="hiddenlink" target="rightframe">KeyguardManager</A><br> +<!-- Class KeyguardManager.KeyguardLock --> +<A HREF="android.app.KeyguardManager.KeyguardLock.html" class="hiddenlink" target="rightframe">KeyguardManager.KeyguardLock</A><br> +<!-- Field largestWidthLimitDp --> +<A NAME="L"></A> +<br><font size="+2">L</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<i>largestWidthLimitDp</i><br> +<nobr> in +<A HREF="android.R.attr.html#android.R.attr.largestWidthLimitDp" class="hiddenlink" target="rightframe">android.R.attr</A> +</nobr><br> +<!-- Field largestWidthLimitDp --> +<nobr> in +<A HREF="android.content.pm.ApplicationInfo.html#android.content.pm.ApplicationInfo.largestWidthLimitDp" class="hiddenlink" target="rightframe">android.content.pm.ApplicationInfo</A> +</nobr><br> +<!-- Class LocalActivityManager --> +<A HREF="android.app.LocalActivityManager.html" class="hiddenlink" target="rightframe">LocalActivityManager</A><br> +<!-- Class Manifest.permission --> +<A NAME="M"></A> +<br><font size="+2">M</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<A HREF="android.Manifest.permission.html" class="hiddenlink" target="rightframe">Manifest.permission</A><br> +<!-- Field NETWORK_TYPE_HSPAP --> +<A NAME="N"></A> +<br><font size="+2">N</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.telephony.TelephonyManager.html#android.telephony.TelephonyManager.NETWORK_TYPE_HSPAP" class="hiddenlink" target="rightframe">NETWORK_TYPE_HSPAP</A> +</nobr><br> +<!-- Method newKeyguardLock --> +<nobr><A HREF="android.app.KeyguardManager.html#android.app.KeyguardManager.newKeyguardLock_changed(java.lang.String)" class="hiddenlink" target="rightframe">newKeyguardLock +(<code>String</code>)</A></nobr><br> +<!-- Method onCreateDialog --> +<A NAME="O"></A> +<br><font size="+2">O</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.app.Activity.html#android.app.Activity.onCreateDialog_changed(int, android.os.Bundle)" class="hiddenlink" target="rightframe">onCreateDialog +(<code>int, Bundle</code>)</A></nobr><br> +<!-- Method onPrepareDialog --> +<nobr><A HREF="android.app.Activity.html#android.app.Activity.onPrepareDialog_changed(int, android.app.Dialog, android.os.Bundle)" class="hiddenlink" target="rightframe">onPrepareDialog +(<code>int, Dialog, Bundle</code>)</A></nobr><br> +<!-- Method onRetainNonConfigurationInstance --> +<nobr><A HREF="android.app.Activity.html#android.app.Activity.onRetainNonConfigurationInstance_changed()" class="hiddenlink" target="rightframe">onRetainNonConfigurationInstance +()</A></nobr><br> +<!-- Method onViewCreated --> +<nobr><A HREF="android.app.Fragment.html#android.app.Fragment.onViewCreated_added(android.view.View, android.os.Bundle)" class="hiddenlink" target="rightframe"><b>onViewCreated</b> +(<code>View, Bundle</code>)</A></nobr><br> +<!-- Class PackageManager --> +<A NAME="P"></A> +<br><font size="+2">P</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<A HREF="android.content.pm.PackageManager.html" class="hiddenlink" target="rightframe">PackageManager</A><br> +<!-- Class Parcelable.ClassLoaderCreator --> +<A HREF="pkg_android.os.html#Parcelable.ClassLoaderCreator" class="hiddenlink" target="rightframe"><b><i>Parcelable.ClassLoaderCreator</i></b></A><br> +<!-- Class ParcelFileDescriptor --> +<A HREF="android.os.ParcelFileDescriptor.html" class="hiddenlink" target="rightframe">ParcelFileDescriptor</A><br> +<!-- Class Point --> +<A HREF="android.graphics.Point.html" class="hiddenlink" target="rightframe">Point</A><br> +<!-- Class PointF --> +<A HREF="android.graphics.PointF.html" class="hiddenlink" target="rightframe">PointF</A><br> +<!-- Class PowerManager --> +<A HREF="android.os.PowerManager.html" class="hiddenlink" target="rightframe">PowerManager</A><br> +<!-- Class R.attr --> +<A NAME="R"></A> +<br><font size="+2">R</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<A HREF="android.R.attr.html" class="hiddenlink" target="rightframe">R.attr</A><br> +<!-- Class R.style --> +<A HREF="android.R.style.html" class="hiddenlink" target="rightframe">R.style</A><br> +<!-- Method readFromParcel --> +<i>readFromParcel</i><br> + <nobr><A HREF="android.graphics.Point.html#android.graphics.Point.readFromParcel_added(android.os.Parcel)" class="hiddenlink" target="rightframe">type <b> +(<code>Parcel</code>)</b> in android.graphics.Point +</A></nobr><br> +<!-- Method readFromParcel --> + <nobr><A HREF="android.graphics.PointF.html#android.graphics.PointF.readFromParcel_added(android.os.Parcel)" class="hiddenlink" target="rightframe">type <b> +(<code>Parcel</code>)</b> in android.graphics.PointF +</A></nobr><br> +<!-- Method removeDialog --> +<nobr><A HREF="android.app.Activity.html#android.app.Activity.removeDialog_changed(int)" class="hiddenlink" target="rightframe">removeDialog +(<code>int</code>)</A></nobr><br> +<!-- Field requiresSmallestWidthDp --> +<i>requiresSmallestWidthDp</i><br> +<nobr> in +<A HREF="android.R.attr.html#android.R.attr.requiresSmallestWidthDp" class="hiddenlink" target="rightframe">android.R.attr</A> +</nobr><br> +<!-- Field requiresSmallestWidthDp --> +<nobr> in +<A HREF="android.content.pm.ApplicationInfo.html#android.content.pm.ApplicationInfo.requiresSmallestWidthDp" class="hiddenlink" target="rightframe">android.content.pm.ApplicationInfo</A> +</nobr><br> +<!-- Method saveFragmentInstanceState --> +<A NAME="S"></A> +<br><font size="+2">S</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.app.FragmentManager.html#android.app.FragmentManager.saveFragmentInstanceState_added(android.app.Fragment)" class="hiddenlink" target="rightframe"><b>saveFragmentInstanceState</b> +(<code>Fragment</code>)</A></nobr><br> +<!-- Field SCREEN_BRIGHT_WAKE_LOCK --> +<nobr><A HREF="android.os.PowerManager.html#android.os.PowerManager.SCREEN_BRIGHT_WAKE_LOCK" class="hiddenlink" target="rightframe">SCREEN_BRIGHT_WAKE_LOCK</A> +</nobr><br> +<!-- Field SCREEN_HEIGHT_DP_UNDEFINED --> +<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.SCREEN_HEIGHT_DP_UNDEFINED" class="hiddenlink" target="rightframe">SCREEN_HEIGHT_DP_UNDEFINED</A> +</nobr><br> +<!-- Field SCREEN_WIDTH_DP_UNDEFINED --> +<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.SCREEN_WIDTH_DP_UNDEFINED" class="hiddenlink" target="rightframe">SCREEN_WIDTH_DP_UNDEFINED</A> +</nobr><br> +<!-- Field screenHeightDp --> +<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.screenHeightDp" class="hiddenlink" target="rightframe">screenHeightDp</A> +</nobr><br> +<!-- Field screenWidthDp --> +<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.screenWidthDp" class="hiddenlink" target="rightframe">screenWidthDp</A> +</nobr><br> +<!-- Field SET_POINTER_SPEED --> +<nobr><A HREF="android.Manifest.permission.html#android.Manifest.permission.SET_POINTER_SPEED" class="hiddenlink" target="rightframe">SET_POINTER_SPEED</A> +</nobr><br> +<!-- Method setCustomAnimations --> +<nobr><A HREF="android.app.FragmentTransaction.html#android.app.FragmentTransaction.setCustomAnimations_added(int, int, int, int)" class="hiddenlink" target="rightframe"><b>setCustomAnimations</b> +(<code>int, int, int, int</code>)</A></nobr><br> +<!-- Method setInitialSavedState --> +<nobr><A HREF="android.app.Fragment.html#android.app.Fragment.setInitialSavedState_added(android.app.Fragment.SavedState)" class="hiddenlink" target="rightframe"><b>setInitialSavedState</b> +(<code>SavedState</code>)</A></nobr><br> +<!-- Method showDialog --> +<i>showDialog</i><br> + <nobr><A HREF="android.app.Activity.html#android.app.Activity.showDialog_changed(int, android.os.Bundle)" class="hiddenlink" target="rightframe">type +(<code>int, Bundle</code>) in android.app.Activity +</A></nobr><br> +<!-- Method showDialog --> + <nobr><A HREF="android.app.Activity.html#android.app.Activity.showDialog_changed(int)" class="hiddenlink" target="rightframe">type +(<code>int</code>) in android.app.Activity +</A></nobr><br> +<!-- Field SMALLEST_SCREEN_WIDTH_DP_UNDEFINED --> +<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED" class="hiddenlink" target="rightframe">SMALLEST_SCREEN_WIDTH_DP_UNDEFINED</A> +</nobr><br> +<!-- Field smallestScreenWidthDp --> +<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.smallestScreenWidthDp" class="hiddenlink" target="rightframe">smallestScreenWidthDp</A> +</nobr><br> +<!-- Class TabActivity --> +<A NAME="T"></A> +<br><font size="+2">T</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<A HREF="android.app.TabActivity.html" class="hiddenlink" target="rightframe">TabActivity</A><br> +<!-- Class TelephonyManager --> +<A HREF="android.telephony.TelephonyManager.html" class="hiddenlink" target="rightframe">TelephonyManager</A><br> +<!-- Field TextAppearance_Holo --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo" class="hiddenlink" target="rightframe">TextAppearance_Holo</A> +</nobr><br> +<!-- Field TextAppearance_Holo_DialogWindowTitle --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_DialogWindowTitle" class="hiddenlink" target="rightframe">TextAppearance_Holo_DialogWindowTitle</A> +</nobr><br> +<!-- Field TextAppearance_Holo_Inverse --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Inverse" class="hiddenlink" target="rightframe">TextAppearance_Holo_Inverse</A> +</nobr><br> +<!-- Field TextAppearance_Holo_Large --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Large" class="hiddenlink" target="rightframe">TextAppearance_Holo_Large</A> +</nobr><br> +<!-- Field TextAppearance_Holo_Large_Inverse --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Large_Inverse" class="hiddenlink" target="rightframe">TextAppearance_Holo_Large_Inverse</A> +</nobr><br> +<!-- Field TextAppearance_Holo_Medium --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Medium" class="hiddenlink" target="rightframe">TextAppearance_Holo_Medium</A> +</nobr><br> +<!-- Field TextAppearance_Holo_Medium_Inverse --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Medium_Inverse" class="hiddenlink" target="rightframe">TextAppearance_Holo_Medium_Inverse</A> +</nobr><br> +<!-- Field TextAppearance_Holo_SearchResult_Subtitle --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_SearchResult_Subtitle" class="hiddenlink" target="rightframe">TextAppearance_Holo_SearchResult_Subtitle</A> +</nobr><br> +<!-- Field TextAppearance_Holo_SearchResult_Title --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_SearchResult_Title" class="hiddenlink" target="rightframe">TextAppearance_Holo_SearchResult_Title</A> +</nobr><br> +<!-- Field TextAppearance_Holo_Small --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Small" class="hiddenlink" target="rightframe">TextAppearance_Holo_Small</A> +</nobr><br> +<!-- Field TextAppearance_Holo_Small_Inverse --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Small_Inverse" class="hiddenlink" target="rightframe">TextAppearance_Holo_Small_Inverse</A> +</nobr><br> +<!-- Field TextAppearance_Holo_Widget --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget</A> +</nobr><br> +<!-- Field TextAppearance_Holo_Widget_ActionBar_Subtitle --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_ActionBar_Subtitle" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_ActionBar_Subtitle</A> +</nobr><br> +<!-- Field TextAppearance_Holo_Widget_ActionBar_Title --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_ActionBar_Title" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_ActionBar_Title</A> +</nobr><br> +<!-- Field TextAppearance_Holo_Widget_ActionMode_Subtitle --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_ActionMode_Subtitle" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_ActionMode_Subtitle</A> +</nobr><br> +<!-- Field TextAppearance_Holo_Widget_ActionMode_Title --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_ActionMode_Title" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_ActionMode_Title</A> +</nobr><br> +<!-- Field TextAppearance_Holo_Widget_Button --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_Button" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_Button</A> +</nobr><br> +<!-- Field TextAppearance_Holo_Widget_DropDownHint --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_DropDownHint" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_DropDownHint</A> +</nobr><br> +<!-- Field TextAppearance_Holo_Widget_DropDownItem --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_DropDownItem" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_DropDownItem</A> +</nobr><br> +<!-- Field TextAppearance_Holo_Widget_EditText --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_EditText" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_EditText</A> +</nobr><br> +<!-- Field TextAppearance_Holo_Widget_IconMenu_Item --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_IconMenu_Item" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_IconMenu_Item</A> +</nobr><br> +<!-- Field TextAppearance_Holo_Widget_PopupMenu --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_PopupMenu" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_PopupMenu</A> +</nobr><br> +<!-- Field TextAppearance_Holo_Widget_PopupMenu_Large --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_PopupMenu_Large" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_PopupMenu_Large</A> +</nobr><br> +<!-- Field TextAppearance_Holo_Widget_PopupMenu_Small --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_PopupMenu_Small" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_PopupMenu_Small</A> +</nobr><br> +<!-- Field TextAppearance_Holo_Widget_TabWidget --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_TabWidget" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_TabWidget</A> +</nobr><br> +<!-- Field TextAppearance_Holo_Widget_TextView --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_TextView" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_TextView</A> +</nobr><br> +<!-- Field TextAppearance_Holo_Widget_TextView_PopupMenu --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_TextView_PopupMenu" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_TextView_PopupMenu</A> +</nobr><br> +<!-- Field TextAppearance_Holo_Widget_TextView_SpinnerItem --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_TextView_SpinnerItem" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_TextView_SpinnerItem</A> +</nobr><br> +<!-- Field TextAppearance_Holo_WindowTitle --> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_WindowTitle" class="hiddenlink" target="rightframe">TextAppearance_Holo_WindowTitle</A> +</nobr><br> +<!-- Field Theme_Holo_Light_NoActionBar --> +<nobr><A HREF="android.R.style.html#android.R.style.Theme_Holo_Light_NoActionBar" class="hiddenlink" target="rightframe">Theme_Holo_Light_NoActionBar</A> +</nobr><br> +<!-- Field Theme_Holo_Light_NoActionBar_Fullscreen --> +<nobr><A HREF="android.R.style.html#android.R.style.Theme_Holo_Light_NoActionBar_Fullscreen" class="hiddenlink" target="rightframe">Theme_Holo_Light_NoActionBar_Fullscreen</A> +</nobr><br> +<!-- Field TWEET_TRANSACTION --> +<nobr><A HREF="android.os.IBinder.html#android.os.IBinder.TWEET_TRANSACTION" class="hiddenlink" target="rightframe">TWEET_TRANSACTION</A> +</nobr><br> +<!-- Field TYPE_BLUETOOTH --> +<nobr><A HREF="android.net.ConnectivityManager.html#android.net.ConnectivityManager.TYPE_BLUETOOTH" class="hiddenlink" target="rightframe">TYPE_BLUETOOTH</A> +</nobr><br> +<!-- Field TYPE_ETHERNET --> +<nobr><A HREF="android.net.ConnectivityManager.html#android.net.ConnectivityManager.TYPE_ETHERNET" class="hiddenlink" target="rightframe">TYPE_ETHERNET</A> +</nobr><br> +<!-- Field UI_MODE_TYPE_TELEVISION --> +<A NAME="U"></A> +<br><font size="+2">U</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.UI_MODE_TYPE_TELEVISION" class="hiddenlink" target="rightframe">UI_MODE_TYPE_TELEVISION</A> +</nobr><br> +<!-- Class UsbDeviceConnection --> +<A HREF="android.hardware.usb.UsbDeviceConnection.html" class="hiddenlink" target="rightframe">UsbDeviceConnection</A><br> +<!-- Field Widget_ActionBar_TabBar --> +<A NAME="W"></A> +<br><font size="+2">W</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.R.style.html#android.R.style.Widget_ActionBar_TabBar" class="hiddenlink" target="rightframe">Widget_ActionBar_TabBar</A> +</nobr><br> +<!-- Field Widget_ActionBar_TabText --> +<nobr><A HREF="android.R.style.html#android.R.style.Widget_ActionBar_TabText" class="hiddenlink" target="rightframe">Widget_ActionBar_TabText</A> +</nobr><br> +<!-- Field Widget_ActionBar_TabView --> +<nobr><A HREF="android.R.style.html#android.R.style.Widget_ActionBar_TabView" class="hiddenlink" target="rightframe">Widget_ActionBar_TabView</A> +</nobr><br> +<!-- Field Widget_Holo_ActionBar_TabBar --> +<nobr><A HREF="android.R.style.html#android.R.style.Widget_Holo_ActionBar_TabBar" class="hiddenlink" target="rightframe">Widget_Holo_ActionBar_TabBar</A> +</nobr><br> +<!-- Field Widget_Holo_ActionBar_TabText --> +<nobr><A HREF="android.R.style.html#android.R.style.Widget_Holo_ActionBar_TabText" class="hiddenlink" target="rightframe">Widget_Holo_ActionBar_TabText</A> +</nobr><br> +<!-- Field Widget_Holo_ActionBar_TabView --> +<nobr><A HREF="android.R.style.html#android.R.style.Widget_Holo_ActionBar_TabView" class="hiddenlink" target="rightframe">Widget_Holo_ActionBar_TabView</A> +</nobr><br> +<!-- Field Widget_Holo_Light_ActionBar_TabBar --> +<nobr><A HREF="android.R.style.html#android.R.style.Widget_Holo_Light_ActionBar_TabBar" class="hiddenlink" target="rightframe">Widget_Holo_Light_ActionBar_TabBar</A> +</nobr><br> +<!-- Field Widget_Holo_Light_ActionBar_TabText --> +<nobr><A HREF="android.R.style.html#android.R.style.Widget_Holo_Light_ActionBar_TabText" class="hiddenlink" target="rightframe">Widget_Holo_Light_ActionBar_TabText</A> +</nobr><br> +<!-- Field Widget_Holo_Light_ActionBar_TabView --> +<nobr><A HREF="android.R.style.html#android.R.style.Widget_Holo_Light_ActionBar_TabView" class="hiddenlink" target="rightframe">Widget_Holo_Light_ActionBar_TabView</A> +</nobr><br> +<!-- Method writeToParcel --> +<i>writeToParcel</i><br> + <nobr><A HREF="android.graphics.Point.html#android.graphics.Point.writeToParcel_added(android.os.Parcel, int)" class="hiddenlink" target="rightframe">type <b> +(<code>Parcel, int</code>)</b> in android.graphics.Point +</A></nobr><br> +<!-- Method writeToParcel --> + <nobr><A HREF="android.graphics.PointF.html#android.graphics.PointF.writeToParcel_added(android.os.Parcel, int)" class="hiddenlink" target="rightframe">type <b> +(<code>Parcel, int</code>)</b> in android.graphics.PointF +</A></nobr><br> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/alldiffs_index_changes.html b/docs/html/sdk/api_diff/13/changes/alldiffs_index_changes.html new file mode 100644 index 0000000..59e766b --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/alldiffs_index_changes.html @@ -0,0 +1,561 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +All Changes Index +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY class="gc-documentation" style="padding:12px;"> +<a NAME="topheader"></a> +<table summary="Index for All Differences" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;"> + <tr> + <th class="indexHeader"> + Filter the Index: + </th> + </tr> + <tr> + <td class="indexText" style="line-height:1.3em;padding-left:2em;"> +<a href="alldiffs_index_all.html" xclass="hiddenlink">All Differences</a> + <br> +<font color="#999999">Removals</font> + <br> +<A HREF="alldiffs_index_additions.html"xclass="hiddenlink">Additions</A> + <br> +<b>Changes</b> + </td> + </tr> +</table> +<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;"> +Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font> +</div> +<!-- Class Activity --> +<A NAME="A"></A> +<br><font size="+2">A</font> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<A HREF="android.app.Activity.html" class="hiddenlink" target="rightframe">Activity</A><br> +<!-- Class ActivityGroup --> +<A HREF="android.app.ActivityGroup.html" class="hiddenlink" target="rightframe">ActivityGroup</A><br> +<!-- Class ActivityInfo --> +<A HREF="android.content.pm.ActivityInfo.html" class="hiddenlink" target="rightframe">ActivityInfo</A><br> +<!-- Package android --> +<A HREF="pkg_android.html" class="hiddenlink" target="rightframe">android</A><br> +<!-- Package android.app --> +<A HREF="pkg_android.app.html" class="hiddenlink" target="rightframe">android.app</A><br> +<!-- Package android.content.pm --> +<A HREF="pkg_android.content.pm.html" class="hiddenlink" target="rightframe">android.content.pm</A><br> +<!-- Package android.content.res --> +<A HREF="pkg_android.content.res.html" class="hiddenlink" target="rightframe">android.content.res</A><br> +<!-- Package android.graphics --> +<A HREF="pkg_android.graphics.html" class="hiddenlink" target="rightframe">android.graphics</A><br> +<!-- Package android.hardware.usb --> +<A HREF="pkg_android.hardware.usb.html" class="hiddenlink" target="rightframe">android.hardware.usb</A><br> +<!-- Package android.net --> +<A HREF="pkg_android.net.html" class="hiddenlink" target="rightframe">android.net</A><br> +<!-- Package android.os --> +<A HREF="pkg_android.os.html" class="hiddenlink" target="rightframe">android.os</A><br> +<!-- Package android.telephony --> +<A HREF="pkg_android.telephony.html" class="hiddenlink" target="rightframe">android.telephony</A><br> +<!-- Package android.util --> +<A HREF="pkg_android.util.html" class="hiddenlink" target="rightframe">android.util</A><br> +<!-- Package android.view --> +<A HREF="pkg_android.view.html" class="hiddenlink" target="rightframe">android.view</A><br> +<!-- Class ApplicationInfo --> +<A HREF="android.content.pm.ApplicationInfo.html" class="hiddenlink" target="rightframe">ApplicationInfo</A><br> +<!-- Class Binder --> +<A NAME="B"></A> +<br><font size="+2">B</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<A HREF="android.os.Binder.html" class="hiddenlink" target="rightframe">Binder</A><br> +<!-- Class Build.VERSION_CODES --> +<A HREF="android.os.Build.VERSION_CODES.html" class="hiddenlink" target="rightframe">Build.VERSION_CODES</A><br> +<!-- Class Configuration --> +<A NAME="C"></A> +<br><font size="+2">C</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<A HREF="android.content.res.Configuration.html" class="hiddenlink" target="rightframe">Configuration</A><br> +<!-- Class ConnectivityManager --> +<A HREF="android.net.ConnectivityManager.html" class="hiddenlink" target="rightframe">ConnectivityManager</A><br> +<!-- Method dismissDialog --> +<A NAME="D"></A> +<br><font size="+2">D</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.app.Activity.html#android.app.Activity.dismissDialog_changed(int)" class="hiddenlink" target="rightframe">dismissDialog +(<code>int</code>)</A></nobr><br> +<!-- Class Display --> +<A HREF="android.view.Display.html" class="hiddenlink" target="rightframe">Display</A><br> +<!-- Class DisplayMetrics --> +<A HREF="android.util.DisplayMetrics.html" class="hiddenlink" target="rightframe">DisplayMetrics</A><br> +<!-- Method exitKeyguardSecurely --> +<A NAME="E"></A> +<br><font size="+2">E</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.app.KeyguardManager.html#android.app.KeyguardManager.exitKeyguardSecurely_changed(android.app.KeyguardManager.OnKeyguardExitResult)" class="hiddenlink" target="rightframe">exitKeyguardSecurely +(<code>OnKeyguardExitResult</code>)</A></nobr><br> +<!-- Class Fragment --> +<A NAME="F"></A> +<br><font size="+2">F</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<A HREF="android.app.Fragment.html" class="hiddenlink" target="rightframe">Fragment</A><br> +<!-- Class FragmentManager --> +<A HREF="android.app.FragmentManager.html" class="hiddenlink" target="rightframe">FragmentManager</A><br> +<!-- Class FragmentTransaction --> +<A HREF="android.app.FragmentTransaction.html" class="hiddenlink" target="rightframe">FragmentTransaction</A><br> +<!-- Method getHeight --> +<A NAME="G"></A> +<br><font size="+2">G</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.view.Display.html#android.view.Display.getHeight_changed()" class="hiddenlink" target="rightframe">getHeight +()</A></nobr><br> +<!-- Method getLastNonConfigurationInstance --> +<nobr><A HREF="android.app.Activity.html#android.app.Activity.getLastNonConfigurationInstance_changed()" class="hiddenlink" target="rightframe">getLastNonConfigurationInstance +()</A></nobr><br> +<!-- Method getWidth --> +<nobr><A HREF="android.view.Display.html#android.view.Display.getWidth_changed()" class="hiddenlink" target="rightframe">getWidth +()</A></nobr><br> +<!-- Class IBinder --> +<A NAME="I"></A> +<br><font size="+2">I</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<A HREF="android.os.IBinder.html" class="hiddenlink" target="rightframe"><i>IBinder</i></A><br> +<!-- Class KeyEvent --> +<A NAME="K"></A> +<br><font size="+2">K</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<A HREF="android.view.KeyEvent.html" class="hiddenlink" target="rightframe">KeyEvent</A><br> +<!-- Class KeyguardManager --> +<A HREF="android.app.KeyguardManager.html" class="hiddenlink" target="rightframe">KeyguardManager</A><br> +<!-- Class KeyguardManager.KeyguardLock --> +<A HREF="android.app.KeyguardManager.KeyguardLock.html" class="hiddenlink" target="rightframe">KeyguardManager.KeyguardLock</A><br> +<!-- Class LocalActivityManager --> +<A NAME="L"></A> +<br><font size="+2">L</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<A HREF="android.app.LocalActivityManager.html" class="hiddenlink" target="rightframe">LocalActivityManager</A><br> +<!-- Class Manifest.permission --> +<A NAME="M"></A> +<br><font size="+2">M</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<A HREF="android.Manifest.permission.html" class="hiddenlink" target="rightframe">Manifest.permission</A><br> +<!-- Method newKeyguardLock --> +<A NAME="N"></A> +<br><font size="+2">N</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.app.KeyguardManager.html#android.app.KeyguardManager.newKeyguardLock_changed(java.lang.String)" class="hiddenlink" target="rightframe">newKeyguardLock +(<code>String</code>)</A></nobr><br> +<!-- Method onCreateDialog --> +<A NAME="O"></A> +<br><font size="+2">O</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.app.Activity.html#android.app.Activity.onCreateDialog_changed(int, android.os.Bundle)" class="hiddenlink" target="rightframe">onCreateDialog +(<code>int, Bundle</code>)</A></nobr><br> +<!-- Method onPrepareDialog --> +<nobr><A HREF="android.app.Activity.html#android.app.Activity.onPrepareDialog_changed(int, android.app.Dialog, android.os.Bundle)" class="hiddenlink" target="rightframe">onPrepareDialog +(<code>int, Dialog, Bundle</code>)</A></nobr><br> +<!-- Method onRetainNonConfigurationInstance --> +<nobr><A HREF="android.app.Activity.html#android.app.Activity.onRetainNonConfigurationInstance_changed()" class="hiddenlink" target="rightframe">onRetainNonConfigurationInstance +()</A></nobr><br> +<!-- Class PackageManager --> +<A NAME="P"></A> +<br><font size="+2">P</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<A HREF="android.content.pm.PackageManager.html" class="hiddenlink" target="rightframe">PackageManager</A><br> +<!-- Class ParcelFileDescriptor --> +<A HREF="android.os.ParcelFileDescriptor.html" class="hiddenlink" target="rightframe">ParcelFileDescriptor</A><br> +<!-- Class Point --> +<A HREF="android.graphics.Point.html" class="hiddenlink" target="rightframe">Point</A><br> +<!-- Class PointF --> +<A HREF="android.graphics.PointF.html" class="hiddenlink" target="rightframe">PointF</A><br> +<!-- Class PowerManager --> +<A HREF="android.os.PowerManager.html" class="hiddenlink" target="rightframe">PowerManager</A><br> +<!-- Class R.attr --> +<A NAME="R"></A> +<br><font size="+2">R</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<A HREF="android.R.attr.html" class="hiddenlink" target="rightframe">R.attr</A><br> +<!-- Class R.style --> +<A HREF="android.R.style.html" class="hiddenlink" target="rightframe">R.style</A><br> +<!-- Method removeDialog --> +<nobr><A HREF="android.app.Activity.html#android.app.Activity.removeDialog_changed(int)" class="hiddenlink" target="rightframe">removeDialog +(<code>int</code>)</A></nobr><br> +<!-- Field SCREEN_BRIGHT_WAKE_LOCK --> +<A NAME="S"></A> +<br><font size="+2">S</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.os.PowerManager.html#android.os.PowerManager.SCREEN_BRIGHT_WAKE_LOCK" class="hiddenlink" target="rightframe">SCREEN_BRIGHT_WAKE_LOCK</A> +</nobr><br> +<!-- Method showDialog --> +<i>showDialog</i><br> + <nobr><A HREF="android.app.Activity.html#android.app.Activity.showDialog_changed(int, android.os.Bundle)" class="hiddenlink" target="rightframe">type +(<code>int, Bundle</code>) in android.app.Activity +</A></nobr><br> +<!-- Method showDialog --> + <nobr><A HREF="android.app.Activity.html#android.app.Activity.showDialog_changed(int)" class="hiddenlink" target="rightframe">type +(<code>int</code>) in android.app.Activity +</A></nobr><br> +<!-- Class TabActivity --> +<A NAME="T"></A> +<br><font size="+2">T</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#U"><font size="-2">U</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<A HREF="android.app.TabActivity.html" class="hiddenlink" target="rightframe">TabActivity</A><br> +<!-- Class TelephonyManager --> +<A HREF="android.telephony.TelephonyManager.html" class="hiddenlink" target="rightframe">TelephonyManager</A><br> +<!-- Class UsbDeviceConnection --> +<A NAME="U"></A> +<br><font size="+2">U</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<A HREF="android.hardware.usb.UsbDeviceConnection.html" class="hiddenlink" target="rightframe">UsbDeviceConnection</A><br> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/alldiffs_index_removals.html b/docs/html/sdk/api_diff/13/changes/alldiffs_index_removals.html new file mode 100644 index 0000000..68d2c20 --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/alldiffs_index_removals.html @@ -0,0 +1,61 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +All Removals Index +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY class="gc-documentation" style="padding:12px;"> +<a NAME="topheader"></a> +<table summary="Index for All Differences" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;"> + <tr> + <th class="indexHeader"> + Filter the Index: + </th> + </tr> + <tr> + <td class="indexText" style="line-height:1.3em;padding-left:2em;"> +<a href="alldiffs_index_all.html" xclass="hiddenlink">All Differences</a> + <br> +<font color="#999999">Removals</font> + <br> +<A HREF="alldiffs_index_additions.html"xclass="hiddenlink">Additions</A> + <br> +<A HREF="alldiffs_index_changes.html"xclass="hiddenlink">Changes</A> + </td> + </tr> +</table> +<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;"> +Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font> +</div> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/android.Manifest.permission.html b/docs/html/sdk/api_diff/13/changes/android.Manifest.permission.html new file mode 100644 index 0000000..5d3cbda --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/android.Manifest.permission.html @@ -0,0 +1,122 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +android.Manifest.permission +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY> +<!-- Start of nav bar --> +<a name="top"></a> +<div id="header" style="margin-bottom:0;padding-bottom:0;"> +<div id="headerLeft"> +<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a> +</div> + <div id="headerRight"> + <div id="headerLinks"> +<!-- <img src="/assets/images/icon_world.jpg" alt="" /> --> +<span class="text"> +<!-- <a href="#">English</a> | --> +<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr> +</span> +</div> + <div class="and-diff-id" style="margin-top:6px;margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td colspan="2" class="diffspechead">API Diff Specification</td> + </tr> + <tr> + <td class="diffspec" style="padding-top:.25em">To Level:</td> + <td class="diffvaluenew" style="padding-top:.25em">13</td> + </tr> + <tr> + <td class="diffspec">From Level:</td> + <td class="diffvalueold">12</td> + </tr> + <tr> + <td class="diffspec">Generated</td> + <td class="diffvalue">2011.06.29 10:50</td> + </tr> + </table> + </div><!-- End and-diff-id --> + <div class="and-diff-id" style="margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a> + </tr> + </table> + </div> <!-- End and-diff-id --> + </div> <!-- End headerRight --> + </div> <!-- End header --> +<div id="body-content" xstyle="padding:12px;padding-right:18px;"> +<div id="doc-content" style="position:relative;"> +<div id="mainBodyFluid"> +<H2> +Class android.<A HREF="../../../../reference/android/Manifest.permission.html" target="_top"><font size="+2"><code>Manifest.permission</code></font></A> +</H2> +<a NAME="constructors"></a> +<a NAME="methods"></a> +<a NAME="fields"></a> +<p> +<a NAME="Added"></a> +<TABLE summary="Added Fields" WIDTH="100%"> +<TR> + <TH VALIGN="TOP" COLSPAN=2>Added Fields</FONT></TD> +</TH> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.Manifest.permission.SET_POINTER_SPEED"></A> + <nobr><code>String</code> <A HREF="../../../../reference/android/Manifest.permission.html#SET_POINTER_SPEED" target="_top"><code>SET_POINTER_SPEED</code></A></nobr> + </TD> + <TD> </TD> +</TR> +</TABLE> + + </div> + <div id="footer"> + <div id="copyright"> + Except as noted, this content is licensed under + <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>. + For details and restrictions, see the <a href="/license.html">Content License</a>. + </div> + <div id="footerlinks"> + <p> + <a href="http://www.android.com/terms.html">Site Terms of Service</a> - + <a href="http://www.android.com/privacy.html">Privacy Policy</a> - + <a href="http://www.android.com/branding.html">Brand Guidelines</a> + </p> + </div> + </div> <!-- end footer --> + </div><!-- end doc-content --> + </div> <!-- end body-content --> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/android.R.attr.html b/docs/html/sdk/api_diff/13/changes/android.R.attr.html new file mode 100644 index 0000000..f8eb54b --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/android.R.attr.html @@ -0,0 +1,136 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +android.R.attr +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY> +<!-- Start of nav bar --> +<a name="top"></a> +<div id="header" style="margin-bottom:0;padding-bottom:0;"> +<div id="headerLeft"> +<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a> +</div> + <div id="headerRight"> + <div id="headerLinks"> +<!-- <img src="/assets/images/icon_world.jpg" alt="" /> --> +<span class="text"> +<!-- <a href="#">English</a> | --> +<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr> +</span> +</div> + <div class="and-diff-id" style="margin-top:6px;margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td colspan="2" class="diffspechead">API Diff Specification</td> + </tr> + <tr> + <td class="diffspec" style="padding-top:.25em">To Level:</td> + <td class="diffvaluenew" style="padding-top:.25em">13</td> + </tr> + <tr> + <td class="diffspec">From Level:</td> + <td class="diffvalueold">12</td> + </tr> + <tr> + <td class="diffspec">Generated</td> + <td class="diffvalue">2011.06.29 10:50</td> + </tr> + </table> + </div><!-- End and-diff-id --> + <div class="and-diff-id" style="margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a> + </tr> + </table> + </div> <!-- End and-diff-id --> + </div> <!-- End headerRight --> + </div> <!-- End header --> +<div id="body-content" xstyle="padding:12px;padding-right:18px;"> +<div id="doc-content" style="position:relative;"> +<div id="mainBodyFluid"> +<H2> +Class android.<A HREF="../../../../reference/android/R.attr.html" target="_top"><font size="+2"><code>R.attr</code></font></A> +</H2> +<a NAME="constructors"></a> +<a NAME="methods"></a> +<a NAME="fields"></a> +<p> +<a NAME="Added"></a> +<TABLE summary="Added Fields" WIDTH="100%"> +<TR> + <TH VALIGN="TOP" COLSPAN=2>Added Fields</FONT></TD> +</TH> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.R.attr.compatibleWidthLimitDp"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/R.attr.html#compatibleWidthLimitDp" target="_top"><code>compatibleWidthLimitDp</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.R.attr.largestWidthLimitDp"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/R.attr.html#largestWidthLimitDp" target="_top"><code>largestWidthLimitDp</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.R.attr.requiresSmallestWidthDp"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/R.attr.html#requiresSmallestWidthDp" target="_top"><code>requiresSmallestWidthDp</code></A></nobr> + </TD> + <TD> </TD> +</TR> +</TABLE> + + </div> + <div id="footer"> + <div id="copyright"> + Except as noted, this content is licensed under + <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>. + For details and restrictions, see the <a href="/license.html">Content License</a>. + </div> + <div id="footerlinks"> + <p> + <a href="http://www.android.com/terms.html">Site Terms of Service</a> - + <a href="http://www.android.com/privacy.html">Privacy Policy</a> - + <a href="http://www.android.com/branding.html">Brand Guidelines</a> + </p> + </div> + </div> <!-- end footer --> + </div><!-- end doc-content --> + </div> <!-- end body-content --> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/android.R.style.html b/docs/html/sdk/api_diff/13/changes/android.R.style.html new file mode 100644 index 0000000..9e385e2 --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/android.R.style.html @@ -0,0 +1,395 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +android.R.style +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY> +<!-- Start of nav bar --> +<a name="top"></a> +<div id="header" style="margin-bottom:0;padding-bottom:0;"> +<div id="headerLeft"> +<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a> +</div> + <div id="headerRight"> + <div id="headerLinks"> +<!-- <img src="/assets/images/icon_world.jpg" alt="" /> --> +<span class="text"> +<!-- <a href="#">English</a> | --> +<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr> +</span> +</div> + <div class="and-diff-id" style="margin-top:6px;margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td colspan="2" class="diffspechead">API Diff Specification</td> + </tr> + <tr> + <td class="diffspec" style="padding-top:.25em">To Level:</td> + <td class="diffvaluenew" style="padding-top:.25em">13</td> + </tr> + <tr> + <td class="diffspec">From Level:</td> + <td class="diffvalueold">12</td> + </tr> + <tr> + <td class="diffspec">Generated</td> + <td class="diffvalue">2011.06.29 10:50</td> + </tr> + </table> + </div><!-- End and-diff-id --> + <div class="and-diff-id" style="margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a> + </tr> + </table> + </div> <!-- End and-diff-id --> + </div> <!-- End headerRight --> + </div> <!-- End header --> +<div id="body-content" xstyle="padding:12px;padding-right:18px;"> +<div id="doc-content" style="position:relative;"> +<div id="mainBodyFluid"> +<H2> +Class android.<A HREF="../../../../reference/android/R.style.html" target="_top"><font size="+2"><code>R.style</code></font></A> +</H2> +<a NAME="constructors"></a> +<a NAME="methods"></a> +<a NAME="fields"></a> +<p> +<a NAME="Added"></a> +<TABLE summary="Added Fields" WIDTH="100%"> +<TR> + <TH VALIGN="TOP" COLSPAN=2>Added Fields</FONT></TD> +</TH> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.R.style.TextAppearance_Holo"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo" target="_top"><code>TextAppearance_Holo</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.R.style.TextAppearance_Holo_DialogWindowTitle"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_DialogWindowTitle" target="_top"><code>TextAppearance_Holo_DialogWindowTitle</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.R.style.TextAppearance_Holo_Inverse"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_Inverse" target="_top"><code>TextAppearance_Holo_Inverse</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.R.style.TextAppearance_Holo_Large"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_Large" target="_top"><code>TextAppearance_Holo_Large</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.R.style.TextAppearance_Holo_Large_Inverse"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_Large_Inverse" target="_top"><code>TextAppearance_Holo_Large_Inverse</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.R.style.TextAppearance_Holo_Medium"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_Medium" target="_top"><code>TextAppearance_Holo_Medium</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.R.style.TextAppearance_Holo_Medium_Inverse"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_Medium_Inverse" target="_top"><code>TextAppearance_Holo_Medium_Inverse</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.R.style.TextAppearance_Holo_SearchResult_Subtitle"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_SearchResult_Subtitle" target="_top"><code>TextAppearance_Holo_SearchResult_Subtitle</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.R.style.TextAppearance_Holo_SearchResult_Title"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_SearchResult_Title" target="_top"><code>TextAppearance_Holo_SearchResult_Title</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.R.style.TextAppearance_Holo_Small"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_Small" target="_top"><code>TextAppearance_Holo_Small</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.R.style.TextAppearance_Holo_Small_Inverse"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_Small_Inverse" target="_top"><code>TextAppearance_Holo_Small_Inverse</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.R.style.TextAppearance_Holo_Widget"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_Widget" target="_top"><code>TextAppearance_Holo_Widget</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.R.style.TextAppearance_Holo_Widget_ActionBar_Subtitle"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_Widget_ActionBar_Subtitle" target="_top"><code>TextAppearance_Holo_Widget_ActionBar_Subtitle</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.R.style.TextAppearance_Holo_Widget_ActionBar_Title"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_Widget_ActionBar_Title" target="_top"><code>TextAppearance_Holo_Widget_ActionBar_Title</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.R.style.TextAppearance_Holo_Widget_ActionMode_Subtitle"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_Widget_ActionMode_Subtitle" target="_top"><code>TextAppearance_Holo_Widget_ActionMode_Subtitle</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.R.style.TextAppearance_Holo_Widget_ActionMode_Title"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_Widget_ActionMode_Title" target="_top"><code>TextAppearance_Holo_Widget_ActionMode_Title</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.R.style.TextAppearance_Holo_Widget_Button"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_Widget_Button" target="_top"><code>TextAppearance_Holo_Widget_Button</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.R.style.TextAppearance_Holo_Widget_DropDownHint"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_Widget_DropDownHint" target="_top"><code>TextAppearance_Holo_Widget_DropDownHint</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.R.style.TextAppearance_Holo_Widget_DropDownItem"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_Widget_DropDownItem" target="_top"><code>TextAppearance_Holo_Widget_DropDownItem</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.R.style.TextAppearance_Holo_Widget_EditText"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_Widget_EditText" target="_top"><code>TextAppearance_Holo_Widget_EditText</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.R.style.TextAppearance_Holo_Widget_IconMenu_Item"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_Widget_IconMenu_Item" target="_top"><code>TextAppearance_Holo_Widget_IconMenu_Item</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.R.style.TextAppearance_Holo_Widget_PopupMenu"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_Widget_PopupMenu" target="_top"><code>TextAppearance_Holo_Widget_PopupMenu</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.R.style.TextAppearance_Holo_Widget_PopupMenu_Large"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_Widget_PopupMenu_Large" target="_top"><code>TextAppearance_Holo_Widget_PopupMenu_Large</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.R.style.TextAppearance_Holo_Widget_PopupMenu_Small"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_Widget_PopupMenu_Small" target="_top"><code>TextAppearance_Holo_Widget_PopupMenu_Small</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.R.style.TextAppearance_Holo_Widget_TabWidget"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_Widget_TabWidget" target="_top"><code>TextAppearance_Holo_Widget_TabWidget</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.R.style.TextAppearance_Holo_Widget_TextView"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_Widget_TextView" target="_top"><code>TextAppearance_Holo_Widget_TextView</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.R.style.TextAppearance_Holo_Widget_TextView_PopupMenu"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_Widget_TextView_PopupMenu" target="_top"><code>TextAppearance_Holo_Widget_TextView_PopupMenu</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.R.style.TextAppearance_Holo_Widget_TextView_SpinnerItem"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_Widget_TextView_SpinnerItem" target="_top"><code>TextAppearance_Holo_Widget_TextView_SpinnerItem</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.R.style.TextAppearance_Holo_WindowTitle"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/R.style.html#TextAppearance_Holo_WindowTitle" target="_top"><code>TextAppearance_Holo_WindowTitle</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.R.style.Theme_Holo_Light_NoActionBar"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/R.style.html#Theme_Holo_Light_NoActionBar" target="_top"><code>Theme_Holo_Light_NoActionBar</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.R.style.Theme_Holo_Light_NoActionBar_Fullscreen"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/R.style.html#Theme_Holo_Light_NoActionBar_Fullscreen" target="_top"><code>Theme_Holo_Light_NoActionBar_Fullscreen</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.R.style.Widget_ActionBar_TabBar"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/R.style.html#Widget_ActionBar_TabBar" target="_top"><code>Widget_ActionBar_TabBar</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.R.style.Widget_ActionBar_TabText"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/R.style.html#Widget_ActionBar_TabText" target="_top"><code>Widget_ActionBar_TabText</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.R.style.Widget_ActionBar_TabView"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/R.style.html#Widget_ActionBar_TabView" target="_top"><code>Widget_ActionBar_TabView</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.R.style.Widget_Holo_ActionBar_TabBar"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/R.style.html#Widget_Holo_ActionBar_TabBar" target="_top"><code>Widget_Holo_ActionBar_TabBar</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.R.style.Widget_Holo_ActionBar_TabText"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/R.style.html#Widget_Holo_ActionBar_TabText" target="_top"><code>Widget_Holo_ActionBar_TabText</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.R.style.Widget_Holo_ActionBar_TabView"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/R.style.html#Widget_Holo_ActionBar_TabView" target="_top"><code>Widget_Holo_ActionBar_TabView</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.R.style.Widget_Holo_Light_ActionBar_TabBar"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/R.style.html#Widget_Holo_Light_ActionBar_TabBar" target="_top"><code>Widget_Holo_Light_ActionBar_TabBar</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.R.style.Widget_Holo_Light_ActionBar_TabText"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/R.style.html#Widget_Holo_Light_ActionBar_TabText" target="_top"><code>Widget_Holo_Light_ActionBar_TabText</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.R.style.Widget_Holo_Light_ActionBar_TabView"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/R.style.html#Widget_Holo_Light_ActionBar_TabView" target="_top"><code>Widget_Holo_Light_ActionBar_TabView</code></A></nobr> + </TD> + <TD> </TD> +</TR> +</TABLE> + + </div> + <div id="footer"> + <div id="copyright"> + Except as noted, this content is licensed under + <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>. + For details and restrictions, see the <a href="/license.html">Content License</a>. + </div> + <div id="footerlinks"> + <p> + <a href="http://www.android.com/terms.html">Site Terms of Service</a> - + <a href="http://www.android.com/privacy.html">Privacy Policy</a> - + <a href="http://www.android.com/branding.html">Brand Guidelines</a> + </p> + </div> + </div> <!-- end footer --> + </div><!-- end doc-content --> + </div> <!-- end body-content --> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/android.app.Activity.html b/docs/html/sdk/api_diff/13/changes/android.app.Activity.html new file mode 100644 index 0000000..b27816b --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/android.app.Activity.html @@ -0,0 +1,195 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +android.app.Activity +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY> +<!-- Start of nav bar --> +<a name="top"></a> +<div id="header" style="margin-bottom:0;padding-bottom:0;"> +<div id="headerLeft"> +<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a> +</div> + <div id="headerRight"> + <div id="headerLinks"> +<!-- <img src="/assets/images/icon_world.jpg" alt="" /> --> +<span class="text"> +<!-- <a href="#">English</a> | --> +<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr> +</span> +</div> + <div class="and-diff-id" style="margin-top:6px;margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td colspan="2" class="diffspechead">API Diff Specification</td> + </tr> + <tr> + <td class="diffspec" style="padding-top:.25em">To Level:</td> + <td class="diffvaluenew" style="padding-top:.25em">13</td> + </tr> + <tr> + <td class="diffspec">From Level:</td> + <td class="diffvalueold">12</td> + </tr> + <tr> + <td class="diffspec">Generated</td> + <td class="diffvalue">2011.06.29 10:50</td> + </tr> + </table> + </div><!-- End and-diff-id --> + <div class="and-diff-id" style="margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a> + </tr> + </table> + </div> <!-- End and-diff-id --> + </div> <!-- End headerRight --> + </div> <!-- End header --> +<div id="body-content" xstyle="padding:12px;padding-right:18px;"> +<div id="doc-content" style="position:relative;"> +<div id="mainBodyFluid"> +<H2> +Class android.app.<A HREF="../../../../reference/android/app/Activity.html" target="_top"><font size="+2"><code>Activity</code></font></A> +</H2> +<a NAME="constructors"></a> +<a NAME="methods"></a> +<p> +<a NAME="Changed"></a> +<TABLE summary="Changed Methods" WIDTH="100%"> +<TR> + <TH VALIGN="TOP" COLSPAN=3>Changed Methods</FONT></TD> +</TH> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.app.Activity.dismissDialog_changed(int)"></A> + <nobr><code>void</code> <A HREF="../../../../reference/android/app/Activity.html#dismissDialog(int)" target="_top"><code>dismissDialog</code></A>(<code>int</code>) </nobr> + </TD> + <TD VALIGN="TOP" WIDTH="30%"> +<b>Now deprecated</b>.<br> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.app.Activity.getLastNonConfigurationInstance_changed()"></A> + <nobr><code>Object</code> <A HREF="../../../../reference/android/app/Activity.html#getLastNonConfigurationInstance()" target="_top"><code>getLastNonConfigurationInstance</code></A>() </nobr> + </TD> + <TD VALIGN="TOP" WIDTH="30%"> +<b>Now deprecated</b>.<br> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.app.Activity.onRetainNonConfigurationInstance_changed()"></A> + <nobr><code>Object</code> <A HREF="../../../../reference/android/app/Activity.html#onRetainNonConfigurationInstance()" target="_top"><code>onRetainNonConfigurationInstance</code></A>() </nobr> + </TD> + <TD VALIGN="TOP" WIDTH="30%"> +<b>Now deprecated</b>.<br> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.app.Activity.removeDialog_changed(int)"></A> + <nobr><code>void</code> <A HREF="../../../../reference/android/app/Activity.html#removeDialog(int)" target="_top"><code>removeDialog</code></A>(<code>int</code>) </nobr> + </TD> + <TD VALIGN="TOP" WIDTH="30%"> +<b>Now deprecated</b>.<br> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.app.Activity.onCreateDialog_changed(int, android.os.Bundle)"></A> + <nobr><code>Dialog</code> <A HREF="../../../../reference/android/app/Activity.html#onCreateDialog(int, android.os.Bundle)" target="_top"><code>onCreateDialog</code></A>(<code>int,</nobr> Bundle<nobr><nobr></code>) </nobr> + </TD> + <TD VALIGN="TOP" WIDTH="30%"> +<b>Now deprecated</b>.<br> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.app.Activity.onPrepareDialog_changed(int, android.app.Dialog, android.os.Bundle)"></A> + <nobr><code>void</code> <A HREF="../../../../reference/android/app/Activity.html#onPrepareDialog(int, android.app.Dialog, android.os.Bundle)" target="_top"><code>onPrepareDialog</code></A>(<code>int,</nobr> Dialog<nobr>,</nobr> Bundle<nobr><nobr></code>) </nobr> + </TD> + <TD VALIGN="TOP" WIDTH="30%"> +<b>Now deprecated</b>.<br> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.app.Activity.showDialog_changed(int, android.os.Bundle)"></A> + <nobr><code>boolean</code> <A HREF="../../../../reference/android/app/Activity.html#showDialog(int, android.os.Bundle)" target="_top"><code>showDialog</code></A>(<code>int,</nobr> Bundle<nobr><nobr></code>) </nobr> + </TD> + <TD VALIGN="TOP" WIDTH="30%"> +<b>Now deprecated</b>.<br> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.app.Activity.showDialog_changed(int)"></A> + <nobr><code>void</code> <A HREF="../../../../reference/android/app/Activity.html#showDialog(int)" target="_top"><code>showDialog</code></A>(<code>int</code>) </nobr> + </TD> + <TD VALIGN="TOP" WIDTH="30%"> +<b>Now deprecated</b>.<br> + </TD> + <TD> </TD> +</TR> +</TABLE> + +<a NAME="fields"></a> + </div> + <div id="footer"> + <div id="copyright"> + Except as noted, this content is licensed under + <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>. + For details and restrictions, see the <a href="/license.html">Content License</a>. + </div> + <div id="footerlinks"> + <p> + <a href="http://www.android.com/terms.html">Site Terms of Service</a> - + <a href="http://www.android.com/privacy.html">Privacy Policy</a> - + <a href="http://www.android.com/branding.html">Brand Guidelines</a> + </p> + </div> + </div> <!-- end footer --> + </div><!-- end doc-content --> + </div> <!-- end body-content --> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/android.app.ActivityGroup.html b/docs/html/sdk/api_diff/13/changes/android.app.ActivityGroup.html new file mode 100644 index 0000000..c755228 --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/android.app.ActivityGroup.html @@ -0,0 +1,108 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +android.app.ActivityGroup +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY> +<!-- Start of nav bar --> +<a name="top"></a> +<div id="header" style="margin-bottom:0;padding-bottom:0;"> +<div id="headerLeft"> +<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a> +</div> + <div id="headerRight"> + <div id="headerLinks"> +<!-- <img src="/assets/images/icon_world.jpg" alt="" /> --> +<span class="text"> +<!-- <a href="#">English</a> | --> +<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr> +</span> +</div> + <div class="and-diff-id" style="margin-top:6px;margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td colspan="2" class="diffspechead">API Diff Specification</td> + </tr> + <tr> + <td class="diffspec" style="padding-top:.25em">To Level:</td> + <td class="diffvaluenew" style="padding-top:.25em">13</td> + </tr> + <tr> + <td class="diffspec">From Level:</td> + <td class="diffvalueold">12</td> + </tr> + <tr> + <td class="diffspec">Generated</td> + <td class="diffvalue">2011.06.29 10:50</td> + </tr> + </table> + </div><!-- End and-diff-id --> + <div class="and-diff-id" style="margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a> + </tr> + </table> + </div> <!-- End and-diff-id --> + </div> <!-- End headerRight --> + </div> <!-- End header --> +<div id="body-content" xstyle="padding:12px;padding-right:18px;"> +<div id="doc-content" style="position:relative;"> +<div id="mainBodyFluid"> +<H2> +Class android.app.<A HREF="../../../../reference/android/app/ActivityGroup.html" target="_top"><font size="+2"><code>ActivityGroup</code></font></A> +</H2> +<p><b>Now deprecated</b>.<br> +<a NAME="constructors"></a> +<a NAME="methods"></a> +<a NAME="fields"></a> + </div> + <div id="footer"> + <div id="copyright"> + Except as noted, this content is licensed under + <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>. + For details and restrictions, see the <a href="/license.html">Content License</a>. + </div> + <div id="footerlinks"> + <p> + <a href="http://www.android.com/terms.html">Site Terms of Service</a> - + <a href="http://www.android.com/privacy.html">Privacy Policy</a> - + <a href="http://www.android.com/branding.html">Brand Guidelines</a> + </p> + </div> + </div> <!-- end footer --> + </div><!-- end doc-content --> + </div> <!-- end body-content --> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/android.app.Fragment.html b/docs/html/sdk/api_diff/13/changes/android.app.Fragment.html new file mode 100644 index 0000000..074d4b3 --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/android.app.Fragment.html @@ -0,0 +1,136 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +android.app.Fragment +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY> +<!-- Start of nav bar --> +<a name="top"></a> +<div id="header" style="margin-bottom:0;padding-bottom:0;"> +<div id="headerLeft"> +<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a> +</div> + <div id="headerRight"> + <div id="headerLinks"> +<!-- <img src="/assets/images/icon_world.jpg" alt="" /> --> +<span class="text"> +<!-- <a href="#">English</a> | --> +<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr> +</span> +</div> + <div class="and-diff-id" style="margin-top:6px;margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td colspan="2" class="diffspechead">API Diff Specification</td> + </tr> + <tr> + <td class="diffspec" style="padding-top:.25em">To Level:</td> + <td class="diffvaluenew" style="padding-top:.25em">13</td> + </tr> + <tr> + <td class="diffspec">From Level:</td> + <td class="diffvalueold">12</td> + </tr> + <tr> + <td class="diffspec">Generated</td> + <td class="diffvalue">2011.06.29 10:50</td> + </tr> + </table> + </div><!-- End and-diff-id --> + <div class="and-diff-id" style="margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a> + </tr> + </table> + </div> <!-- End and-diff-id --> + </div> <!-- End headerRight --> + </div> <!-- End header --> +<div id="body-content" xstyle="padding:12px;padding-right:18px;"> +<div id="doc-content" style="position:relative;"> +<div id="mainBodyFluid"> +<H2> +Class android.app.<A HREF="../../../../reference/android/app/Fragment.html" target="_top"><font size="+2"><code>Fragment</code></font></A> +</H2> +<a NAME="constructors"></a> +<a NAME="methods"></a> +<p> +<a NAME="Added"></a> +<TABLE summary="Added Methods" WIDTH="100%"> +<TR> + <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD> +</TH> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.app.Fragment.isDetached_added()"></A> + <nobr><code>boolean</code> <A HREF="../../../../reference/android/app/Fragment.html#isDetached()" target="_top"><code>isDetached</code></A>()</nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.app.Fragment.onViewCreated_added(android.view.View, android.os.Bundle)"></A> + <nobr><code>void</code> <A HREF="../../../../reference/android/app/Fragment.html#onViewCreated(android.view.View, android.os.Bundle)" target="_top"><code>onViewCreated</code></A>(<code>View,</nobr> Bundle<nobr><nobr></code>)</nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.app.Fragment.setInitialSavedState_added(android.app.Fragment.SavedState)"></A> + <nobr><code>void</code> <A HREF="../../../../reference/android/app/Fragment.html#setInitialSavedState(android.app.Fragment.SavedState)" target="_top"><code>setInitialSavedState</code></A>(<code>SavedState</code>)</nobr> + </TD> + <TD> </TD> +</TR> +</TABLE> + +<a NAME="fields"></a> + </div> + <div id="footer"> + <div id="copyright"> + Except as noted, this content is licensed under + <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>. + For details and restrictions, see the <a href="/license.html">Content License</a>. + </div> + <div id="footerlinks"> + <p> + <a href="http://www.android.com/terms.html">Site Terms of Service</a> - + <a href="http://www.android.com/privacy.html">Privacy Policy</a> - + <a href="http://www.android.com/branding.html">Brand Guidelines</a> + </p> + </div> + </div> <!-- end footer --> + </div><!-- end doc-content --> + </div> <!-- end body-content --> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/android.app.FragmentManager.html b/docs/html/sdk/api_diff/13/changes/android.app.FragmentManager.html new file mode 100644 index 0000000..159b9c9 --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/android.app.FragmentManager.html @@ -0,0 +1,122 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +android.app.FragmentManager +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY> +<!-- Start of nav bar --> +<a name="top"></a> +<div id="header" style="margin-bottom:0;padding-bottom:0;"> +<div id="headerLeft"> +<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a> +</div> + <div id="headerRight"> + <div id="headerLinks"> +<!-- <img src="/assets/images/icon_world.jpg" alt="" /> --> +<span class="text"> +<!-- <a href="#">English</a> | --> +<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr> +</span> +</div> + <div class="and-diff-id" style="margin-top:6px;margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td colspan="2" class="diffspechead">API Diff Specification</td> + </tr> + <tr> + <td class="diffspec" style="padding-top:.25em">To Level:</td> + <td class="diffvaluenew" style="padding-top:.25em">13</td> + </tr> + <tr> + <td class="diffspec">From Level:</td> + <td class="diffvalueold">12</td> + </tr> + <tr> + <td class="diffspec">Generated</td> + <td class="diffvalue">2011.06.29 10:50</td> + </tr> + </table> + </div><!-- End and-diff-id --> + <div class="and-diff-id" style="margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a> + </tr> + </table> + </div> <!-- End and-diff-id --> + </div> <!-- End headerRight --> + </div> <!-- End header --> +<div id="body-content" xstyle="padding:12px;padding-right:18px;"> +<div id="doc-content" style="position:relative;"> +<div id="mainBodyFluid"> +<H2> +Class android.app.<A HREF="../../../../reference/android/app/FragmentManager.html" target="_top"><font size="+2"><code>FragmentManager</code></font></A> +</H2> +<a NAME="constructors"></a> +<a NAME="methods"></a> +<p> +<a NAME="Added"></a> +<TABLE summary="Added Methods" WIDTH="100%"> +<TR> + <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD> +</TH> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.app.FragmentManager.saveFragmentInstanceState_added(android.app.Fragment)"></A> + <nobr><code>SavedState</code> <A HREF="../../../../reference/android/app/FragmentManager.html#saveFragmentInstanceState(android.app.Fragment)" target="_top"><code>saveFragmentInstanceState</code></A>(<code>Fragment</code>)</nobr> + </TD> + <TD> </TD> +</TR> +</TABLE> + +<a NAME="fields"></a> + </div> + <div id="footer"> + <div id="copyright"> + Except as noted, this content is licensed under + <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>. + For details and restrictions, see the <a href="/license.html">Content License</a>. + </div> + <div id="footerlinks"> + <p> + <a href="http://www.android.com/terms.html">Site Terms of Service</a> - + <a href="http://www.android.com/privacy.html">Privacy Policy</a> - + <a href="http://www.android.com/branding.html">Brand Guidelines</a> + </p> + </div> + </div> <!-- end footer --> + </div><!-- end doc-content --> + </div> <!-- end body-content --> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/android.app.FragmentTransaction.html b/docs/html/sdk/api_diff/13/changes/android.app.FragmentTransaction.html new file mode 100644 index 0000000..dbb7deb --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/android.app.FragmentTransaction.html @@ -0,0 +1,136 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +android.app.FragmentTransaction +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY> +<!-- Start of nav bar --> +<a name="top"></a> +<div id="header" style="margin-bottom:0;padding-bottom:0;"> +<div id="headerLeft"> +<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a> +</div> + <div id="headerRight"> + <div id="headerLinks"> +<!-- <img src="/assets/images/icon_world.jpg" alt="" /> --> +<span class="text"> +<!-- <a href="#">English</a> | --> +<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr> +</span> +</div> + <div class="and-diff-id" style="margin-top:6px;margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td colspan="2" class="diffspechead">API Diff Specification</td> + </tr> + <tr> + <td class="diffspec" style="padding-top:.25em">To Level:</td> + <td class="diffvaluenew" style="padding-top:.25em">13</td> + </tr> + <tr> + <td class="diffspec">From Level:</td> + <td class="diffvalueold">12</td> + </tr> + <tr> + <td class="diffspec">Generated</td> + <td class="diffvalue">2011.06.29 10:50</td> + </tr> + </table> + </div><!-- End and-diff-id --> + <div class="and-diff-id" style="margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a> + </tr> + </table> + </div> <!-- End and-diff-id --> + </div> <!-- End headerRight --> + </div> <!-- End header --> +<div id="body-content" xstyle="padding:12px;padding-right:18px;"> +<div id="doc-content" style="position:relative;"> +<div id="mainBodyFluid"> +<H2> +Class android.app.<A HREF="../../../../reference/android/app/FragmentTransaction.html" target="_top"><font size="+2"><code>FragmentTransaction</code></font></A> +</H2> +<a NAME="constructors"></a> +<a NAME="methods"></a> +<p> +<a NAME="Added"></a> +<TABLE summary="Added Methods" WIDTH="100%"> +<TR> + <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD> +</TH> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.app.FragmentTransaction.attach_added(android.app.Fragment)"></A> + <nobr><code>FragmentTransaction</code> <A HREF="../../../../reference/android/app/FragmentTransaction.html#attach(android.app.Fragment)" target="_top"><code>attach</code></A>(<code>Fragment</code>)</nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.app.FragmentTransaction.detach_added(android.app.Fragment)"></A> + <nobr><code>FragmentTransaction</code> <A HREF="../../../../reference/android/app/FragmentTransaction.html#detach(android.app.Fragment)" target="_top"><code>detach</code></A>(<code>Fragment</code>)</nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.app.FragmentTransaction.setCustomAnimations_added(int, int, int, int)"></A> + <nobr><code>FragmentTransaction</code> <A HREF="../../../../reference/android/app/FragmentTransaction.html#setCustomAnimations(int, int, int, int)" target="_top"><code>setCustomAnimations</code></A>(<code>int,</nobr> int<nobr>,</nobr> int<nobr>,</nobr> int<nobr><nobr></code>)</nobr> + </TD> + <TD> </TD> +</TR> +</TABLE> + +<a NAME="fields"></a> + </div> + <div id="footer"> + <div id="copyright"> + Except as noted, this content is licensed under + <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>. + For details and restrictions, see the <a href="/license.html">Content License</a>. + </div> + <div id="footerlinks"> + <p> + <a href="http://www.android.com/terms.html">Site Terms of Service</a> - + <a href="http://www.android.com/privacy.html">Privacy Policy</a> - + <a href="http://www.android.com/branding.html">Brand Guidelines</a> + </p> + </div> + </div> <!-- end footer --> + </div><!-- end doc-content --> + </div> <!-- end body-content --> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/android.app.KeyguardManager.KeyguardLock.html b/docs/html/sdk/api_diff/13/changes/android.app.KeyguardManager.KeyguardLock.html new file mode 100644 index 0000000..3ae02ea --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/android.app.KeyguardManager.KeyguardLock.html @@ -0,0 +1,108 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +android.app.KeyguardManager.KeyguardLock +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY> +<!-- Start of nav bar --> +<a name="top"></a> +<div id="header" style="margin-bottom:0;padding-bottom:0;"> +<div id="headerLeft"> +<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a> +</div> + <div id="headerRight"> + <div id="headerLinks"> +<!-- <img src="/assets/images/icon_world.jpg" alt="" /> --> +<span class="text"> +<!-- <a href="#">English</a> | --> +<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr> +</span> +</div> + <div class="and-diff-id" style="margin-top:6px;margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td colspan="2" class="diffspechead">API Diff Specification</td> + </tr> + <tr> + <td class="diffspec" style="padding-top:.25em">To Level:</td> + <td class="diffvaluenew" style="padding-top:.25em">13</td> + </tr> + <tr> + <td class="diffspec">From Level:</td> + <td class="diffvalueold">12</td> + </tr> + <tr> + <td class="diffspec">Generated</td> + <td class="diffvalue">2011.06.29 10:50</td> + </tr> + </table> + </div><!-- End and-diff-id --> + <div class="and-diff-id" style="margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a> + </tr> + </table> + </div> <!-- End and-diff-id --> + </div> <!-- End headerRight --> + </div> <!-- End header --> +<div id="body-content" xstyle="padding:12px;padding-right:18px;"> +<div id="doc-content" style="position:relative;"> +<div id="mainBodyFluid"> +<H2> +Class android.app.<A HREF="../../../../reference/android/app/KeyguardManager.KeyguardLock.html" target="_top"><font size="+2"><code>KeyguardManager.KeyguardLock</code></font></A> +</H2> +<p><b>Now deprecated</b>.<br> +<a NAME="constructors"></a> +<a NAME="methods"></a> +<a NAME="fields"></a> + </div> + <div id="footer"> + <div id="copyright"> + Except as noted, this content is licensed under + <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>. + For details and restrictions, see the <a href="/license.html">Content License</a>. + </div> + <div id="footerlinks"> + <p> + <a href="http://www.android.com/terms.html">Site Terms of Service</a> - + <a href="http://www.android.com/privacy.html">Privacy Policy</a> - + <a href="http://www.android.com/branding.html">Brand Guidelines</a> + </p> + </div> + </div> <!-- end footer --> + </div><!-- end doc-content --> + </div> <!-- end body-content --> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/android.app.KeyguardManager.html b/docs/html/sdk/api_diff/13/changes/android.app.KeyguardManager.html new file mode 100644 index 0000000..bc38771 --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/android.app.KeyguardManager.html @@ -0,0 +1,135 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +android.app.KeyguardManager +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY> +<!-- Start of nav bar --> +<a name="top"></a> +<div id="header" style="margin-bottom:0;padding-bottom:0;"> +<div id="headerLeft"> +<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a> +</div> + <div id="headerRight"> + <div id="headerLinks"> +<!-- <img src="/assets/images/icon_world.jpg" alt="" /> --> +<span class="text"> +<!-- <a href="#">English</a> | --> +<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr> +</span> +</div> + <div class="and-diff-id" style="margin-top:6px;margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td colspan="2" class="diffspechead">API Diff Specification</td> + </tr> + <tr> + <td class="diffspec" style="padding-top:.25em">To Level:</td> + <td class="diffvaluenew" style="padding-top:.25em">13</td> + </tr> + <tr> + <td class="diffspec">From Level:</td> + <td class="diffvalueold">12</td> + </tr> + <tr> + <td class="diffspec">Generated</td> + <td class="diffvalue">2011.06.29 10:50</td> + </tr> + </table> + </div><!-- End and-diff-id --> + <div class="and-diff-id" style="margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a> + </tr> + </table> + </div> <!-- End and-diff-id --> + </div> <!-- End headerRight --> + </div> <!-- End header --> +<div id="body-content" xstyle="padding:12px;padding-right:18px;"> +<div id="doc-content" style="position:relative;"> +<div id="mainBodyFluid"> +<H2> +Class android.app.<A HREF="../../../../reference/android/app/KeyguardManager.html" target="_top"><font size="+2"><code>KeyguardManager</code></font></A> +</H2> +<a NAME="constructors"></a> +<a NAME="methods"></a> +<p> +<a NAME="Changed"></a> +<TABLE summary="Changed Methods" WIDTH="100%"> +<TR> + <TH VALIGN="TOP" COLSPAN=3>Changed Methods</FONT></TD> +</TH> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.app.KeyguardManager.exitKeyguardSecurely_changed(android.app.KeyguardManager.OnKeyguardExitResult)"></A> + <nobr><code>void</code> <A HREF="../../../../reference/android/app/KeyguardManager.html#exitKeyguardSecurely(android.app.KeyguardManager.OnKeyguardExitResult)" target="_top"><code>exitKeyguardSecurely</code></A>(<code>OnKeyguardExitResult</code>) </nobr> + </TD> + <TD VALIGN="TOP" WIDTH="30%"> +<b>Now deprecated</b>.<br> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.app.KeyguardManager.newKeyguardLock_changed(java.lang.String)"></A> + <nobr><code>KeyguardLock</code> <A HREF="../../../../reference/android/app/KeyguardManager.html#newKeyguardLock(java.lang.String)" target="_top"><code>newKeyguardLock</code></A>(<code>String</code>) </nobr> + </TD> + <TD VALIGN="TOP" WIDTH="30%"> +<b>Now deprecated</b>.<br> + </TD> + <TD> </TD> +</TR> +</TABLE> + +<a NAME="fields"></a> + </div> + <div id="footer"> + <div id="copyright"> + Except as noted, this content is licensed under + <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>. + For details and restrictions, see the <a href="/license.html">Content License</a>. + </div> + <div id="footerlinks"> + <p> + <a href="http://www.android.com/terms.html">Site Terms of Service</a> - + <a href="http://www.android.com/privacy.html">Privacy Policy</a> - + <a href="http://www.android.com/branding.html">Brand Guidelines</a> + </p> + </div> + </div> <!-- end footer --> + </div><!-- end doc-content --> + </div> <!-- end body-content --> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/android.app.LocalActivityManager.html b/docs/html/sdk/api_diff/13/changes/android.app.LocalActivityManager.html new file mode 100644 index 0000000..4ea0848 --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/android.app.LocalActivityManager.html @@ -0,0 +1,108 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +android.app.LocalActivityManager +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY> +<!-- Start of nav bar --> +<a name="top"></a> +<div id="header" style="margin-bottom:0;padding-bottom:0;"> +<div id="headerLeft"> +<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a> +</div> + <div id="headerRight"> + <div id="headerLinks"> +<!-- <img src="/assets/images/icon_world.jpg" alt="" /> --> +<span class="text"> +<!-- <a href="#">English</a> | --> +<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr> +</span> +</div> + <div class="and-diff-id" style="margin-top:6px;margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td colspan="2" class="diffspechead">API Diff Specification</td> + </tr> + <tr> + <td class="diffspec" style="padding-top:.25em">To Level:</td> + <td class="diffvaluenew" style="padding-top:.25em">13</td> + </tr> + <tr> + <td class="diffspec">From Level:</td> + <td class="diffvalueold">12</td> + </tr> + <tr> + <td class="diffspec">Generated</td> + <td class="diffvalue">2011.06.29 10:50</td> + </tr> + </table> + </div><!-- End and-diff-id --> + <div class="and-diff-id" style="margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a> + </tr> + </table> + </div> <!-- End and-diff-id --> + </div> <!-- End headerRight --> + </div> <!-- End header --> +<div id="body-content" xstyle="padding:12px;padding-right:18px;"> +<div id="doc-content" style="position:relative;"> +<div id="mainBodyFluid"> +<H2> +Class android.app.<A HREF="../../../../reference/android/app/LocalActivityManager.html" target="_top"><font size="+2"><code>LocalActivityManager</code></font></A> +</H2> +<p><b>Now deprecated</b>.<br> +<a NAME="constructors"></a> +<a NAME="methods"></a> +<a NAME="fields"></a> + </div> + <div id="footer"> + <div id="copyright"> + Except as noted, this content is licensed under + <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>. + For details and restrictions, see the <a href="/license.html">Content License</a>. + </div> + <div id="footerlinks"> + <p> + <a href="http://www.android.com/terms.html">Site Terms of Service</a> - + <a href="http://www.android.com/privacy.html">Privacy Policy</a> - + <a href="http://www.android.com/branding.html">Brand Guidelines</a> + </p> + </div> + </div> <!-- end footer --> + </div><!-- end doc-content --> + </div> <!-- end body-content --> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/android.app.TabActivity.html b/docs/html/sdk/api_diff/13/changes/android.app.TabActivity.html new file mode 100644 index 0000000..405f7d8 --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/android.app.TabActivity.html @@ -0,0 +1,108 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +android.app.TabActivity +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY> +<!-- Start of nav bar --> +<a name="top"></a> +<div id="header" style="margin-bottom:0;padding-bottom:0;"> +<div id="headerLeft"> +<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a> +</div> + <div id="headerRight"> + <div id="headerLinks"> +<!-- <img src="/assets/images/icon_world.jpg" alt="" /> --> +<span class="text"> +<!-- <a href="#">English</a> | --> +<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr> +</span> +</div> + <div class="and-diff-id" style="margin-top:6px;margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td colspan="2" class="diffspechead">API Diff Specification</td> + </tr> + <tr> + <td class="diffspec" style="padding-top:.25em">To Level:</td> + <td class="diffvaluenew" style="padding-top:.25em">13</td> + </tr> + <tr> + <td class="diffspec">From Level:</td> + <td class="diffvalueold">12</td> + </tr> + <tr> + <td class="diffspec">Generated</td> + <td class="diffvalue">2011.06.29 10:50</td> + </tr> + </table> + </div><!-- End and-diff-id --> + <div class="and-diff-id" style="margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a> + </tr> + </table> + </div> <!-- End and-diff-id --> + </div> <!-- End headerRight --> + </div> <!-- End header --> +<div id="body-content" xstyle="padding:12px;padding-right:18px;"> +<div id="doc-content" style="position:relative;"> +<div id="mainBodyFluid"> +<H2> +Class android.app.<A HREF="../../../../reference/android/app/TabActivity.html" target="_top"><font size="+2"><code>TabActivity</code></font></A> +</H2> +<p><b>Now deprecated</b>.<br> +<a NAME="constructors"></a> +<a NAME="methods"></a> +<a NAME="fields"></a> + </div> + <div id="footer"> + <div id="copyright"> + Except as noted, this content is licensed under + <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>. + For details and restrictions, see the <a href="/license.html">Content License</a>. + </div> + <div id="footerlinks"> + <p> + <a href="http://www.android.com/terms.html">Site Terms of Service</a> - + <a href="http://www.android.com/privacy.html">Privacy Policy</a> - + <a href="http://www.android.com/branding.html">Brand Guidelines</a> + </p> + </div> + </div> <!-- end footer --> + </div><!-- end doc-content --> + </div> <!-- end body-content --> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/android.content.pm.ActivityInfo.html b/docs/html/sdk/api_diff/13/changes/android.content.pm.ActivityInfo.html new file mode 100644 index 0000000..70149a3 --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/android.content.pm.ActivityInfo.html @@ -0,0 +1,129 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +android.content.pm.ActivityInfo +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY> +<!-- Start of nav bar --> +<a name="top"></a> +<div id="header" style="margin-bottom:0;padding-bottom:0;"> +<div id="headerLeft"> +<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a> +</div> + <div id="headerRight"> + <div id="headerLinks"> +<!-- <img src="/assets/images/icon_world.jpg" alt="" /> --> +<span class="text"> +<!-- <a href="#">English</a> | --> +<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr> +</span> +</div> + <div class="and-diff-id" style="margin-top:6px;margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td colspan="2" class="diffspechead">API Diff Specification</td> + </tr> + <tr> + <td class="diffspec" style="padding-top:.25em">To Level:</td> + <td class="diffvaluenew" style="padding-top:.25em">13</td> + </tr> + <tr> + <td class="diffspec">From Level:</td> + <td class="diffvalueold">12</td> + </tr> + <tr> + <td class="diffspec">Generated</td> + <td class="diffvalue">2011.06.29 10:50</td> + </tr> + </table> + </div><!-- End and-diff-id --> + <div class="and-diff-id" style="margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a> + </tr> + </table> + </div> <!-- End and-diff-id --> + </div> <!-- End headerRight --> + </div> <!-- End header --> +<div id="body-content" xstyle="padding:12px;padding-right:18px;"> +<div id="doc-content" style="position:relative;"> +<div id="mainBodyFluid"> +<H2> +Class android.content.pm.<A HREF="../../../../reference/android/content/pm/ActivityInfo.html" target="_top"><font size="+2"><code>ActivityInfo</code></font></A> +</H2> +<a NAME="constructors"></a> +<a NAME="methods"></a> +<a NAME="fields"></a> +<p> +<a NAME="Added"></a> +<TABLE summary="Added Fields" WIDTH="100%"> +<TR> + <TH VALIGN="TOP" COLSPAN=2>Added Fields</FONT></TD> +</TH> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/content/pm/ActivityInfo.html#CONFIG_SCREEN_SIZE" target="_top"><code>CONFIG_SCREEN_SIZE</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.content.pm.ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/content/pm/ActivityInfo.html#CONFIG_SMALLEST_SCREEN_SIZE" target="_top"><code>CONFIG_SMALLEST_SCREEN_SIZE</code></A></nobr> + </TD> + <TD> </TD> +</TR> +</TABLE> + + </div> + <div id="footer"> + <div id="copyright"> + Except as noted, this content is licensed under + <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>. + For details and restrictions, see the <a href="/license.html">Content License</a>. + </div> + <div id="footerlinks"> + <p> + <a href="http://www.android.com/terms.html">Site Terms of Service</a> - + <a href="http://www.android.com/privacy.html">Privacy Policy</a> - + <a href="http://www.android.com/branding.html">Brand Guidelines</a> + </p> + </div> + </div> <!-- end footer --> + </div><!-- end doc-content --> + </div> <!-- end body-content --> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/android.content.pm.ApplicationInfo.html b/docs/html/sdk/api_diff/13/changes/android.content.pm.ApplicationInfo.html new file mode 100644 index 0000000..4aef492 --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/android.content.pm.ApplicationInfo.html @@ -0,0 +1,136 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +android.content.pm.ApplicationInfo +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY> +<!-- Start of nav bar --> +<a name="top"></a> +<div id="header" style="margin-bottom:0;padding-bottom:0;"> +<div id="headerLeft"> +<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a> +</div> + <div id="headerRight"> + <div id="headerLinks"> +<!-- <img src="/assets/images/icon_world.jpg" alt="" /> --> +<span class="text"> +<!-- <a href="#">English</a> | --> +<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr> +</span> +</div> + <div class="and-diff-id" style="margin-top:6px;margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td colspan="2" class="diffspechead">API Diff Specification</td> + </tr> + <tr> + <td class="diffspec" style="padding-top:.25em">To Level:</td> + <td class="diffvaluenew" style="padding-top:.25em">13</td> + </tr> + <tr> + <td class="diffspec">From Level:</td> + <td class="diffvalueold">12</td> + </tr> + <tr> + <td class="diffspec">Generated</td> + <td class="diffvalue">2011.06.29 10:50</td> + </tr> + </table> + </div><!-- End and-diff-id --> + <div class="and-diff-id" style="margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a> + </tr> + </table> + </div> <!-- End and-diff-id --> + </div> <!-- End headerRight --> + </div> <!-- End header --> +<div id="body-content" xstyle="padding:12px;padding-right:18px;"> +<div id="doc-content" style="position:relative;"> +<div id="mainBodyFluid"> +<H2> +Class android.content.pm.<A HREF="../../../../reference/android/content/pm/ApplicationInfo.html" target="_top"><font size="+2"><code>ApplicationInfo</code></font></A> +</H2> +<a NAME="constructors"></a> +<a NAME="methods"></a> +<a NAME="fields"></a> +<p> +<a NAME="Added"></a> +<TABLE summary="Added Fields" WIDTH="100%"> +<TR> + <TH VALIGN="TOP" COLSPAN=2>Added Fields</FONT></TD> +</TH> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.content.pm.ApplicationInfo.compatibleWidthLimitDp"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/content/pm/ApplicationInfo.html#compatibleWidthLimitDp" target="_top"><code>compatibleWidthLimitDp</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.content.pm.ApplicationInfo.largestWidthLimitDp"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/content/pm/ApplicationInfo.html#largestWidthLimitDp" target="_top"><code>largestWidthLimitDp</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.content.pm.ApplicationInfo.requiresSmallestWidthDp"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/content/pm/ApplicationInfo.html#requiresSmallestWidthDp" target="_top"><code>requiresSmallestWidthDp</code></A></nobr> + </TD> + <TD> </TD> +</TR> +</TABLE> + + </div> + <div id="footer"> + <div id="copyright"> + Except as noted, this content is licensed under + <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>. + For details and restrictions, see the <a href="/license.html">Content License</a>. + </div> + <div id="footerlinks"> + <p> + <a href="http://www.android.com/terms.html">Site Terms of Service</a> - + <a href="http://www.android.com/privacy.html">Privacy Policy</a> - + <a href="http://www.android.com/branding.html">Brand Guidelines</a> + </p> + </div> + </div> <!-- end footer --> + </div><!-- end doc-content --> + </div> <!-- end body-content --> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/android.content.pm.PackageManager.html b/docs/html/sdk/api_diff/13/changes/android.content.pm.PackageManager.html new file mode 100644 index 0000000..ca75d7a --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/android.content.pm.PackageManager.html @@ -0,0 +1,143 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +android.content.pm.PackageManager +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY> +<!-- Start of nav bar --> +<a name="top"></a> +<div id="header" style="margin-bottom:0;padding-bottom:0;"> +<div id="headerLeft"> +<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a> +</div> + <div id="headerRight"> + <div id="headerLinks"> +<!-- <img src="/assets/images/icon_world.jpg" alt="" /> --> +<span class="text"> +<!-- <a href="#">English</a> | --> +<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr> +</span> +</div> + <div class="and-diff-id" style="margin-top:6px;margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td colspan="2" class="diffspechead">API Diff Specification</td> + </tr> + <tr> + <td class="diffspec" style="padding-top:.25em">To Level:</td> + <td class="diffvaluenew" style="padding-top:.25em">13</td> + </tr> + <tr> + <td class="diffspec">From Level:</td> + <td class="diffvalueold">12</td> + </tr> + <tr> + <td class="diffspec">Generated</td> + <td class="diffvalue">2011.06.29 10:50</td> + </tr> + </table> + </div><!-- End and-diff-id --> + <div class="and-diff-id" style="margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a> + </tr> + </table> + </div> <!-- End and-diff-id --> + </div> <!-- End headerRight --> + </div> <!-- End header --> +<div id="body-content" xstyle="padding:12px;padding-right:18px;"> +<div id="doc-content" style="position:relative;"> +<div id="mainBodyFluid"> +<H2> +Class android.content.pm.<A HREF="../../../../reference/android/content/pm/PackageManager.html" target="_top"><font size="+2"><code>PackageManager</code></font></A> +</H2> +<a NAME="constructors"></a> +<a NAME="methods"></a> +<a NAME="fields"></a> +<p> +<a NAME="Added"></a> +<TABLE summary="Added Fields" WIDTH="100%"> +<TR> + <TH VALIGN="TOP" COLSPAN=2>Added Fields</FONT></TD> +</TH> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.content.pm.PackageManager.FEATURE_FAKETOUCH_MULTITOUCH_DISTINCT"></A> + <nobr><code>String</code> <A HREF="../../../../reference/android/content/pm/PackageManager.html#FEATURE_FAKETOUCH_MULTITOUCH_DISTINCT" target="_top"><code>FEATURE_FAKETOUCH_MULTITOUCH_DISTINCT</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.content.pm.PackageManager.FEATURE_FAKETOUCH_MULTITOUCH_JAZZHAND"></A> + <nobr><code>String</code> <A HREF="../../../../reference/android/content/pm/PackageManager.html#FEATURE_FAKETOUCH_MULTITOUCH_JAZZHAND" target="_top"><code>FEATURE_FAKETOUCH_MULTITOUCH_JAZZHAND</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.content.pm.PackageManager.FEATURE_SCREEN_LANDSCAPE"></A> + <nobr><code>String</code> <A HREF="../../../../reference/android/content/pm/PackageManager.html#FEATURE_SCREEN_LANDSCAPE" target="_top"><code>FEATURE_SCREEN_LANDSCAPE</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.content.pm.PackageManager.FEATURE_SCREEN_PORTRAIT"></A> + <nobr><code>String</code> <A HREF="../../../../reference/android/content/pm/PackageManager.html#FEATURE_SCREEN_PORTRAIT" target="_top"><code>FEATURE_SCREEN_PORTRAIT</code></A></nobr> + </TD> + <TD> </TD> +</TR> +</TABLE> + + </div> + <div id="footer"> + <div id="copyright"> + Except as noted, this content is licensed under + <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>. + For details and restrictions, see the <a href="/license.html">Content License</a>. + </div> + <div id="footerlinks"> + <p> + <a href="http://www.android.com/terms.html">Site Terms of Service</a> - + <a href="http://www.android.com/privacy.html">Privacy Policy</a> - + <a href="http://www.android.com/branding.html">Brand Guidelines</a> + </p> + </div> + </div> <!-- end footer --> + </div><!-- end doc-content --> + </div> <!-- end body-content --> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/android.content.res.Configuration.html b/docs/html/sdk/api_diff/13/changes/android.content.res.Configuration.html new file mode 100644 index 0000000..110a142 --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/android.content.res.Configuration.html @@ -0,0 +1,164 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +android.content.res.Configuration +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY> +<!-- Start of nav bar --> +<a name="top"></a> +<div id="header" style="margin-bottom:0;padding-bottom:0;"> +<div id="headerLeft"> +<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a> +</div> + <div id="headerRight"> + <div id="headerLinks"> +<!-- <img src="/assets/images/icon_world.jpg" alt="" /> --> +<span class="text"> +<!-- <a href="#">English</a> | --> +<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr> +</span> +</div> + <div class="and-diff-id" style="margin-top:6px;margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td colspan="2" class="diffspechead">API Diff Specification</td> + </tr> + <tr> + <td class="diffspec" style="padding-top:.25em">To Level:</td> + <td class="diffvaluenew" style="padding-top:.25em">13</td> + </tr> + <tr> + <td class="diffspec">From Level:</td> + <td class="diffvalueold">12</td> + </tr> + <tr> + <td class="diffspec">Generated</td> + <td class="diffvalue">2011.06.29 10:50</td> + </tr> + </table> + </div><!-- End and-diff-id --> + <div class="and-diff-id" style="margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a> + </tr> + </table> + </div> <!-- End and-diff-id --> + </div> <!-- End headerRight --> + </div> <!-- End header --> +<div id="body-content" xstyle="padding:12px;padding-right:18px;"> +<div id="doc-content" style="position:relative;"> +<div id="mainBodyFluid"> +<H2> +Class android.content.res.<A HREF="../../../../reference/android/content/res/Configuration.html" target="_top"><font size="+2"><code>Configuration</code></font></A> +</H2> +<a NAME="constructors"></a> +<a NAME="methods"></a> +<a NAME="fields"></a> +<p> +<a NAME="Added"></a> +<TABLE summary="Added Fields" WIDTH="100%"> +<TR> + <TH VALIGN="TOP" COLSPAN=2>Added Fields</FONT></TD> +</TH> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.content.res.Configuration.SCREEN_HEIGHT_DP_UNDEFINED"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/content/res/Configuration.html#SCREEN_HEIGHT_DP_UNDEFINED" target="_top"><code>SCREEN_HEIGHT_DP_UNDEFINED</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.content.res.Configuration.SCREEN_WIDTH_DP_UNDEFINED"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/content/res/Configuration.html#SCREEN_WIDTH_DP_UNDEFINED" target="_top"><code>SCREEN_WIDTH_DP_UNDEFINED</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.content.res.Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/content/res/Configuration.html#SMALLEST_SCREEN_WIDTH_DP_UNDEFINED" target="_top"><code>SMALLEST_SCREEN_WIDTH_DP_UNDEFINED</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.content.res.Configuration.UI_MODE_TYPE_TELEVISION"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/content/res/Configuration.html#UI_MODE_TYPE_TELEVISION" target="_top"><code>UI_MODE_TYPE_TELEVISION</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.content.res.Configuration.screenHeightDp"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/content/res/Configuration.html#screenHeightDp" target="_top"><code>screenHeightDp</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.content.res.Configuration.screenWidthDp"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/content/res/Configuration.html#screenWidthDp" target="_top"><code>screenWidthDp</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.content.res.Configuration.smallestScreenWidthDp"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/content/res/Configuration.html#smallestScreenWidthDp" target="_top"><code>smallestScreenWidthDp</code></A></nobr> + </TD> + <TD> </TD> +</TR> +</TABLE> + + </div> + <div id="footer"> + <div id="copyright"> + Except as noted, this content is licensed under + <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>. + For details and restrictions, see the <a href="/license.html">Content License</a>. + </div> + <div id="footerlinks"> + <p> + <a href="http://www.android.com/terms.html">Site Terms of Service</a> - + <a href="http://www.android.com/privacy.html">Privacy Policy</a> - + <a href="http://www.android.com/branding.html">Brand Guidelines</a> + </p> + </div> + </div> <!-- end footer --> + </div><!-- end doc-content --> + </div> <!-- end body-content --> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/android.graphics.Point.html b/docs/html/sdk/api_diff/13/changes/android.graphics.Point.html new file mode 100644 index 0000000..e3324d2 --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/android.graphics.Point.html @@ -0,0 +1,152 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +android.graphics.Point +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY> +<!-- Start of nav bar --> +<a name="top"></a> +<div id="header" style="margin-bottom:0;padding-bottom:0;"> +<div id="headerLeft"> +<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a> +</div> + <div id="headerRight"> + <div id="headerLinks"> +<!-- <img src="/assets/images/icon_world.jpg" alt="" /> --> +<span class="text"> +<!-- <a href="#">English</a> | --> +<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr> +</span> +</div> + <div class="and-diff-id" style="margin-top:6px;margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td colspan="2" class="diffspechead">API Diff Specification</td> + </tr> + <tr> + <td class="diffspec" style="padding-top:.25em">To Level:</td> + <td class="diffvaluenew" style="padding-top:.25em">13</td> + </tr> + <tr> + <td class="diffspec">From Level:</td> + <td class="diffvalueold">12</td> + </tr> + <tr> + <td class="diffspec">Generated</td> + <td class="diffvalue">2011.06.29 10:50</td> + </tr> + </table> + </div><!-- End and-diff-id --> + <div class="and-diff-id" style="margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a> + </tr> + </table> + </div> <!-- End and-diff-id --> + </div> <!-- End headerRight --> + </div> <!-- End header --> +<div id="body-content" xstyle="padding:12px;padding-right:18px;"> +<div id="doc-content" style="position:relative;"> +<div id="mainBodyFluid"> +<H2> +Class android.graphics.<A HREF="../../../../reference/android/graphics/Point.html" target="_top"><font size="+2"><code>Point</code></font></A> +</H2> +<p><font xsize="+1">Added interface <code>android.os.Parcelable</code>.<br></font> +<a NAME="constructors"></a> +<a NAME="methods"></a> +<p> +<a NAME="Added"></a> +<TABLE summary="Added Methods" WIDTH="100%"> +<TR> + <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD> +</TH> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.graphics.Point.describeContents_added()"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/graphics/Point.html#describeContents()" target="_top"><code>describeContents</code></A>()</nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.graphics.Point.readFromParcel_added(android.os.Parcel)"></A> + <nobr><code>void</code> <A HREF="../../../../reference/android/graphics/Point.html#readFromParcel(android.os.Parcel)" target="_top"><code>readFromParcel</code></A>(<code>Parcel</code>)</nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.graphics.Point.writeToParcel_added(android.os.Parcel, int)"></A> + <nobr><code>void</code> <A HREF="../../../../reference/android/graphics/Point.html#writeToParcel(android.os.Parcel, int)" target="_top"><code>writeToParcel</code></A>(<code>Parcel,</nobr> int<nobr><nobr></code>)</nobr> + </TD> + <TD> </TD> +</TR> +</TABLE> + +<a NAME="fields"></a> +<p> +<a NAME="Added"></a> +<TABLE summary="Added Fields" WIDTH="100%"> +<TR> + <TH VALIGN="TOP" COLSPAN=2>Added Fields</FONT></TD> +</TH> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.graphics.Point.CREATOR"></A> + <nobr><code>Creator</code> <A HREF="../../../../reference/android/graphics/Point.html#CREATOR" target="_top"><code>CREATOR</code></A></nobr> + </TD> + <TD> </TD> +</TR> +</TABLE> + + </div> + <div id="footer"> + <div id="copyright"> + Except as noted, this content is licensed under + <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>. + For details and restrictions, see the <a href="/license.html">Content License</a>. + </div> + <div id="footerlinks"> + <p> + <a href="http://www.android.com/terms.html">Site Terms of Service</a> - + <a href="http://www.android.com/privacy.html">Privacy Policy</a> - + <a href="http://www.android.com/branding.html">Brand Guidelines</a> + </p> + </div> + </div> <!-- end footer --> + </div><!-- end doc-content --> + </div> <!-- end body-content --> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/android.graphics.PointF.html b/docs/html/sdk/api_diff/13/changes/android.graphics.PointF.html new file mode 100644 index 0000000..665c259 --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/android.graphics.PointF.html @@ -0,0 +1,152 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +android.graphics.PointF +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY> +<!-- Start of nav bar --> +<a name="top"></a> +<div id="header" style="margin-bottom:0;padding-bottom:0;"> +<div id="headerLeft"> +<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a> +</div> + <div id="headerRight"> + <div id="headerLinks"> +<!-- <img src="/assets/images/icon_world.jpg" alt="" /> --> +<span class="text"> +<!-- <a href="#">English</a> | --> +<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr> +</span> +</div> + <div class="and-diff-id" style="margin-top:6px;margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td colspan="2" class="diffspechead">API Diff Specification</td> + </tr> + <tr> + <td class="diffspec" style="padding-top:.25em">To Level:</td> + <td class="diffvaluenew" style="padding-top:.25em">13</td> + </tr> + <tr> + <td class="diffspec">From Level:</td> + <td class="diffvalueold">12</td> + </tr> + <tr> + <td class="diffspec">Generated</td> + <td class="diffvalue">2011.06.29 10:50</td> + </tr> + </table> + </div><!-- End and-diff-id --> + <div class="and-diff-id" style="margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a> + </tr> + </table> + </div> <!-- End and-diff-id --> + </div> <!-- End headerRight --> + </div> <!-- End header --> +<div id="body-content" xstyle="padding:12px;padding-right:18px;"> +<div id="doc-content" style="position:relative;"> +<div id="mainBodyFluid"> +<H2> +Class android.graphics.<A HREF="../../../../reference/android/graphics/PointF.html" target="_top"><font size="+2"><code>PointF</code></font></A> +</H2> +<p><font xsize="+1">Added interface <code>android.os.Parcelable</code>.<br></font> +<a NAME="constructors"></a> +<a NAME="methods"></a> +<p> +<a NAME="Added"></a> +<TABLE summary="Added Methods" WIDTH="100%"> +<TR> + <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD> +</TH> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.graphics.PointF.describeContents_added()"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/graphics/PointF.html#describeContents()" target="_top"><code>describeContents</code></A>()</nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.graphics.PointF.readFromParcel_added(android.os.Parcel)"></A> + <nobr><code>void</code> <A HREF="../../../../reference/android/graphics/PointF.html#readFromParcel(android.os.Parcel)" target="_top"><code>readFromParcel</code></A>(<code>Parcel</code>)</nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.graphics.PointF.writeToParcel_added(android.os.Parcel, int)"></A> + <nobr><code>void</code> <A HREF="../../../../reference/android/graphics/PointF.html#writeToParcel(android.os.Parcel, int)" target="_top"><code>writeToParcel</code></A>(<code>Parcel,</nobr> int<nobr><nobr></code>)</nobr> + </TD> + <TD> </TD> +</TR> +</TABLE> + +<a NAME="fields"></a> +<p> +<a NAME="Added"></a> +<TABLE summary="Added Fields" WIDTH="100%"> +<TR> + <TH VALIGN="TOP" COLSPAN=2>Added Fields</FONT></TD> +</TH> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.graphics.PointF.CREATOR"></A> + <nobr><code>Creator</code> <A HREF="../../../../reference/android/graphics/PointF.html#CREATOR" target="_top"><code>CREATOR</code></A></nobr> + </TD> + <TD> </TD> +</TR> +</TABLE> + + </div> + <div id="footer"> + <div id="copyright"> + Except as noted, this content is licensed under + <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>. + For details and restrictions, see the <a href="/license.html">Content License</a>. + </div> + <div id="footerlinks"> + <p> + <a href="http://www.android.com/terms.html">Site Terms of Service</a> - + <a href="http://www.android.com/privacy.html">Privacy Policy</a> - + <a href="http://www.android.com/branding.html">Brand Guidelines</a> + </p> + </div> + </div> <!-- end footer --> + </div><!-- end doc-content --> + </div> <!-- end body-content --> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/android.hardware.usb.UsbDeviceConnection.html b/docs/html/sdk/api_diff/13/changes/android.hardware.usb.UsbDeviceConnection.html new file mode 100644 index 0000000..1eb15ed --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/android.hardware.usb.UsbDeviceConnection.html @@ -0,0 +1,122 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +android.hardware.usb.UsbDeviceConnection +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY> +<!-- Start of nav bar --> +<a name="top"></a> +<div id="header" style="margin-bottom:0;padding-bottom:0;"> +<div id="headerLeft"> +<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a> +</div> + <div id="headerRight"> + <div id="headerLinks"> +<!-- <img src="/assets/images/icon_world.jpg" alt="" /> --> +<span class="text"> +<!-- <a href="#">English</a> | --> +<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr> +</span> +</div> + <div class="and-diff-id" style="margin-top:6px;margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td colspan="2" class="diffspechead">API Diff Specification</td> + </tr> + <tr> + <td class="diffspec" style="padding-top:.25em">To Level:</td> + <td class="diffvaluenew" style="padding-top:.25em">13</td> + </tr> + <tr> + <td class="diffspec">From Level:</td> + <td class="diffvalueold">12</td> + </tr> + <tr> + <td class="diffspec">Generated</td> + <td class="diffvalue">2011.06.29 10:50</td> + </tr> + </table> + </div><!-- End and-diff-id --> + <div class="and-diff-id" style="margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a> + </tr> + </table> + </div> <!-- End and-diff-id --> + </div> <!-- End headerRight --> + </div> <!-- End header --> +<div id="body-content" xstyle="padding:12px;padding-right:18px;"> +<div id="doc-content" style="position:relative;"> +<div id="mainBodyFluid"> +<H2> +Class android.hardware.usb.<A HREF="../../../../reference/android/hardware/usb/UsbDeviceConnection.html" target="_top"><font size="+2"><code>UsbDeviceConnection</code></font></A> +</H2> +<a NAME="constructors"></a> +<a NAME="methods"></a> +<p> +<a NAME="Added"></a> +<TABLE summary="Added Methods" WIDTH="100%"> +<TR> + <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD> +</TH> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.hardware.usb.UsbDeviceConnection.getRawDescriptors_added()"></A> + <nobr><code>byte[]</code> <A HREF="../../../../reference/android/hardware/usb/UsbDeviceConnection.html#getRawDescriptors()" target="_top"><code>getRawDescriptors</code></A>()</nobr> + </TD> + <TD> </TD> +</TR> +</TABLE> + +<a NAME="fields"></a> + </div> + <div id="footer"> + <div id="copyright"> + Except as noted, this content is licensed under + <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>. + For details and restrictions, see the <a href="/license.html">Content License</a>. + </div> + <div id="footerlinks"> + <p> + <a href="http://www.android.com/terms.html">Site Terms of Service</a> - + <a href="http://www.android.com/privacy.html">Privacy Policy</a> - + <a href="http://www.android.com/branding.html">Brand Guidelines</a> + </p> + </div> + </div> <!-- end footer --> + </div><!-- end doc-content --> + </div> <!-- end body-content --> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/android.net.ConnectivityManager.html b/docs/html/sdk/api_diff/13/changes/android.net.ConnectivityManager.html new file mode 100644 index 0000000..977649f --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/android.net.ConnectivityManager.html @@ -0,0 +1,129 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +android.net.ConnectivityManager +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY> +<!-- Start of nav bar --> +<a name="top"></a> +<div id="header" style="margin-bottom:0;padding-bottom:0;"> +<div id="headerLeft"> +<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a> +</div> + <div id="headerRight"> + <div id="headerLinks"> +<!-- <img src="/assets/images/icon_world.jpg" alt="" /> --> +<span class="text"> +<!-- <a href="#">English</a> | --> +<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr> +</span> +</div> + <div class="and-diff-id" style="margin-top:6px;margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td colspan="2" class="diffspechead">API Diff Specification</td> + </tr> + <tr> + <td class="diffspec" style="padding-top:.25em">To Level:</td> + <td class="diffvaluenew" style="padding-top:.25em">13</td> + </tr> + <tr> + <td class="diffspec">From Level:</td> + <td class="diffvalueold">12</td> + </tr> + <tr> + <td class="diffspec">Generated</td> + <td class="diffvalue">2011.06.29 10:50</td> + </tr> + </table> + </div><!-- End and-diff-id --> + <div class="and-diff-id" style="margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a> + </tr> + </table> + </div> <!-- End and-diff-id --> + </div> <!-- End headerRight --> + </div> <!-- End header --> +<div id="body-content" xstyle="padding:12px;padding-right:18px;"> +<div id="doc-content" style="position:relative;"> +<div id="mainBodyFluid"> +<H2> +Class android.net.<A HREF="../../../../reference/android/net/ConnectivityManager.html" target="_top"><font size="+2"><code>ConnectivityManager</code></font></A> +</H2> +<a NAME="constructors"></a> +<a NAME="methods"></a> +<a NAME="fields"></a> +<p> +<a NAME="Added"></a> +<TABLE summary="Added Fields" WIDTH="100%"> +<TR> + <TH VALIGN="TOP" COLSPAN=2>Added Fields</FONT></TD> +</TH> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.net.ConnectivityManager.TYPE_BLUETOOTH"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/net/ConnectivityManager.html#TYPE_BLUETOOTH" target="_top"><code>TYPE_BLUETOOTH</code></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.net.ConnectivityManager.TYPE_ETHERNET"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/net/ConnectivityManager.html#TYPE_ETHERNET" target="_top"><code>TYPE_ETHERNET</code></A></nobr> + </TD> + <TD> </TD> +</TR> +</TABLE> + + </div> + <div id="footer"> + <div id="copyright"> + Except as noted, this content is licensed under + <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>. + For details and restrictions, see the <a href="/license.html">Content License</a>. + </div> + <div id="footerlinks"> + <p> + <a href="http://www.android.com/terms.html">Site Terms of Service</a> - + <a href="http://www.android.com/privacy.html">Privacy Policy</a> - + <a href="http://www.android.com/branding.html">Brand Guidelines</a> + </p> + </div> + </div> <!-- end footer --> + </div><!-- end doc-content --> + </div> <!-- end body-content --> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/android.os.Binder.html b/docs/html/sdk/api_diff/13/changes/android.os.Binder.html new file mode 100644 index 0000000..fd11dd1 --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/android.os.Binder.html @@ -0,0 +1,122 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +android.os.Binder +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY> +<!-- Start of nav bar --> +<a name="top"></a> +<div id="header" style="margin-bottom:0;padding-bottom:0;"> +<div id="headerLeft"> +<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a> +</div> + <div id="headerRight"> + <div id="headerLinks"> +<!-- <img src="/assets/images/icon_world.jpg" alt="" /> --> +<span class="text"> +<!-- <a href="#">English</a> | --> +<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr> +</span> +</div> + <div class="and-diff-id" style="margin-top:6px;margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td colspan="2" class="diffspechead">API Diff Specification</td> + </tr> + <tr> + <td class="diffspec" style="padding-top:.25em">To Level:</td> + <td class="diffvaluenew" style="padding-top:.25em">13</td> + </tr> + <tr> + <td class="diffspec">From Level:</td> + <td class="diffvalueold">12</td> + </tr> + <tr> + <td class="diffspec">Generated</td> + <td class="diffvalue">2011.06.29 10:50</td> + </tr> + </table> + </div><!-- End and-diff-id --> + <div class="and-diff-id" style="margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a> + </tr> + </table> + </div> <!-- End and-diff-id --> + </div> <!-- End headerRight --> + </div> <!-- End header --> +<div id="body-content" xstyle="padding:12px;padding-right:18px;"> +<div id="doc-content" style="position:relative;"> +<div id="mainBodyFluid"> +<H2> +Class android.os.<A HREF="../../../../reference/android/os/Binder.html" target="_top"><font size="+2"><code>Binder</code></font></A> +</H2> +<a NAME="constructors"></a> +<a NAME="methods"></a> +<p> +<a NAME="Added"></a> +<TABLE summary="Added Methods" WIDTH="100%"> +<TR> + <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD> +</TH> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.os.Binder.dumpAsync_added(java.io.FileDescriptor, java.lang.String[])"></A> + <nobr><code>void</code> <A HREF="../../../../reference/android/os/Binder.html#dumpAsync(java.io.FileDescriptor, java.lang.String[])" target="_top"><code>dumpAsync</code></A>(<code>FileDescriptor,</nobr> String[]<nobr><nobr></code>)</nobr> + </TD> + <TD> </TD> +</TR> +</TABLE> + +<a NAME="fields"></a> + </div> + <div id="footer"> + <div id="copyright"> + Except as noted, this content is licensed under + <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>. + For details and restrictions, see the <a href="/license.html">Content License</a>. + </div> + <div id="footerlinks"> + <p> + <a href="http://www.android.com/terms.html">Site Terms of Service</a> - + <a href="http://www.android.com/privacy.html">Privacy Policy</a> - + <a href="http://www.android.com/branding.html">Brand Guidelines</a> + </p> + </div> + </div> <!-- end footer --> + </div><!-- end doc-content --> + </div> <!-- end body-content --> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/android.os.Build.VERSION_CODES.html b/docs/html/sdk/api_diff/13/changes/android.os.Build.VERSION_CODES.html new file mode 100644 index 0000000..0e50af4 --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/android.os.Build.VERSION_CODES.html @@ -0,0 +1,122 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +android.os.Build.VERSION_CODES +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY> +<!-- Start of nav bar --> +<a name="top"></a> +<div id="header" style="margin-bottom:0;padding-bottom:0;"> +<div id="headerLeft"> +<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a> +</div> + <div id="headerRight"> + <div id="headerLinks"> +<!-- <img src="/assets/images/icon_world.jpg" alt="" /> --> +<span class="text"> +<!-- <a href="#">English</a> | --> +<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr> +</span> +</div> + <div class="and-diff-id" style="margin-top:6px;margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td colspan="2" class="diffspechead">API Diff Specification</td> + </tr> + <tr> + <td class="diffspec" style="padding-top:.25em">To Level:</td> + <td class="diffvaluenew" style="padding-top:.25em">13</td> + </tr> + <tr> + <td class="diffspec">From Level:</td> + <td class="diffvalueold">12</td> + </tr> + <tr> + <td class="diffspec">Generated</td> + <td class="diffvalue">2011.06.29 10:50</td> + </tr> + </table> + </div><!-- End and-diff-id --> + <div class="and-diff-id" style="margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a> + </tr> + </table> + </div> <!-- End and-diff-id --> + </div> <!-- End headerRight --> + </div> <!-- End header --> +<div id="body-content" xstyle="padding:12px;padding-right:18px;"> +<div id="doc-content" style="position:relative;"> +<div id="mainBodyFluid"> +<H2> +Class android.os.<A HREF="../../../../reference/android/os/Build.VERSION_CODES.html" target="_top"><font size="+2"><code>Build.VERSION_CODES</code></font></A> +</H2> +<a NAME="constructors"></a> +<a NAME="methods"></a> +<a NAME="fields"></a> +<p> +<a NAME="Added"></a> +<TABLE summary="Added Fields" WIDTH="100%"> +<TR> + <TH VALIGN="TOP" COLSPAN=2>Added Fields</FONT></TD> +</TH> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.os.Build.VERSION_CODES.HONEYCOMB_MR2"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/os/Build.VERSION_CODES.html#HONEYCOMB_MR2" target="_top"><code>HONEYCOMB_MR2</code></A></nobr> + </TD> + <TD> </TD> +</TR> +</TABLE> + + </div> + <div id="footer"> + <div id="copyright"> + Except as noted, this content is licensed under + <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>. + For details and restrictions, see the <a href="/license.html">Content License</a>. + </div> + <div id="footerlinks"> + <p> + <a href="http://www.android.com/terms.html">Site Terms of Service</a> - + <a href="http://www.android.com/privacy.html">Privacy Policy</a> - + <a href="http://www.android.com/branding.html">Brand Guidelines</a> + </p> + </div> + </div> <!-- end footer --> + </div><!-- end doc-content --> + </div> <!-- end body-content --> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/android.os.IBinder.html b/docs/html/sdk/api_diff/13/changes/android.os.IBinder.html new file mode 100644 index 0000000..1a251cd --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/android.os.IBinder.html @@ -0,0 +1,137 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +android.os.IBinder +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY> +<!-- Start of nav bar --> +<a name="top"></a> +<div id="header" style="margin-bottom:0;padding-bottom:0;"> +<div id="headerLeft"> +<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a> +</div> + <div id="headerRight"> + <div id="headerLinks"> +<!-- <img src="/assets/images/icon_world.jpg" alt="" /> --> +<span class="text"> +<!-- <a href="#">English</a> | --> +<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr> +</span> +</div> + <div class="and-diff-id" style="margin-top:6px;margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td colspan="2" class="diffspechead">API Diff Specification</td> + </tr> + <tr> + <td class="diffspec" style="padding-top:.25em">To Level:</td> + <td class="diffvaluenew" style="padding-top:.25em">13</td> + </tr> + <tr> + <td class="diffspec">From Level:</td> + <td class="diffvalueold">12</td> + </tr> + <tr> + <td class="diffspec">Generated</td> + <td class="diffvalue">2011.06.29 10:50</td> + </tr> + </table> + </div><!-- End and-diff-id --> + <div class="and-diff-id" style="margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a> + </tr> + </table> + </div> <!-- End and-diff-id --> + </div> <!-- End headerRight --> + </div> <!-- End header --> +<div id="body-content" xstyle="padding:12px;padding-right:18px;"> +<div id="doc-content" style="position:relative;"> +<div id="mainBodyFluid"> +<H2> +Interface android.os.<A HREF="../../../../reference/android/os/IBinder.html" target="_top"><font size="+2"><code>IBinder</code></font></A> +</H2> +<a NAME="constructors"></a> +<a NAME="methods"></a> +<p> +<a NAME="Added"></a> +<TABLE summary="Added Methods" WIDTH="100%"> +<TR> + <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD> +</TH> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.os.IBinder.dumpAsync_added(java.io.FileDescriptor, java.lang.String[])"></A> + <nobr><code>void</code> <A HREF="../../../../reference/android/os/IBinder.html#dumpAsync(java.io.FileDescriptor, java.lang.String[])" target="_top"><code>dumpAsync</code></A>(<code>FileDescriptor,</nobr> String[]<nobr><nobr></code>)</nobr> + </TD> + <TD> </TD> +</TR> +</TABLE> + +<a NAME="fields"></a> +<p> +<a NAME="Added"></a> +<TABLE summary="Added Fields" WIDTH="100%"> +<TR> + <TH VALIGN="TOP" COLSPAN=2>Added Fields</FONT></TD> +</TH> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.os.IBinder.TWEET_TRANSACTION"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/os/IBinder.html#TWEET_TRANSACTION" target="_top"><code>TWEET_TRANSACTION</code></A></nobr> + </TD> + <TD> </TD> +</TR> +</TABLE> + + </div> + <div id="footer"> + <div id="copyright"> + Except as noted, this content is licensed under + <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>. + For details and restrictions, see the <a href="/license.html">Content License</a>. + </div> + <div id="footerlinks"> + <p> + <a href="http://www.android.com/terms.html">Site Terms of Service</a> - + <a href="http://www.android.com/privacy.html">Privacy Policy</a> - + <a href="http://www.android.com/branding.html">Brand Guidelines</a> + </p> + </div> + </div> <!-- end footer --> + </div><!-- end doc-content --> + </div> <!-- end body-content --> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/android.os.ParcelFileDescriptor.html b/docs/html/sdk/api_diff/13/changes/android.os.ParcelFileDescriptor.html new file mode 100644 index 0000000..3d3d1c3 --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/android.os.ParcelFileDescriptor.html @@ -0,0 +1,136 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +android.os.ParcelFileDescriptor +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY> +<!-- Start of nav bar --> +<a name="top"></a> +<div id="header" style="margin-bottom:0;padding-bottom:0;"> +<div id="headerLeft"> +<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a> +</div> + <div id="headerRight"> + <div id="headerLinks"> +<!-- <img src="/assets/images/icon_world.jpg" alt="" /> --> +<span class="text"> +<!-- <a href="#">English</a> | --> +<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr> +</span> +</div> + <div class="and-diff-id" style="margin-top:6px;margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td colspan="2" class="diffspechead">API Diff Specification</td> + </tr> + <tr> + <td class="diffspec" style="padding-top:.25em">To Level:</td> + <td class="diffvaluenew" style="padding-top:.25em">13</td> + </tr> + <tr> + <td class="diffspec">From Level:</td> + <td class="diffvalueold">12</td> + </tr> + <tr> + <td class="diffspec">Generated</td> + <td class="diffvalue">2011.06.29 10:50</td> + </tr> + </table> + </div><!-- End and-diff-id --> + <div class="and-diff-id" style="margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a> + </tr> + </table> + </div> <!-- End and-diff-id --> + </div> <!-- End headerRight --> + </div> <!-- End header --> +<div id="body-content" xstyle="padding:12px;padding-right:18px;"> +<div id="doc-content" style="position:relative;"> +<div id="mainBodyFluid"> +<H2> +Class android.os.<A HREF="../../../../reference/android/os/ParcelFileDescriptor.html" target="_top"><font size="+2"><code>ParcelFileDescriptor</code></font></A> +</H2> +<a NAME="constructors"></a> +<a NAME="methods"></a> +<p> +<a NAME="Added"></a> +<TABLE summary="Added Methods" WIDTH="100%"> +<TR> + <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD> +</TH> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.os.ParcelFileDescriptor.adoptFd_added(int)"></A> + <nobr><code>ParcelFileDescriptor</code> <A HREF="../../../../reference/android/os/ParcelFileDescriptor.html#adoptFd(int)" target="_top"><code>adoptFd</code></A>(<code>int</code>)</nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.os.ParcelFileDescriptor.dup_added(java.io.FileDescriptor)"></A> + <nobr><code>ParcelFileDescriptor</code> <A HREF="../../../../reference/android/os/ParcelFileDescriptor.html#dup(java.io.FileDescriptor)" target="_top"><code>dup</code></A>(<code>FileDescriptor</code>)</nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.os.ParcelFileDescriptor.fromFd_added(int)"></A> + <nobr><code>ParcelFileDescriptor</code> <A HREF="../../../../reference/android/os/ParcelFileDescriptor.html#fromFd(int)" target="_top"><code>fromFd</code></A>(<code>int</code>)</nobr> + </TD> + <TD> </TD> +</TR> +</TABLE> + +<a NAME="fields"></a> + </div> + <div id="footer"> + <div id="copyright"> + Except as noted, this content is licensed under + <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>. + For details and restrictions, see the <a href="/license.html">Content License</a>. + </div> + <div id="footerlinks"> + <p> + <a href="http://www.android.com/terms.html">Site Terms of Service</a> - + <a href="http://www.android.com/privacy.html">Privacy Policy</a> - + <a href="http://www.android.com/branding.html">Brand Guidelines</a> + </p> + </div> + </div> <!-- end footer --> + </div><!-- end doc-content --> + </div> <!-- end body-content --> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/android.os.PowerManager.html b/docs/html/sdk/api_diff/13/changes/android.os.PowerManager.html new file mode 100644 index 0000000..4af746d --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/android.os.PowerManager.html @@ -0,0 +1,124 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +android.os.PowerManager +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY> +<!-- Start of nav bar --> +<a name="top"></a> +<div id="header" style="margin-bottom:0;padding-bottom:0;"> +<div id="headerLeft"> +<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a> +</div> + <div id="headerRight"> + <div id="headerLinks"> +<!-- <img src="/assets/images/icon_world.jpg" alt="" /> --> +<span class="text"> +<!-- <a href="#">English</a> | --> +<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr> +</span> +</div> + <div class="and-diff-id" style="margin-top:6px;margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td colspan="2" class="diffspechead">API Diff Specification</td> + </tr> + <tr> + <td class="diffspec" style="padding-top:.25em">To Level:</td> + <td class="diffvaluenew" style="padding-top:.25em">13</td> + </tr> + <tr> + <td class="diffspec">From Level:</td> + <td class="diffvalueold">12</td> + </tr> + <tr> + <td class="diffspec">Generated</td> + <td class="diffvalue">2011.06.29 10:50</td> + </tr> + </table> + </div><!-- End and-diff-id --> + <div class="and-diff-id" style="margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a> + </tr> + </table> + </div> <!-- End and-diff-id --> + </div> <!-- End headerRight --> + </div> <!-- End header --> +<div id="body-content" xstyle="padding:12px;padding-right:18px;"> +<div id="doc-content" style="position:relative;"> +<div id="mainBodyFluid"> +<H2> +Class android.os.<A HREF="../../../../reference/android/os/PowerManager.html" target="_top"><font size="+2"><code>PowerManager</code></font></A> +</H2> +<a NAME="constructors"></a> +<a NAME="methods"></a> +<a NAME="fields"></a> +<p> +<a NAME="Changed"></a> +<TABLE summary="Changed Fields" WIDTH="100%"> +<TR> + <TH VALIGN="TOP" COLSPAN=3>Changed Fields</FONT></TD> +</TH> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.os.PowerManager.SCREEN_BRIGHT_WAKE_LOCK"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/os/PowerManager.html#SCREEN_BRIGHT_WAKE_LOCK" target="_top"><code>SCREEN_BRIGHT_WAKE_LOCK</code></font></A></nobr> </TD> + <TD VALIGN="TOP" WIDTH="30%"> +<b>Now deprecated</b>.<br> + </TD> + <TD> </TD> +</TR> +</TABLE> + + </div> + <div id="footer"> + <div id="copyright"> + Except as noted, this content is licensed under + <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>. + For details and restrictions, see the <a href="/license.html">Content License</a>. + </div> + <div id="footerlinks"> + <p> + <a href="http://www.android.com/terms.html">Site Terms of Service</a> - + <a href="http://www.android.com/privacy.html">Privacy Policy</a> - + <a href="http://www.android.com/branding.html">Brand Guidelines</a> + </p> + </div> + </div> <!-- end footer --> + </div><!-- end doc-content --> + </div> <!-- end body-content --> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/android.telephony.TelephonyManager.html b/docs/html/sdk/api_diff/13/changes/android.telephony.TelephonyManager.html new file mode 100644 index 0000000..43d6cf6 --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/android.telephony.TelephonyManager.html @@ -0,0 +1,122 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +android.telephony.TelephonyManager +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY> +<!-- Start of nav bar --> +<a name="top"></a> +<div id="header" style="margin-bottom:0;padding-bottom:0;"> +<div id="headerLeft"> +<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a> +</div> + <div id="headerRight"> + <div id="headerLinks"> +<!-- <img src="/assets/images/icon_world.jpg" alt="" /> --> +<span class="text"> +<!-- <a href="#">English</a> | --> +<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr> +</span> +</div> + <div class="and-diff-id" style="margin-top:6px;margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td colspan="2" class="diffspechead">API Diff Specification</td> + </tr> + <tr> + <td class="diffspec" style="padding-top:.25em">To Level:</td> + <td class="diffvaluenew" style="padding-top:.25em">13</td> + </tr> + <tr> + <td class="diffspec">From Level:</td> + <td class="diffvalueold">12</td> + </tr> + <tr> + <td class="diffspec">Generated</td> + <td class="diffvalue">2011.06.29 10:50</td> + </tr> + </table> + </div><!-- End and-diff-id --> + <div class="and-diff-id" style="margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a> + </tr> + </table> + </div> <!-- End and-diff-id --> + </div> <!-- End headerRight --> + </div> <!-- End header --> +<div id="body-content" xstyle="padding:12px;padding-right:18px;"> +<div id="doc-content" style="position:relative;"> +<div id="mainBodyFluid"> +<H2> +Class android.telephony.<A HREF="../../../../reference/android/telephony/TelephonyManager.html" target="_top"><font size="+2"><code>TelephonyManager</code></font></A> +</H2> +<a NAME="constructors"></a> +<a NAME="methods"></a> +<a NAME="fields"></a> +<p> +<a NAME="Added"></a> +<TABLE summary="Added Fields" WIDTH="100%"> +<TR> + <TH VALIGN="TOP" COLSPAN=2>Added Fields</FONT></TD> +</TH> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.telephony.TelephonyManager.NETWORK_TYPE_HSPAP"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/telephony/TelephonyManager.html#NETWORK_TYPE_HSPAP" target="_top"><code>NETWORK_TYPE_HSPAP</code></A></nobr> + </TD> + <TD> </TD> +</TR> +</TABLE> + + </div> + <div id="footer"> + <div id="copyright"> + Except as noted, this content is licensed under + <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>. + For details and restrictions, see the <a href="/license.html">Content License</a>. + </div> + <div id="footerlinks"> + <p> + <a href="http://www.android.com/terms.html">Site Terms of Service</a> - + <a href="http://www.android.com/privacy.html">Privacy Policy</a> - + <a href="http://www.android.com/branding.html">Brand Guidelines</a> + </p> + </div> + </div> <!-- end footer --> + </div><!-- end doc-content --> + </div> <!-- end body-content --> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/android.util.DisplayMetrics.html b/docs/html/sdk/api_diff/13/changes/android.util.DisplayMetrics.html new file mode 100644 index 0000000..01c329f --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/android.util.DisplayMetrics.html @@ -0,0 +1,122 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +android.util.DisplayMetrics +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY> +<!-- Start of nav bar --> +<a name="top"></a> +<div id="header" style="margin-bottom:0;padding-bottom:0;"> +<div id="headerLeft"> +<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a> +</div> + <div id="headerRight"> + <div id="headerLinks"> +<!-- <img src="/assets/images/icon_world.jpg" alt="" /> --> +<span class="text"> +<!-- <a href="#">English</a> | --> +<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr> +</span> +</div> + <div class="and-diff-id" style="margin-top:6px;margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td colspan="2" class="diffspechead">API Diff Specification</td> + </tr> + <tr> + <td class="diffspec" style="padding-top:.25em">To Level:</td> + <td class="diffvaluenew" style="padding-top:.25em">13</td> + </tr> + <tr> + <td class="diffspec">From Level:</td> + <td class="diffvalueold">12</td> + </tr> + <tr> + <td class="diffspec">Generated</td> + <td class="diffvalue">2011.06.29 10:50</td> + </tr> + </table> + </div><!-- End and-diff-id --> + <div class="and-diff-id" style="margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a> + </tr> + </table> + </div> <!-- End and-diff-id --> + </div> <!-- End headerRight --> + </div> <!-- End header --> +<div id="body-content" xstyle="padding:12px;padding-right:18px;"> +<div id="doc-content" style="position:relative;"> +<div id="mainBodyFluid"> +<H2> +Class android.util.<A HREF="../../../../reference/android/util/DisplayMetrics.html" target="_top"><font size="+2"><code>DisplayMetrics</code></font></A> +</H2> +<a NAME="constructors"></a> +<a NAME="methods"></a> +<a NAME="fields"></a> +<p> +<a NAME="Added"></a> +<TABLE summary="Added Fields" WIDTH="100%"> +<TR> + <TH VALIGN="TOP" COLSPAN=2>Added Fields</FONT></TD> +</TH> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.util.DisplayMetrics.DENSITY_TV"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/util/DisplayMetrics.html#DENSITY_TV" target="_top"><code>DENSITY_TV</code></A></nobr> + </TD> + <TD> </TD> +</TR> +</TABLE> + + </div> + <div id="footer"> + <div id="copyright"> + Except as noted, this content is licensed under + <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>. + For details and restrictions, see the <a href="/license.html">Content License</a>. + </div> + <div id="footerlinks"> + <p> + <a href="http://www.android.com/terms.html">Site Terms of Service</a> - + <a href="http://www.android.com/privacy.html">Privacy Policy</a> - + <a href="http://www.android.com/branding.html">Brand Guidelines</a> + </p> + </div> + </div> <!-- end footer --> + </div><!-- end doc-content --> + </div> <!-- end body-content --> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/android.view.Display.html b/docs/html/sdk/api_diff/13/changes/android.view.Display.html new file mode 100644 index 0000000..872532a --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/android.view.Display.html @@ -0,0 +1,157 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +android.view.Display +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY> +<!-- Start of nav bar --> +<a name="top"></a> +<div id="header" style="margin-bottom:0;padding-bottom:0;"> +<div id="headerLeft"> +<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a> +</div> + <div id="headerRight"> + <div id="headerLinks"> +<!-- <img src="/assets/images/icon_world.jpg" alt="" /> --> +<span class="text"> +<!-- <a href="#">English</a> | --> +<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr> +</span> +</div> + <div class="and-diff-id" style="margin-top:6px;margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td colspan="2" class="diffspechead">API Diff Specification</td> + </tr> + <tr> + <td class="diffspec" style="padding-top:.25em">To Level:</td> + <td class="diffvaluenew" style="padding-top:.25em">13</td> + </tr> + <tr> + <td class="diffspec">From Level:</td> + <td class="diffvalueold">12</td> + </tr> + <tr> + <td class="diffspec">Generated</td> + <td class="diffvalue">2011.06.29 10:50</td> + </tr> + </table> + </div><!-- End and-diff-id --> + <div class="and-diff-id" style="margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a> + </tr> + </table> + </div> <!-- End and-diff-id --> + </div> <!-- End headerRight --> + </div> <!-- End header --> +<div id="body-content" xstyle="padding:12px;padding-right:18px;"> +<div id="doc-content" style="position:relative;"> +<div id="mainBodyFluid"> +<H2> +Class android.view.<A HREF="../../../../reference/android/view/Display.html" target="_top"><font size="+2"><code>Display</code></font></A> +</H2> +<a NAME="constructors"></a> +<a NAME="methods"></a> +<p> +<a NAME="Added"></a> +<TABLE summary="Added Methods" WIDTH="100%"> +<TR> + <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD> +</TH> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.view.Display.getRectSize_added(android.graphics.Rect)"></A> + <nobr><code>void</code> <A HREF="../../../../reference/android/view/Display.html#getRectSize(android.graphics.Rect)" target="_top"><code>getRectSize</code></A>(<code>Rect</code>)</nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.view.Display.getSize_added(android.graphics.Point)"></A> + <nobr><code>void</code> <A HREF="../../../../reference/android/view/Display.html#getSize(android.graphics.Point)" target="_top"><code>getSize</code></A>(<code>Point</code>)</nobr> + </TD> + <TD> </TD> +</TR> +</TABLE> + +<p> +<a NAME="Changed"></a> +<TABLE summary="Changed Methods" WIDTH="100%"> +<TR> + <TH VALIGN="TOP" COLSPAN=3>Changed Methods</FONT></TD> +</TH> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.view.Display.getHeight_changed()"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/view/Display.html#getHeight()" target="_top"><code>getHeight</code></A>() </nobr> + </TD> + <TD VALIGN="TOP" WIDTH="30%"> +<b>Now deprecated</b>.<br> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.view.Display.getWidth_changed()"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/view/Display.html#getWidth()" target="_top"><code>getWidth</code></A>() </nobr> + </TD> + <TD VALIGN="TOP" WIDTH="30%"> +<b>Now deprecated</b>.<br> + </TD> + <TD> </TD> +</TR> +</TABLE> + +<a NAME="fields"></a> + </div> + <div id="footer"> + <div id="copyright"> + Except as noted, this content is licensed under + <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>. + For details and restrictions, see the <a href="/license.html">Content License</a>. + </div> + <div id="footerlinks"> + <p> + <a href="http://www.android.com/terms.html">Site Terms of Service</a> - + <a href="http://www.android.com/privacy.html">Privacy Policy</a> - + <a href="http://www.android.com/branding.html">Brand Guidelines</a> + </p> + </div> + </div> <!-- end footer --> + </div><!-- end doc-content --> + </div> <!-- end body-content --> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/android.view.KeyEvent.html b/docs/html/sdk/api_diff/13/changes/android.view.KeyEvent.html new file mode 100644 index 0000000..eaccac4 --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/android.view.KeyEvent.html @@ -0,0 +1,122 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +android.view.KeyEvent +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY> +<!-- Start of nav bar --> +<a name="top"></a> +<div id="header" style="margin-bottom:0;padding-bottom:0;"> +<div id="headerLeft"> +<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a> +</div> + <div id="headerRight"> + <div id="headerLinks"> +<!-- <img src="/assets/images/icon_world.jpg" alt="" /> --> +<span class="text"> +<!-- <a href="#">English</a> | --> +<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr> +</span> +</div> + <div class="and-diff-id" style="margin-top:6px;margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td colspan="2" class="diffspechead">API Diff Specification</td> + </tr> + <tr> + <td class="diffspec" style="padding-top:.25em">To Level:</td> + <td class="diffvaluenew" style="padding-top:.25em">13</td> + </tr> + <tr> + <td class="diffspec">From Level:</td> + <td class="diffvalueold">12</td> + </tr> + <tr> + <td class="diffspec">Generated</td> + <td class="diffvalue">2011.06.29 10:50</td> + </tr> + </table> + </div><!-- End and-diff-id --> + <div class="and-diff-id" style="margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a> + </tr> + </table> + </div> <!-- End and-diff-id --> + </div> <!-- End headerRight --> + </div> <!-- End header --> +<div id="body-content" xstyle="padding:12px;padding-right:18px;"> +<div id="doc-content" style="position:relative;"> +<div id="mainBodyFluid"> +<H2> +Class android.view.<A HREF="../../../../reference/android/view/KeyEvent.html" target="_top"><font size="+2"><code>KeyEvent</code></font></A> +</H2> +<a NAME="constructors"></a> +<a NAME="methods"></a> +<p> +<a NAME="Added"></a> +<TABLE summary="Added Methods" WIDTH="100%"> +<TR> + <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD> +</TH> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.view.KeyEvent.getModifiers_added()"></A> + <nobr><code>int</code> <A HREF="../../../../reference/android/view/KeyEvent.html#getModifiers()" target="_top"><code>getModifiers</code></A>()</nobr> + </TD> + <TD> </TD> +</TR> +</TABLE> + +<a NAME="fields"></a> + </div> + <div id="footer"> + <div id="copyright"> + Except as noted, this content is licensed under + <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>. + For details and restrictions, see the <a href="/license.html">Content License</a>. + </div> + <div id="footerlinks"> + <p> + <a href="http://www.android.com/terms.html">Site Terms of Service</a> - + <a href="http://www.android.com/privacy.html">Privacy Policy</a> - + <a href="http://www.android.com/branding.html">Brand Guidelines</a> + </p> + </div> + </div> <!-- end footer --> + </div><!-- end doc-content --> + </div> <!-- end body-content --> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/changes-summary.html b/docs/html/sdk/api_diff/13/changes/changes-summary.html new file mode 100644 index 0000000..082fcfb --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/changes-summary.html @@ -0,0 +1,205 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +Android API Differences Report +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<body class="gc-documentation"> +<!-- Start of nav bar --> +<a name="top"></a> +<div id="header" style="margin-bottom:0;padding-bottom:0;"> +<div id="headerLeft"> +<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a> +</div> + <div id="headerRight"> + <div id="headerLinks"> +<!-- <img src="/assets/images/icon_world.jpg" alt="" /> --> +<span class="text"> +<!-- <a href="#">English</a> | --> +<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr> +</span> +</div> + <div class="and-diff-id" style="margin-top:6px;margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td colspan="2" class="diffspechead">API Diff Specification</td> + </tr> + <tr> + <td class="diffspec" style="padding-top:.25em">To Level:</td> + <td class="diffvaluenew" style="padding-top:.25em">13</td> + </tr> + <tr> + <td class="diffspec">From Level:</td> + <td class="diffvalueold">12</td> + </tr> + <tr> + <td class="diffspec">Generated</td> + <td class="diffvalue">2011.06.29 10:50</td> + </tr> + </table> + </div><!-- End and-diff-id --> + <div class="and-diff-id" style="margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a> + </tr> + </table> + </div> <!-- End and-diff-id --> + </div> <!-- End headerRight --> + </div> <!-- End header --> +<div id="body-content" xstyle="padding:12px;padding-right:18px;"> +<div id="doc-content" style="position:relative;"> +<div id="mainBodyFluid"> + <div id="docTitleContainer"> +<h1>Android API Differences Report</h1> +<p>This report details the changes in the core Android framework API between two <a +href="http://developer.android.com/guide/appendix/api-levels.html" target="_top">API Level</a> +specifications. It shows additions, modifications, and removals for packages, classes, methods, and fields. +The report also includes general statistics that characterize the extent and type of the differences.</p> +<p>This report is based a comparison of the Android API specifications +whose API Level identifiers are given in the upper-right corner of this page. It compares a +newer "to" API to an older "from" API, noting all changes relative to the +older API. So, for example, API elements marked as removed are no longer present in the "to" +API specification.</p> +<p>To navigate the report, use the "Select a Diffs Index" and "Filter the Index" +controls on the left. The report uses text formatting to indicate <em>interface names</em>, +<a href= ><code>links to reference documentation</code></a>, and <a href= >links to change +description</a>. The statistics are accessible from the "Statistics" link in the upper-right corner.</p> +<p>For more information about the Android framework API and SDK, +see the <a href="http://developer.android.com/index.html" target="_top">Android Developers site</a>.</p> +<p> +<a NAME="Changed"></a> +<TABLE summary="Changed Packages" WIDTH="100%"> +<TR> + <TH VALIGN="TOP" COLSPAN=3>Changed Packages</FONT></TD> +</TH> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android"></A> + <nobr><A HREF="pkg_android.html">android</A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.app"></A> + <nobr><A HREF="pkg_android.app.html">android.app</A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.content.pm"></A> + <nobr><A HREF="pkg_android.content.pm.html">android.content.pm</A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.content.res"></A> + <nobr><A HREF="pkg_android.content.res.html">android.content.res</A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.graphics"></A> + <nobr><A HREF="pkg_android.graphics.html">android.graphics</A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.hardware.usb"></A> + <nobr><A HREF="pkg_android.hardware.usb.html">android.hardware.usb</A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.net"></A> + <nobr><A HREF="pkg_android.net.html">android.net</A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.os"></A> + <nobr><A HREF="pkg_android.os.html">android.os</A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.telephony"></A> + <nobr><A HREF="pkg_android.telephony.html">android.telephony</A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.util"></A> + <nobr><A HREF="pkg_android.util.html">android.util</A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="android.view"></A> + <nobr><A HREF="pkg_android.view.html">android.view</A></nobr> + </TD> + <TD> </TD> +</TR> +</TABLE> + +<!-- End of API section --> +<!-- Start of packages section --> + </div> + <div id="footer"> + <div id="copyright"> + Except as noted, this content is licensed under + <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>. + For details and restrictions, see the <a href="/license.html">Content License</a>. + </div> + <div id="footerlinks"> + <p> + <a href="http://www.android.com/terms.html">Site Terms of Service</a> - + <a href="http://www.android.com/privacy.html">Privacy Policy</a> - + <a href="http://www.android.com/branding.html">Brand Guidelines</a> + </p> + </div> + </div> <!-- end footer --> + </div><!-- end doc-content --> + </div> <!-- end body-content --> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/classes_index_additions.html b/docs/html/sdk/api_diff/13/changes/classes_index_additions.html new file mode 100644 index 0000000..9ca1958 --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/classes_index_additions.html @@ -0,0 +1,73 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +Class Additions Index +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY class="gc-documentation" style="padding:12px;"> +<a NAME="topheader"></a> +<table summary="Index for Classes" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;"> + <tr> + <th class="indexHeader"> + Filter the Index: + </th> + </tr> + <tr> + <td class="indexText" style="line-height:1.3em;padding-left:2em;"> +<a href="classes_index_all.html" class="staysblack">All Classes</a> + <br> +<font color="#999999">Removals</font> + <br> +<b>Additions</b> + <br> +<A HREF="classes_index_changes.html"xclass="hiddenlink">Changes</A> + </td> + </tr> +</table> +<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;"> +Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font> +</div> +<A NAME="F"></A> +<br><font size="+2">F</font> +<a href="#P"><font size="-2">P</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<A HREF="pkg_android.app.html#Fragment.SavedState" class="hiddenlink" target="rightframe"><b>Fragment.SavedState</b></A><br> +<A NAME="P"></A> +<br><font size="+2">P</font> +<a href="#F"><font size="-2">F</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<A HREF="pkg_android.os.html#Parcelable.ClassLoaderCreator" class="hiddenlink" target="rightframe"><b><i>Parcelable.ClassLoaderCreator</i></b></A><br> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/classes_index_all.html b/docs/html/sdk/api_diff/13/changes/classes_index_all.html new file mode 100644 index 0000000..6bd1021 --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/classes_index_all.html @@ -0,0 +1,300 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +Class Differences Index +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY class="gc-documentation" style="padding:12px;"> +<a NAME="topheader"></a> +<table summary="Index for Classes" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;"> + <tr> + <th class="indexHeader"> + Filter the Index: + </th> + </tr> + <tr> + <td class="indexText" style="line-height:1.3em;padding-left:2em;"> +<b>Classes</b> + <br> +<font color="#999999">Removals</font> + <br> +<A HREF="classes_index_additions.html"xclass="hiddenlink">Additions</A> + <br> +<A HREF="classes_index_changes.html"xclass="hiddenlink">Changes</A> + </td> + </tr> +</table> +<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;"> +Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font> +</div> +<A NAME="A"></A> +<br><font size="+2">A</font> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<A HREF="android.app.Activity.html" class="hiddenlink" target="rightframe">Activity</A><br> +<A HREF="android.app.ActivityGroup.html" class="hiddenlink" target="rightframe">ActivityGroup</A><br> +<A HREF="android.content.pm.ActivityInfo.html" class="hiddenlink" target="rightframe">ActivityInfo</A><br> +<A HREF="android.content.pm.ApplicationInfo.html" class="hiddenlink" target="rightframe">ApplicationInfo</A><br> +<A NAME="B"></A> +<br><font size="+2">B</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<A HREF="android.os.Binder.html" class="hiddenlink" target="rightframe">Binder</A><br> +<A HREF="android.os.Build.VERSION_CODES.html" class="hiddenlink" target="rightframe">Build.VERSION_CODES</A><br> +<A NAME="C"></A> +<br><font size="+2">C</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<A HREF="android.content.res.Configuration.html" class="hiddenlink" target="rightframe">Configuration</A><br> +<A HREF="android.net.ConnectivityManager.html" class="hiddenlink" target="rightframe">ConnectivityManager</A><br> +<A NAME="D"></A> +<br><font size="+2">D</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<A HREF="android.view.Display.html" class="hiddenlink" target="rightframe">Display</A><br> +<A HREF="android.util.DisplayMetrics.html" class="hiddenlink" target="rightframe">DisplayMetrics</A><br> +<A NAME="F"></A> +<br><font size="+2">F</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<A HREF="android.app.Fragment.html" class="hiddenlink" target="rightframe">Fragment</A><br> +<A HREF="pkg_android.app.html#Fragment.SavedState" class="hiddenlink" target="rightframe"><b>Fragment.SavedState</b></A><br> +<A HREF="android.app.FragmentManager.html" class="hiddenlink" target="rightframe">FragmentManager</A><br> +<A HREF="android.app.FragmentTransaction.html" class="hiddenlink" target="rightframe">FragmentTransaction</A><br> +<A NAME="I"></A> +<br><font size="+2">I</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<A HREF="android.os.IBinder.html" class="hiddenlink" target="rightframe"><i>IBinder</i></A><br> +<A NAME="K"></A> +<br><font size="+2">K</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<A HREF="android.view.KeyEvent.html" class="hiddenlink" target="rightframe">KeyEvent</A><br> +<A HREF="android.app.KeyguardManager.html" class="hiddenlink" target="rightframe">KeyguardManager</A><br> +<A HREF="android.app.KeyguardManager.KeyguardLock.html" class="hiddenlink" target="rightframe">KeyguardManager.KeyguardLock</A><br> +<A NAME="L"></A> +<br><font size="+2">L</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<A HREF="android.app.LocalActivityManager.html" class="hiddenlink" target="rightframe">LocalActivityManager</A><br> +<A NAME="M"></A> +<br><font size="+2">M</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<A HREF="android.Manifest.permission.html" class="hiddenlink" target="rightframe">Manifest.permission</A><br> +<A NAME="P"></A> +<br><font size="+2">P</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<A HREF="android.content.pm.PackageManager.html" class="hiddenlink" target="rightframe">PackageManager</A><br> +<A HREF="pkg_android.os.html#Parcelable.ClassLoaderCreator" class="hiddenlink" target="rightframe"><b><i>Parcelable.ClassLoaderCreator</i></b></A><br> +<A HREF="android.os.ParcelFileDescriptor.html" class="hiddenlink" target="rightframe">ParcelFileDescriptor</A><br> +<A HREF="android.graphics.Point.html" class="hiddenlink" target="rightframe">Point</A><br> +<A HREF="android.graphics.PointF.html" class="hiddenlink" target="rightframe">PointF</A><br> +<A HREF="android.os.PowerManager.html" class="hiddenlink" target="rightframe">PowerManager</A><br> +<A NAME="R"></A> +<br><font size="+2">R</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<A HREF="android.R.attr.html" class="hiddenlink" target="rightframe">R.attr</A><br> +<A HREF="android.R.style.html" class="hiddenlink" target="rightframe">R.style</A><br> +<A NAME="T"></A> +<br><font size="+2">T</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#U"><font size="-2">U</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<A HREF="android.app.TabActivity.html" class="hiddenlink" target="rightframe">TabActivity</A><br> +<A HREF="android.telephony.TelephonyManager.html" class="hiddenlink" target="rightframe">TelephonyManager</A><br> +<A NAME="U"></A> +<br><font size="+2">U</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#T"><font size="-2">T</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<A HREF="android.hardware.usb.UsbDeviceConnection.html" class="hiddenlink" target="rightframe">UsbDeviceConnection</A><br> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/classes_index_changes.html b/docs/html/sdk/api_diff/13/changes/classes_index_changes.html new file mode 100644 index 0000000..d76983f --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/classes_index_changes.html @@ -0,0 +1,298 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +Class Changes Index +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY class="gc-documentation" style="padding:12px;"> +<a NAME="topheader"></a> +<table summary="Index for Classes" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;"> + <tr> + <th class="indexHeader"> + Filter the Index: + </th> + </tr> + <tr> + <td class="indexText" style="line-height:1.3em;padding-left:2em;"> +<a href="classes_index_all.html" class="staysblack">All Classes</a> + <br> +<font color="#999999">Removals</font> + <br> +<A HREF="classes_index_additions.html"xclass="hiddenlink">Additions</A> + <br> +<b>Changes</b> + </td> + </tr> +</table> +<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;"> +Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font> +</div> +<A NAME="A"></A> +<br><font size="+2">A</font> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<A HREF="android.app.Activity.html" class="hiddenlink" target="rightframe">Activity</A><br> +<A HREF="android.app.ActivityGroup.html" class="hiddenlink" target="rightframe">ActivityGroup</A><br> +<A HREF="android.content.pm.ActivityInfo.html" class="hiddenlink" target="rightframe">ActivityInfo</A><br> +<A HREF="android.content.pm.ApplicationInfo.html" class="hiddenlink" target="rightframe">ApplicationInfo</A><br> +<A NAME="B"></A> +<br><font size="+2">B</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<A HREF="android.os.Binder.html" class="hiddenlink" target="rightframe">Binder</A><br> +<A HREF="android.os.Build.VERSION_CODES.html" class="hiddenlink" target="rightframe">Build.VERSION_CODES</A><br> +<A NAME="C"></A> +<br><font size="+2">C</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<A HREF="android.content.res.Configuration.html" class="hiddenlink" target="rightframe">Configuration</A><br> +<A HREF="android.net.ConnectivityManager.html" class="hiddenlink" target="rightframe">ConnectivityManager</A><br> +<A NAME="D"></A> +<br><font size="+2">D</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<A HREF="android.view.Display.html" class="hiddenlink" target="rightframe">Display</A><br> +<A HREF="android.util.DisplayMetrics.html" class="hiddenlink" target="rightframe">DisplayMetrics</A><br> +<A NAME="F"></A> +<br><font size="+2">F</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<A HREF="android.app.Fragment.html" class="hiddenlink" target="rightframe">Fragment</A><br> +<A HREF="android.app.FragmentManager.html" class="hiddenlink" target="rightframe">FragmentManager</A><br> +<A HREF="android.app.FragmentTransaction.html" class="hiddenlink" target="rightframe">FragmentTransaction</A><br> +<A NAME="I"></A> +<br><font size="+2">I</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<A HREF="android.os.IBinder.html" class="hiddenlink" target="rightframe"><i>IBinder</i></A><br> +<A NAME="K"></A> +<br><font size="+2">K</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<A HREF="android.view.KeyEvent.html" class="hiddenlink" target="rightframe">KeyEvent</A><br> +<A HREF="android.app.KeyguardManager.html" class="hiddenlink" target="rightframe">KeyguardManager</A><br> +<A HREF="android.app.KeyguardManager.KeyguardLock.html" class="hiddenlink" target="rightframe">KeyguardManager.KeyguardLock</A><br> +<A NAME="L"></A> +<br><font size="+2">L</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<A HREF="android.app.LocalActivityManager.html" class="hiddenlink" target="rightframe">LocalActivityManager</A><br> +<A NAME="M"></A> +<br><font size="+2">M</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<A HREF="android.Manifest.permission.html" class="hiddenlink" target="rightframe">Manifest.permission</A><br> +<A NAME="P"></A> +<br><font size="+2">P</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<A HREF="android.content.pm.PackageManager.html" class="hiddenlink" target="rightframe">PackageManager</A><br> +<A HREF="android.os.ParcelFileDescriptor.html" class="hiddenlink" target="rightframe">ParcelFileDescriptor</A><br> +<A HREF="android.graphics.Point.html" class="hiddenlink" target="rightframe">Point</A><br> +<A HREF="android.graphics.PointF.html" class="hiddenlink" target="rightframe">PointF</A><br> +<A HREF="android.os.PowerManager.html" class="hiddenlink" target="rightframe">PowerManager</A><br> +<A NAME="R"></A> +<br><font size="+2">R</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<A HREF="android.R.attr.html" class="hiddenlink" target="rightframe">R.attr</A><br> +<A HREF="android.R.style.html" class="hiddenlink" target="rightframe">R.style</A><br> +<A NAME="T"></A> +<br><font size="+2">T</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#U"><font size="-2">U</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<A HREF="android.app.TabActivity.html" class="hiddenlink" target="rightframe">TabActivity</A><br> +<A HREF="android.telephony.TelephonyManager.html" class="hiddenlink" target="rightframe">TelephonyManager</A><br> +<A NAME="U"></A> +<br><font size="+2">U</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#B"><font size="-2">B</font></a> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#K"><font size="-2">K</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#M"><font size="-2">M</font></a> +<a href="#P"><font size="-2">P</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#T"><font size="-2">T</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<A HREF="android.hardware.usb.UsbDeviceConnection.html" class="hiddenlink" target="rightframe">UsbDeviceConnection</A><br> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/classes_index_removals.html b/docs/html/sdk/api_diff/13/changes/classes_index_removals.html new file mode 100644 index 0000000..e6da73f --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/classes_index_removals.html @@ -0,0 +1,61 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +Class Removals Index +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY class="gc-documentation" style="padding:12px;"> +<a NAME="topheader"></a> +<table summary="Index for Classes" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;"> + <tr> + <th class="indexHeader"> + Filter the Index: + </th> + </tr> + <tr> + <td class="indexText" style="line-height:1.3em;padding-left:2em;"> +<a href="classes_index_all.html" class="staysblack">All Classes</a> + <br> +<font color="#999999">Removals</font> + <br> +<A HREF="classes_index_additions.html"xclass="hiddenlink">Additions</A> + <br> +<A HREF="classes_index_changes.html"xclass="hiddenlink">Changes</A> + </td> + </tr> +</table> +<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;"> +Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font> +</div> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/constructors_index_additions.html b/docs/html/sdk/api_diff/13/changes/constructors_index_additions.html new file mode 100644 index 0000000..3237ba3 --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/constructors_index_additions.html @@ -0,0 +1,61 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +Constructor Additions Index +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY class="gc-documentation" style="padding:12px;"> +<a NAME="topheader"></a> +<table summary="Index for Constructors" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;"> + <tr> + <th class="indexHeader"> + Filter the Index: + </th> + </tr> + <tr> + <td class="indexText" style="line-height:1.3em;padding-left:2em;"> +<a href="constructors_index_all.html" class="staysblack">All Constructors</a> + <br> +<font color="#999999">Removals</font> + <br> +<font color="#999999">Additions</font> + <br> +<font color="#999999">Changes</font> + </td> + </tr> +</table> +<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;"> +Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font> +</div> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/constructors_index_all.html b/docs/html/sdk/api_diff/13/changes/constructors_index_all.html new file mode 100644 index 0000000..637582e --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/constructors_index_all.html @@ -0,0 +1,61 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +Constructor Differences Index +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY class="gc-documentation" style="padding:12px;"> +<a NAME="topheader"></a> +<table summary="Index for Constructors" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;"> + <tr> + <th class="indexHeader"> + Filter the Index: + </th> + </tr> + <tr> + <td class="indexText" style="line-height:1.3em;padding-left:2em;"> +<b>Constructors</b> + <br> +<font color="#999999">Removals</font> + <br> +<font color="#999999">Additions</font> + <br> +<font color="#999999">Changes</font> + </td> + </tr> +</table> +<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;"> +Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font> +</div> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/constructors_index_changes.html b/docs/html/sdk/api_diff/13/changes/constructors_index_changes.html new file mode 100644 index 0000000..728fa2d --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/constructors_index_changes.html @@ -0,0 +1,61 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +Constructor Changes Index +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY class="gc-documentation" style="padding:12px;"> +<a NAME="topheader"></a> +<table summary="Index for Constructors" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;"> + <tr> + <th class="indexHeader"> + Filter the Index: + </th> + </tr> + <tr> + <td class="indexText" style="line-height:1.3em;padding-left:2em;"> +<a href="constructors_index_all.html" class="staysblack">All Constructors</a> + <br> +<font color="#999999">Removals</font> + <br> +<font color="#999999">Additions</font> + <br> +<font color="#999999">Changes</font> + </td> + </tr> +</table> +<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;"> +Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font> +</div> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/constructors_index_removals.html b/docs/html/sdk/api_diff/13/changes/constructors_index_removals.html new file mode 100644 index 0000000..1b95544 --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/constructors_index_removals.html @@ -0,0 +1,61 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +Constructor Removals Index +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY class="gc-documentation" style="padding:12px;"> +<a NAME="topheader"></a> +<table summary="Index for Constructors" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;"> + <tr> + <th class="indexHeader"> + Filter the Index: + </th> + </tr> + <tr> + <td class="indexText" style="line-height:1.3em;padding-left:2em;"> +<a href="constructors_index_all.html" class="staysblack">All Constructors</a> + <br> +<font color="#999999">Removals</font> + <br> +<font color="#999999">Additions</font> + <br> +<font color="#999999">Changes</font> + </td> + </tr> +</table> +<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;"> +Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font> +</div> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/fields_index_additions.html b/docs/html/sdk/api_diff/13/changes/fields_index_additions.html new file mode 100644 index 0000000..271c9aa --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/fields_index_additions.html @@ -0,0 +1,363 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +Field Additions Index +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY class="gc-documentation" style="padding:12px;"> +<a NAME="topheader"></a> +<table summary="Index for Fields" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;"> + <tr> + <th class="indexHeader"> + Filter the Index: + </th> + </tr> + <tr> + <td class="indexText" style="line-height:1.3em;padding-left:2em;"> +<a href="fields_index_all.html" class="staysblack">All Fields</a> + <br> +<font color="#999999">Removals</font> + <br> +<b>Additions</b> + <br> +<A HREF="fields_index_changes.html"xclass="hiddenlink">Changes</A> + </td> + </tr> +</table> +<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;"> +Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font> +</div> +<A NAME="C"></A> +<br><font size="+2">C</font> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<i>compatibleWidthLimitDp</i><br> +<nobr> in +<A HREF="android.R.attr.html#android.R.attr.compatibleWidthLimitDp" class="hiddenlink" target="rightframe">android.R.attr</A> +</nobr><br> +<nobr> in +<A HREF="android.content.pm.ApplicationInfo.html#android.content.pm.ApplicationInfo.compatibleWidthLimitDp" class="hiddenlink" target="rightframe">android.content.pm.ApplicationInfo</A> +</nobr><br> +<nobr><A HREF="android.content.pm.ActivityInfo.html#android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE" class="hiddenlink" target="rightframe">CONFIG_SCREEN_SIZE</A> +</nobr><br> +<nobr><A HREF="android.content.pm.ActivityInfo.html#android.content.pm.ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE" class="hiddenlink" target="rightframe">CONFIG_SMALLEST_SCREEN_SIZE</A> +</nobr><br> +<i>CREATOR</i><br> +<nobr> in +<A HREF="android.graphics.Point.html#android.graphics.Point.CREATOR" class="hiddenlink" target="rightframe">android.graphics.Point</A> +</nobr><br> +<nobr> in +<A HREF="android.graphics.PointF.html#android.graphics.PointF.CREATOR" class="hiddenlink" target="rightframe">android.graphics.PointF</A> +</nobr><br> +<A NAME="D"></A> +<br><font size="+2">D</font> +<a href="#C"><font size="-2">C</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.util.DisplayMetrics.html#android.util.DisplayMetrics.DENSITY_TV" class="hiddenlink" target="rightframe">DENSITY_TV</A> +</nobr><br> +<A NAME="F"></A> +<br><font size="+2">F</font> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.content.pm.PackageManager.html#android.content.pm.PackageManager.FEATURE_FAKETOUCH_MULTITOUCH_DISTINCT" class="hiddenlink" target="rightframe">FEATURE_FAKETOUCH_MULTITOUCH_DISTINCT</A> +</nobr><br> +<nobr><A HREF="android.content.pm.PackageManager.html#android.content.pm.PackageManager.FEATURE_FAKETOUCH_MULTITOUCH_JAZZHAND" class="hiddenlink" target="rightframe">FEATURE_FAKETOUCH_MULTITOUCH_JAZZHAND</A> +</nobr><br> +<nobr><A HREF="android.content.pm.PackageManager.html#android.content.pm.PackageManager.FEATURE_SCREEN_LANDSCAPE" class="hiddenlink" target="rightframe">FEATURE_SCREEN_LANDSCAPE</A> +</nobr><br> +<nobr><A HREF="android.content.pm.PackageManager.html#android.content.pm.PackageManager.FEATURE_SCREEN_PORTRAIT" class="hiddenlink" target="rightframe">FEATURE_SCREEN_PORTRAIT</A> +</nobr><br> +<A NAME="H"></A> +<br><font size="+2">H</font> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.os.Build.VERSION_CODES.html#android.os.Build.VERSION_CODES.HONEYCOMB_MR2" class="hiddenlink" target="rightframe">HONEYCOMB_MR2</A> +</nobr><br> +<A NAME="L"></A> +<br><font size="+2">L</font> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<i>largestWidthLimitDp</i><br> +<nobr> in +<A HREF="android.R.attr.html#android.R.attr.largestWidthLimitDp" class="hiddenlink" target="rightframe">android.R.attr</A> +</nobr><br> +<nobr> in +<A HREF="android.content.pm.ApplicationInfo.html#android.content.pm.ApplicationInfo.largestWidthLimitDp" class="hiddenlink" target="rightframe">android.content.pm.ApplicationInfo</A> +</nobr><br> +<A NAME="N"></A> +<br><font size="+2">N</font> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.telephony.TelephonyManager.html#android.telephony.TelephonyManager.NETWORK_TYPE_HSPAP" class="hiddenlink" target="rightframe">NETWORK_TYPE_HSPAP</A> +</nobr><br> +<A NAME="R"></A> +<br><font size="+2">R</font> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<i>requiresSmallestWidthDp</i><br> +<nobr> in +<A HREF="android.R.attr.html#android.R.attr.requiresSmallestWidthDp" class="hiddenlink" target="rightframe">android.R.attr</A> +</nobr><br> +<nobr> in +<A HREF="android.content.pm.ApplicationInfo.html#android.content.pm.ApplicationInfo.requiresSmallestWidthDp" class="hiddenlink" target="rightframe">android.content.pm.ApplicationInfo</A> +</nobr><br> +<A NAME="S"></A> +<br><font size="+2">S</font> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.SCREEN_HEIGHT_DP_UNDEFINED" class="hiddenlink" target="rightframe">SCREEN_HEIGHT_DP_UNDEFINED</A> +</nobr><br> +<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.SCREEN_WIDTH_DP_UNDEFINED" class="hiddenlink" target="rightframe">SCREEN_WIDTH_DP_UNDEFINED</A> +</nobr><br> +<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.screenHeightDp" class="hiddenlink" target="rightframe">screenHeightDp</A> +</nobr><br> +<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.screenWidthDp" class="hiddenlink" target="rightframe">screenWidthDp</A> +</nobr><br> +<nobr><A HREF="android.Manifest.permission.html#android.Manifest.permission.SET_POINTER_SPEED" class="hiddenlink" target="rightframe">SET_POINTER_SPEED</A> +</nobr><br> +<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED" class="hiddenlink" target="rightframe">SMALLEST_SCREEN_WIDTH_DP_UNDEFINED</A> +</nobr><br> +<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.smallestScreenWidthDp" class="hiddenlink" target="rightframe">smallestScreenWidthDp</A> +</nobr><br> +<A NAME="T"></A> +<br><font size="+2">T</font> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo" class="hiddenlink" target="rightframe">TextAppearance_Holo</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_DialogWindowTitle" class="hiddenlink" target="rightframe">TextAppearance_Holo_DialogWindowTitle</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Inverse" class="hiddenlink" target="rightframe">TextAppearance_Holo_Inverse</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Large" class="hiddenlink" target="rightframe">TextAppearance_Holo_Large</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Large_Inverse" class="hiddenlink" target="rightframe">TextAppearance_Holo_Large_Inverse</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Medium" class="hiddenlink" target="rightframe">TextAppearance_Holo_Medium</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Medium_Inverse" class="hiddenlink" target="rightframe">TextAppearance_Holo_Medium_Inverse</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_SearchResult_Subtitle" class="hiddenlink" target="rightframe">TextAppearance_Holo_SearchResult_Subtitle</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_SearchResult_Title" class="hiddenlink" target="rightframe">TextAppearance_Holo_SearchResult_Title</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Small" class="hiddenlink" target="rightframe">TextAppearance_Holo_Small</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Small_Inverse" class="hiddenlink" target="rightframe">TextAppearance_Holo_Small_Inverse</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_ActionBar_Subtitle" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_ActionBar_Subtitle</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_ActionBar_Title" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_ActionBar_Title</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_ActionMode_Subtitle" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_ActionMode_Subtitle</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_ActionMode_Title" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_ActionMode_Title</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_Button" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_Button</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_DropDownHint" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_DropDownHint</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_DropDownItem" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_DropDownItem</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_EditText" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_EditText</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_IconMenu_Item" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_IconMenu_Item</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_PopupMenu" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_PopupMenu</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_PopupMenu_Large" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_PopupMenu_Large</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_PopupMenu_Small" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_PopupMenu_Small</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_TabWidget" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_TabWidget</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_TextView" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_TextView</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_TextView_PopupMenu" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_TextView_PopupMenu</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_TextView_SpinnerItem" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_TextView_SpinnerItem</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_WindowTitle" class="hiddenlink" target="rightframe">TextAppearance_Holo_WindowTitle</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.Theme_Holo_Light_NoActionBar" class="hiddenlink" target="rightframe">Theme_Holo_Light_NoActionBar</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.Theme_Holo_Light_NoActionBar_Fullscreen" class="hiddenlink" target="rightframe">Theme_Holo_Light_NoActionBar_Fullscreen</A> +</nobr><br> +<nobr><A HREF="android.os.IBinder.html#android.os.IBinder.TWEET_TRANSACTION" class="hiddenlink" target="rightframe">TWEET_TRANSACTION</A> +</nobr><br> +<nobr><A HREF="android.net.ConnectivityManager.html#android.net.ConnectivityManager.TYPE_BLUETOOTH" class="hiddenlink" target="rightframe">TYPE_BLUETOOTH</A> +</nobr><br> +<nobr><A HREF="android.net.ConnectivityManager.html#android.net.ConnectivityManager.TYPE_ETHERNET" class="hiddenlink" target="rightframe">TYPE_ETHERNET</A> +</nobr><br> +<A NAME="U"></A> +<br><font size="+2">U</font> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.UI_MODE_TYPE_TELEVISION" class="hiddenlink" target="rightframe">UI_MODE_TYPE_TELEVISION</A> +</nobr><br> +<A NAME="W"></A> +<br><font size="+2">W</font> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.R.style.html#android.R.style.Widget_ActionBar_TabBar" class="hiddenlink" target="rightframe">Widget_ActionBar_TabBar</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.Widget_ActionBar_TabText" class="hiddenlink" target="rightframe">Widget_ActionBar_TabText</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.Widget_ActionBar_TabView" class="hiddenlink" target="rightframe">Widget_ActionBar_TabView</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.Widget_Holo_ActionBar_TabBar" class="hiddenlink" target="rightframe">Widget_Holo_ActionBar_TabBar</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.Widget_Holo_ActionBar_TabText" class="hiddenlink" target="rightframe">Widget_Holo_ActionBar_TabText</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.Widget_Holo_ActionBar_TabView" class="hiddenlink" target="rightframe">Widget_Holo_ActionBar_TabView</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.Widget_Holo_Light_ActionBar_TabBar" class="hiddenlink" target="rightframe">Widget_Holo_Light_ActionBar_TabBar</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.Widget_Holo_Light_ActionBar_TabText" class="hiddenlink" target="rightframe">Widget_Holo_Light_ActionBar_TabText</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.Widget_Holo_Light_ActionBar_TabView" class="hiddenlink" target="rightframe">Widget_Holo_Light_ActionBar_TabView</A> +</nobr><br> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/fields_index_all.html b/docs/html/sdk/api_diff/13/changes/fields_index_all.html new file mode 100644 index 0000000..f183408 --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/fields_index_all.html @@ -0,0 +1,365 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +Field Differences Index +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY class="gc-documentation" style="padding:12px;"> +<a NAME="topheader"></a> +<table summary="Index for Fields" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;"> + <tr> + <th class="indexHeader"> + Filter the Index: + </th> + </tr> + <tr> + <td class="indexText" style="line-height:1.3em;padding-left:2em;"> +<b>Fields</b> + <br> +<font color="#999999">Removals</font> + <br> +<A HREF="fields_index_additions.html"xclass="hiddenlink">Additions</A> + <br> +<A HREF="fields_index_changes.html"xclass="hiddenlink">Changes</A> + </td> + </tr> +</table> +<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;"> +Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font> +</div> +<A NAME="C"></A> +<br><font size="+2">C</font> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<i>compatibleWidthLimitDp</i><br> +<nobr> in +<A HREF="android.R.attr.html#android.R.attr.compatibleWidthLimitDp" class="hiddenlink" target="rightframe">android.R.attr</A> +</nobr><br> +<nobr> in +<A HREF="android.content.pm.ApplicationInfo.html#android.content.pm.ApplicationInfo.compatibleWidthLimitDp" class="hiddenlink" target="rightframe">android.content.pm.ApplicationInfo</A> +</nobr><br> +<nobr><A HREF="android.content.pm.ActivityInfo.html#android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE" class="hiddenlink" target="rightframe">CONFIG_SCREEN_SIZE</A> +</nobr><br> +<nobr><A HREF="android.content.pm.ActivityInfo.html#android.content.pm.ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE" class="hiddenlink" target="rightframe">CONFIG_SMALLEST_SCREEN_SIZE</A> +</nobr><br> +<i>CREATOR</i><br> +<nobr> in +<A HREF="android.graphics.Point.html#android.graphics.Point.CREATOR" class="hiddenlink" target="rightframe">android.graphics.Point</A> +</nobr><br> +<nobr> in +<A HREF="android.graphics.PointF.html#android.graphics.PointF.CREATOR" class="hiddenlink" target="rightframe">android.graphics.PointF</A> +</nobr><br> +<A NAME="D"></A> +<br><font size="+2">D</font> +<a href="#C"><font size="-2">C</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.util.DisplayMetrics.html#android.util.DisplayMetrics.DENSITY_TV" class="hiddenlink" target="rightframe">DENSITY_TV</A> +</nobr><br> +<A NAME="F"></A> +<br><font size="+2">F</font> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.content.pm.PackageManager.html#android.content.pm.PackageManager.FEATURE_FAKETOUCH_MULTITOUCH_DISTINCT" class="hiddenlink" target="rightframe">FEATURE_FAKETOUCH_MULTITOUCH_DISTINCT</A> +</nobr><br> +<nobr><A HREF="android.content.pm.PackageManager.html#android.content.pm.PackageManager.FEATURE_FAKETOUCH_MULTITOUCH_JAZZHAND" class="hiddenlink" target="rightframe">FEATURE_FAKETOUCH_MULTITOUCH_JAZZHAND</A> +</nobr><br> +<nobr><A HREF="android.content.pm.PackageManager.html#android.content.pm.PackageManager.FEATURE_SCREEN_LANDSCAPE" class="hiddenlink" target="rightframe">FEATURE_SCREEN_LANDSCAPE</A> +</nobr><br> +<nobr><A HREF="android.content.pm.PackageManager.html#android.content.pm.PackageManager.FEATURE_SCREEN_PORTRAIT" class="hiddenlink" target="rightframe">FEATURE_SCREEN_PORTRAIT</A> +</nobr><br> +<A NAME="H"></A> +<br><font size="+2">H</font> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.os.Build.VERSION_CODES.html#android.os.Build.VERSION_CODES.HONEYCOMB_MR2" class="hiddenlink" target="rightframe">HONEYCOMB_MR2</A> +</nobr><br> +<A NAME="L"></A> +<br><font size="+2">L</font> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<i>largestWidthLimitDp</i><br> +<nobr> in +<A HREF="android.R.attr.html#android.R.attr.largestWidthLimitDp" class="hiddenlink" target="rightframe">android.R.attr</A> +</nobr><br> +<nobr> in +<A HREF="android.content.pm.ApplicationInfo.html#android.content.pm.ApplicationInfo.largestWidthLimitDp" class="hiddenlink" target="rightframe">android.content.pm.ApplicationInfo</A> +</nobr><br> +<A NAME="N"></A> +<br><font size="+2">N</font> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.telephony.TelephonyManager.html#android.telephony.TelephonyManager.NETWORK_TYPE_HSPAP" class="hiddenlink" target="rightframe">NETWORK_TYPE_HSPAP</A> +</nobr><br> +<A NAME="R"></A> +<br><font size="+2">R</font> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<i>requiresSmallestWidthDp</i><br> +<nobr> in +<A HREF="android.R.attr.html#android.R.attr.requiresSmallestWidthDp" class="hiddenlink" target="rightframe">android.R.attr</A> +</nobr><br> +<nobr> in +<A HREF="android.content.pm.ApplicationInfo.html#android.content.pm.ApplicationInfo.requiresSmallestWidthDp" class="hiddenlink" target="rightframe">android.content.pm.ApplicationInfo</A> +</nobr><br> +<A NAME="S"></A> +<br><font size="+2">S</font> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.os.PowerManager.html#android.os.PowerManager.SCREEN_BRIGHT_WAKE_LOCK" class="hiddenlink" target="rightframe">SCREEN_BRIGHT_WAKE_LOCK</A> +</nobr><br> +<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.SCREEN_HEIGHT_DP_UNDEFINED" class="hiddenlink" target="rightframe">SCREEN_HEIGHT_DP_UNDEFINED</A> +</nobr><br> +<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.SCREEN_WIDTH_DP_UNDEFINED" class="hiddenlink" target="rightframe">SCREEN_WIDTH_DP_UNDEFINED</A> +</nobr><br> +<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.screenHeightDp" class="hiddenlink" target="rightframe">screenHeightDp</A> +</nobr><br> +<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.screenWidthDp" class="hiddenlink" target="rightframe">screenWidthDp</A> +</nobr><br> +<nobr><A HREF="android.Manifest.permission.html#android.Manifest.permission.SET_POINTER_SPEED" class="hiddenlink" target="rightframe">SET_POINTER_SPEED</A> +</nobr><br> +<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED" class="hiddenlink" target="rightframe">SMALLEST_SCREEN_WIDTH_DP_UNDEFINED</A> +</nobr><br> +<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.smallestScreenWidthDp" class="hiddenlink" target="rightframe">smallestScreenWidthDp</A> +</nobr><br> +<A NAME="T"></A> +<br><font size="+2">T</font> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#U"><font size="-2">U</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo" class="hiddenlink" target="rightframe">TextAppearance_Holo</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_DialogWindowTitle" class="hiddenlink" target="rightframe">TextAppearance_Holo_DialogWindowTitle</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Inverse" class="hiddenlink" target="rightframe">TextAppearance_Holo_Inverse</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Large" class="hiddenlink" target="rightframe">TextAppearance_Holo_Large</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Large_Inverse" class="hiddenlink" target="rightframe">TextAppearance_Holo_Large_Inverse</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Medium" class="hiddenlink" target="rightframe">TextAppearance_Holo_Medium</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Medium_Inverse" class="hiddenlink" target="rightframe">TextAppearance_Holo_Medium_Inverse</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_SearchResult_Subtitle" class="hiddenlink" target="rightframe">TextAppearance_Holo_SearchResult_Subtitle</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_SearchResult_Title" class="hiddenlink" target="rightframe">TextAppearance_Holo_SearchResult_Title</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Small" class="hiddenlink" target="rightframe">TextAppearance_Holo_Small</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Small_Inverse" class="hiddenlink" target="rightframe">TextAppearance_Holo_Small_Inverse</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_ActionBar_Subtitle" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_ActionBar_Subtitle</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_ActionBar_Title" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_ActionBar_Title</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_ActionMode_Subtitle" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_ActionMode_Subtitle</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_ActionMode_Title" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_ActionMode_Title</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_Button" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_Button</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_DropDownHint" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_DropDownHint</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_DropDownItem" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_DropDownItem</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_EditText" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_EditText</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_IconMenu_Item" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_IconMenu_Item</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_PopupMenu" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_PopupMenu</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_PopupMenu_Large" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_PopupMenu_Large</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_PopupMenu_Small" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_PopupMenu_Small</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_TabWidget" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_TabWidget</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_TextView" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_TextView</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_TextView_PopupMenu" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_TextView_PopupMenu</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_Widget_TextView_SpinnerItem" class="hiddenlink" target="rightframe">TextAppearance_Holo_Widget_TextView_SpinnerItem</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.TextAppearance_Holo_WindowTitle" class="hiddenlink" target="rightframe">TextAppearance_Holo_WindowTitle</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.Theme_Holo_Light_NoActionBar" class="hiddenlink" target="rightframe">Theme_Holo_Light_NoActionBar</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.Theme_Holo_Light_NoActionBar_Fullscreen" class="hiddenlink" target="rightframe">Theme_Holo_Light_NoActionBar_Fullscreen</A> +</nobr><br> +<nobr><A HREF="android.os.IBinder.html#android.os.IBinder.TWEET_TRANSACTION" class="hiddenlink" target="rightframe">TWEET_TRANSACTION</A> +</nobr><br> +<nobr><A HREF="android.net.ConnectivityManager.html#android.net.ConnectivityManager.TYPE_BLUETOOTH" class="hiddenlink" target="rightframe">TYPE_BLUETOOTH</A> +</nobr><br> +<nobr><A HREF="android.net.ConnectivityManager.html#android.net.ConnectivityManager.TYPE_ETHERNET" class="hiddenlink" target="rightframe">TYPE_ETHERNET</A> +</nobr><br> +<A NAME="U"></A> +<br><font size="+2">U</font> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.content.res.Configuration.html#android.content.res.Configuration.UI_MODE_TYPE_TELEVISION" class="hiddenlink" target="rightframe">UI_MODE_TYPE_TELEVISION</A> +</nobr><br> +<A NAME="W"></A> +<br><font size="+2">W</font> +<a href="#C"><font size="-2">C</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#H"><font size="-2">H</font></a> +<a href="#L"><font size="-2">L</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#T"><font size="-2">T</font></a> +<a href="#U"><font size="-2">U</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.R.style.html#android.R.style.Widget_ActionBar_TabBar" class="hiddenlink" target="rightframe">Widget_ActionBar_TabBar</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.Widget_ActionBar_TabText" class="hiddenlink" target="rightframe">Widget_ActionBar_TabText</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.Widget_ActionBar_TabView" class="hiddenlink" target="rightframe">Widget_ActionBar_TabView</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.Widget_Holo_ActionBar_TabBar" class="hiddenlink" target="rightframe">Widget_Holo_ActionBar_TabBar</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.Widget_Holo_ActionBar_TabText" class="hiddenlink" target="rightframe">Widget_Holo_ActionBar_TabText</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.Widget_Holo_ActionBar_TabView" class="hiddenlink" target="rightframe">Widget_Holo_ActionBar_TabView</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.Widget_Holo_Light_ActionBar_TabBar" class="hiddenlink" target="rightframe">Widget_Holo_Light_ActionBar_TabBar</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.Widget_Holo_Light_ActionBar_TabText" class="hiddenlink" target="rightframe">Widget_Holo_Light_ActionBar_TabText</A> +</nobr><br> +<nobr><A HREF="android.R.style.html#android.R.style.Widget_Holo_Light_ActionBar_TabView" class="hiddenlink" target="rightframe">Widget_Holo_Light_ActionBar_TabView</A> +</nobr><br> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/fields_index_changes.html b/docs/html/sdk/api_diff/13/changes/fields_index_changes.html new file mode 100644 index 0000000..953047c --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/fields_index_changes.html @@ -0,0 +1,67 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +Field Changes Index +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY class="gc-documentation" style="padding:12px;"> +<a NAME="topheader"></a> +<table summary="Index for Fields" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;"> + <tr> + <th class="indexHeader"> + Filter the Index: + </th> + </tr> + <tr> + <td class="indexText" style="line-height:1.3em;padding-left:2em;"> +<a href="fields_index_all.html" class="staysblack">All Fields</a> + <br> +<font color="#999999">Removals</font> + <br> +<A HREF="fields_index_additions.html"xclass="hiddenlink">Additions</A> + <br> +<b>Changes</b> + </td> + </tr> +</table> +<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;"> +Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font> +</div> +<A NAME="S"></A> +<br><font size="+2">S</font> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.os.PowerManager.html#android.os.PowerManager.SCREEN_BRIGHT_WAKE_LOCK" class="hiddenlink" target="rightframe">SCREEN_BRIGHT_WAKE_LOCK</A> +</nobr><br> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/fields_index_removals.html b/docs/html/sdk/api_diff/13/changes/fields_index_removals.html new file mode 100644 index 0000000..9f62d88 --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/fields_index_removals.html @@ -0,0 +1,61 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +Field Removals Index +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY class="gc-documentation" style="padding:12px;"> +<a NAME="topheader"></a> +<table summary="Index for Fields" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;"> + <tr> + <th class="indexHeader"> + Filter the Index: + </th> + </tr> + <tr> + <td class="indexText" style="line-height:1.3em;padding-left:2em;"> +<a href="fields_index_all.html" class="staysblack">All Fields</a> + <br> +<font color="#999999">Removals</font> + <br> +<A HREF="fields_index_additions.html"xclass="hiddenlink">Additions</A> + <br> +<A HREF="fields_index_changes.html"xclass="hiddenlink">Changes</A> + </td> + </tr> +</table> +<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;"> +Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font> +</div> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/jdiff_help.html b/docs/html/sdk/api_diff/13/changes/jdiff_help.html new file mode 100644 index 0000000..ec659d4 --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/jdiff_help.html @@ -0,0 +1,134 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +JDiff Help +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY> +<!-- Start of nav bar --> +<TABLE summary="Navigation bar" BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0"> +<TR> +<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> + <TABLE summary="Navigation bar" BORDER="0" CELLPADDING="0" CELLSPACING="3"> + <TR ALIGN="center" VALIGN="top"> + <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../../../reference/index.html" target="_top"><FONT CLASS="NavBarFont1"><B><code>13</code></B></FONT></A> </TD> + <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="changes-summary.html"><FONT CLASS="NavBarFont1"><B>Overview</B></FONT></A> </TD> + <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Package</FONT> </TD> + <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Class</FONT> </TD> + <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="jdiff_statistics.html"><FONT CLASS="NavBarFont1"><B>Statistics</B></FONT></A> </TD> + <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1Rev"> <FONT CLASS="NavBarFont1Rev"><B>Help</B></FONT> </TD> + </TR> + </TABLE> +</TD> +<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM><b>Generated by<br><a href="http://www.jdiff.org" class="staysblack" target="_top">JDiff</a></b></EM></TD> +</TR> +<TR> + <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell2"><FONT SIZE="-2"></FONT> +</TD> + <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell2"><FONT SIZE="-2"> + <A HREF="../changes.html" TARGET="_top"><B>FRAMES</B></A> + <A HREF="jdiff_help.html" TARGET="_top"><B>NO FRAMES</B></A></FONT></TD> +</TR> +</TABLE> +<HR> +<!-- End of nav bar --> +<center> +<H1>JDiff Documentation</H1> +</center> +<BLOCKQUOTE> +JDiff is a <a href="http://java.sun.com/j2se/javadoc/" target="_top">Javadoc</a> doclet which generates a report of the API differences between two versions of a product. It does not report changes in Javadoc comments, or changes in what a class or method does. +This help page describes the different parts of the output from JDiff. +</BLOCKQUOTE> +<BLOCKQUOTE> + See the reference page in the <a href="http://www.jdiff.org">source for JDiff</a> for information about how to generate a report like this one. +</BLOCKQUOTE> +<BLOCKQUOTE> +The indexes shown in the top-left frame help show each type of change in more detail. The index "All Differences" contains all the differences between the APIs, in alphabetical order. +These indexes all use the same format: +<ul> +<li>Removed packages, classes, constructors, methods and fields are <strike>struck through</strike>.</li> +<li>Added packages, classes, constructors, methods and fields appear in <b>bold</b>.</li> +<li>Changed packages, classes, constructors, methods and fields appear in normal text.</li> +</ul> +</BLOCKQUOTE> +<BLOCKQUOTE> +You can always tell when you are reading a JDiff page, rather than a Javadoc page, by the color of the index bar and the color of the background. +Links which take you to a Javadoc page are always in a <code>typewriter</code> font. +Just like Javadoc, all interface names are in <i>italic</i>, and class names are not italicized. Where there are multiple entries in an index with the same name, the heading for them is also in italics, but is not a link. +</BLOCKQUOTE> +<BLOCKQUOTE> +<H3><b><code>Javadoc</code></b></H3> +This is a link to the <a href="../../../../reference/index.html" target="_top">top-level</a> Javadoc page for the new version of the product. +</BLOCKQUOTE> +<BLOCKQUOTE> +<H3>Overview</H3> +The <a href="changes-summary.html">overview</a> is the top-level summary of what was removed, added and changed between versions. +</BLOCKQUOTE> +<BLOCKQUOTE> +<H3>Package</H3> +This is a link to the package containing the current changed class or interface. +</BLOCKQUOTE> +<BLOCKQUOTE> +<H3>Class</H3> +This is highlighted when you are looking at the changed class or interface. +</BLOCKQUOTE> +<BLOCKQUOTE> +<H3>Text Changes</H3> +This is a link to the top-level index of all documentation changes for the current package or class. +If it is not present, then there are no documentation changes for the current package or class. +This link can be removed entirely by not using the <code>-docchanges</code> option. +</BLOCKQUOTE> +<BLOCKQUOTE> +<H3>Statistics</H3> +This is a link to a page which shows statistics about the changes between the two APIs. +This link can be removed entirely by not using the <code>-stats</code> option. +</BLOCKQUOTE> +<BLOCKQUOTE> +<H3>Help</H3> +A link to this Help page for JDiff. +</BLOCKQUOTE> +<BLOCKQUOTE> +<H3>Prev/Next</H3> +These links take you to the previous and next changed package or class. +</BLOCKQUOTE> +<BLOCKQUOTE> +<H3>Frames/No Frames</H3> +These links show and hide the HTML frames. All pages are available with or without frames. +</BLOCKQUOTE> +<BLOCKQUOTE> +<H2>Complex Changes</H2> +There are some complex changes which can occur between versions, for example, when two or more methods with the same name change simultaneously, or when a method or field is moved into or from a superclass. +In these cases, the change will be seen as a removal and an addition, rather than as a change. Unexpected removals or additions are often part of one of these type of changes. +</BLOCKQUOTE> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/jdiff_statistics.html b/docs/html/sdk/api_diff/13/changes/jdiff_statistics.html new file mode 100644 index 0000000..626c765 --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/jdiff_statistics.html @@ -0,0 +1,382 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +API Change Statistics +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<body class="gc-documentation"> +<!-- Start of nav bar --> +<a name="top"></a> +<div id="header" style="margin-bottom:0;xborder-bottom:none;"> +<div id="headerLeft"> +<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a> +</div> + <div id="headerRight"> + <div id="headerLinks"> +<!-- <img src="/assets/images/icon_world.jpg" alt="" /> --> +<span class="text"> +<!-- <a href="#">English</a> | --> +<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr> +</span> +</div> + <div class="and-diff-id" style="margin-top:6px;margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td colspan="2" class="diffspechead">API Diff Specification</td> + </tr> + <tr> + <td class="diffspec" style="padding-top:.25em">To Level:</td> + <td class="diffvaluenew" style="padding-top:.25em">13</td> + </tr> + <tr> + <td class="diffspec">From Level:</td> + <td class="diffvalueold">12</td> + </tr> + <tr> + <td class="diffspec">Generated</td> + <td class="diffvalue">2011.06.29 10:50</td> + </tr> + </table> + </div><!-- End and-diff-id --> + <div class="and-diff-id" style="margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td class="diffspec" colspan="2"><a href="../changes.html" target="_top">Top of Report</a> + </tr> + </table> + </div> <!-- End and-diff-id --> + </div> <!-- End headerRight --> + </div> <!-- End header --> +<div id="body-content"> +<div id="doc-content" style="position:relative;"> +<div id="mainBodyFluid"> +<h1>API Change Statistics</h1> +<p>The overall difference between API Levels 12 and 13 is approximately <span style="color:222;font-weight:bold;">0.04%</span>. +</p> +<br> +<a name="numbers"></a> +<h2>Total of Differences, by Number and Type</h2> +<p> +The table below lists the numbers of program elements (packages, classes, constructors, methods, and fields) that were added, changed, or removed. The table includes only the highest-level program elements — that is, if a class with two methods was added, the number of methods added does not include those two methods, but the number of classes added does include that class. +</p> +<TABLE summary="Number of differences" WIDTH="100%"> +<TR> + <th>Type</th> + <TH ALIGN="center"><b>Additions</b></TH> + <TH ALIGN="center"><b>Changes</b></TH> + <TH ALIGN="center">Removals</TH> + <TH ALIGN="center"><b>Total</b></TH> +</TR> +<TR> + <TD>Packages</TD> + <TD ALIGN="right">0</TD> + <TD ALIGN="right">11</TD> + <TD ALIGN="right">0</TD> + <TD ALIGN="right">11</TD> +</TR> +<TR> + <TD>Classes and <i>Interfaces</i></TD> + <TD ALIGN="right">2</TD> + <TD ALIGN="right">29</TD> + <TD ALIGN="right">0</TD> + <TD ALIGN="right">31</TD> +</TR> +<TR> + <TD>Constructors</TD> + <TD ALIGN="right">0</TD> + <TD ALIGN="right">0</TD> + <TD ALIGN="right">0</TD> + <TD ALIGN="right">0</TD> +</TR> +<TR> + <TD>Methods</TD> + <TD ALIGN="right">22</TD> + <TD ALIGN="right">12</TD> + <TD ALIGN="right">0</TD> + <TD ALIGN="right">34</TD> +</TR> +<TR> + <TD>Fields</TD> + <TD ALIGN="right">68</TD> + <TD ALIGN="right">1</TD> + <TD ALIGN="right">0</TD> + <TD ALIGN="right">69</TD> +</TR> +<TR> + <TD style="background-color:#FAFAFA"><b>Total</b></TD> + <TD style="background-color:#FAFAFA" ALIGN="right"><strong>92</strong></TD> + <TD style="background-color:#FAFAFA" ALIGN="right"><strong>53</strong></TD> + <TD style="background-color:#FAFAFA" ALIGN="right"><strong>0</strong></TD> + <TD style="background-color:#FAFAFA" ALIGN="right"><strong>145</strong></TD> +</TR> +</TABLE> +<br> +<a name="packages"></a> +<h2>Changed Packages, Sorted by Percentage Difference</h2> +<TABLE summary="Packages sorted by percentage difference" WIDTH="100%"> +<TR> + <TH WIDTH="10%">Percentage Difference*</TH> + <TH>Package</TH> +</TR> +<TR> + <TD ALIGN="center">2</TD> + <TD><A HREF="pkg_android.app.html">android.app</A></TD> +</TR> +<TR> + <TD ALIGN="center">1</TD> + <TD><A HREF="pkg_android.os.html">android.os</A></TD> +</TR> +<TR> + <TD ALIGN="center"><1</TD> + <TD><A HREF="pkg_android.hardware.usb.html">android.hardware.usb</A></TD> +</TR> +<TR> + <TD ALIGN="center"><1</TD> + <TD><A HREF="pkg_android.graphics.html">android.graphics</A></TD> +</TR> +<TR> + <TD ALIGN="center"><1</TD> + <TD><A HREF="pkg_android.html">android</A></TD> +</TR> +<TR> + <TD ALIGN="center"><1</TD> + <TD><A HREF="pkg_android.content.res.html">android.content.res</A></TD> +</TR> +<TR> + <TD ALIGN="center"><1</TD> + <TD><A HREF="pkg_android.content.pm.html">android.content.pm</A></TD> +</TR> +<TR> + <TD ALIGN="center"><1</TD> + <TD><A HREF="pkg_android.view.html">android.view</A></TD> +</TR> +<TR> + <TD ALIGN="center"><1</TD> + <TD><A HREF="pkg_android.net.html">android.net</A></TD> +</TR> +<TR> + <TD ALIGN="center"><1</TD> + <TD><A HREF="pkg_android.util.html">android.util</A></TD> +</TR> +<TR> + <TD ALIGN="center"><1</TD> + <TD><A HREF="pkg_android.telephony.html">android.telephony</A></TD> +</TR> +</TABLE> +<p style="font-size:10px">* See <a href="#calculation">Calculation of Change Percentages</a>, below.</p> +<br> +<a name="classes"></a> +<h2>Changed Classes and <i>Interfaces</i>, Sorted by Percentage Difference</h2> +<TABLE summary="Classes sorted by percentage difference" WIDTH="100%"> +<TR WIDTH="20%"> + <TH WIDTH="10%">Percentage<br>Difference*</TH> + <TH><b>Class or <i>Interface</i></b></TH> +</TR> +<TR> + <TD ALIGN="center">33</TD> + <TD><A HREF="android.app.KeyguardManager.html"> +android.app.KeyguardManager</A></TD> +</TR> +<TR> + <TD ALIGN="center">25</TD> + <TD><A HREF="android.app.KeyguardManager.KeyguardLock.html"> +android.app.KeyguardManager.KeyguardLock</A></TD> +</TR> +<TR> + <TD ALIGN="center">20</TD> + <TD><A HREF="android.view.Display.html"> +android.view.Display</A></TD> +</TR> +<TR> + <TD ALIGN="center">18</TD> + <TD><A HREF="android.graphics.Point.html"> +android.graphics.Point</A></TD> +</TR> +<TR> + <TD ALIGN="center">14</TD> + <TD><A HREF="android.graphics.PointF.html"> +android.graphics.PointF</A></TD> +</TR> +<TR> + <TD ALIGN="center">12</TD> + <TD><A HREF="android.app.ActivityGroup.html"> +android.app.ActivityGroup</A></TD> +</TR> +<TR> + <TD ALIGN="center">10</TD> + <TD><A HREF="android.app.TabActivity.html"> +android.app.TabActivity</A></TD> +</TR> +<TR> + <TD ALIGN="center">7</TD> + <TD><A HREF="android.R.style.html"> +android.R.style</A></TD> +</TR> +<TR> + <TD ALIGN="center">6</TD> + <TD><A HREF="android.os.ParcelFileDescriptor.html"> +android.os.ParcelFileDescriptor</A></TD> +</TR> +<TR> + <TD ALIGN="center">6</TD> + <TD><A HREF="android.os.IBinder.html"> +<i>android.os.IBinder</i></A></TD> +</TR> +<TR> + <TD ALIGN="center">5</TD> + <TD><A HREF="android.hardware.usb.UsbDeviceConnection.html"> +android.hardware.usb.UsbDeviceConnection</A></TD> +</TR> +<TR> + <TD ALIGN="center">4</TD> + <TD><A HREF="android.app.FragmentTransaction.html"> +android.app.FragmentTransaction</A></TD> +</TR> +<TR> + <TD ALIGN="center">4</TD> + <TD><A HREF="android.content.res.Configuration.html"> +android.content.res.Configuration</A></TD> +</TR> +<TR> + <TD ALIGN="center">4</TD> + <TD><A HREF="android.os.PowerManager.html"> +android.os.PowerManager</A></TD> +</TR> +<TR> + <TD ALIGN="center">3</TD> + <TD><A HREF="android.app.LocalActivityManager.html"> +android.app.LocalActivityManager</A></TD> +</TR> +<TR> + <TD ALIGN="center">3</TD> + <TD><A HREF="android.net.ConnectivityManager.html"> +android.net.ConnectivityManager</A></TD> +</TR> +<TR> + <TD ALIGN="center">3</TD> + <TD><A HREF="android.app.Activity.html"> +android.app.Activity</A></TD> +</TR> +<TR> + <TD ALIGN="center">3</TD> + <TD><A HREF="android.os.Build.VERSION_CODES.html"> +android.os.Build.VERSION_CODES</A></TD> +</TR> +<TR> + <TD ALIGN="center">3</TD> + <TD><A HREF="android.content.pm.ApplicationInfo.html"> +android.content.pm.ApplicationInfo</A></TD> +</TR> +<TR> + <TD ALIGN="center">3</TD> + <TD><A HREF="android.util.DisplayMetrics.html"> +android.util.DisplayMetrics</A></TD> +</TR> +<TR> + <TD ALIGN="center">2</TD> + <TD><A HREF="android.os.Binder.html"> +android.os.Binder</A></TD> +</TR> +<TR> + <TD ALIGN="center">2</TD> + <TD><A HREF="android.app.Fragment.html"> +android.app.Fragment</A></TD> +</TR> +<TR> + <TD ALIGN="center">2</TD> + <TD><A HREF="android.app.FragmentManager.html"> +android.app.FragmentManager</A></TD> +</TR> +<TR> + <TD ALIGN="center">1</TD> + <TD><A HREF="android.content.pm.ActivityInfo.html"> +android.content.pm.ActivityInfo</A></TD> +</TR> +<TR> + <TD ALIGN="center">1</TD> + <TD><A HREF="android.content.pm.PackageManager.html"> +android.content.pm.PackageManager</A></TD> +</TR> +<TR> + <TD ALIGN="center"><1</TD> + <TD><A HREF="android.telephony.TelephonyManager.html"> +android.telephony.TelephonyManager</A></TD> +</TR> +<TR> + <TD ALIGN="center"><1</TD> + <TD><A HREF="android.Manifest.permission.html"> +android.Manifest.permission</A></TD> +</TR> +<TR> + <TD ALIGN="center"><1</TD> + <TD><A HREF="android.R.attr.html"> +android.R.attr</A></TD> +</TR> +<TR> + <TD ALIGN="center"><1</TD> + <TD><A HREF="android.view.KeyEvent.html"> +android.view.KeyEvent</A></TD> +</TR> +</TABLE> +<p style="font-size:10px">* See <a href="#calculation">Calculation of Change Percentages</a>, below.</p> +<br> +<h2 id="calculation">Calculation of Change Percentages</h2> +<p> +The percent change statistic reported for all elements in the "to" API Level specification is defined recursively as follows:</p> +<pre> +Percentage difference = 100 * (added + removed + 2*changed) + ----------------------------------- + sum of public elements in BOTH APIs +</pre> +<p>where <code>added</code> is the number of packages added, <code>removed</code> is the number of packages removed, and <code>changed</code> is the number of packages changed. +This definition is applied recursively for the classes and their program elements, so the value for a changed package will be less than 1, unless every class in that package has changed. +The definition ensures that if all packages are removed and all new packages are +added, the change will be 100%.</p> + </div> + <div id="footer"> + <div id="copyright"> + Except as noted, this content is licensed under + <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>. + For details and restrictions, see the <a href="/license.html">Content License</a>. + </div> + <div id="footerlinks"> + <p> + <a href="http://www.android.com/terms.html">Site Terms of Service</a> - + <a href="http://www.android.com/privacy.html">Privacy Policy</a> - + <a href="http://www.android.com/branding.html">Brand Guidelines</a> + </p> + </div> + </div> <!-- end footer --> + </div><!-- end doc-content --> + </div> <!-- end body-content --> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY></HTML> diff --git a/docs/html/sdk/api_diff/13/changes/jdiff_topleftframe.html b/docs/html/sdk/api_diff/13/changes/jdiff_topleftframe.html new file mode 100644 index 0000000..36f9836 --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/jdiff_topleftframe.html @@ -0,0 +1,63 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +Android API Version Differences +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY class="gc-documentation" style="padding:12px;"> +<table class="jdiffIndex" summary="Links to diff index files" BORDER="0" WIDTH="100%" cellspacing="0" cellpadding="0" style="margin:0"> +<TR> + <th class="indexHeader" nowrap> + Select a Diffs Index:</th> +</TR> +<TR> + <TD><FONT CLASS="indexText" size="-2"><A HREF="alldiffs_index_all.html" TARGET="bottomleftframe">All Differences</A></FONT><br></TD> +</TR> +<TR> + <TD NOWRAP><FONT CLASS="indexText" size="-2"><A HREF="packages_index_all.html" TARGET="bottomleftframe">By Package</A></FONT><br></TD> +</TR> +<TR> + <TD NOWRAP><FONT CLASS="indexText" size="-2"><A HREF="classes_index_all.html" TARGET="bottomleftframe">By Class</A></FONT><br></TD> +</TR> +<TR> + <TD NOWRAP><FONT CLASS="indexText" size="-2"><A HREF="constructors_index_all.html" TARGET="bottomleftframe">By Constructor</A></FONT><br></TD> +</TR> +<TR> + <TD NOWRAP><FONT CLASS="indexText" size="-2"><A HREF="methods_index_all.html" TARGET="bottomleftframe">By Method</A></FONT><br></TD> +</TR> +<TR> + <TD NOWRAP><FONT CLASS="indexText" size="-2"><A HREF="fields_index_all.html" TARGET="bottomleftframe">By Field</A></FONT><br></TD> +</TR> +</TABLE> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/methods_index_additions.html b/docs/html/sdk/api_diff/13/changes/methods_index_additions.html new file mode 100644 index 0000000..fbbf5a6 --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/methods_index_additions.html @@ -0,0 +1,225 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +Method Additions Index +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY class="gc-documentation" style="padding:12px;"> +<a NAME="topheader"></a> +<table summary="Index for Methods" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;"> + <tr> + <th class="indexHeader"> + Filter the Index: + </th> + </tr> + <tr> + <td class="indexText" style="line-height:1.3em;padding-left:2em;"> +<a href="methods_index_all.html" class="staysblack">All Methods</a> + <br> +<font color="#999999">Removals</font> + <br> +<b>Additions</b> + <br> +<A HREF="methods_index_changes.html"xclass="hiddenlink">Changes</A> + </td> + </tr> +</table> +<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;"> +Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font> +</div> +<A NAME="A"></A> +<br><font size="+2">A</font> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.os.ParcelFileDescriptor.html#android.os.ParcelFileDescriptor.adoptFd_added(int)" class="hiddenlink" target="rightframe"><b>adoptFd</b> +(<code>int</code>)</A></nobr><br> +<nobr><A HREF="android.app.FragmentTransaction.html#android.app.FragmentTransaction.attach_added(android.app.Fragment)" class="hiddenlink" target="rightframe"><b>attach</b> +(<code>Fragment</code>)</A></nobr><br> +<A NAME="D"></A> +<br><font size="+2">D</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<i>describeContents</i><br> + <nobr><A HREF="android.graphics.Point.html#android.graphics.Point.describeContents_added()" class="hiddenlink" target="rightframe">type <b> +()</b> in android.graphics.Point +</A></nobr><br> + <nobr><A HREF="android.graphics.PointF.html#android.graphics.PointF.describeContents_added()" class="hiddenlink" target="rightframe">type <b> +()</b> in android.graphics.PointF +</A></nobr><br> +<nobr><A HREF="android.app.FragmentTransaction.html#android.app.FragmentTransaction.detach_added(android.app.Fragment)" class="hiddenlink" target="rightframe"><b>detach</b> +(<code>Fragment</code>)</A></nobr><br> +<i>dumpAsync</i><br> + <nobr><A HREF="android.os.Binder.html#android.os.Binder.dumpAsync_added(java.io.FileDescriptor, java.lang.String[])" class="hiddenlink" target="rightframe">type <b> +(<code>FileDescriptor, String[]</code>)</b> in android.os.Binder +</A></nobr><br> + <nobr><A HREF="android.os.IBinder.html#android.os.IBinder.dumpAsync_added(java.io.FileDescriptor, java.lang.String[])" class="hiddenlink" target="rightframe">type <b> +(<code>FileDescriptor, String[]</code>)</b> in android.os.IBinder +</A></nobr><br> +<nobr><A HREF="android.os.ParcelFileDescriptor.html#android.os.ParcelFileDescriptor.dup_added(java.io.FileDescriptor)" class="hiddenlink" target="rightframe"><b>dup</b> +(<code>FileDescriptor</code>)</A></nobr><br> +<A NAME="F"></A> +<br><font size="+2">F</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.os.ParcelFileDescriptor.html#android.os.ParcelFileDescriptor.fromFd_added(int)" class="hiddenlink" target="rightframe"><b>fromFd</b> +(<code>int</code>)</A></nobr><br> +<A NAME="G"></A> +<br><font size="+2">G</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.view.KeyEvent.html#android.view.KeyEvent.getModifiers_added()" class="hiddenlink" target="rightframe"><b>getModifiers</b> +()</A></nobr><br> +<nobr><A HREF="android.hardware.usb.UsbDeviceConnection.html#android.hardware.usb.UsbDeviceConnection.getRawDescriptors_added()" class="hiddenlink" target="rightframe"><b>getRawDescriptors</b> +()</A></nobr><br> +<nobr><A HREF="android.view.Display.html#android.view.Display.getRectSize_added(android.graphics.Rect)" class="hiddenlink" target="rightframe"><b>getRectSize</b> +(<code>Rect</code>)</A></nobr><br> +<nobr><A HREF="android.view.Display.html#android.view.Display.getSize_added(android.graphics.Point)" class="hiddenlink" target="rightframe"><b>getSize</b> +(<code>Point</code>)</A></nobr><br> +<A NAME="I"></A> +<br><font size="+2">I</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.app.Fragment.html#android.app.Fragment.isDetached_added()" class="hiddenlink" target="rightframe"><b>isDetached</b> +()</A></nobr><br> +<A NAME="O"></A> +<br><font size="+2">O</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.app.Fragment.html#android.app.Fragment.onViewCreated_added(android.view.View, android.os.Bundle)" class="hiddenlink" target="rightframe"><b>onViewCreated</b> +(<code>View, Bundle</code>)</A></nobr><br> +<A NAME="R"></A> +<br><font size="+2">R</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<i>readFromParcel</i><br> + <nobr><A HREF="android.graphics.Point.html#android.graphics.Point.readFromParcel_added(android.os.Parcel)" class="hiddenlink" target="rightframe">type <b> +(<code>Parcel</code>)</b> in android.graphics.Point +</A></nobr><br> + <nobr><A HREF="android.graphics.PointF.html#android.graphics.PointF.readFromParcel_added(android.os.Parcel)" class="hiddenlink" target="rightframe">type <b> +(<code>Parcel</code>)</b> in android.graphics.PointF +</A></nobr><br> +<A NAME="S"></A> +<br><font size="+2">S</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.app.FragmentManager.html#android.app.FragmentManager.saveFragmentInstanceState_added(android.app.Fragment)" class="hiddenlink" target="rightframe"><b>saveFragmentInstanceState</b> +(<code>Fragment</code>)</A></nobr><br> +<nobr><A HREF="android.app.FragmentTransaction.html#android.app.FragmentTransaction.setCustomAnimations_added(int, int, int, int)" class="hiddenlink" target="rightframe"><b>setCustomAnimations</b> +(<code>int, int, int, int</code>)</A></nobr><br> +<nobr><A HREF="android.app.Fragment.html#android.app.Fragment.setInitialSavedState_added(android.app.Fragment.SavedState)" class="hiddenlink" target="rightframe"><b>setInitialSavedState</b> +(<code>SavedState</code>)</A></nobr><br> +<A NAME="W"></A> +<br><font size="+2">W</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<i>writeToParcel</i><br> + <nobr><A HREF="android.graphics.Point.html#android.graphics.Point.writeToParcel_added(android.os.Parcel, int)" class="hiddenlink" target="rightframe">type <b> +(<code>Parcel, int</code>)</b> in android.graphics.Point +</A></nobr><br> + <nobr><A HREF="android.graphics.PointF.html#android.graphics.PointF.writeToParcel_added(android.os.Parcel, int)" class="hiddenlink" target="rightframe">type <b> +(<code>Parcel, int</code>)</b> in android.graphics.PointF +</A></nobr><br> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/methods_index_all.html b/docs/html/sdk/api_diff/13/changes/methods_index_all.html new file mode 100644 index 0000000..84d0a2c --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/methods_index_all.html @@ -0,0 +1,298 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +Method Differences Index +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY class="gc-documentation" style="padding:12px;"> +<a NAME="topheader"></a> +<table summary="Index for Methods" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;"> + <tr> + <th class="indexHeader"> + Filter the Index: + </th> + </tr> + <tr> + <td class="indexText" style="line-height:1.3em;padding-left:2em;"> +<b>Methods</b> + <br> +<font color="#999999">Removals</font> + <br> +<A HREF="methods_index_additions.html"xclass="hiddenlink">Additions</A> + <br> +<A HREF="methods_index_changes.html"xclass="hiddenlink">Changes</A> + </td> + </tr> +</table> +<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;"> +Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font> +</div> +<A NAME="A"></A> +<br><font size="+2">A</font> +<a href="#D"><font size="-2">D</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.os.ParcelFileDescriptor.html#android.os.ParcelFileDescriptor.adoptFd_added(int)" class="hiddenlink" target="rightframe"><b>adoptFd</b> +(<code>int</code>)</A></nobr><br> +<nobr><A HREF="android.app.FragmentTransaction.html#android.app.FragmentTransaction.attach_added(android.app.Fragment)" class="hiddenlink" target="rightframe"><b>attach</b> +(<code>Fragment</code>)</A></nobr><br> +<A NAME="D"></A> +<br><font size="+2">D</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<i>describeContents</i><br> + <nobr><A HREF="android.graphics.Point.html#android.graphics.Point.describeContents_added()" class="hiddenlink" target="rightframe">type <b> +()</b> in android.graphics.Point +</A></nobr><br> + <nobr><A HREF="android.graphics.PointF.html#android.graphics.PointF.describeContents_added()" class="hiddenlink" target="rightframe">type <b> +()</b> in android.graphics.PointF +</A></nobr><br> +<nobr><A HREF="android.app.FragmentTransaction.html#android.app.FragmentTransaction.detach_added(android.app.Fragment)" class="hiddenlink" target="rightframe"><b>detach</b> +(<code>Fragment</code>)</A></nobr><br> +<nobr><A HREF="android.app.Activity.html#android.app.Activity.dismissDialog_changed(int)" class="hiddenlink" target="rightframe">dismissDialog +(<code>int</code>)</A></nobr><br> +<i>dumpAsync</i><br> + <nobr><A HREF="android.os.Binder.html#android.os.Binder.dumpAsync_added(java.io.FileDescriptor, java.lang.String[])" class="hiddenlink" target="rightframe">type <b> +(<code>FileDescriptor, String[]</code>)</b> in android.os.Binder +</A></nobr><br> + <nobr><A HREF="android.os.IBinder.html#android.os.IBinder.dumpAsync_added(java.io.FileDescriptor, java.lang.String[])" class="hiddenlink" target="rightframe">type <b> +(<code>FileDescriptor, String[]</code>)</b> in android.os.IBinder +</A></nobr><br> +<nobr><A HREF="android.os.ParcelFileDescriptor.html#android.os.ParcelFileDescriptor.dup_added(java.io.FileDescriptor)" class="hiddenlink" target="rightframe"><b>dup</b> +(<code>FileDescriptor</code>)</A></nobr><br> +<A NAME="E"></A> +<br><font size="+2">E</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.app.KeyguardManager.html#android.app.KeyguardManager.exitKeyguardSecurely_changed(android.app.KeyguardManager.OnKeyguardExitResult)" class="hiddenlink" target="rightframe">exitKeyguardSecurely +(<code>OnKeyguardExitResult</code>)</A></nobr><br> +<A NAME="F"></A> +<br><font size="+2">F</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.os.ParcelFileDescriptor.html#android.os.ParcelFileDescriptor.fromFd_added(int)" class="hiddenlink" target="rightframe"><b>fromFd</b> +(<code>int</code>)</A></nobr><br> +<A NAME="G"></A> +<br><font size="+2">G</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.view.Display.html#android.view.Display.getHeight_changed()" class="hiddenlink" target="rightframe">getHeight +()</A></nobr><br> +<nobr><A HREF="android.app.Activity.html#android.app.Activity.getLastNonConfigurationInstance_changed()" class="hiddenlink" target="rightframe">getLastNonConfigurationInstance +()</A></nobr><br> +<nobr><A HREF="android.view.KeyEvent.html#android.view.KeyEvent.getModifiers_added()" class="hiddenlink" target="rightframe"><b>getModifiers</b> +()</A></nobr><br> +<nobr><A HREF="android.hardware.usb.UsbDeviceConnection.html#android.hardware.usb.UsbDeviceConnection.getRawDescriptors_added()" class="hiddenlink" target="rightframe"><b>getRawDescriptors</b> +()</A></nobr><br> +<nobr><A HREF="android.view.Display.html#android.view.Display.getRectSize_added(android.graphics.Rect)" class="hiddenlink" target="rightframe"><b>getRectSize</b> +(<code>Rect</code>)</A></nobr><br> +<nobr><A HREF="android.view.Display.html#android.view.Display.getSize_added(android.graphics.Point)" class="hiddenlink" target="rightframe"><b>getSize</b> +(<code>Point</code>)</A></nobr><br> +<nobr><A HREF="android.view.Display.html#android.view.Display.getWidth_changed()" class="hiddenlink" target="rightframe">getWidth +()</A></nobr><br> +<A NAME="I"></A> +<br><font size="+2">I</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.app.Fragment.html#android.app.Fragment.isDetached_added()" class="hiddenlink" target="rightframe"><b>isDetached</b> +()</A></nobr><br> +<A NAME="N"></A> +<br><font size="+2">N</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.app.KeyguardManager.html#android.app.KeyguardManager.newKeyguardLock_changed(java.lang.String)" class="hiddenlink" target="rightframe">newKeyguardLock +(<code>String</code>)</A></nobr><br> +<A NAME="O"></A> +<br><font size="+2">O</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.app.Activity.html#android.app.Activity.onCreateDialog_changed(int, android.os.Bundle)" class="hiddenlink" target="rightframe">onCreateDialog +(<code>int, Bundle</code>)</A></nobr><br> +<nobr><A HREF="android.app.Activity.html#android.app.Activity.onPrepareDialog_changed(int, android.app.Dialog, android.os.Bundle)" class="hiddenlink" target="rightframe">onPrepareDialog +(<code>int, Dialog, Bundle</code>)</A></nobr><br> +<nobr><A HREF="android.app.Activity.html#android.app.Activity.onRetainNonConfigurationInstance_changed()" class="hiddenlink" target="rightframe">onRetainNonConfigurationInstance +()</A></nobr><br> +<nobr><A HREF="android.app.Fragment.html#android.app.Fragment.onViewCreated_added(android.view.View, android.os.Bundle)" class="hiddenlink" target="rightframe"><b>onViewCreated</b> +(<code>View, Bundle</code>)</A></nobr><br> +<A NAME="R"></A> +<br><font size="+2">R</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#S"><font size="-2">S</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<i>readFromParcel</i><br> + <nobr><A HREF="android.graphics.Point.html#android.graphics.Point.readFromParcel_added(android.os.Parcel)" class="hiddenlink" target="rightframe">type <b> +(<code>Parcel</code>)</b> in android.graphics.Point +</A></nobr><br> + <nobr><A HREF="android.graphics.PointF.html#android.graphics.PointF.readFromParcel_added(android.os.Parcel)" class="hiddenlink" target="rightframe">type <b> +(<code>Parcel</code>)</b> in android.graphics.PointF +</A></nobr><br> +<nobr><A HREF="android.app.Activity.html#android.app.Activity.removeDialog_changed(int)" class="hiddenlink" target="rightframe">removeDialog +(<code>int</code>)</A></nobr><br> +<A NAME="S"></A> +<br><font size="+2">S</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#W"><font size="-2">W</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.app.FragmentManager.html#android.app.FragmentManager.saveFragmentInstanceState_added(android.app.Fragment)" class="hiddenlink" target="rightframe"><b>saveFragmentInstanceState</b> +(<code>Fragment</code>)</A></nobr><br> +<nobr><A HREF="android.app.FragmentTransaction.html#android.app.FragmentTransaction.setCustomAnimations_added(int, int, int, int)" class="hiddenlink" target="rightframe"><b>setCustomAnimations</b> +(<code>int, int, int, int</code>)</A></nobr><br> +<nobr><A HREF="android.app.Fragment.html#android.app.Fragment.setInitialSavedState_added(android.app.Fragment.SavedState)" class="hiddenlink" target="rightframe"><b>setInitialSavedState</b> +(<code>SavedState</code>)</A></nobr><br> +<i>showDialog</i><br> + <nobr><A HREF="android.app.Activity.html#android.app.Activity.showDialog_changed(int, android.os.Bundle)" class="hiddenlink" target="rightframe">type +(<code>int, Bundle</code>) in android.app.Activity +</A></nobr><br> + <nobr><A HREF="android.app.Activity.html#android.app.Activity.showDialog_changed(int)" class="hiddenlink" target="rightframe">type +(<code>int</code>) in android.app.Activity +</A></nobr><br> +<A NAME="W"></A> +<br><font size="+2">W</font> +<a href="#A"><font size="-2">A</font></a> +<a href="#D"><font size="-2">D</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#F"><font size="-2">F</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#I"><font size="-2">I</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<i>writeToParcel</i><br> + <nobr><A HREF="android.graphics.Point.html#android.graphics.Point.writeToParcel_added(android.os.Parcel, int)" class="hiddenlink" target="rightframe">type <b> +(<code>Parcel, int</code>)</b> in android.graphics.Point +</A></nobr><br> + <nobr><A HREF="android.graphics.PointF.html#android.graphics.PointF.writeToParcel_added(android.os.Parcel, int)" class="hiddenlink" target="rightframe">type <b> +(<code>Parcel, int</code>)</b> in android.graphics.PointF +</A></nobr><br> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/methods_index_changes.html b/docs/html/sdk/api_diff/13/changes/methods_index_changes.html new file mode 100644 index 0000000..97cc3ef --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/methods_index_changes.html @@ -0,0 +1,158 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +Method Changes Index +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY class="gc-documentation" style="padding:12px;"> +<a NAME="topheader"></a> +<table summary="Index for Methods" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;"> + <tr> + <th class="indexHeader"> + Filter the Index: + </th> + </tr> + <tr> + <td class="indexText" style="line-height:1.3em;padding-left:2em;"> +<a href="methods_index_all.html" class="staysblack">All Methods</a> + <br> +<font color="#999999">Removals</font> + <br> +<A HREF="methods_index_additions.html"xclass="hiddenlink">Additions</A> + <br> +<b>Changes</b> + </td> + </tr> +</table> +<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;"> +Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font> +</div> +<A NAME="D"></A> +<br><font size="+2">D</font> +<a href="#E"><font size="-2">E</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.app.Activity.html#android.app.Activity.dismissDialog_changed(int)" class="hiddenlink" target="rightframe">dismissDialog +(<code>int</code>)</A></nobr><br> +<A NAME="E"></A> +<br><font size="+2">E</font> +<a href="#D"><font size="-2">D</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.app.KeyguardManager.html#android.app.KeyguardManager.exitKeyguardSecurely_changed(android.app.KeyguardManager.OnKeyguardExitResult)" class="hiddenlink" target="rightframe">exitKeyguardSecurely +(<code>OnKeyguardExitResult</code>)</A></nobr><br> +<A NAME="G"></A> +<br><font size="+2">G</font> +<a href="#D"><font size="-2">D</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.view.Display.html#android.view.Display.getHeight_changed()" class="hiddenlink" target="rightframe">getHeight +()</A></nobr><br> +<nobr><A HREF="android.app.Activity.html#android.app.Activity.getLastNonConfigurationInstance_changed()" class="hiddenlink" target="rightframe">getLastNonConfigurationInstance +()</A></nobr><br> +<nobr><A HREF="android.view.Display.html#android.view.Display.getWidth_changed()" class="hiddenlink" target="rightframe">getWidth +()</A></nobr><br> +<A NAME="N"></A> +<br><font size="+2">N</font> +<a href="#D"><font size="-2">D</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.app.KeyguardManager.html#android.app.KeyguardManager.newKeyguardLock_changed(java.lang.String)" class="hiddenlink" target="rightframe">newKeyguardLock +(<code>String</code>)</A></nobr><br> +<A NAME="O"></A> +<br><font size="+2">O</font> +<a href="#D"><font size="-2">D</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#R"><font size="-2">R</font></a> +<a href="#S"><font size="-2">S</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.app.Activity.html#android.app.Activity.onCreateDialog_changed(int, android.os.Bundle)" class="hiddenlink" target="rightframe">onCreateDialog +(<code>int, Bundle</code>)</A></nobr><br> +<nobr><A HREF="android.app.Activity.html#android.app.Activity.onPrepareDialog_changed(int, android.app.Dialog, android.os.Bundle)" class="hiddenlink" target="rightframe">onPrepareDialog +(<code>int, Dialog, Bundle</code>)</A></nobr><br> +<nobr><A HREF="android.app.Activity.html#android.app.Activity.onRetainNonConfigurationInstance_changed()" class="hiddenlink" target="rightframe">onRetainNonConfigurationInstance +()</A></nobr><br> +<A NAME="R"></A> +<br><font size="+2">R</font> +<a href="#D"><font size="-2">D</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#S"><font size="-2">S</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<nobr><A HREF="android.app.Activity.html#android.app.Activity.removeDialog_changed(int)" class="hiddenlink" target="rightframe">removeDialog +(<code>int</code>)</A></nobr><br> +<A NAME="S"></A> +<br><font size="+2">S</font> +<a href="#D"><font size="-2">D</font></a> +<a href="#E"><font size="-2">E</font></a> +<a href="#G"><font size="-2">G</font></a> +<a href="#N"><font size="-2">N</font></a> +<a href="#O"><font size="-2">O</font></a> +<a href="#R"><font size="-2">R</font></a> + <a href="#topheader"><font size="-2">TOP</font></a> +<p><div style="line-height:1.5em;color:black"> +<i>showDialog</i><br> + <nobr><A HREF="android.app.Activity.html#android.app.Activity.showDialog_changed(int, android.os.Bundle)" class="hiddenlink" target="rightframe">type +(<code>int, Bundle</code>) in android.app.Activity +</A></nobr><br> + <nobr><A HREF="android.app.Activity.html#android.app.Activity.showDialog_changed(int)" class="hiddenlink" target="rightframe">type +(<code>int</code>) in android.app.Activity +</A></nobr><br> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/methods_index_removals.html b/docs/html/sdk/api_diff/13/changes/methods_index_removals.html new file mode 100644 index 0000000..b5aea4f --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/methods_index_removals.html @@ -0,0 +1,61 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +Method Removals Index +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY class="gc-documentation" style="padding:12px;"> +<a NAME="topheader"></a> +<table summary="Index for Methods" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;"> + <tr> + <th class="indexHeader"> + Filter the Index: + </th> + </tr> + <tr> + <td class="indexText" style="line-height:1.3em;padding-left:2em;"> +<a href="methods_index_all.html" class="staysblack">All Methods</a> + <br> +<font color="#999999">Removals</font> + <br> +<A HREF="methods_index_additions.html"xclass="hiddenlink">Additions</A> + <br> +<A HREF="methods_index_changes.html"xclass="hiddenlink">Changes</A> + </td> + </tr> +</table> +<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;"> +Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font> +</div> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/packages_index_additions.html b/docs/html/sdk/api_diff/13/changes/packages_index_additions.html new file mode 100644 index 0000000..1776064 --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/packages_index_additions.html @@ -0,0 +1,63 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +Package Additions Index +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY class="gc-documentation" style="padding:12px;"> +<a NAME="topheader"></a> +<table summary="Index for Packages" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;"> + <tr> + <th class="indexHeader"> + Filter the Index: + </th> + </tr> + <tr> + <td class="indexText" style="line-height:1.3em;padding-left:2em;"> +<a href="packages_index_all.html" class="staysblack">All Packages</a> + <br> +<font color="#999999">Removals</font> + <br> +<font color="#999999">Additions</font> + <br> +<A HREF="packages_index_changes.html"xclass="hiddenlink">Changes</A> + </td> + </tr> +</table> +<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;"> +Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font> +</div> +<br> +<div id="indexTableEntries"> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/packages_index_all.html b/docs/html/sdk/api_diff/13/changes/packages_index_all.html new file mode 100644 index 0000000..c23f4a6 --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/packages_index_all.html @@ -0,0 +1,75 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +Package Differences Index +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY class="gc-documentation" style="padding:12px;"> +<a NAME="topheader"></a> +<table summary="Index for Packages" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;"> + <tr> + <th class="indexHeader"> + Filter the Index: + </th> + </tr> + <tr> + <td class="indexText" style="line-height:1.3em;padding-left:2em;"> +<b>Packages</b> + <br> +<font color="#999999">Removals</font> + <br> +<font color="#999999">Additions</font> + <br> +<A HREF="packages_index_changes.html"xclass="hiddenlink">Changes</A> + </td> + </tr> +</table> +<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;"> +Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font> +</div> +<br> +<div id="indexTableEntries"> +<A NAME="A"></A> +<A HREF="pkg_android.html" class="hiddenlink" target="rightframe">android</A><br> +<A HREF="pkg_android.app.html" class="hiddenlink" target="rightframe">android.app</A><br> +<A HREF="pkg_android.content.pm.html" class="hiddenlink" target="rightframe">android.content.pm</A><br> +<A HREF="pkg_android.content.res.html" class="hiddenlink" target="rightframe">android.content.res</A><br> +<A HREF="pkg_android.graphics.html" class="hiddenlink" target="rightframe">android.graphics</A><br> +<A HREF="pkg_android.hardware.usb.html" class="hiddenlink" target="rightframe">android.hardware.usb</A><br> +<A HREF="pkg_android.net.html" class="hiddenlink" target="rightframe">android.net</A><br> +<A HREF="pkg_android.os.html" class="hiddenlink" target="rightframe">android.os</A><br> +<A HREF="pkg_android.telephony.html" class="hiddenlink" target="rightframe">android.telephony</A><br> +<A HREF="pkg_android.util.html" class="hiddenlink" target="rightframe">android.util</A><br> +<A HREF="pkg_android.view.html" class="hiddenlink" target="rightframe">android.view</A><br> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/packages_index_changes.html b/docs/html/sdk/api_diff/13/changes/packages_index_changes.html new file mode 100644 index 0000000..d00b449 --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/packages_index_changes.html @@ -0,0 +1,75 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +Package Changes Index +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY class="gc-documentation" style="padding:12px;"> +<a NAME="topheader"></a> +<table summary="Index for Packages" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;"> + <tr> + <th class="indexHeader"> + Filter the Index: + </th> + </tr> + <tr> + <td class="indexText" style="line-height:1.3em;padding-left:2em;"> +<a href="packages_index_all.html" class="staysblack">All Packages</a> + <br> +<font color="#999999">Removals</font> + <br> +<font color="#999999">Additions</font> + <br> +<b>Changes</b> + </td> + </tr> +</table> +<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;"> +Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font> +</div> +<br> +<div id="indexTableEntries"> +<A NAME="A"></A> +<A HREF="pkg_android.html" class="hiddenlink" target="rightframe">android</A><br> +<A HREF="pkg_android.app.html" class="hiddenlink" target="rightframe">android.app</A><br> +<A HREF="pkg_android.content.pm.html" class="hiddenlink" target="rightframe">android.content.pm</A><br> +<A HREF="pkg_android.content.res.html" class="hiddenlink" target="rightframe">android.content.res</A><br> +<A HREF="pkg_android.graphics.html" class="hiddenlink" target="rightframe">android.graphics</A><br> +<A HREF="pkg_android.hardware.usb.html" class="hiddenlink" target="rightframe">android.hardware.usb</A><br> +<A HREF="pkg_android.net.html" class="hiddenlink" target="rightframe">android.net</A><br> +<A HREF="pkg_android.os.html" class="hiddenlink" target="rightframe">android.os</A><br> +<A HREF="pkg_android.telephony.html" class="hiddenlink" target="rightframe">android.telephony</A><br> +<A HREF="pkg_android.util.html" class="hiddenlink" target="rightframe">android.util</A><br> +<A HREF="pkg_android.view.html" class="hiddenlink" target="rightframe">android.view</A><br> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/packages_index_removals.html b/docs/html/sdk/api_diff/13/changes/packages_index_removals.html new file mode 100644 index 0000000..9fd0f7e --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/packages_index_removals.html @@ -0,0 +1,63 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +Package Removals Index +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY class="gc-documentation" style="padding:12px;"> +<a NAME="topheader"></a> +<table summary="Index for Packages" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;"> + <tr> + <th class="indexHeader"> + Filter the Index: + </th> + </tr> + <tr> + <td class="indexText" style="line-height:1.3em;padding-left:2em;"> +<a href="packages_index_all.html" class="staysblack">All Packages</a> + <br> +<font color="#999999">Removals</font> + <br> +<font color="#999999">Additions</font> + <br> +<A HREF="packages_index_changes.html"xclass="hiddenlink">Changes</A> + </td> + </tr> +</table> +<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;"> +Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font> +</div> +<br> +<div id="indexTableEntries"> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/pkg_android.app.html b/docs/html/sdk/api_diff/13/changes/pkg_android.app.html new file mode 100644 index 0000000..d728895 --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/pkg_android.app.html @@ -0,0 +1,190 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +android.app +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY> +<!-- Start of nav bar --> +<a name="top"></a> +<div id="header" style="margin-bottom:0;padding-bottom:0;"> +<div id="headerLeft"> +<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a> +</div> + <div id="headerRight"> + <div id="headerLinks"> +<!-- <img src="/assets/images/icon_world.jpg" alt="" /> --> +<span class="text"> +<!-- <a href="#">English</a> | --> +<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr> +</span> +</div> + <div class="and-diff-id" style="margin-top:6px;margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td colspan="2" class="diffspechead">API Diff Specification</td> + </tr> + <tr> + <td class="diffspec" style="padding-top:.25em">To Level:</td> + <td class="diffvaluenew" style="padding-top:.25em">13</td> + </tr> + <tr> + <td class="diffspec">From Level:</td> + <td class="diffvalueold">12</td> + </tr> + <tr> + <td class="diffspec">Generated</td> + <td class="diffvalue">2011.06.29 10:50</td> + </tr> + </table> + </div><!-- End and-diff-id --> + <div class="and-diff-id" style="margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a> + </tr> + </table> + </div> <!-- End and-diff-id --> + </div> <!-- End headerRight --> + </div> <!-- End header --> +<div id="body-content" xstyle="padding:12px;padding-right:18px;"> +<div id="doc-content" style="position:relative;"> +<div id="mainBodyFluid"> +<H2> +Package <A HREF="../../../../reference/android/app/package-summary.html" target="_top"><font size="+1"><code>android.app</code></font></A> +</H2> +<p> +<a NAME="Added"></a> +<TABLE summary="Added Classes" WIDTH="100%"> +<TR> + <TH VALIGN="TOP" COLSPAN=2>Added Classes</FONT></TD> +</TH> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="Fragment.SavedState"></A> + <nobr><A HREF="../../../../reference/android/app/Fragment.SavedState.html" target="_top"><code>Fragment.SavedState</code></A></nobr> + </TD> + <TD> </TD> +</TR> +</TABLE> + +<p> +<a NAME="Changed"></a> +<TABLE summary="Changed Classes" WIDTH="100%"> +<TR> + <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD> +</TH> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="Activity"></A> + <nobr><A HREF="android.app.Activity.html">Activity</A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="ActivityGroup"></A> + <nobr><A HREF="android.app.ActivityGroup.html">ActivityGroup</A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="Fragment"></A> + <nobr><A HREF="android.app.Fragment.html">Fragment</A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="FragmentManager"></A> + <nobr><A HREF="android.app.FragmentManager.html">FragmentManager</A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="FragmentTransaction"></A> + <nobr><A HREF="android.app.FragmentTransaction.html">FragmentTransaction</A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="KeyguardManager"></A> + <nobr><A HREF="android.app.KeyguardManager.html">KeyguardManager</A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="KeyguardManager.KeyguardLock"></A> + <nobr><A HREF="android.app.KeyguardManager.KeyguardLock.html">KeyguardManager.KeyguardLock</A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="LocalActivityManager"></A> + <nobr><A HREF="android.app.LocalActivityManager.html">LocalActivityManager</A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="TabActivity"></A> + <nobr><A HREF="android.app.TabActivity.html">TabActivity</A></nobr> + </TD> + <TD> </TD> +</TR> +</TABLE> + + </div> + <div id="footer"> + <div id="copyright"> + Except as noted, this content is licensed under + <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>. + For details and restrictions, see the <a href="/license.html">Content License</a>. + </div> + <div id="footerlinks"> + <p> + <a href="http://www.android.com/terms.html">Site Terms of Service</a> - + <a href="http://www.android.com/privacy.html">Privacy Policy</a> - + <a href="http://www.android.com/branding.html">Brand Guidelines</a> + </p> + </div> + </div> <!-- end footer --> + </div><!-- end doc-content --> + </div> <!-- end body-content --> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/pkg_android.content.pm.html b/docs/html/sdk/api_diff/13/changes/pkg_android.content.pm.html new file mode 100644 index 0000000..60ab502 --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/pkg_android.content.pm.html @@ -0,0 +1,133 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +android.content.pm +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY> +<!-- Start of nav bar --> +<a name="top"></a> +<div id="header" style="margin-bottom:0;padding-bottom:0;"> +<div id="headerLeft"> +<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a> +</div> + <div id="headerRight"> + <div id="headerLinks"> +<!-- <img src="/assets/images/icon_world.jpg" alt="" /> --> +<span class="text"> +<!-- <a href="#">English</a> | --> +<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr> +</span> +</div> + <div class="and-diff-id" style="margin-top:6px;margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td colspan="2" class="diffspechead">API Diff Specification</td> + </tr> + <tr> + <td class="diffspec" style="padding-top:.25em">To Level:</td> + <td class="diffvaluenew" style="padding-top:.25em">13</td> + </tr> + <tr> + <td class="diffspec">From Level:</td> + <td class="diffvalueold">12</td> + </tr> + <tr> + <td class="diffspec">Generated</td> + <td class="diffvalue">2011.06.29 10:50</td> + </tr> + </table> + </div><!-- End and-diff-id --> + <div class="and-diff-id" style="margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a> + </tr> + </table> + </div> <!-- End and-diff-id --> + </div> <!-- End headerRight --> + </div> <!-- End header --> +<div id="body-content" xstyle="padding:12px;padding-right:18px;"> +<div id="doc-content" style="position:relative;"> +<div id="mainBodyFluid"> +<H2> +Package <A HREF="../../../../reference/android/content/pm/package-summary.html" target="_top"><font size="+1"><code>android.content.pm</code></font></A> +</H2> +<p> +<a NAME="Changed"></a> +<TABLE summary="Changed Classes" WIDTH="100%"> +<TR> + <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD> +</TH> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="ActivityInfo"></A> + <nobr><A HREF="android.content.pm.ActivityInfo.html">ActivityInfo</A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="ApplicationInfo"></A> + <nobr><A HREF="android.content.pm.ApplicationInfo.html">ApplicationInfo</A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="PackageManager"></A> + <nobr><A HREF="android.content.pm.PackageManager.html">PackageManager</A></nobr> + </TD> + <TD> </TD> +</TR> +</TABLE> + + </div> + <div id="footer"> + <div id="copyright"> + Except as noted, this content is licensed under + <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>. + For details and restrictions, see the <a href="/license.html">Content License</a>. + </div> + <div id="footerlinks"> + <p> + <a href="http://www.android.com/terms.html">Site Terms of Service</a> - + <a href="http://www.android.com/privacy.html">Privacy Policy</a> - + <a href="http://www.android.com/branding.html">Brand Guidelines</a> + </p> + </div> + </div> <!-- end footer --> + </div><!-- end doc-content --> + </div> <!-- end body-content --> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/pkg_android.content.res.html b/docs/html/sdk/api_diff/13/changes/pkg_android.content.res.html new file mode 100644 index 0000000..01c31d0 --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/pkg_android.content.res.html @@ -0,0 +1,119 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +android.content.res +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY> +<!-- Start of nav bar --> +<a name="top"></a> +<div id="header" style="margin-bottom:0;padding-bottom:0;"> +<div id="headerLeft"> +<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a> +</div> + <div id="headerRight"> + <div id="headerLinks"> +<!-- <img src="/assets/images/icon_world.jpg" alt="" /> --> +<span class="text"> +<!-- <a href="#">English</a> | --> +<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr> +</span> +</div> + <div class="and-diff-id" style="margin-top:6px;margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td colspan="2" class="diffspechead">API Diff Specification</td> + </tr> + <tr> + <td class="diffspec" style="padding-top:.25em">To Level:</td> + <td class="diffvaluenew" style="padding-top:.25em">13</td> + </tr> + <tr> + <td class="diffspec">From Level:</td> + <td class="diffvalueold">12</td> + </tr> + <tr> + <td class="diffspec">Generated</td> + <td class="diffvalue">2011.06.29 10:50</td> + </tr> + </table> + </div><!-- End and-diff-id --> + <div class="and-diff-id" style="margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a> + </tr> + </table> + </div> <!-- End and-diff-id --> + </div> <!-- End headerRight --> + </div> <!-- End header --> +<div id="body-content" xstyle="padding:12px;padding-right:18px;"> +<div id="doc-content" style="position:relative;"> +<div id="mainBodyFluid"> +<H2> +Package <A HREF="../../../../reference/android/content/res/package-summary.html" target="_top"><font size="+1"><code>android.content.res</code></font></A> +</H2> +<p> +<a NAME="Changed"></a> +<TABLE summary="Changed Classes" WIDTH="100%"> +<TR> + <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD> +</TH> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="Configuration"></A> + <nobr><A HREF="android.content.res.Configuration.html">Configuration</A></nobr> + </TD> + <TD> </TD> +</TR> +</TABLE> + + </div> + <div id="footer"> + <div id="copyright"> + Except as noted, this content is licensed under + <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>. + For details and restrictions, see the <a href="/license.html">Content License</a>. + </div> + <div id="footerlinks"> + <p> + <a href="http://www.android.com/terms.html">Site Terms of Service</a> - + <a href="http://www.android.com/privacy.html">Privacy Policy</a> - + <a href="http://www.android.com/branding.html">Brand Guidelines</a> + </p> + </div> + </div> <!-- end footer --> + </div><!-- end doc-content --> + </div> <!-- end body-content --> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/pkg_android.graphics.html b/docs/html/sdk/api_diff/13/changes/pkg_android.graphics.html new file mode 100644 index 0000000..31ddb13 --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/pkg_android.graphics.html @@ -0,0 +1,126 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +android.graphics +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY> +<!-- Start of nav bar --> +<a name="top"></a> +<div id="header" style="margin-bottom:0;padding-bottom:0;"> +<div id="headerLeft"> +<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a> +</div> + <div id="headerRight"> + <div id="headerLinks"> +<!-- <img src="/assets/images/icon_world.jpg" alt="" /> --> +<span class="text"> +<!-- <a href="#">English</a> | --> +<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr> +</span> +</div> + <div class="and-diff-id" style="margin-top:6px;margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td colspan="2" class="diffspechead">API Diff Specification</td> + </tr> + <tr> + <td class="diffspec" style="padding-top:.25em">To Level:</td> + <td class="diffvaluenew" style="padding-top:.25em">13</td> + </tr> + <tr> + <td class="diffspec">From Level:</td> + <td class="diffvalueold">12</td> + </tr> + <tr> + <td class="diffspec">Generated</td> + <td class="diffvalue">2011.06.29 10:50</td> + </tr> + </table> + </div><!-- End and-diff-id --> + <div class="and-diff-id" style="margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a> + </tr> + </table> + </div> <!-- End and-diff-id --> + </div> <!-- End headerRight --> + </div> <!-- End header --> +<div id="body-content" xstyle="padding:12px;padding-right:18px;"> +<div id="doc-content" style="position:relative;"> +<div id="mainBodyFluid"> +<H2> +Package <A HREF="../../../../reference/android/graphics/package-summary.html" target="_top"><font size="+1"><code>android.graphics</code></font></A> +</H2> +<p> +<a NAME="Changed"></a> +<TABLE summary="Changed Classes" WIDTH="100%"> +<TR> + <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD> +</TH> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="Point"></A> + <nobr><A HREF="android.graphics.Point.html">Point</A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="PointF"></A> + <nobr><A HREF="android.graphics.PointF.html">PointF</A></nobr> + </TD> + <TD> </TD> +</TR> +</TABLE> + + </div> + <div id="footer"> + <div id="copyright"> + Except as noted, this content is licensed under + <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>. + For details and restrictions, see the <a href="/license.html">Content License</a>. + </div> + <div id="footerlinks"> + <p> + <a href="http://www.android.com/terms.html">Site Terms of Service</a> - + <a href="http://www.android.com/privacy.html">Privacy Policy</a> - + <a href="http://www.android.com/branding.html">Brand Guidelines</a> + </p> + </div> + </div> <!-- end footer --> + </div><!-- end doc-content --> + </div> <!-- end body-content --> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/pkg_android.hardware.usb.html b/docs/html/sdk/api_diff/13/changes/pkg_android.hardware.usb.html new file mode 100644 index 0000000..ec768c9 --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/pkg_android.hardware.usb.html @@ -0,0 +1,119 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +android.hardware.usb +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY> +<!-- Start of nav bar --> +<a name="top"></a> +<div id="header" style="margin-bottom:0;padding-bottom:0;"> +<div id="headerLeft"> +<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a> +</div> + <div id="headerRight"> + <div id="headerLinks"> +<!-- <img src="/assets/images/icon_world.jpg" alt="" /> --> +<span class="text"> +<!-- <a href="#">English</a> | --> +<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr> +</span> +</div> + <div class="and-diff-id" style="margin-top:6px;margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td colspan="2" class="diffspechead">API Diff Specification</td> + </tr> + <tr> + <td class="diffspec" style="padding-top:.25em">To Level:</td> + <td class="diffvaluenew" style="padding-top:.25em">13</td> + </tr> + <tr> + <td class="diffspec">From Level:</td> + <td class="diffvalueold">12</td> + </tr> + <tr> + <td class="diffspec">Generated</td> + <td class="diffvalue">2011.06.29 10:50</td> + </tr> + </table> + </div><!-- End and-diff-id --> + <div class="and-diff-id" style="margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a> + </tr> + </table> + </div> <!-- End and-diff-id --> + </div> <!-- End headerRight --> + </div> <!-- End header --> +<div id="body-content" xstyle="padding:12px;padding-right:18px;"> +<div id="doc-content" style="position:relative;"> +<div id="mainBodyFluid"> +<H2> +Package <A HREF="../../../../reference/android/hardware/usb/package-summary.html" target="_top"><font size="+1"><code>android.hardware.usb</code></font></A> +</H2> +<p> +<a NAME="Changed"></a> +<TABLE summary="Changed Classes" WIDTH="100%"> +<TR> + <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD> +</TH> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="UsbDeviceConnection"></A> + <nobr><A HREF="android.hardware.usb.UsbDeviceConnection.html">UsbDeviceConnection</A></nobr> + </TD> + <TD> </TD> +</TR> +</TABLE> + + </div> + <div id="footer"> + <div id="copyright"> + Except as noted, this content is licensed under + <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>. + For details and restrictions, see the <a href="/license.html">Content License</a>. + </div> + <div id="footerlinks"> + <p> + <a href="http://www.android.com/terms.html">Site Terms of Service</a> - + <a href="http://www.android.com/privacy.html">Privacy Policy</a> - + <a href="http://www.android.com/branding.html">Brand Guidelines</a> + </p> + </div> + </div> <!-- end footer --> + </div><!-- end doc-content --> + </div> <!-- end body-content --> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/pkg_android.html b/docs/html/sdk/api_diff/13/changes/pkg_android.html new file mode 100644 index 0000000..6b14637 --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/pkg_android.html @@ -0,0 +1,133 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +android +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY> +<!-- Start of nav bar --> +<a name="top"></a> +<div id="header" style="margin-bottom:0;padding-bottom:0;"> +<div id="headerLeft"> +<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a> +</div> + <div id="headerRight"> + <div id="headerLinks"> +<!-- <img src="/assets/images/icon_world.jpg" alt="" /> --> +<span class="text"> +<!-- <a href="#">English</a> | --> +<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr> +</span> +</div> + <div class="and-diff-id" style="margin-top:6px;margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td colspan="2" class="diffspechead">API Diff Specification</td> + </tr> + <tr> + <td class="diffspec" style="padding-top:.25em">To Level:</td> + <td class="diffvaluenew" style="padding-top:.25em">13</td> + </tr> + <tr> + <td class="diffspec">From Level:</td> + <td class="diffvalueold">12</td> + </tr> + <tr> + <td class="diffspec">Generated</td> + <td class="diffvalue">2011.06.29 10:50</td> + </tr> + </table> + </div><!-- End and-diff-id --> + <div class="and-diff-id" style="margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a> + </tr> + </table> + </div> <!-- End and-diff-id --> + </div> <!-- End headerRight --> + </div> <!-- End header --> +<div id="body-content" xstyle="padding:12px;padding-right:18px;"> +<div id="doc-content" style="position:relative;"> +<div id="mainBodyFluid"> +<H2> +Package <A HREF="../../../../reference/android/package-summary.html" target="_top"><font size="+1"><code>android</code></font></A> +</H2> +<p> +<a NAME="Changed"></a> +<TABLE summary="Changed Classes" WIDTH="100%"> +<TR> + <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD> +</TH> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="Manifest.permission"></A> + <nobr><A HREF="android.Manifest.permission.html">Manifest.permission</A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="R.attr"></A> + <nobr><A HREF="android.R.attr.html">R.attr</A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="R.style"></A> + <nobr><A HREF="android.R.style.html">R.style</A></nobr> + </TD> + <TD> </TD> +</TR> +</TABLE> + + </div> + <div id="footer"> + <div id="copyright"> + Except as noted, this content is licensed under + <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>. + For details and restrictions, see the <a href="/license.html">Content License</a>. + </div> + <div id="footerlinks"> + <p> + <a href="http://www.android.com/terms.html">Site Terms of Service</a> - + <a href="http://www.android.com/privacy.html">Privacy Policy</a> - + <a href="http://www.android.com/branding.html">Brand Guidelines</a> + </p> + </div> + </div> <!-- end footer --> + </div><!-- end doc-content --> + </div> <!-- end body-content --> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/pkg_android.net.html b/docs/html/sdk/api_diff/13/changes/pkg_android.net.html new file mode 100644 index 0000000..f3f82cc --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/pkg_android.net.html @@ -0,0 +1,119 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +android.net +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY> +<!-- Start of nav bar --> +<a name="top"></a> +<div id="header" style="margin-bottom:0;padding-bottom:0;"> +<div id="headerLeft"> +<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a> +</div> + <div id="headerRight"> + <div id="headerLinks"> +<!-- <img src="/assets/images/icon_world.jpg" alt="" /> --> +<span class="text"> +<!-- <a href="#">English</a> | --> +<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr> +</span> +</div> + <div class="and-diff-id" style="margin-top:6px;margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td colspan="2" class="diffspechead">API Diff Specification</td> + </tr> + <tr> + <td class="diffspec" style="padding-top:.25em">To Level:</td> + <td class="diffvaluenew" style="padding-top:.25em">13</td> + </tr> + <tr> + <td class="diffspec">From Level:</td> + <td class="diffvalueold">12</td> + </tr> + <tr> + <td class="diffspec">Generated</td> + <td class="diffvalue">2011.06.29 10:50</td> + </tr> + </table> + </div><!-- End and-diff-id --> + <div class="and-diff-id" style="margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a> + </tr> + </table> + </div> <!-- End and-diff-id --> + </div> <!-- End headerRight --> + </div> <!-- End header --> +<div id="body-content" xstyle="padding:12px;padding-right:18px;"> +<div id="doc-content" style="position:relative;"> +<div id="mainBodyFluid"> +<H2> +Package <A HREF="../../../../reference/android/net/package-summary.html" target="_top"><font size="+1"><code>android.net</code></font></A> +</H2> +<p> +<a NAME="Changed"></a> +<TABLE summary="Changed Classes" WIDTH="100%"> +<TR> + <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD> +</TH> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="ConnectivityManager"></A> + <nobr><A HREF="android.net.ConnectivityManager.html">ConnectivityManager</A></nobr> + </TD> + <TD> </TD> +</TR> +</TABLE> + + </div> + <div id="footer"> + <div id="copyright"> + Except as noted, this content is licensed under + <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>. + For details and restrictions, see the <a href="/license.html">Content License</a>. + </div> + <div id="footerlinks"> + <p> + <a href="http://www.android.com/terms.html">Site Terms of Service</a> - + <a href="http://www.android.com/privacy.html">Privacy Policy</a> - + <a href="http://www.android.com/branding.html">Brand Guidelines</a> + </p> + </div> + </div> <!-- end footer --> + </div><!-- end doc-content --> + </div> <!-- end body-content --> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/pkg_android.os.html b/docs/html/sdk/api_diff/13/changes/pkg_android.os.html new file mode 100644 index 0000000..b9a8c09 --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/pkg_android.os.html @@ -0,0 +1,162 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +android.os +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY> +<!-- Start of nav bar --> +<a name="top"></a> +<div id="header" style="margin-bottom:0;padding-bottom:0;"> +<div id="headerLeft"> +<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a> +</div> + <div id="headerRight"> + <div id="headerLinks"> +<!-- <img src="/assets/images/icon_world.jpg" alt="" /> --> +<span class="text"> +<!-- <a href="#">English</a> | --> +<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr> +</span> +</div> + <div class="and-diff-id" style="margin-top:6px;margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td colspan="2" class="diffspechead">API Diff Specification</td> + </tr> + <tr> + <td class="diffspec" style="padding-top:.25em">To Level:</td> + <td class="diffvaluenew" style="padding-top:.25em">13</td> + </tr> + <tr> + <td class="diffspec">From Level:</td> + <td class="diffvalueold">12</td> + </tr> + <tr> + <td class="diffspec">Generated</td> + <td class="diffvalue">2011.06.29 10:50</td> + </tr> + </table> + </div><!-- End and-diff-id --> + <div class="and-diff-id" style="margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a> + </tr> + </table> + </div> <!-- End and-diff-id --> + </div> <!-- End headerRight --> + </div> <!-- End header --> +<div id="body-content" xstyle="padding:12px;padding-right:18px;"> +<div id="doc-content" style="position:relative;"> +<div id="mainBodyFluid"> +<H2> +Package <A HREF="../../../../reference/android/os/package-summary.html" target="_top"><font size="+1"><code>android.os</code></font></A> +</H2> +<p> +<a NAME="Added"></a> +<TABLE summary="Added Interfaces" WIDTH="100%"> +<TR> + <TH VALIGN="TOP" COLSPAN=2>Added Interfaces</FONT></TD> +</TH> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="Parcelable.ClassLoaderCreator"></A> + <nobr><A HREF="../../../../reference/android/os/Parcelable.ClassLoaderCreator.html" target="_top"><code><I>Parcelable.ClassLoaderCreator</I></code></A></nobr> + </TD> + <TD> </TD> +</TR> +</TABLE> + +<p> +<a NAME="Changed"></a> +<TABLE summary="Changed Classes and Interfaces" WIDTH="100%"> +<TR> + <TH VALIGN="TOP" COLSPAN=2>Changed Classes and Interfaces</FONT></TD> +</TH> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="Binder"></A> + <nobr><A HREF="android.os.Binder.html">Binder</A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="Build.VERSION_CODES"></A> + <nobr><A HREF="android.os.Build.VERSION_CODES.html">Build.VERSION_CODES</A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="IBinder"></A> + <nobr><A HREF="android.os.IBinder.html"><I>IBinder</I></A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="ParcelFileDescriptor"></A> + <nobr><A HREF="android.os.ParcelFileDescriptor.html">ParcelFileDescriptor</A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="PowerManager"></A> + <nobr><A HREF="android.os.PowerManager.html">PowerManager</A></nobr> + </TD> + <TD> </TD> +</TR> +</TABLE> + + </div> + <div id="footer"> + <div id="copyright"> + Except as noted, this content is licensed under + <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>. + For details and restrictions, see the <a href="/license.html">Content License</a>. + </div> + <div id="footerlinks"> + <p> + <a href="http://www.android.com/terms.html">Site Terms of Service</a> - + <a href="http://www.android.com/privacy.html">Privacy Policy</a> - + <a href="http://www.android.com/branding.html">Brand Guidelines</a> + </p> + </div> + </div> <!-- end footer --> + </div><!-- end doc-content --> + </div> <!-- end body-content --> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/pkg_android.telephony.html b/docs/html/sdk/api_diff/13/changes/pkg_android.telephony.html new file mode 100644 index 0000000..9a00876 --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/pkg_android.telephony.html @@ -0,0 +1,119 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +android.telephony +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY> +<!-- Start of nav bar --> +<a name="top"></a> +<div id="header" style="margin-bottom:0;padding-bottom:0;"> +<div id="headerLeft"> +<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a> +</div> + <div id="headerRight"> + <div id="headerLinks"> +<!-- <img src="/assets/images/icon_world.jpg" alt="" /> --> +<span class="text"> +<!-- <a href="#">English</a> | --> +<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr> +</span> +</div> + <div class="and-diff-id" style="margin-top:6px;margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td colspan="2" class="diffspechead">API Diff Specification</td> + </tr> + <tr> + <td class="diffspec" style="padding-top:.25em">To Level:</td> + <td class="diffvaluenew" style="padding-top:.25em">13</td> + </tr> + <tr> + <td class="diffspec">From Level:</td> + <td class="diffvalueold">12</td> + </tr> + <tr> + <td class="diffspec">Generated</td> + <td class="diffvalue">2011.06.29 10:50</td> + </tr> + </table> + </div><!-- End and-diff-id --> + <div class="and-diff-id" style="margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a> + </tr> + </table> + </div> <!-- End and-diff-id --> + </div> <!-- End headerRight --> + </div> <!-- End header --> +<div id="body-content" xstyle="padding:12px;padding-right:18px;"> +<div id="doc-content" style="position:relative;"> +<div id="mainBodyFluid"> +<H2> +Package <A HREF="../../../../reference/android/telephony/package-summary.html" target="_top"><font size="+1"><code>android.telephony</code></font></A> +</H2> +<p> +<a NAME="Changed"></a> +<TABLE summary="Changed Classes" WIDTH="100%"> +<TR> + <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD> +</TH> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="TelephonyManager"></A> + <nobr><A HREF="android.telephony.TelephonyManager.html">TelephonyManager</A></nobr> + </TD> + <TD> </TD> +</TR> +</TABLE> + + </div> + <div id="footer"> + <div id="copyright"> + Except as noted, this content is licensed under + <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>. + For details and restrictions, see the <a href="/license.html">Content License</a>. + </div> + <div id="footerlinks"> + <p> + <a href="http://www.android.com/terms.html">Site Terms of Service</a> - + <a href="http://www.android.com/privacy.html">Privacy Policy</a> - + <a href="http://www.android.com/branding.html">Brand Guidelines</a> + </p> + </div> + </div> <!-- end footer --> + </div><!-- end doc-content --> + </div> <!-- end body-content --> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/pkg_android.util.html b/docs/html/sdk/api_diff/13/changes/pkg_android.util.html new file mode 100644 index 0000000..0d92956 --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/pkg_android.util.html @@ -0,0 +1,119 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +android.util +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY> +<!-- Start of nav bar --> +<a name="top"></a> +<div id="header" style="margin-bottom:0;padding-bottom:0;"> +<div id="headerLeft"> +<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a> +</div> + <div id="headerRight"> + <div id="headerLinks"> +<!-- <img src="/assets/images/icon_world.jpg" alt="" /> --> +<span class="text"> +<!-- <a href="#">English</a> | --> +<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr> +</span> +</div> + <div class="and-diff-id" style="margin-top:6px;margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td colspan="2" class="diffspechead">API Diff Specification</td> + </tr> + <tr> + <td class="diffspec" style="padding-top:.25em">To Level:</td> + <td class="diffvaluenew" style="padding-top:.25em">13</td> + </tr> + <tr> + <td class="diffspec">From Level:</td> + <td class="diffvalueold">12</td> + </tr> + <tr> + <td class="diffspec">Generated</td> + <td class="diffvalue">2011.06.29 10:50</td> + </tr> + </table> + </div><!-- End and-diff-id --> + <div class="and-diff-id" style="margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a> + </tr> + </table> + </div> <!-- End and-diff-id --> + </div> <!-- End headerRight --> + </div> <!-- End header --> +<div id="body-content" xstyle="padding:12px;padding-right:18px;"> +<div id="doc-content" style="position:relative;"> +<div id="mainBodyFluid"> +<H2> +Package <A HREF="../../../../reference/android/util/package-summary.html" target="_top"><font size="+1"><code>android.util</code></font></A> +</H2> +<p> +<a NAME="Changed"></a> +<TABLE summary="Changed Classes" WIDTH="100%"> +<TR> + <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD> +</TH> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="DisplayMetrics"></A> + <nobr><A HREF="android.util.DisplayMetrics.html">DisplayMetrics</A></nobr> + </TD> + <TD> </TD> +</TR> +</TABLE> + + </div> + <div id="footer"> + <div id="copyright"> + Except as noted, this content is licensed under + <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>. + For details and restrictions, see the <a href="/license.html">Content License</a>. + </div> + <div id="footerlinks"> + <p> + <a href="http://www.android.com/terms.html">Site Terms of Service</a> - + <a href="http://www.android.com/privacy.html">Privacy Policy</a> - + <a href="http://www.android.com/branding.html">Brand Guidelines</a> + </p> + </div> + </div> <!-- end footer --> + </div><!-- end doc-content --> + </div> <!-- end body-content --> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/changes/pkg_android.view.html b/docs/html/sdk/api_diff/13/changes/pkg_android.view.html new file mode 100644 index 0000000..22fde46 --- /dev/null +++ b/docs/html/sdk/api_diff/13/changes/pkg_android.view.html @@ -0,0 +1,126 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<HTML style="overflow:auto;"> +<HEAD> +<meta name="generator" content="JDiff v1.1.0"> +<!-- Generated by the JDiff Javadoc doclet --> +<!-- (http://www.jdiff.org) --> +<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared."> +<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet"> +<TITLE> +android.view +</TITLE> +<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" /> +<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" /> +<noscript> +<style type="text/css"> +body{overflow:auto;} +#body-content{position:relative; top:0;} +#doc-content{overflow:visible;border-left:3px solid #666;} +#side-nav{padding:0;} +#side-nav .toggle-list ul {display:block;} +#resize-packages-nav{border-bottom:3px solid #666;} +</style> +</noscript> +<style type="text/css"> +</style> +</HEAD> +<BODY> +<!-- Start of nav bar --> +<a name="top"></a> +<div id="header" style="margin-bottom:0;padding-bottom:0;"> +<div id="headerLeft"> +<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a> +</div> + <div id="headerRight"> + <div id="headerLinks"> +<!-- <img src="/assets/images/icon_world.jpg" alt="" /> --> +<span class="text"> +<!-- <a href="#">English</a> | --> +<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr> +</span> +</div> + <div class="and-diff-id" style="margin-top:6px;margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td colspan="2" class="diffspechead">API Diff Specification</td> + </tr> + <tr> + <td class="diffspec" style="padding-top:.25em">To Level:</td> + <td class="diffvaluenew" style="padding-top:.25em">13</td> + </tr> + <tr> + <td class="diffspec">From Level:</td> + <td class="diffvalueold">12</td> + </tr> + <tr> + <td class="diffspec">Generated</td> + <td class="diffvalue">2011.06.29 10:50</td> + </tr> + </table> + </div><!-- End and-diff-id --> + <div class="and-diff-id" style="margin-right:8px;"> + <table class="diffspectable"> + <tr> + <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a> + </tr> + </table> + </div> <!-- End and-diff-id --> + </div> <!-- End headerRight --> + </div> <!-- End header --> +<div id="body-content" xstyle="padding:12px;padding-right:18px;"> +<div id="doc-content" style="position:relative;"> +<div id="mainBodyFluid"> +<H2> +Package <A HREF="../../../../reference/android/view/package-summary.html" target="_top"><font size="+1"><code>android.view</code></font></A> +</H2> +<p> +<a NAME="Changed"></a> +<TABLE summary="Changed Classes" WIDTH="100%"> +<TR> + <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD> +</TH> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="Display"></A> + <nobr><A HREF="android.view.Display.html">Display</A></nobr> + </TD> + <TD> </TD> +</TR> +<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor"> + <TD VALIGN="TOP" WIDTH="25%"> + <A NAME="KeyEvent"></A> + <nobr><A HREF="android.view.KeyEvent.html">KeyEvent</A></nobr> + </TD> + <TD> </TD> +</TR> +</TABLE> + + </div> + <div id="footer"> + <div id="copyright"> + Except as noted, this content is licensed under + <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>. + For details and restrictions, see the <a href="/license.html">Content License</a>. + </div> + <div id="footerlinks"> + <p> + <a href="http://www.android.com/terms.html">Site Terms of Service</a> - + <a href="http://www.android.com/privacy.html">Privacy Policy</a> - + <a href="http://www.android.com/branding.html">Brand Guidelines</a> + </p> + </div> + </div> <!-- end footer --> + </div><!-- end doc-content --> + </div> <!-- end body-content --> +<script src="http://www.google-analytics.com/ga.js" type="text/javascript"> +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-5831155-1"); + pageTracker._setAllowAnchor(true); + pageTracker._initData(); + pageTracker._trackPageview(); + } catch(e) {} +</script> +</BODY> +</HTML> diff --git a/docs/html/sdk/api_diff/13/stylesheet-jdiff.css b/docs/html/sdk/api_diff/13/stylesheet-jdiff.css new file mode 100644 index 0000000..edafaa3 --- /dev/null +++ b/docs/html/sdk/api_diff/13/stylesheet-jdiff.css @@ -0,0 +1,44 @@ + +/* (http://www.jdiff.org) */ + +div.and-diff-id {border: 1px solid #eee;position:relative;float:right;clear:both;padding:0px;} +table.diffspectable {border:1px;padding:0px;margin:0px;} +.diffspechead {background-color:#eee;} +.diffspectable tr {border:0px;padding:0px;} +.diffspectable td {background-color:eee;border:0px;font-size:90%;font-weight:normal;padding:0px;padding-left:1px;padding-right:1px;text-align:center;color:777;} +td.diffvalueold {color:orange;background-color:white;border:0px;font-size:80%;font-style:normal;text-align:left;padding:0px;padding-left:1px;padding-right:1px;line-height:.95em;} +td.diffvaluenew {color:green;background-color:white;border:0px;font-size:80%;font-weight:normal;text-align:left;padding:0px;padding-left:1px;padding-right:1px;line-height:.95em;} +td.diffvalue {color:444;background-color:white;border:0px;font-size:80%;font-weight:normal;text-align:left;padding:0px;padding-left:1px;padding-right:1px;line-height:.95em;} +td.diffspec {background-color:white;border:0px;font-size:80%;font-weight:normal;padding:1px;color:444;text-align:right;padding-right:.5em;line-height:.95em;} +tt {font-size:11pt;font-family:monospace;} +.indexHeader { + font-size:96%; + line-height:.8em;} +.jdiffIndex td { + font-size:96%; + xline-height:.8em; + padding:2px; + padding-left:1em;} +.indexText { + font-size:100%; + padding-left:1em;} +#indexTableCaption { + font-size:96%; + margin-top:.25em; + margin-bottom:0; + } +.hiddenlink { + font-size:96%; + line-height:.8em; + text-decoration:none;} +a { + text-decoration:none;} +a:hover { + text-decoration:underline;} +.indexBox { + border: 1px solid red; + margin:1em 0 0 0;} +.letterIndexHead { + font-size: 1.5em;font-weight:9; + margin:0 0 0em 0; + border: 1px solid red;} diff --git a/docs/html/sdk/sdk_toc.cs b/docs/html/sdk/sdk_toc.cs index 0539adb..829ed52 100644 --- a/docs/html/sdk/sdk_toc.cs +++ b/docs/html/sdk/sdk_toc.cs @@ -76,6 +76,14 @@ class="new">new!</span></li> </ul> <ul> <li class="toggle-list"> + <div><a href="<?cs var:toroot ?>sdk/android-3.2.html"> + <span class="en">Android 3.2 Platform</span></a> <span class="new">new!</span></div> + <ul> + <!-- <li><a href="<?cs var:toroot ?>sdk/android-3.2-highlights.html">Platform Highlights</a></li> --> + <li><a href="<?cs var:toroot ?>sdk/api_diff/13/changes.html">API Differences Report »</a></li> + </ul> + </li> + <li class="toggle-list"> <div><a href="<?cs var:toroot ?>sdk/android-3.1.html"> <span class="en">Android 3.1 Platform</span></a></div> <ul> diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp index 4a85faf..3476bd5 100644 --- a/graphics/jni/android_renderscript_RenderScript.cpp +++ b/graphics/jni/android_renderscript_RenderScript.cpp @@ -504,6 +504,7 @@ nAllocationCopyToBitmap(JNIEnv *_env, jobject _this, RsContext con, jint alloc, void* ptr = bitmap.getPixels(); rsAllocationCopyToBitmap(con, (RsAllocation)alloc, ptr, bitmap.getSize()); bitmap.unlockPixels(); + bitmap.notifyPixelsChanged(); } static void ReleaseBitmapCallback(void *bmp) diff --git a/include/gui/ISurfaceTexture.h b/include/gui/ISurfaceTexture.h index e764425..1eda646 100644 --- a/include/gui/ISurfaceTexture.h +++ b/include/gui/ISurfaceTexture.h @@ -51,7 +51,7 @@ protected: // the given slot index, and the client is expected to mirror the // slot->buffer mapping so that it's not necessary to transfer a // GraphicBuffer for every dequeue operation. - virtual sp<GraphicBuffer> requestBuffer(int slot) = 0; + virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf) = 0; // setBufferCount sets the number of buffer slots available. Calling this // will also cause all buffer slots to be emptied. The caller should empty @@ -79,8 +79,8 @@ protected: // must be monotonically increasing. Its other properties (zero point, etc) // are client-dependent, and should be documented by the client. // - // outWidth, outHeight and outTransform are filed with the default width - // default height of the window and current transform applied to buffers, + // outWidth, outHeight and outTransform are filled with the default width + // and height of the window and current transform applied to buffers, // respectively. virtual status_t queueBuffer(int slot, int64_t timestamp, uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) = 0; @@ -94,12 +94,6 @@ protected: virtual status_t setTransform(uint32_t transform) = 0; virtual status_t setScalingMode(int mode) = 0; - // getAllocator retrieves the binder object that must be referenced as long - // as the GraphicBuffers dequeued from this ISurfaceTexture are referenced. - // Holding this binder reference prevents SurfaceFlinger from freeing the - // buffers before the client is done with them. - virtual sp<IBinder> getAllocator() = 0; - // query retrieves some information for this surface // 'what' tokens allowed are that of android_natives.h virtual int query(int what, int* value) = 0; diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h index 945f4bc..134c208 100644 --- a/include/gui/SurfaceTexture.h +++ b/include/gui/SurfaceTexture.h @@ -69,7 +69,7 @@ public: // SurfaceTexture object (i.e. they are not owned by the client). virtual status_t setBufferCount(int bufferCount); - virtual sp<GraphicBuffer> requestBuffer(int buf); + virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf); // dequeueBuffer gets the next buffer slot index for the client to use. If a // buffer slot is available then that slot index is written to the location @@ -190,6 +190,17 @@ public: // getCurrentScalingMode returns the scaling mode of the current buffer uint32_t getCurrentScalingMode() const; + // abandon frees all the buffers and puts the SurfaceTexture into the + // 'abandoned' state. Once put in this state the SurfaceTexture can never + // leave it. When in the 'abandoned' state, all methods of the + // ISurfaceTexture interface will fail with the NO_INIT error. + // + // Note that while calling this method causes all the buffers to be freed + // from the perspective of the the SurfaceTexture, if there are additional + // references on the buffers (e.g. if a buffer is referenced by a client or + // by OpenGL ES as a texture) then those buffer will remain allocated. + void abandon(); + // dump our state in a String void dump(String8& result) const; void dump(String8& result, const char* prefix, char* buffer, size_t SIZE) const; @@ -343,8 +354,7 @@ private: // mCurrentTextureBuf is the graphic buffer of the current texture. It's // possible that this buffer is not associated with any buffer slot, so we - // must track it separately in order to properly use - // IGraphicBufferAlloc::freeAllGraphicBuffersExcept. + // must track it separately in order to support the getCurrentBuffer method. sp<GraphicBuffer> mCurrentTextureBuf; // mCurrentCrop is the crop rectangle that applies to the current texture. @@ -412,6 +422,13 @@ private: typedef Vector<int> Fifo; Fifo mQueue; + // mAbandoned indicates that the SurfaceTexture will no longer be used to + // consume images buffers pushed to it using the ISurfaceTexture interface. + // It is initialized to false, and set to true in the abandon method. A + // SurfaceTexture that has been abandoned will return the NO_INIT error from + // all ISurfaceTexture methods capable of returning an error. + bool mAbandoned; + // mMutex is the mutex used to prevent concurrent access to the member // variables of SurfaceTexture objects. It must be locked whenever the // member variables are accessed. diff --git a/include/gui/SurfaceTextureClient.h b/include/gui/SurfaceTextureClient.h index 829d8ab..56f029f 100644 --- a/include/gui/SurfaceTextureClient.h +++ b/include/gui/SurfaceTextureClient.h @@ -106,10 +106,6 @@ private: // interactions with the server using this interface. sp<ISurfaceTexture> mSurfaceTexture; - // mAllocator is the binder object that is referenced to prevent the - // dequeued buffers from being freed prematurely. - sp<IBinder> mAllocator; - // mSlots stores the buffers that have been allocated for each buffer slot. // It is initialized to null pointers, and gets filled in with the result of // ISurfaceTexture::requestBuffer when the client dequeues a buffer from a diff --git a/include/media/AudioEffect.h b/include/media/AudioEffect.h index dd93fd8..496b23e 100644 --- a/include/media/AudioEffect.h +++ b/include/media/AudioEffect.h @@ -188,7 +188,7 @@ public: * sessionID: audio session this effect is associated to. If 0, the effect will be global to * the output mix. If not 0, the effect will be applied to all players * (AudioTrack or MediaPLayer) within the same audio session. - * output: HAL audio output stream to which this effect must be attached. Leave at 0 for + * io: HAL audio output or input stream to which this effect must be attached. Leave at 0 for * automatic output selection by AudioFlinger. */ @@ -198,7 +198,7 @@ public: effect_callback_t cbf = 0, void* user = 0, int sessionId = 0, - audio_io_handle_t output = 0 + audio_io_handle_t io = 0 ); /* Constructor. @@ -210,7 +210,7 @@ public: effect_callback_t cbf = 0, void* user = 0, int sessionId = 0, - audio_io_handle_t output = 0 + audio_io_handle_t io = 0 ); /* Terminates the AudioEffect and unregisters it from AudioFlinger. @@ -232,7 +232,7 @@ public: effect_callback_t cbf = 0, void* user = 0, int sessionId = 0, - audio_io_handle_t output = 0 + audio_io_handle_t io = 0 ); /* Result of constructing the AudioEffect. This must be checked diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h index 89213b7..f20e234 100644 --- a/include/media/AudioSystem.h +++ b/include/media/AudioSystem.h @@ -160,7 +160,8 @@ public: uint32_t samplingRate = 0, uint32_t format = AUDIO_FORMAT_DEFAULT, uint32_t channels = AUDIO_CHANNEL_IN_MONO, - audio_in_acoustics_t acoustics = (audio_in_acoustics_t)0); + audio_in_acoustics_t acoustics = (audio_in_acoustics_t)0, + int sessionId = 0); static status_t startInput(audio_io_handle_t input); static status_t stopInput(audio_io_handle_t input); static void releaseInput(audio_io_handle_t input); @@ -175,7 +176,7 @@ public: static audio_io_handle_t getOutputForEffect(effect_descriptor_t *desc); static status_t registerEffect(effect_descriptor_t *desc, - audio_io_handle_t output, + audio_io_handle_t io, uint32_t strategy, int session, int id); diff --git a/include/media/IAudioPolicyService.h b/include/media/IAudioPolicyService.h index 0fc8dbf..86b9f85 100644 --- a/include/media/IAudioPolicyService.h +++ b/include/media/IAudioPolicyService.h @@ -65,7 +65,8 @@ public: uint32_t samplingRate = 0, uint32_t format = AUDIO_FORMAT_DEFAULT, uint32_t channels = 0, - audio_in_acoustics_t acoustics = (audio_in_acoustics_t)0) = 0; + audio_in_acoustics_t acoustics = (audio_in_acoustics_t)0, + int audioSession = 0) = 0; virtual status_t startInput(audio_io_handle_t input) = 0; virtual status_t stopInput(audio_io_handle_t input) = 0; virtual void releaseInput(audio_io_handle_t input) = 0; @@ -78,7 +79,7 @@ public: virtual uint32_t getDevicesForStream(audio_stream_type_t stream) = 0; virtual audio_io_handle_t getOutputForEffect(effect_descriptor_t *desc) = 0; virtual status_t registerEffect(effect_descriptor_t *desc, - audio_io_handle_t output, + audio_io_handle_t io, uint32_t strategy, int session, int id) = 0; diff --git a/include/media/IMediaRecorder.h b/include/media/IMediaRecorder.h index a73267d..007aea6 100644 --- a/include/media/IMediaRecorder.h +++ b/include/media/IMediaRecorder.h @@ -26,6 +26,7 @@ class Surface; class ICamera; class ICameraRecordingProxy; class IMediaRecorderClient; +class ISurfaceTexture; class IMediaRecorder: public IInterface { @@ -55,6 +56,7 @@ public: virtual status_t init() = 0; virtual status_t close() = 0; virtual status_t release() = 0; + virtual sp<ISurfaceTexture> querySurfaceMediaSource() = 0; }; // ---------------------------------------------------------------------------- diff --git a/include/media/MediaProfiles.h b/include/media/MediaProfiles.h index ed26e63..69d5001 100644 --- a/include/media/MediaProfiles.h +++ b/include/media/MediaProfiles.h @@ -45,6 +45,18 @@ enum camcorder_quality { CAMCORDER_QUALITY_TIME_LAPSE_LIST_END = 1006, }; +/** + *Set CIF as default maximum import and export resolution of video editor. + *The maximum import and export resolutions are platform specific, + *which should be defined in media_profiles.xml. + */ +enum videoeditor_capability { + VIDEOEDITOR_DEFAULT_MAX_INPUT_FRAME_WIDTH = 352, + VIDEOEDITOR_DEFUALT_MAX_INPUT_FRAME_HEIGHT = 288, + VIDEOEDITOR_DEFAULT_MAX_OUTPUT_FRAME_WIDTH = 352, + VIDEOEDITOR_DEFUALT_MAX_OUTPUT_FRAME_HEIGHT = 288, +}; + enum video_decoder { VIDEO_DECODER_WMV, }; @@ -117,6 +129,17 @@ public: int getVideoEncoderParamByName(const char *name, video_encoder codec) const; /** + * Returns the value for the given param name for the video editor cap + * param or -1 if error. + * Supported param name are: + * videoeditor.input.width.max - max input video frame width + * videoeditor.input.height.max - max input video frame height + * videoeditor.output.width.max - max output video frame width + * videoeditor.output.height.max - max output video frame height + */ + int getVideoEditorCapParamByName(const char *name) const; + + /** * Returns the audio encoders supported. */ Vector<audio_encoder> getAudioEncoders() const; @@ -164,7 +187,7 @@ private: MediaProfiles& operator=(const MediaProfiles&); // Don't call me MediaProfiles(const MediaProfiles&); // Don't call me - MediaProfiles() {} // Dummy default constructor + MediaProfiles() { mVideoEditorCap = NULL; } // Dummy default constructor ~MediaProfiles(); // Don't delete me struct VideoCodec { @@ -310,6 +333,22 @@ private: Vector<int> mLevels; }; + struct VideoEditorCap { + VideoEditorCap(int inFrameWidth, int inFrameHeight, + int outFrameWidth, int outFrameHeight) + : mMaxInputFrameWidth(inFrameWidth), + mMaxInputFrameHeight(inFrameHeight), + mMaxOutputFrameWidth(outFrameWidth), + mMaxOutputFrameHeight(outFrameHeight) {} + + ~VideoEditorCap() {} + + int mMaxInputFrameWidth; + int mMaxInputFrameHeight; + int mMaxOutputFrameWidth; + int mMaxOutputFrameHeight; + }; + int getCamcorderProfileIndex(int cameraId, camcorder_quality quality) const; void initRequiredProfileRefs(const Vector<int>& cameraIds); int getRequiredProfileRefIndex(int cameraId); @@ -321,6 +360,7 @@ private: static void logAudioEncoderCap(const AudioEncoderCap& cap); static void logVideoDecoderCap(const VideoDecoderCap& cap); static void logAudioDecoderCap(const AudioDecoderCap& cap); + static void logVideoEditorCap(const VideoEditorCap& cap); // If the xml configuration file does exist, use the settings // from the xml @@ -332,6 +372,8 @@ private: static VideoDecoderCap* createVideoDecoderCap(const char **atts); static VideoEncoderCap* createVideoEncoderCap(const char **atts); static AudioEncoderCap* createAudioEncoderCap(const char **atts); + static VideoEditorCap* createVideoEditorCap( + const char **atts, MediaProfiles *profiles); static CamcorderProfile* createCamcorderProfile( int cameraId, const char **atts, Vector<int>& cameraIds); @@ -375,6 +417,7 @@ private: static void createDefaultEncoderOutputFileFormats(MediaProfiles *profiles); static void createDefaultImageEncodingQualityLevels(MediaProfiles *profiles); static void createDefaultImageDecodingMaxMemory(MediaProfiles *profiles); + static void createDefaultVideoEditorCap(MediaProfiles *profiles); static VideoEncoderCap* createDefaultH263VideoEncoderCap(); static VideoEncoderCap* createDefaultM4vVideoEncoderCap(); static AudioEncoderCap* createDefaultAmrNBEncoderCap(); @@ -431,6 +474,7 @@ private: RequiredProfiles *mRequiredProfileRefs; Vector<int> mCameraIds; + VideoEditorCap* mVideoEditorCap; }; }; // namespace android diff --git a/include/media/MediaRecorderBase.h b/include/media/MediaRecorderBase.h index 1c08969..ef799f5 100644 --- a/include/media/MediaRecorderBase.h +++ b/include/media/MediaRecorderBase.h @@ -26,6 +26,7 @@ namespace android { class ICameraRecordingProxy; class Surface; +class ISurfaceTexture; struct MediaRecorderBase { MediaRecorderBase() {} @@ -54,6 +55,7 @@ struct MediaRecorderBase { virtual status_t reset() = 0; virtual status_t getMaxAmplitude(int *max) = 0; virtual status_t dump(int fd, const Vector<String16>& args) const = 0; + virtual sp<ISurfaceTexture> querySurfaceMediaSource() const = 0; private: MediaRecorderBase(const MediaRecorderBase &); diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h index af12d3c..72d3736 100644 --- a/include/media/mediarecorder.h +++ b/include/media/mediarecorder.h @@ -31,12 +31,15 @@ class Surface; class IMediaRecorder; class ICamera; class ICameraRecordingProxy; +class ISurfaceTexture; +class SurfaceTextureClient; typedef void (*media_completion_f)(status_t status, void *cookie); enum video_source { VIDEO_SOURCE_DEFAULT = 0, VIDEO_SOURCE_CAMERA = 1, + VIDEO_SOURCE_GRALLOC_BUFFER = 2, VIDEO_SOURCE_LIST_END // must be last - used to validate audio source type }; @@ -226,6 +229,7 @@ public: status_t close(); status_t release(); void notify(int msg, int ext1, int ext2); + sp<ISurfaceTexture> querySurfaceMediaSourceFromMediaServer(); private: void doCleanUp(); @@ -233,6 +237,12 @@ private: sp<IMediaRecorder> mMediaRecorder; sp<MediaRecorderListener> mListener; + + // Reference toISurfaceTexture + // for encoding GL Frames. That is useful only when the + // video source is set to VIDEO_SOURCE_GRALLOC_BUFFER + sp<ISurfaceTexture> mSurfaceMediaSource; + media_recorder_states mCurrentState; bool mIsAudioSourceSet; bool mIsVideoSourceSet; diff --git a/include/media/mediascanner.h b/include/media/mediascanner.h index 765c039..803bffb 100644 --- a/include/media/mediascanner.h +++ b/include/media/mediascanner.h @@ -23,23 +23,33 @@ #include <utils/Errors.h> #include <pthread.h> +struct dirent; + namespace android { class MediaScannerClient; class StringArray; +enum MediaScanResult { + // This file or directory was scanned successfully. + MEDIA_SCAN_RESULT_OK, + // This file or directory was skipped because it was not found, could + // not be opened, was of an unsupported type, or was malfored in some way. + MEDIA_SCAN_RESULT_SKIPPED, + // The scan should be aborted due to a fatal error such as out of memory + // or an exception. + MEDIA_SCAN_RESULT_ERROR, +}; + struct MediaScanner { MediaScanner(); virtual ~MediaScanner(); - virtual status_t processFile( - const char *path, const char *mimeType, - MediaScannerClient &client) = 0; + virtual MediaScanResult processFile( + const char *path, const char *mimeType, MediaScannerClient &client) = 0; - typedef bool (*ExceptionCheck)(void* env); - virtual status_t processDirectory( - const char *path, MediaScannerClient &client, - ExceptionCheck exceptionCheck, void *exceptionEnv); + virtual MediaScanResult processDirectory( + const char *path, MediaScannerClient &client); void setLocale(const char *locale); @@ -53,9 +63,11 @@ private: // current locale (like "ja_JP"), created/destroyed with strdup()/free() char *mLocale; - status_t doProcessDirectory( - char *path, int pathRemaining, MediaScannerClient &client, - bool noMedia, ExceptionCheck exceptionCheck, void *exceptionEnv); + MediaScanResult doProcessDirectory( + char *path, int pathRemaining, MediaScannerClient &client, bool noMedia); + MediaScanResult doProcessDirectoryEntry( + char *path, int pathRemaining, MediaScannerClient &client, bool noMedia, + struct dirent* entry, char* fileSpot); MediaScanner(const MediaScanner &); MediaScanner &operator=(const MediaScanner &); @@ -68,13 +80,13 @@ public: virtual ~MediaScannerClient(); void setLocale(const char* locale); void beginFile(); - bool addStringTag(const char* name, const char* value); + status_t addStringTag(const char* name, const char* value); void endFile(); - virtual bool scanFile(const char* path, long long lastModified, + virtual status_t scanFile(const char* path, long long lastModified, long long fileSize, bool isDirectory, bool noMedia) = 0; - virtual bool handleStringTag(const char* name, const char* value) = 0; - virtual bool setMimeType(const char* mimeType) = 0; + virtual status_t handleStringTag(const char* name, const char* value) = 0; + virtual status_t setMimeType(const char* mimeType) = 0; protected: void convertValues(uint32_t encoding); diff --git a/include/media/stagefright/DataSource.h b/include/media/stagefright/DataSource.h index 48d1464..713af92 100644 --- a/include/media/stagefright/DataSource.h +++ b/include/media/stagefright/DataSource.h @@ -20,6 +20,7 @@ #include <sys/types.h> +#include <media/stagefright/MediaErrors.h> #include <utils/Errors.h> #include <utils/KeyedVector.h> #include <utils/List.h> @@ -61,6 +62,10 @@ public: return 0; } + virtual status_t reconnectAtOffset(off64_t offset) { + return ERROR_UNSUPPORTED; + } + //////////////////////////////////////////////////////////////////////////// bool sniff(String8 *mimeType, float *confidence, sp<AMessage> *meta); diff --git a/include/media/stagefright/HardwareAPI.h b/include/media/stagefright/HardwareAPI.h index 946a0aa..32eed3f 100644 --- a/include/media/stagefright/HardwareAPI.h +++ b/include/media/stagefright/HardwareAPI.h @@ -99,6 +99,13 @@ struct GetAndroidNativeBufferUsageParams { OMX_U32 nUsage; // OUT }; +// An enum OMX_COLOR_FormatAndroidOpaque to indicate an opaque colorformat +// is declared in media/stagefright/openmax/OMX_IVCommon.h +// This will inform the encoder that the actual +// colorformat will be relayed by the GRalloc Buffers. +// OMX_COLOR_FormatAndroidOpaque = 0x7F000001, + + } // namespace android extern android::OMXPluginBase *createOMXPlugin(); diff --git a/include/media/stagefright/MediaSource.h b/include/media/stagefright/MediaSource.h index 37dbcd8..3818e63 100644 --- a/include/media/stagefright/MediaSource.h +++ b/include/media/stagefright/MediaSource.h @@ -29,7 +29,7 @@ namespace android { class MediaBuffer; class MetaData; -struct MediaSource : public RefBase { +struct MediaSource : public virtual RefBase { MediaSource(); // To be called before any other methods on this object, except diff --git a/include/media/stagefright/StagefrightMediaScanner.h b/include/media/stagefright/StagefrightMediaScanner.h index 108acb4..6510a59 100644 --- a/include/media/stagefright/StagefrightMediaScanner.h +++ b/include/media/stagefright/StagefrightMediaScanner.h @@ -26,7 +26,7 @@ struct StagefrightMediaScanner : public MediaScanner { StagefrightMediaScanner(); virtual ~StagefrightMediaScanner(); - virtual status_t processFile( + virtual MediaScanResult processFile( const char *path, const char *mimeType, MediaScannerClient &client); @@ -35,6 +35,10 @@ struct StagefrightMediaScanner : public MediaScanner { private: StagefrightMediaScanner(const StagefrightMediaScanner &); StagefrightMediaScanner &operator=(const StagefrightMediaScanner &); + + MediaScanResult processFileInternal( + const char *path, const char *mimeType, + MediaScannerClient &client); }; } // namespace android diff --git a/include/media/stagefright/SurfaceMediaSource.h b/include/media/stagefright/SurfaceMediaSource.h new file mode 100644 index 0000000..56bd9c3 --- /dev/null +++ b/include/media/stagefright/SurfaceMediaSource.h @@ -0,0 +1,350 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_GUI_SURFACEMEDIASOURCE_H +#define ANDROID_GUI_SURFACEMEDIASOURCE_H + +#include <gui/ISurfaceTexture.h> + +#include <utils/threads.h> +#include <utils/Vector.h> +#include <media/stagefright/MediaSource.h> +#include <media/stagefright/MediaBuffer.h> + +namespace android { +// ---------------------------------------------------------------------------- + +class IGraphicBufferAlloc; +class String8; +class GraphicBuffer; + +class SurfaceMediaSource : public BnSurfaceTexture, public MediaSource, + public MediaBufferObserver { +public: + enum { MIN_UNDEQUEUED_BUFFERS = 3 }; + enum { + MIN_ASYNC_BUFFER_SLOTS = MIN_UNDEQUEUED_BUFFERS + 1, + MIN_SYNC_BUFFER_SLOTS = MIN_UNDEQUEUED_BUFFERS + }; + enum { NUM_BUFFER_SLOTS = 32 }; + enum { NO_CONNECTED_API = 0 }; + + struct FrameAvailableListener : public virtual RefBase { + // onFrameAvailable() is called from queueBuffer() is the FIFO is + // empty. You can use SurfaceMediaSource::getQueuedCount() to + // figure out if there are more frames waiting. + // This is called without any lock held can be called concurrently by + // multiple threads. + virtual void onFrameAvailable() = 0; + }; + + SurfaceMediaSource(uint32_t bufW, uint32_t bufH); + + virtual ~SurfaceMediaSource(); + + + // For the MediaSource interface for use by StageFrightRecorder: + virtual status_t start(MetaData *params = NULL); + virtual status_t stop(); + virtual status_t read( + MediaBuffer **buffer, const ReadOptions *options = NULL); + virtual sp<MetaData> getFormat(); + + // Get / Set the frame rate used for encoding. Default fps = 30 + status_t setFrameRate(int32_t fps) ; + int32_t getFrameRate( ) const; + + // The call for the StageFrightRecorder to tell us that + // it is done using the MediaBuffer data so that its state + // can be set to FREE for dequeuing + virtual void signalBufferReturned(MediaBuffer* buffer); + // end of MediaSource interface + + uint32_t getBufferCount( ) const { return mBufferCount;} + + + // setBufferCount updates the number of available buffer slots. After + // calling this all buffer slots are both unallocated and owned by the + // SurfaceMediaSource object (i.e. they are not owned by the client). + virtual status_t setBufferCount(int bufferCount); + + virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf); + + // dequeueBuffer gets the next buffer slot index for the client to use. If a + // buffer slot is available then that slot index is written to the location + // pointed to by the buf argument and a status of OK is returned. If no + // slot is available then a status of -EBUSY is returned and buf is + // unmodified. + virtual status_t dequeueBuffer(int *buf, uint32_t w, uint32_t h, + uint32_t format, uint32_t usage); + + // queueBuffer returns a filled buffer to the SurfaceMediaSource. In addition, a + // timestamp must be provided for the buffer. The timestamp is in + // nanoseconds, and must be monotonically increasing. Its other semantics + // (zero point, etc) are client-dependent and should be documented by the + // client. + virtual status_t queueBuffer(int buf, int64_t timestamp, + uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform); + virtual void cancelBuffer(int buf); + + // onFrameReceivedLocked informs the buffer consumers (StageFrightRecorder) + // or listeners that a frame has been received + // The buffer is not made available for dequeueing immediately. We need to + // wait to hear from StageFrightRecorder to set the buffer FREE + // Make sure this is called when the mutex is locked + virtual status_t onFrameReceivedLocked(); + + virtual status_t setScalingMode(int mode) { } // no op for encoding + virtual int query(int what, int* value); + + // Just confirming to the ISurfaceTexture interface as of now + virtual status_t setCrop(const Rect& reg) { return OK; } + virtual status_t setTransform(uint32_t transform) {return OK;} + + // setSynchronousMode set whether dequeueBuffer is synchronous or + // asynchronous. In synchronous mode, dequeueBuffer blocks until + // a buffer is available, the currently bound buffer can be dequeued and + // queued buffers will be retired in order. + // The default mode is synchronous. + // TODO: Clarify the minute differences bet sycn /async + // modes (S.Encoder vis-a-vis SurfaceTexture) + virtual status_t setSynchronousMode(bool enabled); + + // connect attempts to connect a client API to the SurfaceMediaSource. This + // must be called before any other ISurfaceTexture methods are called except + // for getAllocator. + // + // This method will fail if the connect was previously called on the + // SurfaceMediaSource and no corresponding disconnect call was made. + virtual status_t connect(int api); + + // disconnect attempts to disconnect a client API from the SurfaceMediaSource. + // Calling this method will cause any subsequent calls to other + // ISurfaceTexture methods to fail except for getAllocator and connect. + // Successfully calling connect after this will allow the other methods to + // succeed again. + // + // This method will fail if the the SurfaceMediaSource is not currently + // connected to the specified client API. + virtual status_t disconnect(int api); + + // getqueuedCount returns the number of queued frames waiting in the + // FIFO. In asynchronous mode, this always returns 0 or 1 since + // frames are not accumulating in the FIFO. + size_t getQueuedCount() const; + + // setBufferCountServer set the buffer count. If the client has requested + // a buffer count using setBufferCount, the server-buffer count will + // take effect once the client sets the count back to zero. + status_t setBufferCountServer(int bufferCount); + + // getTimestamp retrieves the timestamp associated with the image + // set by the most recent call to updateFrameInfoLocked(). + // + // The timestamp is in nanoseconds, and is monotonically increasing. Its + // other semantics (zero point, etc) are source-dependent and should be + // documented by the source. + int64_t getTimestamp(); + + // setFrameAvailableListener sets the listener object that will be notified + // when a new frame becomes available. + void setFrameAvailableListener(const sp<FrameAvailableListener>& listener); + + // getCurrentBuffer returns the buffer associated with the current image. + sp<GraphicBuffer> getCurrentBuffer() const; + + // dump our state in a String + void dump(String8& result) const; + void dump(String8& result, const char* prefix, char* buffer, + size_t SIZE) const; + + // isMetaDataStoredInVideoBuffers tells the encoder whether we will + // pass metadata through the buffers. Currently, it is force set to true + bool isMetaDataStoredInVideoBuffers() const; + +protected: + + // freeAllBuffers frees the resources (both GraphicBuffer and EGLImage) for + // all slots. + void freeAllBuffers(); + static bool isExternalFormat(uint32_t format); + +private: + + status_t setBufferCountServerLocked(int bufferCount); + + enum { INVALID_BUFFER_SLOT = -1 }; + + struct BufferSlot { + + BufferSlot() + : mBufferState(BufferSlot::FREE), + mRequestBufferCalled(false), + mTimestamp(0) { + } + + // mGraphicBuffer points to the buffer allocated for this slot or is + // NULL if no buffer has been allocated. + sp<GraphicBuffer> mGraphicBuffer; + + // BufferState represents the different states in which a buffer slot + // can be. + enum BufferState { + // FREE indicates that the buffer is not currently being used and + // will not be used in the future until it gets dequeued and + // subseqently queued by the client. + FREE = 0, + + // DEQUEUED indicates that the buffer has been dequeued by the + // client, but has not yet been queued or canceled. The buffer is + // considered 'owned' by the client, and the server should not use + // it for anything. + // + // Note that when in synchronous-mode (mSynchronousMode == true), + // the buffer that's currently attached to the texture may be + // dequeued by the client. That means that the current buffer can + // be in either the DEQUEUED or QUEUED state. In asynchronous mode, + // however, the current buffer is always in the QUEUED state. + DEQUEUED = 1, + + // QUEUED indicates that the buffer has been queued by the client, + // and has not since been made available for the client to dequeue. + // Attaching the buffer to the texture does NOT transition the + // buffer away from the QUEUED state. However, in Synchronous mode + // the current buffer may be dequeued by the client under some + // circumstances. See the note about the current buffer in the + // documentation for DEQUEUED. + QUEUED = 2, + }; + + // mBufferState is the current state of this buffer slot. + BufferState mBufferState; + + // mRequestBufferCalled is used for validating that the client did + // call requestBuffer() when told to do so. Technically this is not + // needed but useful for debugging and catching client bugs. + bool mRequestBufferCalled; + + // mTimestamp is the current timestamp for this buffer slot. This gets + // to set by queueBuffer each time this slot is queued. + int64_t mTimestamp; + }; + + // mSlots is the array of buffer slots that must be mirrored on the client + // side. This allows buffer ownership to be transferred between the client + // and server without sending a GraphicBuffer over binder. The entire array + // is initialized to NULL at construction time, and buffers are allocated + // for a slot when requestBuffer is called with that slot's index. + BufferSlot mSlots[NUM_BUFFER_SLOTS]; + + // mDefaultWidth holds the default width of allocated buffers. It is used + // in requestBuffers() if a width and height of zero is specified. + uint32_t mDefaultWidth; + + // mDefaultHeight holds the default height of allocated buffers. It is used + // in requestBuffers() if a width and height of zero is specified. + uint32_t mDefaultHeight; + + // mPixelFormat holds the pixel format of allocated buffers. It is used + // in requestBuffers() if a format of zero is specified. + uint32_t mPixelFormat; + + // mBufferCount is the number of buffer slots that the client and server + // must maintain. It defaults to MIN_ASYNC_BUFFER_SLOTS and can be changed + // by calling setBufferCount or setBufferCountServer + int mBufferCount; + + // mClientBufferCount is the number of buffer slots requested by the + // client. The default is zero, which means the client doesn't care how + // many buffers there are + int mClientBufferCount; + + // mServerBufferCount buffer count requested by the server-side + int mServerBufferCount; + + // mCurrentSlot is the buffer slot index of the buffer that is currently + // being used by buffer consumer + // (e.g. StageFrightRecorder in the case of SurfaceMediaSource or GLTexture + // in the case of SurfaceTexture). + // It is initialized to INVALID_BUFFER_SLOT, + // indicating that no buffer slot is currently bound to the texture. Note, + // however, that a value of INVALID_BUFFER_SLOT does not necessarily mean + // that no buffer is bound to the texture. A call to setBufferCount will + // reset mCurrentTexture to INVALID_BUFFER_SLOT. + int mCurrentSlot; + + + // mCurrentBuf is the graphic buffer of the current slot to be used by + // buffer consumer. It's possible that this buffer is not associated + // with any buffer slot, so we must track it separately in order to + // properly use IGraphicBufferAlloc::freeAllGraphicBuffersExcept. + sp<GraphicBuffer> mCurrentBuf; + + + // mCurrentTimestamp is the timestamp for the current texture. It + // gets set to mLastQueuedTimestamp each time updateTexImage is called. + int64_t mCurrentTimestamp; + + // mGraphicBufferAlloc is the connection to SurfaceFlinger that is used to + // allocate new GraphicBuffer objects. + sp<IGraphicBufferAlloc> mGraphicBufferAlloc; + + // mFrameAvailableListener is the listener object that will be called when a + // new frame becomes available. If it is not NULL it will be called from + // queueBuffer. + sp<FrameAvailableListener> mFrameAvailableListener; + + // mSynchronousMode whether we're in synchronous mode or not + bool mSynchronousMode; + + // mConnectedApi indicates the API that is currently connected to this + // SurfaceTexture. It defaults to NO_CONNECTED_API (= 0), and gets updated + // by the connect and disconnect methods. + int mConnectedApi; + + // mDequeueCondition condition used for dequeueBuffer in synchronous mode + mutable Condition mDequeueCondition; + + + // mQueue is a FIFO of queued buffers used in synchronous mode + typedef Vector<int> Fifo; + Fifo mQueue; + + // mMutex is the mutex used to prevent concurrent access to the member + // variables of SurfaceMediaSource objects. It must be locked whenever the + // member variables are accessed. + mutable Mutex mMutex; + + ////////////////////////// For MediaSource + // Set to a default of 30 fps if not specified by the client side + int32_t mFrameRate; + + // mStarted is a flag to check if the recording has started + bool mStarted; + + // mFrameAvailableCondition condition used to indicate whether there + // is a frame available for dequeuing + Condition mFrameAvailableCondition; + Condition mFrameCompleteCondition; + + // Avoid copying and equating and default constructor + DISALLOW_IMPLICIT_CONSTRUCTORS(SurfaceMediaSource); +}; + +// ---------------------------------------------------------------------------- +}; // namespace android + +#endif // ANDROID_GUI_SURFACEMEDIASOURCE_H diff --git a/include/media/stagefright/openmax/OMX_IVCommon.h b/include/media/stagefright/openmax/OMX_IVCommon.h index 7ed072b..97170d7 100644 --- a/include/media/stagefright/openmax/OMX_IVCommon.h +++ b/include/media/stagefright/openmax/OMX_IVCommon.h @@ -16,29 +16,29 @@ * ------------------------------------------------------------------- */ /** - * Copyright (c) 2008 The Khronos Group Inc. - * + * Copyright (c) 2008 The Khronos Group Inc. + * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject - * to the following conditions: + * to the following conditions: * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * + * in all copies or substantial portions of the Software. + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ -/** +/** * @file OMX_IVCommon.h - OpenMax IL version 1.1.2 * The structures needed by Video and Image components to exchange * parameters and configuration data with the components. @@ -53,7 +53,7 @@ extern "C" { /** * Each OMX header must include all required header files to allow the header * to compile without errors. The includes below are required for this header - * file to compile successfully + * file to compile successfully */ #include <OMX_Core.h> @@ -64,8 +64,8 @@ extern "C" { */ -/** - * Enumeration defining possible uncompressed image/video formats. +/** + * Enumeration defining possible uncompressed image/video formats. * * ENUMS: * Unused : Placeholder value when format is N/A @@ -113,7 +113,7 @@ typedef enum OMX_COLOR_FORMATTYPE { OMX_COLOR_Format16bitBGR565, OMX_COLOR_Format18bitRGB666, OMX_COLOR_Format18bitARGB1665, - OMX_COLOR_Format19bitARGB1666, + OMX_COLOR_Format19bitARGB1666, OMX_COLOR_Format24bitRGB888, OMX_COLOR_Format24bitBGR888, OMX_COLOR_Format24bitARGB1887, @@ -136,55 +136,62 @@ typedef enum OMX_COLOR_FORMATTYPE { OMX_COLOR_FormatRawBayer8bit, OMX_COLOR_FormatRawBayer10bit, OMX_COLOR_FormatRawBayer8bitcompressed, - OMX_COLOR_FormatL2, - OMX_COLOR_FormatL4, - OMX_COLOR_FormatL8, - OMX_COLOR_FormatL16, - OMX_COLOR_FormatL24, + OMX_COLOR_FormatL2, + OMX_COLOR_FormatL4, + OMX_COLOR_FormatL8, + OMX_COLOR_FormatL16, + OMX_COLOR_FormatL24, OMX_COLOR_FormatL32, OMX_COLOR_FormatYUV420PackedSemiPlanar, OMX_COLOR_FormatYUV422PackedSemiPlanar, OMX_COLOR_Format18BitBGR666, OMX_COLOR_Format24BitARGB6666, OMX_COLOR_Format24BitABGR6666, - OMX_COLOR_FormatKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_COLOR_FormatKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ OMX_COLOR_FormatVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + /**<Reserved android opaque colorformat. Tells the encoder that + * the actual colorformat will be relayed by the + * Gralloc Buffers. + * FIXME: In the process of reserving some enum values for + * Android-specific OMX IL colorformats. Change this enum to + * an acceptable range once that is done.*/ + OMX_COLOR_FormatAndroidOpaque = 0x7F000001, OMX_TI_COLOR_FormatYUV420PackedSemiPlanar = 0x7F000100, OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00, OMX_COLOR_FormatMax = 0x7FFFFFFF } OMX_COLOR_FORMATTYPE; -/** +/** * Defines the matrix for conversion from RGB to YUV or vice versa. - * iColorMatrix should be initialized with the fixed point values + * iColorMatrix should be initialized with the fixed point values * used in converting between formats. */ typedef struct OMX_CONFIG_COLORCONVERSIONTYPE { OMX_U32 nSize; /**< Size of the structure in bytes */ - OMX_VERSIONTYPE nVersion; /**< OMX specification version info */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version info */ OMX_U32 nPortIndex; /**< Port that this struct applies to */ OMX_S32 xColorMatrix[3][3]; /**< Stored in signed Q16 format */ OMX_S32 xColorOffset[4]; /**< Stored in signed Q16 format */ }OMX_CONFIG_COLORCONVERSIONTYPE; -/** - * Structure defining percent to scale each frame dimension. For example: +/** + * Structure defining percent to scale each frame dimension. For example: * To make the width 50% larger, use fWidth = 1.5 and to make the width * 1/2 the original size, use fWidth = 0.5 */ typedef struct OMX_CONFIG_SCALEFACTORTYPE { OMX_U32 nSize; /**< Size of the structure in bytes */ - OMX_VERSIONTYPE nVersion; /**< OMX specification version info */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version info */ OMX_U32 nPortIndex; /**< Port that this struct applies to */ OMX_S32 xWidth; /**< Fixed point value stored as Q16 */ OMX_S32 xHeight; /**< Fixed point value stored as Q16 */ }OMX_CONFIG_SCALEFACTORTYPE; -/** - * Enumeration of possible image filter types +/** + * Enumeration of possible image filter types */ typedef enum OMX_IMAGEFILTERTYPE { OMX_ImageFilterNone, @@ -195,23 +202,23 @@ typedef enum OMX_IMAGEFILTERTYPE { OMX_ImageFilterOilPaint, OMX_ImageFilterHatch, OMX_ImageFilterGpen, - OMX_ImageFilterAntialias, - OMX_ImageFilterDeRing, + OMX_ImageFilterAntialias, + OMX_ImageFilterDeRing, OMX_ImageFilterSolarize, - OMX_ImageFilterKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_ImageFilterKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ OMX_ImageFilterVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ OMX_ImageFilterMax = 0x7FFFFFFF } OMX_IMAGEFILTERTYPE; -/** - * Image filter configuration +/** + * Image filter configuration * * STRUCT MEMBERS: - * nSize : Size of the structure in bytes + * nSize : Size of the structure in bytes * nVersion : OMX specification version information - * nPortIndex : Port that this structure applies to - * eImageFilter : Image filter type enumeration + * nPortIndex : Port that this structure applies to + * eImageFilter : Image filter type enumeration */ typedef struct OMX_CONFIG_IMAGEFILTERTYPE { OMX_U32 nSize; @@ -221,22 +228,22 @@ typedef struct OMX_CONFIG_IMAGEFILTERTYPE { } OMX_CONFIG_IMAGEFILTERTYPE; -/** - * Customized U and V for color enhancement +/** + * Customized U and V for color enhancement * * STRUCT MEMBERS: * nSize : Size of the structure in bytes - * nVersion : OMX specification version information + * nVersion : OMX specification version information * nPortIndex : Port that this structure applies to * bColorEnhancement : Enable/disable color enhancement - * nCustomizedU : Practical values: 16-240, range: 0-255, value set for + * nCustomizedU : Practical values: 16-240, range: 0-255, value set for * U component - * nCustomizedV : Practical values: 16-240, range: 0-255, value set for + * nCustomizedV : Practical values: 16-240, range: 0-255, value set for * V component */ typedef struct OMX_CONFIG_COLORENHANCEMENTTYPE { OMX_U32 nSize; - OMX_VERSIONTYPE nVersion; + OMX_VERSIONTYPE nVersion; OMX_U32 nPortIndex; OMX_BOOL bColorEnhancement; OMX_U8 nCustomizedU; @@ -244,12 +251,12 @@ typedef struct OMX_CONFIG_COLORENHANCEMENTTYPE { } OMX_CONFIG_COLORENHANCEMENTTYPE; -/** - * Define color key and color key mask +/** + * Define color key and color key mask * * STRUCT MEMBERS: * nSize : Size of the structure in bytes - * nVersion : OMX specification version information + * nVersion : OMX specification version information * nPortIndex : Port that this structure applies to * nARGBColor : 32bit Alpha, Red, Green, Blue Color * nARGBMask : 32bit Mask for Alpha, Red, Green, Blue channels @@ -263,12 +270,12 @@ typedef struct OMX_CONFIG_COLORKEYTYPE { } OMX_CONFIG_COLORKEYTYPE; -/** - * List of color blend types for pre/post processing +/** + * List of color blend types for pre/post processing * * ENUMS: * None : No color blending present - * AlphaConstant : Function is (alpha_constant * src) + + * AlphaConstant : Function is (alpha_constant * src) + * (1 - alpha_constant) * dst) * AlphaPerPixel : Function is (alpha * src) + (1 - alpha) * dst) * Alternate : Function is alternating pixels from src and dst @@ -284,21 +291,21 @@ typedef enum OMX_COLORBLENDTYPE { OMX_ColorBlendAnd, OMX_ColorBlendOr, OMX_ColorBlendInvert, - OMX_ColorBlendKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_ColorBlendKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ OMX_ColorBlendVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ OMX_ColorBlendMax = 0x7FFFFFFF } OMX_COLORBLENDTYPE; -/** - * Color blend configuration +/** + * Color blend configuration * * STRUCT MEMBERS: - * nSize : Size of the structure in bytes - * nVersion : OMX specification version information - * nPortIndex : Port that this structure applies to + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to * nRGBAlphaConstant : Constant global alpha values when global alpha is used - * eColorBlend : Color blend type enumeration + * eColorBlend : Color blend type enumeration */ typedef struct OMX_CONFIG_COLORBLENDTYPE { OMX_U32 nSize; @@ -309,15 +316,15 @@ typedef struct OMX_CONFIG_COLORBLENDTYPE { } OMX_CONFIG_COLORBLENDTYPE; -/** +/** * Hold frame dimension * * STRUCT MEMBERS: - * nSize : Size of the structure in bytes + * nSize : Size of the structure in bytes * nVersion : OMX specification version information - * nPortIndex : Port that this structure applies to - * nWidth : Frame width in pixels - * nHeight : Frame height in pixels + * nPortIndex : Port that this structure applies to + * nWidth : Frame width in pixels + * nHeight : Frame height in pixels */ typedef struct OMX_FRAMESIZETYPE { OMX_U32 nSize; @@ -329,69 +336,69 @@ typedef struct OMX_FRAMESIZETYPE { /** - * Rotation configuration + * Rotation configuration * * STRUCT MEMBERS: - * nSize : Size of the structure in bytes + * nSize : Size of the structure in bytes * nVersion : OMX specification version information * nPortIndex : Port that this structure applies to - * nRotation : +/- integer rotation value + * nRotation : +/- integer rotation value */ typedef struct OMX_CONFIG_ROTATIONTYPE { OMX_U32 nSize; OMX_VERSIONTYPE nVersion; OMX_U32 nPortIndex; - OMX_S32 nRotation; + OMX_S32 nRotation; } OMX_CONFIG_ROTATIONTYPE; -/** - * Possible mirroring directions for pre/post processing +/** + * Possible mirroring directions for pre/post processing * * ENUMS: - * None : No mirroring - * Vertical : Vertical mirroring, flip on X axis - * Horizontal : Horizontal mirroring, flip on Y axis + * None : No mirroring + * Vertical : Vertical mirroring, flip on X axis + * Horizontal : Horizontal mirroring, flip on Y axis * Both : Both vertical and horizontal mirroring */ typedef enum OMX_MIRRORTYPE { OMX_MirrorNone = 0, OMX_MirrorVertical, OMX_MirrorHorizontal, - OMX_MirrorBoth, - OMX_MirrorKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_MirrorBoth, + OMX_MirrorKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ OMX_MirrorVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ - OMX_MirrorMax = 0x7FFFFFFF + OMX_MirrorMax = 0x7FFFFFFF } OMX_MIRRORTYPE; -/** - * Mirroring configuration +/** + * Mirroring configuration * * STRUCT MEMBERS: - * nSize : Size of the structure in bytes + * nSize : Size of the structure in bytes * nVersion : OMX specification version information - * nPortIndex : Port that this structure applies to - * eMirror : Mirror type enumeration + * nPortIndex : Port that this structure applies to + * eMirror : Mirror type enumeration */ typedef struct OMX_CONFIG_MIRRORTYPE { OMX_U32 nSize; - OMX_VERSIONTYPE nVersion; + OMX_VERSIONTYPE nVersion; OMX_U32 nPortIndex; OMX_MIRRORTYPE eMirror; } OMX_CONFIG_MIRRORTYPE; -/** - * Position information only +/** + * Position information only * * STRUCT MEMBERS: - * nSize : Size of the structure in bytes + * nSize : Size of the structure in bytes * nVersion : OMX specification version information * nPortIndex : Port that this structure applies to - * nX : X coordinate for the point - * nY : Y coordinate for the point - */ + * nX : X coordinate for the point + * nY : Y coordinate for the point + */ typedef struct OMX_CONFIG_POINTTYPE { OMX_U32 nSize; OMX_VERSIONTYPE nVersion; @@ -401,37 +408,37 @@ typedef struct OMX_CONFIG_POINTTYPE { } OMX_CONFIG_POINTTYPE; -/** - * Frame size plus position +/** + * Frame size plus position * * STRUCT MEMBERS: - * nSize : Size of the structure in bytes - * nVersion : OMX specification version information - * nPortIndex : Port that this structure applies to + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to * nLeft : X Coordinate of the top left corner of the rectangle * nTop : Y Coordinate of the top left corner of the rectangle - * nWidth : Width of the rectangle - * nHeight : Height of the rectangle + * nWidth : Width of the rectangle + * nHeight : Height of the rectangle */ typedef struct OMX_CONFIG_RECTTYPE { OMX_U32 nSize; - OMX_VERSIONTYPE nVersion; - OMX_U32 nPortIndex; - OMX_S32 nLeft; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_S32 nLeft; OMX_S32 nTop; OMX_U32 nWidth; OMX_U32 nHeight; } OMX_CONFIG_RECTTYPE; -/** - * Deblocking state; it is required to be set up before starting the codec +/** + * Deblocking state; it is required to be set up before starting the codec * * STRUCT MEMBERS: - * nSize : Size of the structure in bytes - * nVersion : OMX specification version information + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information * nPortIndex : Port that this structure applies to - * bDeblocking : Enable/disable deblocking mode + * bDeblocking : Enable/disable deblocking mode */ typedef struct OMX_PARAM_DEBLOCKINGTYPE { OMX_U32 nSize; @@ -441,13 +448,13 @@ typedef struct OMX_PARAM_DEBLOCKINGTYPE { } OMX_PARAM_DEBLOCKINGTYPE; -/** - * Stabilization state +/** + * Stabilization state * * STRUCT MEMBERS: - * nSize : Size of the structure in bytes - * nVersion : OMX specification version information - * nPortIndex : Port that this structure applies to + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to * bStab : Enable/disable frame stabilization state */ typedef struct OMX_CONFIG_FRAMESTABTYPE { @@ -458,8 +465,8 @@ typedef struct OMX_CONFIG_FRAMESTABTYPE { } OMX_CONFIG_FRAMESTABTYPE; -/** - * White Balance control type +/** + * White Balance control type * * STRUCT MEMBERS: * SunLight : Referenced in JSR-234 @@ -476,20 +483,20 @@ typedef enum OMX_WHITEBALCONTROLTYPE { OMX_WhiteBalControlIncandescent, OMX_WhiteBalControlFlash, OMX_WhiteBalControlHorizon, - OMX_WhiteBalControlKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_WhiteBalControlKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ OMX_WhiteBalControlVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ OMX_WhiteBalControlMax = 0x7FFFFFFF } OMX_WHITEBALCONTROLTYPE; -/** - * White Balance control configuration +/** + * White Balance control configuration * * STRUCT MEMBERS: - * nSize : Size of the structure in bytes + * nSize : Size of the structure in bytes * nVersion : OMX specification version information - * nPortIndex : Port that this structure applies to - * eWhiteBalControl : White balance enumeration + * nPortIndex : Port that this structure applies to + * eWhiteBalControl : White balance enumeration */ typedef struct OMX_CONFIG_WHITEBALCONTROLTYPE { OMX_U32 nSize; @@ -499,8 +506,8 @@ typedef struct OMX_CONFIG_WHITEBALCONTROLTYPE { } OMX_CONFIG_WHITEBALCONTROLTYPE; -/** - * Exposure control type +/** + * Exposure control type */ typedef enum OMX_EXPOSURECONTROLTYPE { OMX_ExposureControlOff = 0, @@ -513,20 +520,20 @@ typedef enum OMX_EXPOSURECONTROLTYPE { OMX_ExposureControlBeach, OMX_ExposureControlLargeAperture, OMX_ExposureControlSmallApperture, - OMX_ExposureControlKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_ExposureControlKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ OMX_ExposureControlVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ OMX_ExposureControlMax = 0x7FFFFFFF } OMX_EXPOSURECONTROLTYPE; -/** - * White Balance control configuration +/** + * White Balance control configuration * * STRUCT MEMBERS: - * nSize : Size of the structure in bytes + * nSize : Size of the structure in bytes * nVersion : OMX specification version information - * nPortIndex : Port that this structure applies to - * eExposureControl : Exposure control enumeration + * nPortIndex : Port that this structure applies to + * eExposureControl : Exposure control enumeration */ typedef struct OMX_CONFIG_EXPOSURECONTROLTYPE { OMX_U32 nSize; @@ -536,16 +543,16 @@ typedef struct OMX_CONFIG_EXPOSURECONTROLTYPE { } OMX_CONFIG_EXPOSURECONTROLTYPE; -/** - * Defines sensor supported mode. +/** + * Defines sensor supported mode. * * STRUCT MEMBERS: - * nSize : Size of the structure in bytes + * nSize : Size of the structure in bytes * nVersion : OMX specification version information - * nPortIndex : Port that this structure applies to - * nFrameRate : Single shot mode is indicated by a 0 + * nPortIndex : Port that this structure applies to + * nFrameRate : Single shot mode is indicated by a 0 * bOneShot : Enable for single shot, disable for streaming - * sFrameSize : Framesize + * sFrameSize : Framesize */ typedef struct OMX_PARAM_SENSORMODETYPE { OMX_U32 nSize; @@ -557,13 +564,13 @@ typedef struct OMX_PARAM_SENSORMODETYPE { } OMX_PARAM_SENSORMODETYPE; -/** - * Defines contrast level +/** + * Defines contrast level * * STRUCT MEMBERS: - * nSize : Size of the structure in bytes - * nVersion : OMX specification version information - * nPortIndex : Port that this structure applies to + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to * nContrast : Values allowed for contrast -100 to 100, zero means no change */ typedef struct OMX_CONFIG_CONTRASTTYPE { @@ -574,14 +581,14 @@ typedef struct OMX_CONFIG_CONTRASTTYPE { } OMX_CONFIG_CONTRASTTYPE; -/** - * Defines brightness level +/** + * Defines brightness level * * STRUCT MEMBERS: - * nSize : Size of the structure in bytes - * nVersion : OMX specification version information - * nPortIndex : Port that this structure applies to - * nBrightness : 0-100% + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nBrightness : 0-100% */ typedef struct OMX_CONFIG_BRIGHTNESSTYPE { OMX_U32 nSize; @@ -591,16 +598,16 @@ typedef struct OMX_CONFIG_BRIGHTNESSTYPE { } OMX_CONFIG_BRIGHTNESSTYPE; -/** - * Defines backlight level configuration for a video sink, e.g. LCD panel +/** + * Defines backlight level configuration for a video sink, e.g. LCD panel * * STRUCT MEMBERS: * nSize : Size of the structure in bytes - * nVersion : OMX specification version information + * nVersion : OMX specification version information * nPortIndex : Port that this structure applies to * nBacklight : Values allowed for backlight 0-100% - * nTimeout : Number of milliseconds before backlight automatically turns - * off. A value of 0x0 disables backight timeout + * nTimeout : Number of milliseconds before backlight automatically turns + * off. A value of 0x0 disables backight timeout */ typedef struct OMX_CONFIG_BACKLIGHTTYPE { OMX_U32 nSize; @@ -611,12 +618,12 @@ typedef struct OMX_CONFIG_BACKLIGHTTYPE { } OMX_CONFIG_BACKLIGHTTYPE; -/** - * Defines setting for Gamma +/** + * Defines setting for Gamma * * STRUCT MEMBERS: * nSize : Size of the structure in bytes - * nVersion : OMX specification version information + * nVersion : OMX specification version information * nPortIndex : Port that this structure applies to * nGamma : Values allowed for gamma -100 to 100, zero means no change */ @@ -628,14 +635,14 @@ typedef struct OMX_CONFIG_GAMMATYPE { } OMX_CONFIG_GAMMATYPE; -/** - * Define for setting saturation - * +/** + * Define for setting saturation + * * STRUCT MEMBERS: * nSize : Size of the structure in bytes * nVersion : OMX specification version information * nPortIndex : Port that this structure applies to - * nSaturation : Values allowed for saturation -100 to 100, zero means + * nSaturation : Values allowed for saturation -100 to 100, zero means * no change */ typedef struct OMX_CONFIG_SATURATIONTYPE { @@ -646,14 +653,14 @@ typedef struct OMX_CONFIG_SATURATIONTYPE { } OMX_CONFIG_SATURATIONTYPE; -/** - * Define for setting Lightness +/** + * Define for setting Lightness * * STRUCT MEMBERS: * nSize : Size of the structure in bytes * nVersion : OMX specification version information * nPortIndex : Port that this structure applies to - * nLightness : Values allowed for lightness -100 to 100, zero means no + * nLightness : Values allowed for lightness -100 to 100, zero means no * change */ typedef struct OMX_CONFIG_LIGHTNESSTYPE { @@ -664,17 +671,17 @@ typedef struct OMX_CONFIG_LIGHTNESSTYPE { } OMX_CONFIG_LIGHTNESSTYPE; -/** - * Plane blend configuration +/** + * Plane blend configuration * * STRUCT MEMBERS: - * nSize : Size of the structure in bytes + * nSize : Size of the structure in bytes * nVersion : OMX specification version information * nPortIndex : Index of input port associated with the plane. - * nDepth : Depth of the plane in relation to the screen. Higher - * numbered depths are "behind" lower number depths. + * nDepth : Depth of the plane in relation to the screen. Higher + * numbered depths are "behind" lower number depths. * This number defaults to the Port Index number. - * nAlpha : Transparency blending component for the entire plane. + * nAlpha : Transparency blending component for the entire plane. * See blending modes for more detail. */ typedef struct OMX_CONFIG_PLANEBLENDTYPE { @@ -686,17 +693,17 @@ typedef struct OMX_CONFIG_PLANEBLENDTYPE { } OMX_CONFIG_PLANEBLENDTYPE; -/** +/** * Define interlace type * * STRUCT MEMBERS: - * nSize : Size of the structure in bytes - * nVersion : OMX specification version information + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information * nPortIndex : Port that this structure applies to - * bEnable : Enable control variable for this functionality + * bEnable : Enable control variable for this functionality * (see below) - * nInterleavePortIndex : Index of input or output port associated with - * the interleaved plane. + * nInterleavePortIndex : Index of input or output port associated with + * the interleaved plane. * pPlanarPortIndexes[4] : Index of input or output planar ports. */ typedef struct OMX_PARAM_INTERLEAVETYPE { @@ -708,8 +715,8 @@ typedef struct OMX_PARAM_INTERLEAVETYPE { } OMX_PARAM_INTERLEAVETYPE; -/** - * Defines the picture effect used for an input picture +/** + * Defines the picture effect used for an input picture */ typedef enum OMX_TRANSITIONEFFECTTYPE { OMX_EffectNone, @@ -719,18 +726,18 @@ typedef enum OMX_TRANSITIONEFFECTTYPE { OMX_EffectDissolve, OMX_EffectWipe, OMX_EffectUnspecifiedMixOfTwoScenes, - OMX_EffectKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_EffectKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ OMX_EffectVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ OMX_EffectMax = 0x7FFFFFFF } OMX_TRANSITIONEFFECTTYPE; -/** - * Structure used to configure current transition effect +/** + * Structure used to configure current transition effect * * STRUCT MEMBERS: * nSize : Size of the structure in bytes - * nVersion : OMX specification version information + * nVersion : OMX specification version information * nPortIndex : Port that this structure applies to * eEffect : Effect to enable */ @@ -742,43 +749,43 @@ typedef struct OMX_CONFIG_TRANSITIONEFFECTTYPE { } OMX_CONFIG_TRANSITIONEFFECTTYPE; -/** - * Defines possible data unit types for encoded video data. The data unit +/** + * Defines possible data unit types for encoded video data. The data unit * types are used both for encoded video input for playback as well as - * encoded video output from recording. + * encoded video output from recording. */ typedef enum OMX_DATAUNITTYPE { OMX_DataUnitCodedPicture, OMX_DataUnitVideoSegment, OMX_DataUnitSeveralSegments, OMX_DataUnitArbitraryStreamSection, - OMX_DataUnitKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_DataUnitKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ OMX_DataUnitVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ OMX_DataUnitMax = 0x7FFFFFFF } OMX_DATAUNITTYPE; -/** - * Defines possible encapsulation types for coded video data unit. The - * encapsulation information is used both for encoded video input for - * playback as well as encoded video output from recording. +/** + * Defines possible encapsulation types for coded video data unit. The + * encapsulation information is used both for encoded video input for + * playback as well as encoded video output from recording. */ typedef enum OMX_DATAUNITENCAPSULATIONTYPE { OMX_DataEncapsulationElementaryStream, OMX_DataEncapsulationGenericPayload, OMX_DataEncapsulationRtpPayload, - OMX_DataEncapsulationKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_DataEncapsulationKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ OMX_DataEncapsulationVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ OMX_DataEncapsulationMax = 0x7FFFFFFF } OMX_DATAUNITENCAPSULATIONTYPE; -/** - * Structure used to configure the type of being decoded/encoded +/** + * Structure used to configure the type of being decoded/encoded */ typedef struct OMX_PARAM_DATAUNITTYPE { OMX_U32 nSize; /**< Size of the structure in bytes */ - OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ OMX_U32 nPortIndex; /**< Port that this structure applies to */ OMX_DATAUNITTYPE eUnitType; OMX_DATAUNITENCAPSULATIONTYPE eEncapsulationType; @@ -786,25 +793,25 @@ typedef struct OMX_PARAM_DATAUNITTYPE { /** - * Defines dither types + * Defines dither types */ typedef enum OMX_DITHERTYPE { OMX_DitherNone, OMX_DitherOrdered, OMX_DitherErrorDiffusion, OMX_DitherOther, - OMX_DitherKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_DitherKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ OMX_DitherVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ OMX_DitherMax = 0x7FFFFFFF } OMX_DITHERTYPE; -/** - * Structure used to configure current type of dithering +/** + * Structure used to configure current type of dithering */ typedef struct OMX_CONFIG_DITHERTYPE { OMX_U32 nSize; /**< Size of the structure in bytes */ - OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ OMX_U32 nPortIndex; /**< Port that this structure applies to */ OMX_DITHERTYPE eDither; /**< Type of dithering to use */ } OMX_CONFIG_DITHERTYPE; @@ -813,28 +820,28 @@ typedef struct OMX_CONFIG_CAPTUREMODETYPE { OMX_U32 nSize; OMX_VERSIONTYPE nVersion; OMX_U32 nPortIndex; /**< Port that this structure applies to */ - OMX_BOOL bContinuous; /**< If true then ignore frame rate and emit capture + OMX_BOOL bContinuous; /**< If true then ignore frame rate and emit capture * data as fast as possible (otherwise obey port's frame rate). */ - OMX_BOOL bFrameLimited; /**< If true then terminate capture after the port emits the - * specified number of frames (otherwise the port does not - * terminate the capture until instructed to do so by the client). - * Even if set, the client may manually terminate the capture prior + OMX_BOOL bFrameLimited; /**< If true then terminate capture after the port emits the + * specified number of frames (otherwise the port does not + * terminate the capture until instructed to do so by the client). + * Even if set, the client may manually terminate the capture prior * to reaching the limit. */ OMX_U32 nFrameLimit; /**< Limit on number of frames emitted during a capture (only * valid if bFrameLimited is set). */ } OMX_CONFIG_CAPTUREMODETYPE; typedef enum OMX_METERINGTYPE { - + OMX_MeteringModeAverage, /**< Center-weighted average metering. */ OMX_MeteringModeSpot, /**< Spot (partial) metering. */ OMX_MeteringModeMatrix, /**< Matrix or evaluative metering. */ - - OMX_MeteringKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + + OMX_MeteringKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ OMX_MeteringVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ OMX_EVModeMax = 0x7fffffff } OMX_METERINGTYPE; - + typedef struct OMX_CONFIG_EXPOSUREVALUETYPE { OMX_U32 nSize; OMX_VERSIONTYPE nVersion; @@ -843,14 +850,14 @@ typedef struct OMX_CONFIG_EXPOSUREVALUETYPE { OMX_S32 xEVCompensation; /**< Fixed point value stored as Q16 */ OMX_U32 nApertureFNumber; /**< e.g. nApertureFNumber = 2 implies "f/2" - Q16 format */ OMX_BOOL bAutoAperture; /**< Whether aperture number is defined automatically */ - OMX_U32 nShutterSpeedMsec; /**< Shutterspeed in milliseconds */ - OMX_BOOL bAutoShutterSpeed; /**< Whether shutter speed is defined automatically */ + OMX_U32 nShutterSpeedMsec; /**< Shutterspeed in milliseconds */ + OMX_BOOL bAutoShutterSpeed; /**< Whether shutter speed is defined automatically */ OMX_U32 nSensitivity; /**< e.g. nSensitivity = 100 implies "ISO 100" */ OMX_BOOL bAutoSensitivity; /**< Whether sensitivity is defined automatically */ } OMX_CONFIG_EXPOSUREVALUETYPE; -/** - * Focus region configuration +/** + * Focus region configuration * * STRUCT MEMBERS: * nSize : Size of the structure in bytes @@ -881,8 +888,8 @@ typedef struct OMX_CONFIG_FOCUSREGIONTYPE { OMX_BOOL bBottomRight; } OMX_CONFIG_FOCUSREGIONTYPE; -/** - * Focus Status type +/** + * Focus Status type */ typedef enum OMX_FOCUSSTATUSTYPE { OMX_FocusStatusOff = 0, @@ -890,13 +897,13 @@ typedef enum OMX_FOCUSSTATUSTYPE { OMX_FocusStatusReached, OMX_FocusStatusUnableToReach, OMX_FocusStatusLost, - OMX_FocusStatusKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_FocusStatusKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ OMX_FocusStatusVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ OMX_FocusStatusMax = 0x7FFFFFFF } OMX_FOCUSSTATUSTYPE; -/** - * Focus status configuration +/** + * Focus status configuration * * STRUCT MEMBERS: * nSize : Size of the structure in bytes diff --git a/include/surfaceflinger/ISurfaceComposerClient.h b/include/surfaceflinger/ISurfaceComposerClient.h index 6e9a654..02cabc1 100644 --- a/include/surfaceflinger/ISurfaceComposerClient.h +++ b/include/surfaceflinger/ISurfaceComposerClient.h @@ -45,9 +45,6 @@ public: struct surface_data_t { int32_t token; int32_t identity; - uint32_t width; - uint32_t height; - uint32_t format; status_t readFromParcel(const Parcel& parcel); status_t writeToParcel(Parcel* parcel) const; }; diff --git a/include/surfaceflinger/Surface.h b/include/surfaceflinger/Surface.h index c2a494d..9c352ad 100644 --- a/include/surfaceflinger/Surface.h +++ b/include/surfaceflinger/Surface.h @@ -57,7 +57,6 @@ public: static bool isSameSurface( const sp<SurfaceControl>& lhs, const sp<SurfaceControl>& rhs); - uint32_t getFlags() const { return mFlags; } uint32_t getIdentity() const { return mIdentity; } // release surface data from java @@ -86,25 +85,13 @@ private: SurfaceControl& operator = (SurfaceControl& rhs); SurfaceControl(const SurfaceControl& rhs); - friend class SurfaceComposerClient; - - // camera and camcorder need access to the ISurface binder interface for preview - friend class CameraService; - friend class MediaRecorder; - // mediaplayer needs access to ISurface for display - friend class MediaPlayer; - // for testing - friend class Test; - // videoEditor preview classes - friend class VideoEditorPreviewController; friend class Surface; SurfaceControl( const sp<SurfaceComposerClient>& client, const sp<ISurface>& surface, - const ISurfaceComposerClient::surface_data_t& data, - uint32_t w, uint32_t h, PixelFormat format, uint32_t flags); + const ISurfaceComposerClient::surface_data_t& data); ~SurfaceControl(); @@ -115,10 +102,6 @@ private: sp<ISurface> mSurface; SurfaceID mToken; uint32_t mIdentity; - uint32_t mWidth; - uint32_t mHeight; - PixelFormat mFormat; - uint32_t mFlags; mutable Mutex mLock; mutable sp<Surface> mSurfaceData; @@ -139,17 +122,13 @@ public: uint32_t reserved[2]; }; - static status_t writeToParcel( - const sp<Surface>& control, Parcel* parcel); - + static status_t writeToParcel(const sp<Surface>& control, Parcel* parcel); static sp<Surface> readFromParcel(const Parcel& data); - static bool isValid(const sp<Surface>& surface) { return (surface != 0) && surface->isValid(); } bool isValid(); - uint32_t getFlags() const { return mFlags; } uint32_t getIdentity() const { return mIdentity; } sp<ISurfaceTexture> getSurfaceTexture(); @@ -176,22 +155,14 @@ private: * private stuff... */ void init(); - status_t validate(bool inCancelBuffer = false) const; static void cleanCachedSurfacesLocked(); virtual int query(int what, int* value) const; // constants - status_t mInitCheck; sp<ISurface> mSurface; uint32_t mIdentity; - PixelFormat mFormat; - uint32_t mFlags; - - // query() must be called from dequeueBuffer() thread - uint32_t mWidth; - uint32_t mHeight; // A cache of Surface objects that have been deserialized into this process. static Mutex sCachedSurfacesLock; diff --git a/include/ui/PixelFormat.h b/include/ui/PixelFormat.h index f46f25c..848c5a1 100644 --- a/include/ui/PixelFormat.h +++ b/include/ui/PixelFormat.h @@ -55,7 +55,7 @@ enum { PIXEL_FORMAT_OPAQUE = -1, // System chooses an opaque format (no alpha bits required) - + // real pixel formats supported for rendering ----------------------------- PIXEL_FORMAT_RGBA_8888 = HAL_PIXEL_FORMAT_RGBA_8888, // 4x8-bit RGBA @@ -84,7 +84,7 @@ struct PixelFormatInfo INDEX_GREEN = 2, INDEX_BLUE = 3 }; - + enum { // components ALPHA = 1, RGB = 2, @@ -98,10 +98,10 @@ struct PixelFormatInfo uint8_t h; uint8_t l; }; - + inline PixelFormatInfo() : version(sizeof(PixelFormatInfo)) { } size_t getScanlineSize(unsigned int width) const; - size_t getSize(size_t ci) const { + size_t getSize(size_t ci) const { return (ci <= 3) ? (cinfo[ci].h - cinfo[ci].l) : 0; } size_t version; @@ -112,7 +112,7 @@ struct PixelFormatInfo szinfo cinfo[4]; struct { uint8_t h_alpha; - uint8_t l_alpha; + uint8_t l_alpha; uint8_t h_red; uint8_t l_red; uint8_t h_green; diff --git a/include/utils/Pool.h b/include/utils/Pool.h deleted file mode 100644 index 2ee768e..0000000 --- a/include/utils/Pool.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef UTILS_POOL_H -#define UTILS_POOL_H - -#include <utils/TypeHelpers.h> - -namespace android { - -class PoolImpl { -public: - PoolImpl(size_t objSize); - ~PoolImpl(); - - void* allocImpl(); - void freeImpl(void* obj); - -private: - size_t mObjSize; -}; - -/* - * A homogeneous typed memory pool for fixed size objects. - * Not intended to be thread-safe. - */ -template<typename T> -class Pool : private PoolImpl { -public: - /* Creates an initially empty pool. */ - Pool() : PoolImpl(sizeof(T)) { } - - /* Destroys the pool. - * Assumes that the pool is empty. */ - ~Pool() { } - - /* Allocates an object from the pool, growing the pool if needed. */ - inline T* alloc() { - void* mem = allocImpl(); - if (! traits<T>::has_trivial_ctor) { - return new (mem) T(); - } else { - return static_cast<T*>(mem); - } - } - - /* Frees an object from the pool. */ - inline void free(T* obj) { - if (! traits<T>::has_trivial_dtor) { - obj->~T(); - } - freeImpl(obj); - } -}; - -} // namespace android - -#endif // UTILS_POOL_H diff --git a/libs/gui/ISurfaceComposerClient.cpp b/libs/gui/ISurfaceComposerClient.cpp index bc97cac..ace16aa 100644 --- a/libs/gui/ISurfaceComposerClient.cpp +++ b/libs/gui/ISurfaceComposerClient.cpp @@ -132,9 +132,6 @@ status_t ISurfaceComposerClient::surface_data_t::readFromParcel(const Parcel& pa { token = parcel.readInt32(); identity = parcel.readInt32(); - width = parcel.readInt32(); - height = parcel.readInt32(); - format = parcel.readInt32(); return NO_ERROR; } @@ -142,9 +139,6 @@ status_t ISurfaceComposerClient::surface_data_t::writeToParcel(Parcel* parcel) c { parcel->writeInt32(token); parcel->writeInt32(identity); - parcel->writeInt32(width); - parcel->writeInt32(height); - parcel->writeInt32(format); return NO_ERROR; } diff --git a/libs/gui/ISurfaceTexture.cpp b/libs/gui/ISurfaceTexture.cpp index be90e2e..55246dc 100644 --- a/libs/gui/ISurfaceTexture.cpp +++ b/libs/gui/ISurfaceTexture.cpp @@ -38,7 +38,6 @@ enum { CANCEL_BUFFER, SET_CROP, SET_TRANSFORM, - GET_ALLOCATOR, QUERY, SET_SYNCHRONOUS_MODE, CONNECT, @@ -55,18 +54,18 @@ public: { } - virtual sp<GraphicBuffer> requestBuffer(int bufferIdx) { + virtual status_t requestBuffer(int bufferIdx, sp<GraphicBuffer>* buf) { Parcel data, reply; data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor()); data.writeInt32(bufferIdx); remote()->transact(REQUEST_BUFFER, data, &reply); - sp<GraphicBuffer> buffer; bool nonNull = reply.readInt32(); if (nonNull) { - buffer = new GraphicBuffer(); - reply.read(*buffer); + *buf = new GraphicBuffer(); + reply.read(**buf); } - return buffer; + status_t result = reply.readInt32(); + return result; } virtual status_t setBufferCount(int bufferCount) @@ -144,13 +143,6 @@ public: return result; } - virtual sp<IBinder> getAllocator() { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor()); - remote()->transact(GET_ALLOCATOR, data, &reply); - return reply.readStrongBinder(); - } - virtual int query(int what, int* value) { Parcel data, reply; data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor()); @@ -200,11 +192,13 @@ status_t BnSurfaceTexture::onTransact( case REQUEST_BUFFER: { CHECK_INTERFACE(ISurfaceTexture, data, reply); int bufferIdx = data.readInt32(); - sp<GraphicBuffer> buffer(requestBuffer(bufferIdx)); + sp<GraphicBuffer> buffer; + int result = requestBuffer(bufferIdx, &buffer); reply->writeInt32(buffer != 0); if (buffer != 0) { reply->write(*buffer); } + reply->writeInt32(result); return NO_ERROR; } break; case SET_BUFFER_COUNT: { @@ -270,12 +264,6 @@ status_t BnSurfaceTexture::onTransact( reply->writeInt32(result); return NO_ERROR; } break; - case GET_ALLOCATOR: { - CHECK_INTERFACE(ISurfaceTexture, data, reply); - sp<IBinder> result = getAllocator(); - reply->writeStrongBinder(result); - return NO_ERROR; - } break; case QUERY: { CHECK_INTERFACE(ISurfaceTexture, data, reply); int value; diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index dabe643f..c4f9e53 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -26,15 +26,12 @@ #include <utils/Log.h> #include <utils/threads.h> -#include <binder/IMemory.h> #include <binder/IPCThreadState.h> #include <gui/SurfaceTextureClient.h> #include <ui/DisplayInfo.h> #include <ui/GraphicBuffer.h> -#include <ui/GraphicBufferMapper.h> -#include <ui/GraphicLog.h> #include <ui/Rect.h> #include <surfaceflinger/ISurface.h> @@ -42,8 +39,6 @@ #include <surfaceflinger/Surface.h> #include <surfaceflinger/SurfaceComposerClient.h> -#include <private/surfaceflinger/LayerState.h> - namespace android { // ============================================================================ @@ -53,12 +48,9 @@ namespace android { SurfaceControl::SurfaceControl( const sp<SurfaceComposerClient>& client, const sp<ISurface>& surface, - const ISurfaceComposerClient::surface_data_t& data, - uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) + const ISurfaceComposerClient::surface_data_t& data) : mClient(client), mSurface(surface), - mToken(data.token), mIdentity(data.identity), - mWidth(data.width), mHeight(data.height), mFormat(data.format), - mFlags(flags) + mToken(data.token), mIdentity(data.identity) { } @@ -187,24 +179,12 @@ status_t SurfaceControl::writeSurfaceToParcel( { sp<ISurface> sur; uint32_t identity = 0; - uint32_t width = 0; - uint32_t height = 0; - uint32_t format = 0; - uint32_t flags = 0; if (SurfaceControl::isValid(control)) { sur = control->mSurface; identity = control->mIdentity; - width = control->mWidth; - height = control->mHeight; - format = control->mFormat; - flags = control->mFlags; } parcel->writeStrongBinder(sur!=0 ? sur->asBinder() : NULL); parcel->writeInt32(identity); - parcel->writeInt32(width); - parcel->writeInt32(height); - parcel->writeInt32(format); - parcel->writeInt32(flags); return NO_ERROR; } @@ -225,25 +205,17 @@ sp<Surface> SurfaceControl::getSurface() const Surface::Surface(const sp<SurfaceControl>& surface) : SurfaceTextureClient(), - mInitCheck(NO_INIT), mSurface(surface->mSurface), - mIdentity(surface->mIdentity), - mFormat(surface->mFormat), mFlags(surface->mFlags), - mWidth(surface->mWidth), mHeight(surface->mHeight) + mIdentity(surface->mIdentity) { init(); } Surface::Surface(const Parcel& parcel, const sp<IBinder>& ref) - : SurfaceTextureClient(), - mInitCheck(NO_INIT) + : SurfaceTextureClient() { mSurface = interface_cast<ISurface>(ref); mIdentity = parcel.readInt32(); - mWidth = parcel.readInt32(); - mHeight = parcel.readInt32(); - mFormat = parcel.readInt32(); - mFlags = parcel.readInt32(); init(); } @@ -252,31 +224,16 @@ status_t Surface::writeToParcel( { sp<ISurface> sur; uint32_t identity = 0; - uint32_t width = 0; - uint32_t height = 0; - uint32_t format = 0; - uint32_t flags = 0; if (Surface::isValid(surface)) { sur = surface->mSurface; identity = surface->mIdentity; - width = surface->mWidth; - height = surface->mHeight; - format = surface->mFormat; - flags = surface->mFlags; } else if (surface != 0 && surface->mSurface != 0) { LOGW("Parceling invalid surface with non-NULL ISurface as NULL: " - "mSurface = %p, mIdentity = %d, mWidth = %d, mHeight = %d, " - "mFormat = %d, mFlags = 0x%08x, mInitCheck = %d", - surface->mSurface.get(), surface->mIdentity, surface->mWidth, - surface->mHeight, surface->mFormat, surface->mFlags, - surface->mInitCheck); + "mSurface = %p, mIdentity = %d", + surface->mSurface.get(), surface->mIdentity); } parcel->writeStrongBinder(sur!=0 ? sur->asBinder() : NULL); parcel->writeInt32(identity); - parcel->writeInt32(width); - parcel->writeInt32(height); - parcel->writeInt32(format); - parcel->writeInt32(flags); return NO_ERROR; } @@ -325,10 +282,6 @@ void Surface::init() const_cast<float&>(ANativeWindow::xdpi) = dinfo.xdpi; const_cast<float&>(ANativeWindow::ydpi) = dinfo.ydpi; const_cast<uint32_t&>(ANativeWindow::flags) = 0; - - if (surfaceTexture != NULL) { - mInitCheck = NO_ERROR; - } } } @@ -341,21 +294,11 @@ Surface::~Surface() } bool Surface::isValid() { - return mInitCheck == NO_ERROR; -} - -status_t Surface::validate(bool inCancelBuffer) const -{ - // check that we initialized ourself properly - if (mInitCheck != NO_ERROR) { - LOGE("invalid token (identity=%u)", mIdentity); - return mInitCheck; - } - return NO_ERROR; + return getISurfaceTexture() != NULL; } sp<ISurfaceTexture> Surface::getSurfaceTexture() { - return mSurface != NULL ? mSurface->getSurfaceTexture() : NULL; + return getISurfaceTexture(); } sp<IBinder> Surface::asBinder() const { @@ -367,7 +310,6 @@ sp<IBinder> Surface::asBinder() const { int Surface::query(int what, int* value) const { switch (what) { case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER: - // TODO: this is not needed anymore *value = 1; return NO_ERROR; case NATIVE_WINDOW_CONCRETE_TYPE: diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 8cead80..3b0ffea 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -339,7 +339,7 @@ sp<SurfaceControl> SurfaceComposerClient::createSurface( sp<ISurface> surface = mClient->createSurface(&data, name, display, w, h, format, flags); if (surface != 0) { - result = new SurfaceControl(this, surface, data, w, h, format, flags); + result = new SurfaceControl(this, surface, data); } } return result; diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp index 0f08570..c190195 100644 --- a/libs/gui/SurfaceTexture.cpp +++ b/libs/gui/SurfaceTexture.cpp @@ -94,7 +94,8 @@ SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode) : mTexName(tex), mSynchronousMode(false), mAllowSynchronousMode(allowSynchronousMode), - mConnectedApi(NO_CONNECTED_API) { + mConnectedApi(NO_CONNECTED_API), + mAbandoned(false) { LOGV("SurfaceTexture::SurfaceTexture"); sp<ISurfaceComposer> composer(ComposerService::getComposerService()); mGraphicBufferAlloc = composer->createGraphicBufferAlloc(); @@ -150,6 +151,11 @@ status_t SurfaceTexture::setBufferCount(int bufferCount) { LOGV("SurfaceTexture::setBufferCount"); Mutex::Autolock lock(mMutex); + if (mAbandoned) { + LOGE("setBufferCount: SurfaceTexture has been abandoned!"); + return NO_INIT; + } + if (bufferCount > NUM_BUFFER_SLOTS) { LOGE("setBufferCount: bufferCount larger than slots available"); return BAD_VALUE; @@ -199,22 +205,32 @@ status_t SurfaceTexture::setDefaultBufferSize(uint32_t w, uint32_t h) return OK; } -sp<GraphicBuffer> SurfaceTexture::requestBuffer(int buf) { +status_t SurfaceTexture::requestBuffer(int slot, sp<GraphicBuffer>* buf) { LOGV("SurfaceTexture::requestBuffer"); Mutex::Autolock lock(mMutex); - if (buf < 0 || mBufferCount <= buf) { + if (mAbandoned) { + LOGE("requestBuffer: SurfaceTexture has been abandoned!"); + return NO_INIT; + } + if (slot < 0 || mBufferCount <= slot) { LOGE("requestBuffer: slot index out of range [0, %d]: %d", - mBufferCount, buf); - return 0; + mBufferCount, slot); + return BAD_VALUE; } - mSlots[buf].mRequestBufferCalled = true; - return mSlots[buf].mGraphicBuffer; + mSlots[slot].mRequestBufferCalled = true; + *buf = mSlots[slot].mGraphicBuffer; + return NO_ERROR; } status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h, uint32_t format, uint32_t usage) { LOGV("SurfaceTexture::dequeueBuffer"); + if (mAbandoned) { + LOGE("dequeueBuffer: SurfaceTexture has been abandoned!"); + return NO_INIT; + } + if ((w && !h) || (!w && h)) { LOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h); return BAD_VALUE; @@ -252,6 +268,11 @@ status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h, // wait for the FIFO to drain while (!mQueue.isEmpty()) { mDequeueCondition.wait(mMutex); + if (mAbandoned) { + LOGE("dequeueBuffer: SurfaceTexture was abandoned while " + "blocked!"); + return NO_INIT; + } } minBufferCountNeeded = mSynchronousMode ? MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS; @@ -380,6 +401,11 @@ status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h, status_t SurfaceTexture::setSynchronousMode(bool enabled) { Mutex::Autolock lock(mMutex); + if (mAbandoned) { + LOGE("setSynchronousMode: SurfaceTexture has been abandoned!"); + return NO_INIT; + } + status_t err = OK; if (!mAllowSynchronousMode && enabled) return err; @@ -410,6 +436,10 @@ status_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp, { // scope for the lock Mutex::Autolock lock(mMutex); + if (mAbandoned) { + LOGE("queueBuffer: SurfaceTexture has been abandoned!"); + return NO_INIT; + } if (buf < 0 || buf >= mBufferCount) { LOGE("queueBuffer: slot index out of range [0, %d]: %d", mBufferCount, buf); @@ -475,6 +505,12 @@ status_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp, void SurfaceTexture::cancelBuffer(int buf) { LOGV("SurfaceTexture::cancelBuffer"); Mutex::Autolock lock(mMutex); + + if (mAbandoned) { + LOGW("cancelBuffer: SurfaceTexture has been abandoned!"); + return; + } + if (buf < 0 || buf >= mBufferCount) { LOGE("cancelBuffer: slot index out of range [0, %d]: %d", mBufferCount, buf); @@ -491,6 +527,10 @@ void SurfaceTexture::cancelBuffer(int buf) { status_t SurfaceTexture::setCrop(const Rect& crop) { LOGV("SurfaceTexture::setCrop"); Mutex::Autolock lock(mMutex); + if (mAbandoned) { + LOGE("setCrop: SurfaceTexture has been abandoned!"); + return NO_INIT; + } mNextCrop = crop; return OK; } @@ -498,6 +538,10 @@ status_t SurfaceTexture::setCrop(const Rect& crop) { status_t SurfaceTexture::setTransform(uint32_t transform) { LOGV("SurfaceTexture::setTransform"); Mutex::Autolock lock(mMutex); + if (mAbandoned) { + LOGE("setTransform: SurfaceTexture has been abandoned!"); + return NO_INIT; + } mNextTransform = transform; return OK; } @@ -505,6 +549,12 @@ status_t SurfaceTexture::setTransform(uint32_t transform) { status_t SurfaceTexture::connect(int api) { LOGV("SurfaceTexture::connect(this=%p, %d)", this, api); Mutex::Autolock lock(mMutex); + + if (mAbandoned) { + LOGE("connect: SurfaceTexture has been abandoned!"); + return NO_INIT; + } + int err = NO_ERROR; switch (api) { case NATIVE_WINDOW_API_EGL: @@ -529,6 +579,12 @@ status_t SurfaceTexture::connect(int api) { status_t SurfaceTexture::disconnect(int api) { LOGV("SurfaceTexture::disconnect(this=%p, %d)", this, api); Mutex::Autolock lock(mMutex); + + if (mAbandoned) { + LOGE("connect: SurfaceTexture has been abandoned!"); + return NO_INIT; + } + int err = NO_ERROR; switch (api) { case NATIVE_WINDOW_API_EGL: @@ -786,11 +842,6 @@ void SurfaceTexture::setFrameAvailableListener( mFrameAvailableListener = listener; } -sp<IBinder> SurfaceTexture::getAllocator() { - LOGV("SurfaceTexture::getAllocator"); - return mGraphicBufferAlloc->asBinder(); -} - void SurfaceTexture::freeAllBuffers() { for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { mSlots[i].mGraphicBuffer = 0; @@ -842,6 +893,12 @@ uint32_t SurfaceTexture::getCurrentScalingMode() const { int SurfaceTexture::query(int what, int* outValue) { Mutex::Autolock lock(mMutex); + + if (mAbandoned) { + LOGE("query: SurfaceTexture has been abandoned!"); + return NO_INIT; + } + int value; switch (what) { case NATIVE_WINDOW_WIDTH: @@ -868,6 +925,13 @@ int SurfaceTexture::query(int what, int* outValue) return NO_ERROR; } +void SurfaceTexture::abandon() { + Mutex::Autolock lock(mMutex); + freeAllBuffers(); + mAbandoned = true; + mDequeueCondition.signal(); +} + void SurfaceTexture::dump(String8& result) const { char buffer[1024]; diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp index 1dc6cd2..df0ad5a 100644 --- a/libs/gui/SurfaceTextureClient.cpp +++ b/libs/gui/SurfaceTextureClient.cpp @@ -55,6 +55,9 @@ void SurfaceTextureClient::init() { mQueryWidth = 0; mQueryHeight = 0; mQueryFormat = 0; + mDefaultWidth = 0; + mDefaultHeight = 0; + mTransformHint = 0; mConnectedToCpu = false; } @@ -62,9 +65,6 @@ void SurfaceTextureClient::setISurfaceTexture( const sp<ISurfaceTexture>& surfaceTexture) { mSurfaceTexture = surfaceTexture; - - // Get a reference to the allocator. - mAllocator = mSurfaceTexture->getAllocator(); } sp<ISurfaceTexture> SurfaceTextureClient::getISurfaceTexture() const { @@ -148,10 +148,11 @@ int SurfaceTextureClient::dequeueBuffer(android_native_buffer_t** buffer) { } if ((result & ISurfaceTexture::BUFFER_NEEDS_REALLOCATION) || gbuf == 0) { - gbuf = mSurfaceTexture->requestBuffer(buf); - if (gbuf == 0) { - LOGE("dequeueBuffer: ISurfaceTexture::requestBuffer failed"); - return NO_MEMORY; + result = mSurfaceTexture->requestBuffer(buf, &gbuf); + if (result != NO_ERROR) { + LOGE("dequeueBuffer: ISurfaceTexture::requestBuffer failed: %d", + result); + return result; } mQueryWidth = gbuf->width; mQueryHeight = gbuf->height; diff --git a/libs/gui/tests/SurfaceTextureClient_test.cpp b/libs/gui/tests/SurfaceTextureClient_test.cpp index 2b8f204..c1a3c98 100644 --- a/libs/gui/tests/SurfaceTextureClient_test.cpp +++ b/libs/gui/tests/SurfaceTextureClient_test.cpp @@ -116,11 +116,6 @@ TEST_F(SurfaceTextureClientTest, ConcreteTypeIsSurfaceTextureClient) { EXPECT_EQ(NATIVE_WINDOW_SURFACE_TEXTURE_CLIENT, result); } -TEST_F(SurfaceTextureClientTest, ANativeWindowLockFails) { - ANativeWindow_Buffer buf; - ASSERT_EQ(BAD_VALUE, ANativeWindow_lock(mANW.get(), &buf, NULL)); -} - TEST_F(SurfaceTextureClientTest, EglCreateWindowSurfaceSucceeds) { EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); ASSERT_EQ(EGL_SUCCESS, eglGetError()); diff --git a/libs/gui/tests/SurfaceTexture_test.cpp b/libs/gui/tests/SurfaceTexture_test.cpp index 9abe89d..0fac6cd 100644 --- a/libs/gui/tests/SurfaceTexture_test.cpp +++ b/libs/gui/tests/SurfaceTexture_test.cpp @@ -1018,6 +1018,83 @@ TEST_F(SurfaceTextureGLTest, DISABLED_TexturingFromGLFilledRGBABufferPow2) { EXPECT_TRUE(checkPixel( 3, 52, 153, 153, 153, 153)); } +TEST_F(SurfaceTextureGLTest, AbandonUnblocksDequeueBuffer) { + class ProducerThread : public Thread { + public: + ProducerThread(const sp<ANativeWindow>& anw): + mANW(anw), + mDequeueError(NO_ERROR) { + } + + virtual ~ProducerThread() { + } + + virtual bool threadLoop() { + Mutex::Autolock lock(mMutex); + ANativeWindowBuffer* anb; + + // Frame 1 + if (mANW->dequeueBuffer(mANW.get(), &anb) != NO_ERROR) { + return false; + } + if (anb == NULL) { + return false; + } + if (mANW->queueBuffer(mANW.get(), anb) + != NO_ERROR) { + return false; + } + + // Frame 2 + if (mANW->dequeueBuffer(mANW.get(), &anb) != NO_ERROR) { + return false; + } + if (anb == NULL) { + return false; + } + if (mANW->queueBuffer(mANW.get(), anb) + != NO_ERROR) { + return false; + } + + // Frame 3 - error expected + mDequeueError = mANW->dequeueBuffer(mANW.get(), &anb); + return false; + } + + status_t getDequeueError() { + Mutex::Autolock lock(mMutex); + return mDequeueError; + } + + private: + sp<ANativeWindow> mANW; + status_t mDequeueError; + Mutex mMutex; + }; + + sp<FrameWaiter> fw(new FrameWaiter); + mST->setFrameAvailableListener(fw); + ASSERT_EQ(OK, mST->setSynchronousMode(true)); + ASSERT_EQ(OK, mST->setBufferCountServer(2)); + + sp<Thread> pt(new ProducerThread(mANW)); + pt->run(); + + fw->waitForFrame(); + fw->waitForFrame(); + + // Sleep for 100ms to allow the producer thread's dequeueBuffer call to + // block waiting for a buffer to become available. + usleep(100000); + + mST->abandon(); + + pt->requestExitAndWait(); + ASSERT_EQ(NO_INIT, + reinterpret_cast<ProducerThread*>(pt.get())->getDequeueError()); +} + /* * This test is for testing GL -> GL texture streaming via SurfaceTexture. It * contains functionality to create a producer thread that will perform GL @@ -1205,7 +1282,7 @@ protected: sp<FrameCondition> mFC; }; -TEST_F(SurfaceTextureGLToGLTest, UpdateTexImageBeforeFrameFinishedWorks) { +TEST_F(SurfaceTextureGLToGLTest, UpdateTexImageBeforeFrameFinishedCompletes) { class PT : public ProducerThread { virtual void render() { glClearColor(0.0f, 1.0f, 0.0f, 1.0f); @@ -1223,7 +1300,7 @@ TEST_F(SurfaceTextureGLToGLTest, UpdateTexImageBeforeFrameFinishedWorks) { // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported! } -TEST_F(SurfaceTextureGLToGLTest, UpdateTexImageAfterFrameFinishedWorks) { +TEST_F(SurfaceTextureGLToGLTest, UpdateTexImageAfterFrameFinishedCompletes) { class PT : public ProducerThread { virtual void render() { glClearColor(0.0f, 1.0f, 0.0f, 1.0f); @@ -1241,7 +1318,7 @@ TEST_F(SurfaceTextureGLToGLTest, UpdateTexImageAfterFrameFinishedWorks) { // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported! } -TEST_F(SurfaceTextureGLToGLTest, RepeatedUpdateTexImageBeforeFrameFinishedWorks) { +TEST_F(SurfaceTextureGLToGLTest, RepeatedUpdateTexImageBeforeFrameFinishedCompletes) { enum { NUM_ITERATIONS = 1024 }; class PT : public ProducerThread { @@ -1269,7 +1346,7 @@ TEST_F(SurfaceTextureGLToGLTest, RepeatedUpdateTexImageBeforeFrameFinishedWorks) } } -TEST_F(SurfaceTextureGLToGLTest, RepeatedUpdateTexImageAfterFrameFinishedWorks) { +TEST_F(SurfaceTextureGLToGLTest, RepeatedUpdateTexImageAfterFrameFinishedCompletes) { enum { NUM_ITERATIONS = 1024 }; class PT : public ProducerThread { @@ -1297,4 +1374,70 @@ TEST_F(SurfaceTextureGLToGLTest, RepeatedUpdateTexImageAfterFrameFinishedWorks) } } +// XXX: This test is disabled because it is currently hanging on some devices. +TEST_F(SurfaceTextureGLToGLTest, DISABLED_RepeatedSwapBuffersWhileDequeueStalledCompletes) { + enum { NUM_ITERATIONS = 64 }; + + class PT : public ProducerThread { + virtual void render() { + for (int i = 0; i < NUM_ITERATIONS; i++) { + glClearColor(0.0f, 1.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + LOGV("+swapBuffers"); + swapBuffers(); + LOGV("-swapBuffers"); + } + } + }; + + ASSERT_EQ(OK, mST->setSynchronousMode(true)); + ASSERT_EQ(OK, mST->setBufferCountServer(2)); + + runProducerThread(new PT()); + + // Allow three frames to be rendered and queued before starting the + // rendering in this thread. For the latter two frames we don't call + // updateTexImage so the next dequeue from the producer thread will block + // waiting for a frame to become available. + mFC->waitForFrame(); + mFC->finishFrame(); + + // We must call updateTexImage to consume the first frame so that the + // SurfaceTexture is able to reduce the buffer count to 2. This is because + // the GL driver may dequeue a buffer when the EGLSurface is created, and + // that happens before we call setBufferCountServer. It's possible that the + // driver does not dequeue a buffer at EGLSurface creation time, so we + // cannot rely on this to cause the second dequeueBuffer call to block. + mST->updateTexImage(); + + mFC->waitForFrame(); + mFC->finishFrame(); + mFC->waitForFrame(); + mFC->finishFrame(); + + // Sleep for 100ms to allow the producer thread's dequeueBuffer call to + // block waiting for a buffer to become available. + usleep(100000); + + // Render and present a number of images. This thread should not be blocked + // by the fact that the producer thread is blocking in dequeue. + for (int i = 0; i < NUM_ITERATIONS; i++) { + glClear(GL_COLOR_BUFFER_BIT); + eglSwapBuffers(mEglDisplay, mEglSurface); + } + + // Consume the two pending buffers to unblock the producer thread. + mST->updateTexImage(); + mST->updateTexImage(); + + // Consume the remaining buffers from the producer thread. + for (int i = 0; i < NUM_ITERATIONS-3; i++) { + mFC->waitForFrame(); + mFC->finishFrame(); + LOGV("+updateTexImage"); + mST->updateTexImage(); + LOGV("-updateTexImage"); + } +} + } // namespace android diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp index 8b1caeee..886c05c 100644 --- a/libs/hwui/DisplayListRenderer.cpp +++ b/libs/hwui/DisplayListRenderer.cpp @@ -883,7 +883,6 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level) /////////////////////////////////////////////////////////////////////////////// DisplayListRenderer::DisplayListRenderer(): mWriter(MIN_WRITER_SIZE) { - mDisplayList = NULL; } DisplayListRenderer::~DisplayListRenderer() { @@ -923,13 +922,13 @@ void DisplayListRenderer::reset() { // Operations /////////////////////////////////////////////////////////////////////////////// -DisplayList* DisplayListRenderer::getDisplayList() { - if (mDisplayList == NULL) { - mDisplayList = new DisplayList(*this); +DisplayList* DisplayListRenderer::getDisplayList(DisplayList* displayList) { + if (!displayList) { + displayList = new DisplayList(*this); } else { - mDisplayList->initFromDisplayListRenderer(*this, true); + displayList->initFromDisplayListRenderer(*this, true); } - return mDisplayList; + return displayList; } void DisplayListRenderer::setViewport(int width, int height) { diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h index b83259f..8157631 100644 --- a/libs/hwui/DisplayListRenderer.h +++ b/libs/hwui/DisplayListRenderer.h @@ -217,7 +217,7 @@ public: DisplayListRenderer(); ~DisplayListRenderer(); - DisplayList* getDisplayList(); + DisplayList* getDisplayList(DisplayList* displayList); void setViewport(int width, int height); void prepareDirty(float left, float top, float right, float bottom, bool opaque); @@ -474,8 +474,6 @@ private: SkWriter32 mWriter; - DisplayList *mDisplayList; - int mRestoreSaveCount; friend class DisplayList; diff --git a/libs/ui/FramebufferNativeWindow.cpp b/libs/ui/FramebufferNativeWindow.cpp index 412552e..0e8ae61 100644 --- a/libs/ui/FramebufferNativeWindow.cpp +++ b/libs/ui/FramebufferNativeWindow.cpp @@ -310,35 +310,21 @@ int FramebufferNativeWindow::perform(ANativeWindow* window, int operation, ...) { switch (operation) { - case NATIVE_WINDOW_SET_USAGE: - // TODO: we should implement this - return NO_ERROR; case NATIVE_WINDOW_CONNECT: - // TODO: we should implement this - return NO_ERROR; case NATIVE_WINDOW_DISCONNECT: - // TODO: we should implement this + case NATIVE_WINDOW_SET_USAGE: + case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY: + case NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS: + case NATIVE_WINDOW_SET_BUFFERS_FORMAT: + case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM: + // TODO: we should implement these return NO_ERROR; + case NATIVE_WINDOW_LOCK: - return INVALID_OPERATION; case NATIVE_WINDOW_UNLOCK_AND_POST: - return INVALID_OPERATION; case NATIVE_WINDOW_SET_CROP: - return INVALID_OPERATION; case NATIVE_WINDOW_SET_BUFFER_COUNT: - // TODO: we should implement this - return INVALID_OPERATION; - case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY: - return INVALID_OPERATION; - case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM: - return INVALID_OPERATION; case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP: - return INVALID_OPERATION; - case NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS: - return INVALID_OPERATION; - case NATIVE_WINDOW_SET_BUFFERS_FORMAT: - // TODO: we should implement this - return NO_ERROR; case NATIVE_WINDOW_SET_SCALING_MODE: return INVALID_OPERATION; } diff --git a/libs/utils/Android.mk b/libs/utils/Android.mk index f633357..e4eadbd 100644 --- a/libs/utils/Android.mk +++ b/libs/utils/Android.mk @@ -29,7 +29,6 @@ commonSources:= \ Flattenable.cpp \ LinearTransform.cpp \ ObbFile.cpp \ - Pool.cpp \ PropertyMap.cpp \ RefBase.cpp \ ResourceTypes.cpp \ diff --git a/libs/utils/Pool.cpp b/libs/utils/Pool.cpp deleted file mode 100644 index 8f18cb9..0000000 --- a/libs/utils/Pool.cpp +++ /dev/null @@ -1,37 +0,0 @@ -// -// Copyright 2010 The Android Open Source Project -// -// A simple memory pool. -// -#define LOG_TAG "Pool" - -//#define LOG_NDEBUG 0 - -#include <cutils/log.h> -#include <utils/Pool.h> - -#include <stdlib.h> - -namespace android { - -// TODO Provide a real implementation of a pool. This is just a stub for initial development. - -PoolImpl::PoolImpl(size_t objSize) : - mObjSize(objSize) { -} - -PoolImpl::~PoolImpl() { -} - -void* PoolImpl::allocImpl() { - void* ptr = malloc(mObjSize); - LOG_ALWAYS_FATAL_IF(ptr == NULL, "Cannot allocate new pool object."); - return ptr; -} - -void PoolImpl::freeImpl(void* obj) { - LOG_ALWAYS_FATAL_IF(obj == NULL, "Caller attempted to free NULL pool object."); - return free(obj); -} - -} // namespace android diff --git a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java index 29dec63..0adba06 100755 --- a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java +++ b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java @@ -325,7 +325,7 @@ public class GpsNetInitiatedHandler { } catch (UnsupportedEncodingException e) { - Log.e(TAG, e.getMessage()); + throw new AssertionError(); } return decoded; } @@ -338,7 +338,7 @@ public class GpsNetInitiatedHandler { } catch (UnsupportedEncodingException e) { - Log.e(TAG, e.getMessage()); + throw new AssertionError(); } return decoded; } diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java index c567a6e..855e831 100644 --- a/media/java/android/media/AudioRecord.java +++ b/media/java/android/media/AudioRecord.java @@ -185,7 +185,10 @@ public class AudioRecord * Size of the native audio buffer. */ private int mNativeBufferSizeInBytes = 0; - + /** + * Audio session ID + */ + private int mSessionId = 0; //--------------------------------------------------------- // Constructor, Finalize @@ -227,15 +230,20 @@ public class AudioRecord audioBuffSizeCheck(bufferSizeInBytes); // native initialization + int[] session = new int[1]; + session[0] = 0; //TODO: update native initialization when information about hardware init failure // due to capture device already open is available. int initResult = native_setup( new WeakReference<AudioRecord>(this), - mRecordSource, mSampleRate, mChannels, mAudioFormat, mNativeBufferSizeInBytes); + mRecordSource, mSampleRate, mChannels, mAudioFormat, mNativeBufferSizeInBytes, + session); if (initResult != SUCCESS) { loge("Error code "+initResult+" when initializing native AudioRecord object."); return; // with mState == STATE_UNINITIALIZED } + mSessionId = session[0]; + mState = STATE_INITIALIZED; } @@ -485,6 +493,15 @@ public class AudioRecord } } + /** + * Returns the audio session ID. + * + * @return the ID of the audio session this AudioRecord belongs to. + * @hide + */ + public int getAudioSessionId() { + return mSessionId; + } //--------------------------------------------------------- // Transport control methods @@ -763,7 +780,8 @@ public class AudioRecord //-------------------- private native final int native_setup(Object audiorecord_this, - int recordSource, int sampleRate, int nbChannels, int audioFormat, int buffSizeInBytes); + int recordSource, int sampleRate, int nbChannels, int audioFormat, + int buffSizeInBytes, int[] sessionId); private native final void native_finalize(); diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java index 2e9b64c..682560a 100644 --- a/media/java/android/media/AudioService.java +++ b/media/java/android/media/AudioService.java @@ -332,10 +332,10 @@ public class AudioService extends IAudioService.Stub { SOUND_EFFECT_DEFAULT_VOLUME_DB); mVolumePanel = new VolumePanel(context, this); - mSettingsObserver = new SettingsObserver(); mForcedUseForComm = AudioSystem.FORCE_NONE; createAudioSystemThread(); readPersistedSettings(); + mSettingsObserver = new SettingsObserver(); createStreamStates(); // Call setMode() to initialize mSetModeDeathHandlers mMode = AudioSystem.MODE_INVALID; @@ -433,15 +433,20 @@ public class AudioService extends IAudioService.Stub { mVibrateSetting = System.getInt(cr, System.VIBRATE_ON, 0); + // make sure settings for ringer mode are consistent with device type: non voice capable + // devices (tablets) include media stream in silent mode whereas phones don't. mRingerModeAffectedStreams = Settings.System.getInt(cr, Settings.System.MODE_RINGER_STREAMS_AFFECTED, ((1 << AudioSystem.STREAM_RING)|(1 << AudioSystem.STREAM_NOTIFICATION)| - (1 << AudioSystem.STREAM_SYSTEM)|(1 << AudioSystem.STREAM_SYSTEM_ENFORCED)| - (1 << AudioSystem.STREAM_MUSIC))); - - if (!mVoiceCapable) { + (1 << AudioSystem.STREAM_SYSTEM)|(1 << AudioSystem.STREAM_SYSTEM_ENFORCED))); + if (mVoiceCapable) { + mRingerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_MUSIC); + } else { mRingerModeAffectedStreams |= (1 << AudioSystem.STREAM_MUSIC); } + Settings.System.putInt(cr, + Settings.System.MODE_RINGER_STREAMS_AFFECTED, mRingerModeAffectedStreams); + mMuteAffectedStreams = System.getInt(cr, System.MUTE_STREAMS_AFFECTED, ((1 << AudioSystem.STREAM_MUSIC)|(1 << AudioSystem.STREAM_RING)|(1 << AudioSystem.STREAM_SYSTEM))); @@ -2172,12 +2177,14 @@ public class AudioService extends IAudioService.Stub { super.onChange(selfChange); synchronized (mSettingsLock) { int ringerModeAffectedStreams = Settings.System.getInt(mContentResolver, - Settings.System.MODE_RINGER_STREAMS_AFFECTED, - 0); - if (!mVoiceCapable) { + Settings.System.MODE_RINGER_STREAMS_AFFECTED, + ((1 << AudioSystem.STREAM_RING)|(1 << AudioSystem.STREAM_NOTIFICATION)| + (1 << AudioSystem.STREAM_SYSTEM)|(1 << AudioSystem.STREAM_SYSTEM_ENFORCED))); + if (mVoiceCapable) { + ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_MUSIC); + } else { ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_MUSIC); } - if (ringerModeAffectedStreams != mRingerModeAffectedStreams) { /* * Ensure all stream types that should be affected by ringer mode diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java index e3cbd57..72069ac 100644 --- a/media/java/android/media/MediaRecorder.java +++ b/media/java/android/media/MediaRecorder.java @@ -81,9 +81,6 @@ public class MediaRecorder private String mPath; private FileDescriptor mFd; - private boolean mPrepareAuxiliaryFile = false; - private String mPathAux; - private FileDescriptor mFdAux; private EventHandler mEventHandler; private OnErrorListener mOnErrorListener; private OnInfoListener mOnInfoListener; @@ -557,84 +554,23 @@ public class MediaRecorder } /** - * Sets the auxiliary time lapse video's resolution and bitrate. - * - * The auxiliary video's resolution and bitrate are determined by the CamcorderProfile - * quality level {@link android.media.CamcorderProfile#QUALITY_HIGH}. - */ - private void setAuxVideoParameters() { - CamcorderProfile profile = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH); - setParameter(String.format("video-aux-param-width=%d", profile.videoFrameWidth)); - setParameter(String.format("video-aux-param-height=%d", profile.videoFrameHeight)); - setParameter(String.format("video-aux-param-encoding-bitrate=%d", profile.videoBitRate)); - } - - /** - * Pass in the file descriptor for the auxiliary time lapse video. Call this before - * prepare(). - * - * Sets file descriptor and parameters for auxiliary time lapse video. Time lapse mode - * can capture video (using the still camera) at resolutions higher than that can be - * played back on the device. This function or - * {@link #setAuxiliaryOutputFile(String)} enable capture of a smaller video in - * parallel with the main time lapse video, which can be used to play back on the - * device. The smaller video is created by downsampling the main video. This call is - * optional and does not have to be called if parallel capture of a downsampled video - * is not desired. - * - * Note that while the main video resolution and bitrate is determined from the - * CamcorderProfile in {@link #setProfile(CamcorderProfile)}, the auxiliary video's - * resolution and bitrate are determined by the CamcorderProfile quality level - * {@link android.media.CamcorderProfile#QUALITY_HIGH}. All other encoding parameters - * remain the same for the main video and the auxiliary video. - * - * E.g. if the device supports the time lapse profile quality level - * {@link android.media.CamcorderProfile#QUALITY_TIME_LAPSE_1080P} but can playback at - * most 480p, the application might want to capture an auxiliary video of resolution - * 480p using this call. - * - * @param fd an open file descriptor to be written into. + * Currently not implemented. It does nothing. + * @deprecated Time lapse mode video recording using camera still image capture + * is not desirable, and will not be supported. */ public void setAuxiliaryOutputFile(FileDescriptor fd) { - mPrepareAuxiliaryFile = true; - mPathAux = null; - mFdAux = fd; - setAuxVideoParameters(); + Log.w(TAG, "setAuxiliaryOutputFile(FileDescriptor) is no longer supported."); } /** - * Pass in the file path for the auxiliary time lapse video. Call this before - * prepare(). - * - * Sets file path and parameters for auxiliary time lapse video. Time lapse mode can - * capture video (using the still camera) at resolutions higher than that can be - * played back on the device. This function or - * {@link #setAuxiliaryOutputFile(FileDescriptor)} enable capture of a smaller - * video in parallel with the main time lapse video, which can be used to play back on - * the device. The smaller video is created by downsampling the main video. This call - * is optional and does not have to be called if parallel capture of a downsampled - * video is not desired. - * - * Note that while the main video resolution and bitrate is determined from the - * CamcorderProfile in {@link #setProfile(CamcorderProfile)}, the auxiliary video's - * resolution and bitrate are determined by the CamcorderProfile quality level - * {@link android.media.CamcorderProfile#QUALITY_HIGH}. All other encoding parameters - * remain the same for the main video and the auxiliary video. - * - * E.g. if the device supports the time lapse profile quality level - * {@link android.media.CamcorderProfile#QUALITY_TIME_LAPSE_1080P} but can playback at - * most 480p, the application might want to capture an auxiliary video of resolution - * 480p using this call. - * - * @param path The pathname to use. + * Currently not implemented. It does nothing. + * @deprecated Time lapse mode video recording using camera still image capture + * is not desirable, and will not be supported. */ public void setAuxiliaryOutputFile(String path) { - mPrepareAuxiliaryFile = true; - mFdAux = null; - mPathAux = path; - setAuxVideoParameters(); + Log.w(TAG, "setAuxiliaryOutputFile(String) is no longer supported."); } /** @@ -668,8 +604,6 @@ public class MediaRecorder // native implementation private native void _setOutputFile(FileDescriptor fd, long offset, long length) throws IllegalStateException, IOException; - private native void _setOutputFileAux(FileDescriptor fd) - throws IllegalStateException, IOException; private native void _prepare() throws IllegalStateException, IOException; /** @@ -696,21 +630,6 @@ public class MediaRecorder throw new IOException("No valid output file"); } - if (mPrepareAuxiliaryFile) { - if (mPathAux != null) { - FileOutputStream fos = new FileOutputStream(mPathAux); - try { - _setOutputFileAux(fos.getFD()); - } finally { - fos.close(); - } - } else if (mFdAux != null) { - _setOutputFileAux(mFdAux); - } else { - throw new IOException("No valid output file"); - } - } - _prepare(); } diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java index 8c8569a..a8ac510 100644 --- a/media/java/android/media/MediaScanner.java +++ b/media/java/android/media/MediaScanner.java @@ -372,8 +372,14 @@ public class MediaScanner private class FileInserter { - ContentValues[] mValues = new ContentValues[1000]; - int mIndex = 0; + private final Uri mUri; + private final ContentValues[] mValues; + private int mIndex; + + public FileInserter(Uri uri, int count) { + mUri = uri; + mValues = new ContentValues[count]; + } public Uri insert(ContentValues values) { if (mIndex == mValues.length) { @@ -389,13 +395,17 @@ public class MediaScanner mValues[mIndex++] = null; } try { - mMediaProvider.bulkInsert(mFilesUri, mValues); + mMediaProvider.bulkInsert(mUri, mValues); } catch (RemoteException e) { Log.e(TAG, "RemoteException in FileInserter.flush()", e); } mIndex = 0; } } + + private FileInserter mAudioInserter; + private FileInserter mVideoInserter; + private FileInserter mImageInserter; private FileInserter mFileInserter; // hashes file path to FileCacheEntry. @@ -707,9 +717,7 @@ public class MediaScanner map.put(MediaStore.MediaColumns.MIME_TYPE, mMimeType); map.put(MediaStore.MediaColumns.IS_DRM, mIsDrm); - if (mNoMedia) { - map.put(MediaStore.MediaColumns.NO_MEDIA, true); - } else { + if (!mNoMedia) { if (MediaFile.isVideoFileType(mFileType)) { map.put(Video.Media.ARTIST, (mArtist != null && mArtist.length() > 0 ? mArtist : MediaStore.UNKNOWN_STRING)); @@ -837,23 +845,35 @@ public class MediaScanner } } - // For inserts we always use the file URI so we can insert in bulk. - // For updates we compute the URI based on the media type. Uri tableUri = mFilesUri; + FileInserter inserter = mFileInserter; + if (!mNoMedia) { + if (MediaFile.isVideoFileType(mFileType)) { + tableUri = mVideoUri; + inserter = mVideoInserter; + } else if (MediaFile.isImageFileType(mFileType)) { + tableUri = mImagesUri; + inserter = mImageInserter; + } else if (MediaFile.isAudioFileType(mFileType)) { + tableUri = mAudioUri; + inserter = mAudioInserter; + } + } Uri result = null; if (rowId == 0) { if (mMtpObjectHandle != 0) { values.put(MediaStore.MediaColumns.MEDIA_SCANNER_NEW_OBJECT_ID, mMtpObjectHandle); } - int format = entry.mFormat; - if (format == 0) { - format = MediaFile.getFormatCode(entry.mPath, mMimeType); + if (tableUri == mFilesUri) { + int format = entry.mFormat; + if (format == 0) { + format = MediaFile.getFormatCode(entry.mPath, mMimeType); + } + values.put(Files.FileColumns.FORMAT, format); } - values.put(Files.FileColumns.FORMAT, format); - // new file, insert it - if (mFileInserter != null) { - result = mFileInserter.insert(values); + if (inserter != null) { + result = inserter.insert(values); } else { result = mMediaProvider.insert(tableUri, values); } @@ -863,16 +883,6 @@ public class MediaScanner entry.mRowId = rowId; } } else { - if (!mNoMedia) { - if (MediaFile.isVideoFileType(mFileType)) { - tableUri = mVideoUri; - } else if (MediaFile.isImageFileType(mFileType)) { - tableUri = mImagesUri; - } else if (MediaFile.isAudioFileType(mFileType)) { - tableUri = mAudioUri; - } - } - // updated file result = ContentUris.withAppendedId(tableUri, rowId); // path should never change, and we want to avoid replacing mixed cased paths @@ -1200,12 +1210,25 @@ public class MediaScanner initialize(volumeName); prescan(null, true); long prescan = System.currentTimeMillis(); - mFileInserter = new FileInserter(); + + // create FileInserters for bulk inserts + mAudioInserter = new FileInserter(mAudioUri, 500); + mVideoInserter = new FileInserter(mVideoUri, 500); + mImageInserter = new FileInserter(mImagesUri, 500); + mFileInserter = new FileInserter(mFilesUri, 500); for (int i = 0; i < directories.length; i++) { processDirectory(directories[i], mClient); } + + // flush remaining inserts + mAudioInserter.flush(); + mVideoInserter.flush(); + mImageInserter.flush(); mFileInserter.flush(); + mAudioInserter = null; + mVideoInserter = null; + mImageInserter = null; mFileInserter = null; long scan = System.currentTimeMillis(); diff --git a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java index 0d2bcd5..6b0fb12 100644 --- a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java +++ b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java @@ -912,11 +912,14 @@ class MediaArtistNativeHelper { /** 720p 1280 X 720 */ public static final int V720p = 10; - /** 1080 x 720 */ + /** W720p 1080 x 720 */ public static final int W720p = 11; - /** 1080 960 x 720 */ + /** S720p 960 x 720 */ public static final int S720p = 12; + + /** 1080p 1920 x 1080 */ + public static final int V1080p = 13; } /** @@ -3548,6 +3551,8 @@ class MediaArtistNativeHelper { retValue = VideoFrameSize.WVGA16x9; else if (height == MediaProperties.HEIGHT_720) retValue = VideoFrameSize.V720p; + else if (height == MediaProperties.HEIGHT_1080) + retValue = VideoFrameSize.V1080p; break; case MediaProperties.ASPECT_RATIO_4_3: if (height == MediaProperties.HEIGHT_480) diff --git a/media/java/android/media/videoeditor/MediaImageItem.java b/media/java/android/media/videoeditor/MediaImageItem.java index 4faa83a..73cc7e2 100755 --- a/media/java/android/media/videoeditor/MediaImageItem.java +++ b/media/java/android/media/videoeditor/MediaImageItem.java @@ -503,51 +503,75 @@ public class MediaImageItem extends MediaItem { return adjustedOverlays; } - - /** - * This function sets the Ken Burn effect generated clip - * name. + * This function get the proper width by given aspect ratio + * and height. * - * @param generatedFilePath The name of the generated clip + * @param aspectRatio Given aspect ratio + * @param height Given height */ - @Override - void setGeneratedImageClip(String generatedFilePath) { - super.setGeneratedImageClip(generatedFilePath); + private int getWidthByAspectRatioAndHeight(int aspectRatio, int height) { + int width = 0; - - // set the Kenburns clip width and height - mGeneratedClipHeight = getScaledHeight(); - switch (mVideoEditor.getAspectRatio()) { + switch (aspectRatio) { case MediaProperties.ASPECT_RATIO_3_2: - if (mGeneratedClipHeight == MediaProperties.HEIGHT_480) - mGeneratedClipWidth = 720; - else if (mGeneratedClipHeight == MediaProperties.HEIGHT_720) - mGeneratedClipWidth = 1080; + if (height == MediaProperties.HEIGHT_480) + width = 720; + else if (height == MediaProperties.HEIGHT_720) + width = 1080; break; + case MediaProperties.ASPECT_RATIO_16_9: - if (mGeneratedClipHeight == MediaProperties.HEIGHT_360) - mGeneratedClipWidth = 640; - else if (mGeneratedClipHeight == MediaProperties.HEIGHT_480) - mGeneratedClipWidth = 854; - else if (mGeneratedClipHeight == MediaProperties.HEIGHT_720) - mGeneratedClipWidth = 1280; + if (height == MediaProperties.HEIGHT_360) + width = 640; + else if (height == MediaProperties.HEIGHT_480) + width = 854; + else if (height == MediaProperties.HEIGHT_720) + width = 1280; + else if (height == MediaProperties.HEIGHT_1080) + width = 1920; break; + case MediaProperties.ASPECT_RATIO_4_3: - if (mGeneratedClipHeight == MediaProperties.HEIGHT_480) - mGeneratedClipWidth = 640; - if (mGeneratedClipHeight == MediaProperties.HEIGHT_720) - mGeneratedClipWidth = 960; + if (height == MediaProperties.HEIGHT_480) + width = 640; + if (height == MediaProperties.HEIGHT_720) + width = 960; break; + case MediaProperties.ASPECT_RATIO_5_3: - if (mGeneratedClipHeight == MediaProperties.HEIGHT_480) - mGeneratedClipWidth = 800; + if (height == MediaProperties.HEIGHT_480) + width = 800; break; + case MediaProperties.ASPECT_RATIO_11_9: - if (mGeneratedClipHeight == MediaProperties.HEIGHT_144) - mGeneratedClipWidth = 176; + if (height == MediaProperties.HEIGHT_144) + width = 176; break; + + default : { + throw new IllegalArgumentException( + "Illegal arguments for aspectRatio"); + } } + + return width; + } + + /** + * This function sets the Ken Burn effect generated clip + * name. + * + * @param generatedFilePath The name of the generated clip + */ + @Override + void setGeneratedImageClip(String generatedFilePath) { + super.setGeneratedImageClip(generatedFilePath); + + // set the Kenburns clip width and height + mGeneratedClipHeight = getScaledHeight(); + mGeneratedClipWidth = getWidthByAspectRatioAndHeight( + mVideoEditor.getAspectRatio(), mGeneratedClipHeight); } /** @@ -841,37 +865,8 @@ public class MediaImageItem extends MediaItem { clipSettings.fileType = FileType.THREE_GPP; mGeneratedClipHeight = getScaledHeight(); - switch (mVideoEditor.getAspectRatio()) { - case MediaProperties.ASPECT_RATIO_3_2: - if (mGeneratedClipHeight == MediaProperties.HEIGHT_480) - mGeneratedClipWidth = 720; - else if (mGeneratedClipHeight == MediaProperties.HEIGHT_720) - mGeneratedClipWidth = 1080; - break; - case MediaProperties.ASPECT_RATIO_16_9: - if (mGeneratedClipHeight == MediaProperties.HEIGHT_360) - mGeneratedClipWidth = 640; - else if (mGeneratedClipHeight == MediaProperties.HEIGHT_480) - mGeneratedClipWidth = 854; - else if (mGeneratedClipHeight == MediaProperties.HEIGHT_720) - mGeneratedClipWidth = 1280; - break; - case MediaProperties.ASPECT_RATIO_4_3: - if (mGeneratedClipHeight == MediaProperties.HEIGHT_480) - mGeneratedClipWidth = 640; - if (mGeneratedClipHeight == MediaProperties.HEIGHT_720) - mGeneratedClipWidth = 960; - break; - case MediaProperties.ASPECT_RATIO_5_3: - if (mGeneratedClipHeight == MediaProperties.HEIGHT_480) - mGeneratedClipWidth = 800; - break; - case MediaProperties.ASPECT_RATIO_11_9: - if (mGeneratedClipHeight == MediaProperties.HEIGHT_144) - mGeneratedClipWidth = 176; - break; - } - + mGeneratedClipWidth = getWidthByAspectRatioAndHeight( + mVideoEditor.getAspectRatio(), mGeneratedClipHeight); } else { if (getGeneratedImageClip() == null) { clipSettings.clipPath = getDecodedImageFileName(); diff --git a/media/java/android/media/videoeditor/MediaProperties.java b/media/java/android/media/videoeditor/MediaProperties.java index 0225807..ff13e5d 100755 --- a/media/java/android/media/videoeditor/MediaProperties.java +++ b/media/java/android/media/videoeditor/MediaProperties.java @@ -17,8 +17,9 @@ package android.media.videoeditor; +import android.media.videoeditor.VideoEditorProfile; import android.util.Pair; - +import java.lang.System; /** * This class defines all properties of a media file such as supported height, * aspect ratio, bitrate for export function. @@ -33,7 +34,7 @@ public class MediaProperties { public static final int HEIGHT_360 = 360; public static final int HEIGHT_480 = 480; public static final int HEIGHT_720 = 720; - public static final int HEIGHT_1088 = 1088; + public static final int HEIGHT_1080 = 1080; /** * Supported aspect ratios @@ -63,8 +64,7 @@ public class MediaProperties { private static final Pair<Integer, Integer>[] ASPECT_RATIO_3_2_RESOLUTIONS = new Pair[] { new Pair<Integer, Integer>(720, HEIGHT_480), -//*tmpLSA*/ new Pair<Integer, Integer>(1080, HEIGHT_720) -/*tmpLSA*/ new Pair<Integer, Integer>(1088, HEIGHT_720) + new Pair<Integer, Integer>(1080, HEIGHT_720) }; @SuppressWarnings({"unchecked"}) @@ -92,6 +92,7 @@ public class MediaProperties { new Pair[] { new Pair<Integer, Integer>(848, HEIGHT_480), new Pair<Integer, Integer>(1280, HEIGHT_720), + new Pair<Integer, Integer>(1920, HEIGHT_1080), }; /** @@ -345,7 +346,31 @@ public class MediaProperties { } } - return resolutions; + /** Check the platform specific maximum export resolution */ + VideoEditorProfile veProfile = VideoEditorProfile.get(); + if (veProfile == null) { + throw new RuntimeException("Can't get the video editor profile"); + } + final int maxWidth = veProfile.maxOutputVideoFrameWidth; + final int maxHeight = veProfile.maxOutputVideoFrameHeight; + Pair<Integer, Integer>[] tmpResolutions = new Pair[resolutions.length]; + int numSupportedResolution = 0; + int i = 0; + + /** Get supported resolution list */ + for (i = 0; i < resolutions.length; i++) { + if ((resolutions[i].first <= maxWidth) && + (resolutions[i].second <= maxHeight)) { + tmpResolutions[numSupportedResolution] = resolutions[i]; + numSupportedResolution++; + } + } + final Pair<Integer, Integer>[] supportedResolutions = + new Pair[numSupportedResolution]; + System.arraycopy(tmpResolutions, 0, + supportedResolutions, 0, numSupportedResolution); + + return supportedResolutions; } /** diff --git a/media/java/android/media/videoeditor/MediaVideoItem.java b/media/java/android/media/videoeditor/MediaVideoItem.java index 4758de6..6248651 100755 --- a/media/java/android/media/videoeditor/MediaVideoItem.java +++ b/media/java/android/media/videoeditor/MediaVideoItem.java @@ -23,6 +23,7 @@ import java.lang.ref.SoftReference; import android.graphics.Bitmap; import android.media.videoeditor.MediaArtistNativeHelper.ClipSettings; import android.media.videoeditor.MediaArtistNativeHelper.Properties; +import android.media.videoeditor.VideoEditorProfile; import android.view.Surface; import android.view.SurfaceHolder; @@ -118,6 +119,21 @@ public class MediaVideoItem extends MediaItem { throw new IllegalArgumentException(e.getMessage() + " : " + filename); } + /** Check the platform specific maximum import resolution */ + VideoEditorProfile veProfile = VideoEditorProfile.get(); + if (veProfile == null) { + throw new RuntimeException("Can't get the video editor profile"); + } + final int maxInputWidth = veProfile.maxInputVideoFrameWidth; + final int maxInputHeight = veProfile.maxInputVideoFrameHeight; + if ((properties.width > maxInputWidth) || + (properties.height > maxInputHeight)) { + throw new IllegalArgumentException( + "Unsupported import resolution. Supported maximum width:" + + maxInputWidth + " height:" + maxInputHeight + + ", current width:" + properties.width + + " height:" + properties.height); + } switch (mMANativeHelper.getFileType(properties.fileType)) { case MediaProperties.FILE_3GP: case MediaProperties.FILE_MP4: diff --git a/media/java/android/media/videoeditor/VideoEditor.java b/media/java/android/media/videoeditor/VideoEditor.java index 59e4540..720e8022 100755 --- a/media/java/android/media/videoeditor/VideoEditor.java +++ b/media/java/android/media/videoeditor/VideoEditor.java @@ -370,7 +370,7 @@ public interface VideoEditor { */ public void export(String filename, int height, int bitrate, ExportProgressListener listener) - throws IOException; + throws IOException; /** * Create the output movie based on all media items added and the applied @@ -413,7 +413,7 @@ public interface VideoEditor { */ public void export(String filename, int height, int bitrate, int audioCodec, int videoCodec, ExportProgressListener listener) - throws IOException; + throws IOException; /** * Cancel the running export operation. This method blocks until the export diff --git a/media/java/android/media/videoeditor/VideoEditorImpl.java b/media/java/android/media/videoeditor/VideoEditorImpl.java index 649b98a..ea7fe63 100755 --- a/media/java/android/media/videoeditor/VideoEditorImpl.java +++ b/media/java/android/media/videoeditor/VideoEditorImpl.java @@ -337,7 +337,8 @@ public class VideoEditorImpl implements VideoEditor { */ public void export(String filename, int height, int bitrate, int audioCodec, int videoCodec, - ExportProgressListener listener) throws IOException { + ExportProgressListener listener) + throws IOException { switch (audioCodec) { case MediaProperties.ACODEC_AAC_LC: @@ -372,7 +373,8 @@ public class VideoEditorImpl implements VideoEditor { * {@inheritDoc} */ public void export(String filename, int height, int bitrate, - ExportProgressListener listener) throws IOException { + ExportProgressListener listener) + throws IOException { if (filename == null) { throw new IllegalArgumentException("export: filename is null"); } @@ -386,6 +388,20 @@ public class VideoEditorImpl implements VideoEditor { throw new IllegalStateException("No MediaItems added"); } + /** Check the platform specific maximum export resolution */ + VideoEditorProfile veProfile = VideoEditorProfile.get(); + if (veProfile == null) { + throw new RuntimeException("Can't get the video editor profile"); + } + final int maxOutputHeight = veProfile.maxOutputVideoFrameHeight; + final int maxOutputWidth = veProfile.maxOutputVideoFrameWidth; + if (height > maxOutputHeight) { + throw new IllegalArgumentException( + "Unsupported export resolution. Supported maximum width:" + + maxOutputWidth + " height:" + maxOutputHeight + + " current height:" + height); + } + switch (height) { case MediaProperties.HEIGHT_144: break; @@ -397,6 +413,8 @@ public class VideoEditorImpl implements VideoEditor { break; case MediaProperties.HEIGHT_720: break; + case MediaProperties.HEIGHT_1080: + break; default: { String message = "Unsupported height value " + height; diff --git a/media/java/android/media/videoeditor/VideoEditorProfile.java b/media/java/android/media/videoeditor/VideoEditorProfile.java new file mode 100755 index 0000000..7d9fc8f --- /dev/null +++ b/media/java/android/media/videoeditor/VideoEditorProfile.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.media.videoeditor; + +/** + * The VideoEditorProfile class is used to retrieve the + * predefined videoeditor profile settings for videoeditor applications. + * These settings are read-only. + * + * <p>The videoeditor profile specifies the following set of parameters: + * <ul> + * <li> max input video frame width + * <li> max input video frame height + * <li> max output video frame width + * <li> max output video frame height + * </ul> + * {@hide} + */ +public class VideoEditorProfile +{ + /** + * The max input video frame width + */ + public int maxInputVideoFrameWidth; + + /** + * The max input video frame height + */ + public int maxInputVideoFrameHeight; + + /** + * The max ouput video frame width + */ + public int maxOutputVideoFrameWidth; + + /** + * The max ouput video frame height + */ + public int maxOutputVideoFrameHeight; + + /** + * Returns the videoeditor profile + */ + public static VideoEditorProfile get() { + return native_get_videoeditor_profile(); + } + + static { + System.loadLibrary("media_jni"); + native_init(); + } + + // Private constructor called by JNI + private VideoEditorProfile(int inputWidth, + int inputHeight, + int outputWidth, + int outputHeight) { + + this.maxInputVideoFrameWidth = inputWidth; + this.maxInputVideoFrameHeight = inputHeight; + this.maxOutputVideoFrameWidth = outputWidth; + this.maxOutputVideoFrameHeight = outputHeight; + } + + // Methods implemented by JNI + private static native final void native_init(); + private static native final VideoEditorProfile + native_get_videoeditor_profile(); +} diff --git a/media/jni/android_media_MediaProfiles.cpp b/media/jni/android_media_MediaProfiles.cpp index 08a6de1..2b8dfe4 100644 --- a/media/jni/android_media_MediaProfiles.cpp +++ b/media/jni/android_media_MediaProfiles.cpp @@ -286,6 +286,44 @@ android_media_MediaProfiles_native_get_image_encoding_quality_level(JNIEnv *env, } return static_cast<jint>(levels[index]); } +static jobject +android_media_MediaProfiles_native_get_videoeditor_profile(JNIEnv *env, jobject thiz) +{ + LOGV("native_get_videoeditor_profile"); + + int maxInputFrameWidth = + sProfiles->getVideoEditorCapParamByName("videoeditor.input.width.max"); + int maxInputFrameHeight = + sProfiles->getVideoEditorCapParamByName("videoeditor.input.height.max"); + int maxOutputFrameWidth = + sProfiles->getVideoEditorCapParamByName("videoeditor.output.width.max"); + int maxOutputFrameHeight = + sProfiles->getVideoEditorCapParamByName("videoeditor.output.height.max"); + + // Check on the values retrieved + if (maxInputFrameWidth == -1 || maxInputFrameHeight == -1 || + maxOutputFrameWidth == -1 || maxOutputFrameHeight == -1) { + + jniThrowException(env, "java/lang/RuntimeException",\ + "Error retrieving videoeditor profile params"); + return NULL; + } + LOGV("native_get_videoeditor_profile \ + inWidth:%d inHeight:%d,outWidth:%d, outHeight:%d",\ + maxInputFrameWidth,maxInputFrameHeight,\ + maxOutputFrameWidth,maxOutputFrameHeight); + + jclass VideoEditorProfileClazz = + env->FindClass("android/media/videoeditor/VideoEditorProfile"); + jmethodID VideoEditorProfileConstructorMethodID = + env->GetMethodID(VideoEditorProfileClazz, "<init>", "(IIII)V"); + return env->NewObject(VideoEditorProfileClazz, + VideoEditorProfileConstructorMethodID, + maxInputFrameWidth, + maxInputFrameHeight, + maxOutputFrameWidth, + maxOutputFrameHeight); +} static JNINativeMethod gMethodsForEncoderCapabilitiesClass[] = { {"native_init", "()V", (void *)android_media_MediaProfiles_native_init}, @@ -324,10 +362,17 @@ static JNINativeMethod gMethodsForCameraProfileClass[] = { {"native_get_image_encoding_quality_level","(II)I", (void *)android_media_MediaProfiles_native_get_image_encoding_quality_level}, }; +static JNINativeMethod gMethodsForVideoEditorProfileClass[] = { + {"native_init", "()V", (void *)android_media_MediaProfiles_native_init}, + {"native_get_videoeditor_profile", "()Landroid/media/videoeditor/VideoEditorProfile;", + (void *)android_media_MediaProfiles_native_get_videoeditor_profile}, +}; + static const char* const kEncoderCapabilitiesClassPathName = "android/media/EncoderCapabilities"; static const char* const kDecoderCapabilitiesClassPathName = "android/media/DecoderCapabilities"; static const char* const kCamcorderProfileClassPathName = "android/media/CamcorderProfile"; static const char* const kCameraProfileClassPathName = "android/media/CameraProfile"; +static const char* const kVideoEditorProfileClassPathName = "android/media/videoeditor/VideoEditorProfile"; // This function only registers the native methods, and is called from // JNI_OnLoad in android_media_MediaPlayer.cpp @@ -353,6 +398,11 @@ int register_android_media_MediaProfiles(JNIEnv *env) gMethodsForCameraProfileClass, NELEM(gMethodsForCameraProfileClass)); + int ret5 = AndroidRuntime::registerNativeMethods(env, + kVideoEditorProfileClassPathName, + gMethodsForVideoEditorProfileClass, + NELEM(gMethodsForVideoEditorProfileClass)); + // Success if all return values from above are 0 - return (ret1 || ret2 || ret3 || ret4); + return (ret1 || ret2 || ret3 || ret4 || ret5); } diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp index 12391c8..922f7ed 100644 --- a/media/jni/android_media_MediaRecorder.cpp +++ b/media/jni/android_media_MediaRecorder.cpp @@ -127,7 +127,7 @@ static bool process_media_recorder_call(JNIEnv *env, status_t opStatus, const ch return false; } -static sp<MediaRecorder> getMediaRecorder(JNIEnv* env, jobject thiz) +sp<MediaRecorder> getMediaRecorder(JNIEnv* env, jobject thiz) { Mutex::Autolock l(sLock); MediaRecorder* const p = (MediaRecorder*)env->GetIntField(thiz, fields.context); @@ -261,20 +261,6 @@ android_media_MediaRecorder_setOutputFileFD(JNIEnv *env, jobject thiz, jobject f } static void -android_media_MediaRecorder_setOutputFileAuxFD(JNIEnv *env, jobject thiz, jobject fileDescriptor) -{ - LOGV("setOutputFile"); - if (fileDescriptor == NULL) { - jniThrowException(env, "java/lang/IllegalArgumentException", NULL); - return; - } - int fd = jniGetFDFromFileDescriptor(env, fileDescriptor); - sp<MediaRecorder> mr = getMediaRecorder(env, thiz); - status_t opStatus = mr->setOutputFileAuxiliary(fd); - process_media_recorder_call(env, opStatus, "java/io/IOException", "setOutputFile failed."); -} - -static void android_media_MediaRecorder_setVideoSize(JNIEnv *env, jobject thiz, jint width, jint height) { LOGV("setVideoSize(%d, %d)", width, height); @@ -475,7 +461,6 @@ static JNINativeMethod gMethods[] = { {"setAudioEncoder", "(I)V", (void *)android_media_MediaRecorder_setAudioEncoder}, {"setParameter", "(Ljava/lang/String;)V", (void *)android_media_MediaRecorder_setParameter}, {"_setOutputFile", "(Ljava/io/FileDescriptor;JJ)V", (void *)android_media_MediaRecorder_setOutputFileFD}, - {"_setOutputFileAux", "(Ljava/io/FileDescriptor;)V", (void *)android_media_MediaRecorder_setOutputFileAuxFD}, {"setVideoSize", "(II)V", (void *)android_media_MediaRecorder_setVideoSize}, {"setVideoFrameRate", "(I)V", (void *)android_media_MediaRecorder_setVideoFrameRate}, {"setMaxDuration", "(I)V", (void *)android_media_MediaRecorder_setMaxDuration}, diff --git a/media/jni/android_media_MediaScanner.cpp b/media/jni/android_media_MediaScanner.cpp index d0d2d1e..b88296f 100644 --- a/media/jni/android_media_MediaScanner.cpp +++ b/media/jni/android_media_MediaScanner.cpp @@ -46,6 +46,16 @@ struct fields_t { }; static fields_t fields; +static status_t checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) { + if (env->ExceptionCheck()) { + LOGE("An exception was thrown by callback '%s'.", methodName); + LOGE_EX(env); + env->ExceptionClear(); + return UNKNOWN_ERROR; + } + return OK; +} + class MyMediaScannerClient : public MediaScannerClient { public: @@ -86,9 +96,7 @@ public: mEnv->DeleteGlobalRef(mClient); } - // Returns true if it succeeded, false if an exception occured - // in the Java code - virtual bool scanFile(const char* path, long long lastModified, + virtual status_t scanFile(const char* path, long long lastModified, long long fileSize, bool isDirectory, bool noMedia) { LOGV("scanFile: path(%s), time(%lld), size(%lld) and isDir(%d)", @@ -96,27 +104,29 @@ public: jstring pathStr; if ((pathStr = mEnv->NewStringUTF(path)) == NULL) { - return false; + mEnv->ExceptionClear(); + return NO_MEMORY; } mEnv->CallVoidMethod(mClient, mScanFileMethodID, pathStr, lastModified, fileSize, isDirectory, noMedia); mEnv->DeleteLocalRef(pathStr); - return (!mEnv->ExceptionCheck()); + return checkAndClearExceptionFromCallback(mEnv, "scanFile"); } - // Returns true if it succeeded, false if an exception occured - // in the Java code - virtual bool handleStringTag(const char* name, const char* value) + virtual status_t handleStringTag(const char* name, const char* value) { LOGV("handleStringTag: name(%s) and value(%s)", name, value); jstring nameStr, valueStr; if ((nameStr = mEnv->NewStringUTF(name)) == NULL) { - return false; + mEnv->ExceptionClear(); + return NO_MEMORY; } if ((valueStr = mEnv->NewStringUTF(value)) == NULL) { - return false; + mEnv->DeleteLocalRef(nameStr); + mEnv->ExceptionClear(); + return NO_MEMORY; } mEnv->CallVoidMethod( @@ -124,23 +134,22 @@ public: mEnv->DeleteLocalRef(nameStr); mEnv->DeleteLocalRef(valueStr); - return (!mEnv->ExceptionCheck()); + return checkAndClearExceptionFromCallback(mEnv, "handleStringTag"); } - // Returns true if it succeeded, false if an exception occured - // in the Java code - virtual bool setMimeType(const char* mimeType) + virtual status_t setMimeType(const char* mimeType) { LOGV("setMimeType: %s", mimeType); jstring mimeTypeStr; if ((mimeTypeStr = mEnv->NewStringUTF(mimeType)) == NULL) { - return false; + mEnv->ExceptionClear(); + return NO_MEMORY; } mEnv->CallVoidMethod(mClient, mSetMimeTypeMethodID, mimeTypeStr); mEnv->DeleteLocalRef(mimeTypeStr); - return (!mEnv->ExceptionCheck()); + return checkAndClearExceptionFromCallback(mEnv, "setMimeType"); } private: @@ -152,12 +161,6 @@ private: }; -static bool ExceptionCheck(void* env) -{ - LOGV("ExceptionCheck"); - return ((JNIEnv *)env)->ExceptionCheck(); -} - static MediaScanner *getNativeScanner_l(JNIEnv* env, jobject thiz) { return (MediaScanner *) env->GetIntField(thiz, fields.context); @@ -190,7 +193,10 @@ android_media_MediaScanner_processDirectory( } MyMediaScannerClient myClient(env, client); - mp->processDirectory(pathStr, myClient, ExceptionCheck, env); + MediaScanResult result = mp->processDirectory(pathStr, myClient); + if (result == MEDIA_SCAN_RESULT_ERROR) { + LOGE("An error occurred while scanning directory '%s'.", pathStr); + } env->ReleaseStringUTFChars(path, pathStr); } @@ -227,7 +233,10 @@ android_media_MediaScanner_processFile( } MyMediaScannerClient myClient(env, client); - mp->processFile(pathStr, mimeTypeStr, myClient); + MediaScanResult result = mp->processFile(pathStr, mimeTypeStr, myClient); + if (result == MEDIA_SCAN_RESULT_ERROR) { + LOGE("An error occurred while scanning file '%s'.", pathStr); + } env->ReleaseStringUTFChars(path, pathStr); if (mimeType) { env->ReleaseStringUTFChars(mimeType, mimeTypeStr); diff --git a/media/jni/mediaeditor/VideoEditorClasses.cpp b/media/jni/mediaeditor/VideoEditorClasses.cpp index 277e16c..4c0e731 100755 --- a/media/jni/mediaeditor/VideoEditorClasses.cpp +++ b/media/jni/mediaeditor/VideoEditorClasses.cpp @@ -439,9 +439,10 @@ VIDEOEDIT_JAVA_DEFINE_CONSTANTS(VideoFrameSize) VIDEOEDIT_JAVA_CONSTANT_INIT("NTSC", M4VIDEOEDITING_kNTSC), VIDEOEDIT_JAVA_CONSTANT_INIT("nHD", M4VIDEOEDITING_k640_360), VIDEOEDIT_JAVA_CONSTANT_INIT("WVGA16x9", M4VIDEOEDITING_k854_480), - VIDEOEDIT_JAVA_CONSTANT_INIT("V720p", M4VIDEOEDITING_kHD1280), - VIDEOEDIT_JAVA_CONSTANT_INIT("W720p", M4VIDEOEDITING_kHD1080), - VIDEOEDIT_JAVA_CONSTANT_INIT("S720p", M4VIDEOEDITING_kHD960) + VIDEOEDIT_JAVA_CONSTANT_INIT("V720p", M4VIDEOEDITING_k1280_720), + VIDEOEDIT_JAVA_CONSTANT_INIT("W720p", M4VIDEOEDITING_k1080_720), + VIDEOEDIT_JAVA_CONSTANT_INIT("S720p", M4VIDEOEDITING_k960_720), + VIDEOEDIT_JAVA_CONSTANT_INIT("V1080p", M4VIDEOEDITING_k1920_1080) }; VIDEOEDIT_JAVA_DEFINE_CONSTANT_CLASS(VideoFrameSize, VIDEO_FRAME_SIZE_CLASS_NAME, diff --git a/media/jni/mediaeditor/VideoEditorPropertiesMain.cpp b/media/jni/mediaeditor/VideoEditorPropertiesMain.cpp index 9de7207..93fe702 100755 --- a/media/jni/mediaeditor/VideoEditorPropertiesMain.cpp +++ b/media/jni/mediaeditor/VideoEditorPropertiesMain.cpp @@ -214,18 +214,6 @@ jobject videoEditProp_getProperties( "Invalid File or File not found "); } - /** - * Max resolution supported is 1280 x 720. - */ - if ( (pClipProperties->uiVideoWidth > 1280) - || (pClipProperties->uiVideoHeight > 720) ) - { - result = M4MCS_ERR_INVALID_INPUT_VIDEO_FRAME_SIZE; - videoEditJava_checkAndThrowIllegalArgumentException( - &gotten, pEnv, (M4NO_ERROR != result), - "Unsupported input video frame size"); - } - #ifdef USE_SOFTWARE_DECODER /** * Input clip with non-multiples of 16 is not supported. diff --git a/media/libeffects/data/audio_effects.conf b/media/libeffects/data/audio_effects.conf index e6a7b37..b8fa487 100644 --- a/media/libeffects/data/audio_effects.conf +++ b/media/libeffects/data/audio_effects.conf @@ -1,5 +1,10 @@ # List of effect libraries to load. Each library element must contain a "path" element # giving the full path of the library .so file. +# libraries { +# <lib name> { +# path <lib path> +# } +# } libraries { bundle { path /system/lib/soundfx/libbundlewrapper.so @@ -10,6 +15,9 @@ libraries { visualizer { path /system/lib/soundfx/libvisualizer.so } + pre_processing { + path /system/lib/soundfx/libaudiopreprocessing.so + } } # list of effects to load. Each effect element must contain a "library" and a "uuid" element. @@ -17,6 +25,16 @@ libraries { # "libraries" element. # The name of the effect element is indicative, only the value of the "uuid" element # designates the effect. +# The uuid is the implementation specific UUID as specified by the effect vendor. This is not the +# generic effect type UUID. +# effects { +# <fx name> { +# library <lib name> +# uuid <effect uuid> +# } +# ... +# } + effects { bassboost { library bundle @@ -54,4 +72,55 @@ effects { library visualizer uuid d069d9e0-8329-11df-9168-0002a5d5c51b } + agc { + library pre_processing + uuid aa8130e0-66fc-11e0-bad0-0002a5d5c51b + } + aec { + library pre_processing + uuid bb392ec0-8d4d-11e0-a896-0002a5d5c51b + } + ns { + library pre_processing + uuid c06c8400-8e06-11e0-9cb6-0002a5d5c51b + } } +# Audio preprocessor configurations. +# The pre processor configuration consists in a list of elements each describing +# pre processor settings for a given input source. Valid input source names are: +# "mic", "camcorder", "voice_recognition", "voice_communication" +# Each input source element contains a list of effects elements. The name of the effect +# element must be the name of one of the effects in the "effects" list of the file. +# Each effect element may optionally contain a list of parameters and their +# default value to apply when the pre processor effect is created. +# A parameter is defined by a "param" element and a "value" element. Each of these elements +# consists in one or more elements specifying a type followed by a value. +# The types defined are: "int", "short", "float", "bool" and "string" +# When both "param" and "value" are a single int, a simple form is allowed where just +# the param and value pair is present in the parameter description +# pre_processing { +# <input source name> { +# <fx name> { +# <param 1 name> { +# param { +# int|short|float|bool|string <value> +# [ int|short|float|bool|string <value> ] +# ... +# } +# value { +# int|short|float|bool|string <value> +# [ int|short|float|bool|string <value> ] +# ... +# } +# } +# <param 2 name > {<param> <value>} +# ... +# } +# ... +# } +# ... +# } + +# +# TODO: add default audio pre processor configurations after debug and tuning phase +# diff --git a/media/libeffects/factory/Android.mk b/media/libeffects/factory/Android.mk index 26265ae..2f2b974 100644 --- a/media/libeffects/factory/Android.mk +++ b/media/libeffects/factory/Android.mk @@ -14,4 +14,7 @@ LOCAL_MODULE:= libeffects LOCAL_SHARED_LIBRARIES += libdl +LOCAL_C_INCLUDES := \ + system/media/audio_effects/include + include $(BUILD_SHARED_LIBRARY) diff --git a/media/libeffects/factory/EffectsFactory.c b/media/libeffects/factory/EffectsFactory.c index a9689bc..d333510 100644 --- a/media/libeffects/factory/EffectsFactory.c +++ b/media/libeffects/factory/EffectsFactory.c @@ -24,6 +24,7 @@ #include <cutils/misc.h> #include <cutils/config_utils.h> +#include <audio_effects/audio_effects_conf.h> static list_elem_t *gEffectList; // list of effect_entry_t: all currently created effects static list_elem_t *gLibraryList; // list of lib_entry_t: all currently loaded libraries diff --git a/media/libeffects/factory/EffectsFactory.h b/media/libeffects/factory/EffectsFactory.h index fcc0dba..c1d4319 100644 --- a/media/libeffects/factory/EffectsFactory.h +++ b/media/libeffects/factory/EffectsFactory.h @@ -26,13 +26,6 @@ extern "C" { #endif -#define AUDIO_EFFECT_DEFAULT_CONFIG_FILE "/system/etc/audio_effects.conf" -#define AUDIO_EFFECT_VENDOR_CONFIG_FILE "/vendor/etc/audio_effects.conf" -#define EFFECTS_TAG "effects" -#define LIBRARIES_TAG "libraries" -#define PATH_TAG "path" -#define LIBRARY_TAG "library" -#define UUID_TAG "uuid" typedef struct list_elem_s { void *object; diff --git a/media/libmedia/AudioEffect.cpp b/media/libmedia/AudioEffect.cpp index 8d98900..3919551 100644 --- a/media/libmedia/AudioEffect.cpp +++ b/media/libmedia/AudioEffect.cpp @@ -47,11 +47,11 @@ AudioEffect::AudioEffect(const effect_uuid_t *type, effect_callback_t cbf, void* user, int sessionId, - audio_io_handle_t output + audio_io_handle_t io ) : mStatus(NO_INIT) { - mStatus = set(type, uuid, priority, cbf, user, sessionId, output); + mStatus = set(type, uuid, priority, cbf, user, sessionId, io); } AudioEffect::AudioEffect(const char *typeStr, @@ -60,7 +60,7 @@ AudioEffect::AudioEffect(const char *typeStr, effect_callback_t cbf, void* user, int sessionId, - audio_io_handle_t output + audio_io_handle_t io ) : mStatus(NO_INIT) { @@ -83,7 +83,7 @@ AudioEffect::AudioEffect(const char *typeStr, } } - mStatus = set(pType, pUuid, priority, cbf, user, sessionId, output); + mStatus = set(pType, pUuid, priority, cbf, user, sessionId, io); } status_t AudioEffect::set(const effect_uuid_t *type, @@ -92,13 +92,13 @@ status_t AudioEffect::set(const effect_uuid_t *type, effect_callback_t cbf, void* user, int sessionId, - audio_io_handle_t output) + audio_io_handle_t io) { sp<IEffect> iEffect; sp<IMemory> cblk; int enabled; - LOGV("set %p mUserData: %p", this, user); + LOGV("set %p mUserData: %p uuid: %p timeLow %08x", this, user, type, type ? type->timeLow : 0); if (mIEffect != 0) { LOGW("Effect already in use"); @@ -135,7 +135,7 @@ status_t AudioEffect::set(const effect_uuid_t *type, mIEffectClient = new EffectClient(this); iEffect = audioFlinger->createEffect(getpid(), (effect_descriptor_t *)&mDescriptor, - mIEffectClient, priority, output, mSessionId, &mStatus, &mId, &enabled); + mIEffectClient, priority, io, mSessionId, &mStatus, &mId, &enabled); if (iEffect == 0 || (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS)) { LOGE("set(): AudioFlinger could not create effect, status: %d", mStatus); diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index 4c4aad0..1ec596e 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -162,8 +162,19 @@ status_t AudioRecord::set( int channelCount = popcount(channelMask); + if (sessionId == 0 ) { + mSessionId = AudioSystem::newAudioSessionId(); + } else { + mSessionId = sessionId; + } + LOGV("set(): mSessionId %d", mSessionId); + audio_io_handle_t input = AudioSystem::getInput(inputSource, - sampleRate, format, channelMask, (audio_in_acoustics_t)flags); + sampleRate, + format, + channelMask, + (audio_in_acoustics_t)flags, + mSessionId); if (input == 0) { LOGE("Could not get audio input for record source %d", inputSource); return BAD_VALUE; @@ -187,8 +198,6 @@ status_t AudioRecord::set( notificationFrames = frameCount/2; } - mSessionId = sessionId; - // create the IAudioRecord status = openRecord_l(sampleRate, format, channelMask, frameCount, flags, input); @@ -589,8 +598,10 @@ audio_io_handle_t AudioRecord::getInput_l() { mInput = AudioSystem::getInput(mInputSource, mCblk->sampleRate, - mFormat, mChannelMask, - (audio_in_acoustics_t)mFlags); + mFormat, + mChannelMask, + (audio_in_acoustics_t)mFlags, + mSessionId); return mInput; } diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index 6cb3847..5009957 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -605,11 +605,12 @@ audio_io_handle_t AudioSystem::getInput(int inputSource, uint32_t samplingRate, uint32_t format, uint32_t channels, - audio_in_acoustics_t acoustics) + audio_in_acoustics_t acoustics, + int sessionId) { const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service(); if (aps == 0) return 0; - return aps->getInput(inputSource, samplingRate, format, channels, acoustics); + return aps->getInput(inputSource, samplingRate, format, channels, acoustics, sessionId); } status_t AudioSystem::startInput(audio_io_handle_t input) @@ -678,14 +679,14 @@ audio_io_handle_t AudioSystem::getOutputForEffect(effect_descriptor_t *desc) } status_t AudioSystem::registerEffect(effect_descriptor_t *desc, - audio_io_handle_t output, + audio_io_handle_t io, uint32_t strategy, int session, int id) { const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service(); if (aps == 0) return PERMISSION_DENIED; - return aps->registerEffect(desc, output, strategy, session, id); + return aps->registerEffect(desc, io, strategy, session, id); } status_t AudioSystem::unregisterEffect(int id) @@ -695,9 +696,11 @@ status_t AudioSystem::unregisterEffect(int id) return aps->unregisterEffect(id); } -status_t AudioSystem::isStreamActive(int stream, bool* state, uint32_t inPastMs) { +status_t AudioSystem::isStreamActive(int stream, bool* state, uint32_t inPastMs) +{ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service(); if (aps == 0) return PERMISSION_DENIED; + if (state == NULL) return BAD_VALUE; *state = aps->isStreamActive(stream, inPastMs); return NO_ERROR; } diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp index 9fbcee0..49d410f 100644 --- a/media/libmedia/IAudioPolicyService.cpp +++ b/media/libmedia/IAudioPolicyService.cpp @@ -184,7 +184,8 @@ public: uint32_t samplingRate, uint32_t format, uint32_t channels, - audio_in_acoustics_t acoustics) + audio_in_acoustics_t acoustics, + int audioSession) { Parcel data, reply; data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); @@ -193,6 +194,7 @@ public: data.writeInt32(static_cast <uint32_t>(format)); data.writeInt32(channels); data.writeInt32(static_cast <uint32_t>(acoustics)); + data.writeInt32(audioSession); remote()->transact(GET_INPUT, data, &reply); return static_cast <audio_io_handle_t> (reply.readInt32()); } @@ -285,7 +287,7 @@ public: } virtual status_t registerEffect(effect_descriptor_t *desc, - audio_io_handle_t output, + audio_io_handle_t io, uint32_t strategy, int session, int id) @@ -293,7 +295,7 @@ public: Parcel data, reply; data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); data.write(desc, sizeof(effect_descriptor_t)); - data.writeInt32(output); + data.writeInt32(io); data.writeInt32(strategy); data.writeInt32(session); data.writeInt32(id); @@ -439,11 +441,13 @@ status_t BnAudioPolicyService::onTransact( uint32_t channels = data.readInt32(); audio_in_acoustics_t acoustics = static_cast <audio_in_acoustics_t>(data.readInt32()); + int audioSession = data.readInt32(); audio_io_handle_t input = getInput(inputSource, samplingRate, format, channels, - acoustics); + acoustics, + audioSession); reply->writeInt32(static_cast <int>(input)); return NO_ERROR; } break; @@ -528,12 +532,12 @@ status_t BnAudioPolicyService::onTransact( CHECK_INTERFACE(IAudioPolicyService, data, reply); effect_descriptor_t desc; data.read(&desc, sizeof(effect_descriptor_t)); - audio_io_handle_t output = data.readInt32(); + audio_io_handle_t io = data.readInt32(); uint32_t strategy = data.readInt32(); int session = data.readInt32(); int id = data.readInt32(); reply->writeInt32(static_cast <int32_t>(registerEffect(&desc, - output, + io, strategy, session, id))); diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp index a44ef5a..7e44c29 100644 --- a/media/libmedia/IMediaRecorder.cpp +++ b/media/libmedia/IMediaRecorder.cpp @@ -23,14 +23,17 @@ #include <camera/ICamera.h> #include <media/IMediaRecorderClient.h> #include <media/IMediaRecorder.h> +#include <gui/ISurfaceTexture.h> #include <unistd.h> + namespace android { enum { RELEASE = IBinder::FIRST_CALL_TRANSACTION, INIT, CLOSE, + QUERY_SURFACE_MEDIASOURCE, RESET, STOP, START, @@ -71,6 +74,19 @@ public: return reply.readInt32(); } + sp<ISurfaceTexture> querySurfaceMediaSource() + { + LOGV("Query SurfaceMediaSource"); + Parcel data, reply; + data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); + remote()->transact(QUERY_SURFACE_MEDIASOURCE, data, &reply); + int returnedNull = reply.readInt32(); + if (returnedNull) { + return NULL; + } + return interface_cast<ISurfaceTexture>(reply.readStrongBinder()); + } + status_t setPreviewSurface(const sp<Surface>& surface) { LOGV("setPreviewSurface(%p)", surface.get()); @@ -440,6 +456,20 @@ status_t BnMediaRecorder::onTransact( reply->writeInt32(setCamera(camera, proxy)); return NO_ERROR; } break; + case QUERY_SURFACE_MEDIASOURCE: { + LOGV("QUERY_SURFACE_MEDIASOURCE"); + CHECK_INTERFACE(IMediaRecorder, data, reply); + // call the mediaserver side to create + // a surfacemediasource + sp<ISurfaceTexture> surfaceMediaSource = querySurfaceMediaSource(); + // The mediaserver might have failed to create a source + int returnedNull= (surfaceMediaSource == NULL) ? 1 : 0 ; + reply->writeInt32(returnedNull); + if (!returnedNull) { + reply->writeStrongBinder(surfaceMediaSource->asBinder()); + } + return NO_ERROR; + } break; default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/media/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp index 069bbb7..f0f07a2 100644 --- a/media/libmedia/MediaProfiles.cpp +++ b/media/libmedia/MediaProfiles.cpp @@ -132,6 +132,16 @@ MediaProfiles::logAudioDecoderCap(const MediaProfiles::AudioDecoderCap& cap) LOGV("codec = %d", cap.mCodec); } +/*static*/ void +MediaProfiles::logVideoEditorCap(const MediaProfiles::VideoEditorCap& cap) +{ + LOGV("videoeditor cap:"); + LOGV("mMaxInputFrameWidth = %d", cap.mMaxInputFrameWidth); + LOGV("mMaxInputFrameHeight = %d", cap.mMaxInputFrameHeight); + LOGV("mMaxOutputFrameWidth = %d", cap.mMaxOutputFrameWidth); + LOGV("mMaxOutputFrameHeight = %d", cap.mMaxOutputFrameHeight); +} + /*static*/ int MediaProfiles::findTagForName(const MediaProfiles::NameToTagMap *map, size_t nMappings, const char *name) { @@ -368,6 +378,24 @@ void MediaProfiles::addStartTimeOffset(int cameraId, const char** atts) mStartTimeOffsets.replaceValueFor(cameraId, offsetTimeMs); } +/*static*/ MediaProfiles::VideoEditorCap* +MediaProfiles::createVideoEditorCap(const char **atts, MediaProfiles *profiles) +{ + CHECK(!strcmp("maxInputFrameWidth", atts[0]) && + !strcmp("maxInputFrameHeight", atts[2]) && + !strcmp("maxOutputFrameWidth", atts[4]) && + !strcmp("maxOutputFrameHeight", atts[6])); + + MediaProfiles::VideoEditorCap *pVideoEditorCap = + new MediaProfiles::VideoEditorCap(atoi(atts[1]), atoi(atts[3]), + atoi(atts[5]), atoi(atts[7])); + + logVideoEditorCap(*pVideoEditorCap); + profiles->mVideoEditorCap = pVideoEditorCap; + + return pVideoEditorCap; +} + /*static*/ void MediaProfiles::startElementHandler(void *userData, const char *name, const char **atts) { @@ -398,6 +426,8 @@ MediaProfiles::startElementHandler(void *userData, const char *name, const char createCamcorderProfile(profiles->mCurrentCameraId, atts, profiles->mCameraIds)); } else if (strcmp("ImageEncoding", name) == 0) { profiles->addImageEncodingQualityLevel(profiles->mCurrentCameraId, atts); + } else if (strcmp("VideoEditorCap", name) == 0) { + createVideoEditorCap(atts, profiles); } } @@ -790,6 +820,17 @@ MediaProfiles::createDefaultImageEncodingQualityLevels(MediaProfiles *profiles) profiles->mImageEncodingQualityLevels.add(levels); } +/*static*/ void +MediaProfiles::createDefaultVideoEditorCap(MediaProfiles *profiles) +{ + profiles->mVideoEditorCap = + new MediaProfiles::VideoEditorCap( + VIDEOEDITOR_DEFAULT_MAX_INPUT_FRAME_WIDTH, + VIDEOEDITOR_DEFUALT_MAX_INPUT_FRAME_HEIGHT, + VIDEOEDITOR_DEFAULT_MAX_OUTPUT_FRAME_WIDTH, + VIDEOEDITOR_DEFUALT_MAX_OUTPUT_FRAME_HEIGHT); +} + /*static*/ MediaProfiles* MediaProfiles::createDefaultInstance() { @@ -801,6 +842,7 @@ MediaProfiles::createDefaultInstance() createDefaultAudioDecoders(profiles); createDefaultEncoderOutputFileFormats(profiles); createDefaultImageEncodingQualityLevels(profiles); + createDefaultVideoEditorCap(profiles); return profiles; } @@ -899,6 +941,28 @@ int MediaProfiles::getVideoEncoderParamByName(const char *name, video_encoder co return -1; } +int MediaProfiles::getVideoEditorCapParamByName(const char *name) const +{ + LOGV("getVideoEditorCapParamByName: %s", name); + + if (mVideoEditorCap == NULL) { + LOGE("The mVideoEditorCap is not created, then create default cap."); + createDefaultVideoEditorCap(sInstance); + } + + if (!strcmp("videoeditor.input.width.max", name)) + return mVideoEditorCap->mMaxInputFrameWidth; + if (!strcmp("videoeditor.input.height.max", name)) + return mVideoEditorCap->mMaxInputFrameHeight; + if (!strcmp("videoeditor.output.width.max", name)) + return mVideoEditorCap->mMaxOutputFrameWidth; + if (!strcmp("videoeditor.output.height.max", name)) + return mVideoEditorCap->mMaxOutputFrameHeight; + + LOGE("The given video editor param name %s is not found", name); + return -1; +} + Vector<audio_encoder> MediaProfiles::getAudioEncoders() const { Vector<audio_encoder> encoders; diff --git a/media/libmedia/MediaScanner.cpp b/media/libmedia/MediaScanner.cpp index 45bdff4..41f8593 100644 --- a/media/libmedia/MediaScanner.cpp +++ b/media/libmedia/MediaScanner.cpp @@ -47,16 +47,15 @@ const char *MediaScanner::locale() const { return mLocale; } -status_t MediaScanner::processDirectory( - const char *path, MediaScannerClient &client, - ExceptionCheck exceptionCheck, void *exceptionEnv) { +MediaScanResult MediaScanner::processDirectory( + const char *path, MediaScannerClient &client) { int pathLength = strlen(path); if (pathLength >= PATH_MAX) { - return UNKNOWN_ERROR; + return MEDIA_SCAN_RESULT_SKIPPED; } char* pathBuffer = (char *)malloc(PATH_MAX + 1); if (!pathBuffer) { - return UNKNOWN_ERROR; + return MEDIA_SCAN_RESULT_ERROR; } int pathRemaining = PATH_MAX - pathLength; @@ -69,21 +68,18 @@ status_t MediaScanner::processDirectory( client.setLocale(locale()); - status_t result = - doProcessDirectory(pathBuffer, pathRemaining, client, false, exceptionCheck, exceptionEnv); + MediaScanResult result = doProcessDirectory(pathBuffer, pathRemaining, client, false); free(pathBuffer); return result; } -status_t MediaScanner::doProcessDirectory( - char *path, int pathRemaining, MediaScannerClient &client, - bool noMedia, ExceptionCheck exceptionCheck, void *exceptionEnv) { +MediaScanResult MediaScanner::doProcessDirectory( + char *path, int pathRemaining, MediaScannerClient &client, bool noMedia) { // place to copy file or directory name char* fileSpot = path + strlen(path); struct dirent* entry; - struct stat statbuf; // Treat all files as non-media in directories that contain a ".nomedia" file if (pathRemaining >= 8 /* strlen(".nomedia") */ ) { @@ -99,76 +95,88 @@ status_t MediaScanner::doProcessDirectory( DIR* dir = opendir(path); if (!dir) { - LOGD("opendir %s failed, errno: %d", path, errno); - return UNKNOWN_ERROR; + LOGW("Error opening directory '%s', skipping: %s.", path, strerror(errno)); + return MEDIA_SCAN_RESULT_SKIPPED; } + MediaScanResult result = MEDIA_SCAN_RESULT_OK; while ((entry = readdir(dir))) { - const char* name = entry->d_name; - - // ignore "." and ".." - if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) { - continue; + if (doProcessDirectoryEntry(path, pathRemaining, client, noMedia, entry, fileSpot) + == MEDIA_SCAN_RESULT_ERROR) { + result = MEDIA_SCAN_RESULT_ERROR; + break; } + } + closedir(dir); + return result; +} - int nameLength = strlen(name); - if (nameLength + 1 > pathRemaining) { - // path too long! - continue; - } - strcpy(fileSpot, name); - - int type = entry->d_type; - if (type == DT_UNKNOWN) { - // If the type is unknown, stat() the file instead. - // This is sometimes necessary when accessing NFS mounted filesystems, but - // could be needed in other cases well. - if (stat(path, &statbuf) == 0) { - if (S_ISREG(statbuf.st_mode)) { - type = DT_REG; - } else if (S_ISDIR(statbuf.st_mode)) { - type = DT_DIR; - } - } else { - LOGD("stat() failed for %s: %s", path, strerror(errno) ); +MediaScanResult MediaScanner::doProcessDirectoryEntry( + char *path, int pathRemaining, MediaScannerClient &client, bool noMedia, + struct dirent* entry, char* fileSpot) { + struct stat statbuf; + const char* name = entry->d_name; + + // ignore "." and ".." + if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) { + return MEDIA_SCAN_RESULT_SKIPPED; + } + + int nameLength = strlen(name); + if (nameLength + 1 > pathRemaining) { + // path too long! + return MEDIA_SCAN_RESULT_SKIPPED; + } + strcpy(fileSpot, name); + + int type = entry->d_type; + if (type == DT_UNKNOWN) { + // If the type is unknown, stat() the file instead. + // This is sometimes necessary when accessing NFS mounted filesystems, but + // could be needed in other cases well. + if (stat(path, &statbuf) == 0) { + if (S_ISREG(statbuf.st_mode)) { + type = DT_REG; + } else if (S_ISDIR(statbuf.st_mode)) { + type = DT_DIR; } + } else { + LOGD("stat() failed for %s: %s", path, strerror(errno) ); } - if (type == DT_REG || type == DT_DIR) { - if (type == DT_DIR) { - bool childNoMedia = noMedia; - // set noMedia flag on directories with a name that starts with '.' - // for example, the Mac ".Trashes" directory - if (name[0] == '.') - childNoMedia = true; - - // report the directory to the client - if (stat(path, &statbuf) == 0) { - client.scanFile(path, statbuf.st_mtime, 0, true, childNoMedia); - } - - // and now process its contents - strcat(fileSpot, "/"); - int err = doProcessDirectory(path, pathRemaining - nameLength - 1, client, - childNoMedia, exceptionCheck, exceptionEnv); - if (err) { - // pass exceptions up - ignore other errors - if (exceptionCheck && exceptionCheck(exceptionEnv)) goto failure; - LOGE("Error processing '%s' - skipping\n", path); - continue; - } - } else { - stat(path, &statbuf); - client.scanFile(path, statbuf.st_mtime, statbuf.st_size, false, noMedia); - if (exceptionCheck && exceptionCheck(exceptionEnv)) goto failure; + } + if (type == DT_DIR) { + bool childNoMedia = noMedia; + // set noMedia flag on directories with a name that starts with '.' + // for example, the Mac ".Trashes" directory + if (name[0] == '.') + childNoMedia = true; + + // report the directory to the client + if (stat(path, &statbuf) == 0) { + status_t status = client.scanFile(path, statbuf.st_mtime, 0, + true /*isDirectory*/, childNoMedia); + if (status) { + return MEDIA_SCAN_RESULT_ERROR; } } + + // and now process its contents + strcat(fileSpot, "/"); + MediaScanResult result = doProcessDirectory(path, pathRemaining - nameLength - 1, + client, childNoMedia); + if (result == MEDIA_SCAN_RESULT_ERROR) { + return MEDIA_SCAN_RESULT_ERROR; + } + } else if (type == DT_REG) { + stat(path, &statbuf); + status_t status = client.scanFile(path, statbuf.st_mtime, statbuf.st_size, + false /*isDirectory*/, noMedia); + if (status) { + return MEDIA_SCAN_RESULT_ERROR; + } } - closedir(dir); - return OK; -failure: - closedir(dir); - return -1; + return MEDIA_SCAN_RESULT_OK; } } // namespace android diff --git a/media/libmedia/MediaScannerClient.cpp b/media/libmedia/MediaScannerClient.cpp index bd3596e..7a7aeb6 100644 --- a/media/libmedia/MediaScannerClient.cpp +++ b/media/libmedia/MediaScannerClient.cpp @@ -62,7 +62,7 @@ void MediaScannerClient::beginFile() mValues = new StringArray; } -bool MediaScannerClient::addStringTag(const char* name, const char* value) +status_t MediaScannerClient::addStringTag(const char* name, const char* value) { if (mLocaleEncoding != kEncodingNone) { // don't bother caching strings that are all ASCII. @@ -212,8 +212,10 @@ void MediaScannerClient::endFile() // finally, push all name/value pairs to the client for (int i = 0; i < mNames->size(); i++) { - if (!handleStringTag(mNames->getEntry(i), mValues->getEntry(i))) + status_t status = handleStringTag(mNames->getEntry(i), mValues->getEntry(i)); + if (status) { break; + } } } // else addStringTag() has done all the work so we have nothing to do diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp index 178039c..a11fb80 100644 --- a/media/libmedia/mediaplayer.cpp +++ b/media/libmedia/mediaplayer.cpp @@ -84,6 +84,8 @@ void MediaPlayer::disconnect() if (p != 0) { p->disconnect(); } + + disconnectNativeWindow(); } // always call with lock held @@ -226,6 +228,7 @@ status_t MediaPlayer::setVideoSurface(const sp<Surface>& surface) NATIVE_WINDOW_API_MEDIA); if (err != OK) { + LOGE("setVideoSurface failed: %d", err); // Note that we must do the reset before disconnecting from the ANW. // Otherwise queue/dequeue calls could be made on the disconnected // ANW, which may result in errors. @@ -275,6 +278,7 @@ status_t MediaPlayer::setVideoSurfaceTexture( NATIVE_WINDOW_API_MEDIA); if (err != OK) { + LOGE("setVideoSurfaceTexture failed: %d", err); // Note that we must do the reset before disconnecting from the ANW. // Otherwise queue/dequeue calls could be made on the disconnected // ANW, which may result in errors. diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp index 9e4edd0..fab674c 100644 --- a/media/libmedia/mediarecorder.cpp +++ b/media/libmedia/mediarecorder.cpp @@ -25,6 +25,7 @@ #include <media/IMediaPlayerService.h> #include <media/IMediaRecorder.h> #include <media/mediaplayer.h> // for MEDIA_ERROR_SERVER_DIED +#include <gui/ISurfaceTexture.h> namespace android { @@ -127,7 +128,9 @@ status_t MediaRecorder::setVideoSource(int vs) return INVALID_OPERATION; } + // following call is made over the Binder Interface status_t ret = mMediaRecorder->setVideoSource(vs); + if (OK != ret) { LOGV("setVideoSource failed: %d", ret); mCurrentState = MEDIA_RECORDER_ERROR; @@ -357,7 +360,7 @@ status_t MediaRecorder::setVideoSize(int width, int height) return INVALID_OPERATION; } if (!mIsVideoSourceSet) { - LOGE("try to set video size without setting video source first"); + LOGE("Cannot set video size without setting video source first"); return INVALID_OPERATION; } @@ -367,9 +370,27 @@ status_t MediaRecorder::setVideoSize(int width, int height) mCurrentState = MEDIA_RECORDER_ERROR; return ret; } + return ret; } +// Query a SurfaceMediaSurface through the Mediaserver, over the +// binder interface. This is used by the Filter Framework (MeidaEncoder) +// to get an <ISurfaceTexture> object to hook up to ANativeWindow. +sp<ISurfaceTexture> MediaRecorder:: + querySurfaceMediaSourceFromMediaServer() +{ + Mutex::Autolock _l(mLock); + mSurfaceMediaSource = + mMediaRecorder->querySurfaceMediaSource(); + if (mSurfaceMediaSource == NULL) { + LOGE("SurfaceMediaSource could not be initialized!"); + } + return mSurfaceMediaSource; +} + + + status_t MediaRecorder::setVideoFrameRate(int frames_per_second) { LOGV("setVideoFrameRate(%d)", frames_per_second); @@ -382,7 +403,7 @@ status_t MediaRecorder::setVideoFrameRate(int frames_per_second) return INVALID_OPERATION; } if (!mIsVideoSourceSet) { - LOGE("try to set video frame rate without setting video source first"); + LOGE("Cannot set video frame rate without setting video source first"); return INVALID_OPERATION; } @@ -621,7 +642,7 @@ status_t MediaRecorder::release() return INVALID_OPERATION; } -MediaRecorder::MediaRecorder() +MediaRecorder::MediaRecorder() : mSurfaceMediaSource(NULL) { LOGV("constructor"); @@ -632,6 +653,8 @@ MediaRecorder::MediaRecorder() if (mMediaRecorder != NULL) { mCurrentState = MEDIA_RECORDER_IDLE; } + + doCleanUp(); } @@ -646,6 +669,10 @@ MediaRecorder::~MediaRecorder() if (mMediaRecorder != NULL) { mMediaRecorder.clear(); } + + if (mSurfaceMediaSource != NULL) { + mSurfaceMediaSource.clear(); + } } status_t MediaRecorder::setListener(const sp<MediaRecorderListener>& listener) diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp index 115db1a..905b885 100644 --- a/media/libmediaplayerservice/MediaRecorderClient.cpp +++ b/media/libmediaplayerservice/MediaRecorderClient.cpp @@ -41,6 +41,7 @@ #include "MediaPlayerService.h" #include "StagefrightRecorder.h" +#include <gui/ISurfaceTexture.h> namespace android { @@ -57,6 +58,20 @@ static bool checkPermission(const char* permissionString) { return ok; } + +sp<ISurfaceTexture> MediaRecorderClient::querySurfaceMediaSource() +{ + LOGV("Query SurfaceMediaSource"); + Mutex::Autolock lock(mLock); + if (mRecorder == NULL) { + LOGE("recorder is not initialized"); + return NULL; + } + return mRecorder->querySurfaceMediaSource(); +} + + + status_t MediaRecorderClient::setCamera(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy) { diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h index bbca529..c87a3c0 100644 --- a/media/libmediaplayerservice/MediaRecorderClient.h +++ b/media/libmediaplayerservice/MediaRecorderClient.h @@ -25,45 +25,51 @@ namespace android { class MediaRecorderBase; class MediaPlayerService; class ICameraRecordingProxy; +class ISurfaceTexture; class MediaRecorderClient : public BnMediaRecorder { public: - virtual status_t setCamera(const sp<ICamera>& camera, - const sp<ICameraRecordingProxy>& proxy); - virtual status_t setPreviewSurface(const sp<Surface>& surface); - virtual status_t setVideoSource(int vs); - virtual status_t setAudioSource(int as); - virtual status_t setOutputFormat(int of); - virtual status_t setVideoEncoder(int ve); - virtual status_t setAudioEncoder(int ae); - virtual status_t setOutputFile(const char* path); - virtual status_t setOutputFile(int fd, int64_t offset, int64_t length); - virtual status_t setOutputFileAuxiliary(int fd); - virtual status_t setVideoSize(int width, int height); - virtual status_t setVideoFrameRate(int frames_per_second); - virtual status_t setParameters(const String8& params); - virtual status_t setListener(const sp<IMediaRecorderClient>& listener); - virtual status_t prepare(); - virtual status_t getMaxAmplitude(int* max); - virtual status_t start(); - virtual status_t stop(); - virtual status_t reset(); - virtual status_t init(); - virtual status_t close(); - virtual status_t release(); + virtual status_t setCamera(const sp<ICamera>& camera, + const sp<ICameraRecordingProxy>& proxy); + virtual status_t setPreviewSurface(const sp<Surface>& surface); + virtual status_t setVideoSource(int vs); + virtual status_t setAudioSource(int as); + virtual status_t setOutputFormat(int of); + virtual status_t setVideoEncoder(int ve); + virtual status_t setAudioEncoder(int ae); + virtual status_t setOutputFile(const char* path); + virtual status_t setOutputFile(int fd, int64_t offset, + int64_t length); + virtual status_t setOutputFileAuxiliary(int fd); + virtual status_t setVideoSize(int width, int height); + virtual status_t setVideoFrameRate(int frames_per_second); + virtual status_t setParameters(const String8& params); + virtual status_t setListener( + const sp<IMediaRecorderClient>& listener); + virtual status_t prepare(); + virtual status_t getMaxAmplitude(int* max); + virtual status_t start(); + virtual status_t stop(); + virtual status_t reset(); + virtual status_t init(); + virtual status_t close(); + virtual status_t release(); + virtual status_t dump(int fd, const Vector<String16>& args) const; + virtual sp<ISurfaceTexture> querySurfaceMediaSource(); - virtual status_t dump(int fd, const Vector<String16>& args) const; private: - friend class MediaPlayerService; // for accessing private constructor + friend class MediaPlayerService; // for accessing private constructor - MediaRecorderClient(const sp<MediaPlayerService>& service, pid_t pid); - virtual ~MediaRecorderClient(); + MediaRecorderClient( + const sp<MediaPlayerService>& service, + pid_t pid); + virtual ~MediaRecorderClient(); - pid_t mPid; - Mutex mLock; - MediaRecorderBase *mRecorder; - sp<MediaPlayerService> mMediaPlayerService; + pid_t mPid; + Mutex mLock; + MediaRecorderBase *mRecorder; + sp<MediaPlayerService> mMediaPlayerService; }; }; // namespace android diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp index 223e0be..6427bb7 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.cpp +++ b/media/libmediaplayerservice/StagefrightRecorder.cpp @@ -38,10 +38,12 @@ #include <media/stagefright/MetaData.h> #include <media/stagefright/OMXClient.h> #include <media/stagefright/OMXCodec.h> +#include <media/stagefright/SurfaceMediaSource.h> #include <media/MediaProfiles.h> #include <camera/ICamera.h> #include <camera/CameraParameters.h> #include <surfaceflinger/Surface.h> + #include <utils/Errors.h> #include <sys/types.h> #include <ctype.h> @@ -69,7 +71,7 @@ StagefrightRecorder::StagefrightRecorder() mOutputFd(-1), mOutputFdAux(-1), mAudioSource(AUDIO_SOURCE_CNT), mVideoSource(VIDEO_SOURCE_LIST_END), - mStarted(false) { + mStarted(false), mSurfaceMediaSource(NULL) { LOGV("Constructor"); reset(); @@ -85,6 +87,14 @@ status_t StagefrightRecorder::init() { return OK; } +// The client side of mediaserver asks it to creat a SurfaceMediaSource +// and return a interface reference. The client side will use that +// while encoding GL Frames +sp<ISurfaceTexture> StagefrightRecorder::querySurfaceMediaSource() const { + LOGV("Get SurfaceMediaSource"); + return mSurfaceMediaSource; +} + status_t StagefrightRecorder::setAudioSource(audio_source_t as) { LOGV("setAudioSource: %d", as); if (as < AUDIO_SOURCE_DEFAULT || @@ -1006,13 +1016,13 @@ status_t StagefrightRecorder::startRTPRecording() { source = createAudioSource(); } else { - sp<CameraSource> cameraSource; - status_t err = setupCameraSource(&cameraSource); + sp<MediaSource> mediaSource; + status_t err = setupMediaSource(&mediaSource); if (err != OK) { return err; } - err = setupVideoEncoder(cameraSource, mVideoBitRate, &source); + err = setupVideoEncoder(mediaSource, mVideoBitRate, &source); if (err != OK) { return err; } @@ -1042,20 +1052,19 @@ status_t StagefrightRecorder::startMPEG2TSRecording() { } } - if (mVideoSource == VIDEO_SOURCE_DEFAULT - || mVideoSource == VIDEO_SOURCE_CAMERA) { + if (mVideoSource < VIDEO_SOURCE_LIST_END) { if (mVideoEncoder != VIDEO_ENCODER_H264) { return ERROR_UNSUPPORTED; } - sp<CameraSource> cameraSource; - status_t err = setupCameraSource(&cameraSource); + sp<MediaSource> mediaSource; + status_t err = setupMediaSource(&mediaSource); if (err != OK) { return err; } sp<MediaSource> encoder; - err = setupVideoEncoder(cameraSource, mVideoBitRate, &encoder); + err = setupVideoEncoder(mediaSource, mVideoBitRate, &encoder); if (err != OK) { return err; @@ -1289,6 +1298,60 @@ void StagefrightRecorder::clipVideoFrameHeight() { } } +// Set up the appropriate MediaSource depending on the chosen option +status_t StagefrightRecorder::setupMediaSource( + sp<MediaSource> *mediaSource) { + if (mVideoSource == VIDEO_SOURCE_DEFAULT + || mVideoSource == VIDEO_SOURCE_CAMERA) { + sp<CameraSource> cameraSource; + status_t err = setupCameraSource(&cameraSource); + if (err != OK) { + return err; + } + *mediaSource = cameraSource; + } else if (mVideoSource == VIDEO_SOURCE_GRALLOC_BUFFER) { + // If using GRAlloc buffers, setup surfacemediasource. + // Later a handle to that will be passed + // to the client side when queried + status_t err = setupSurfaceMediaSource(); + if (err != OK) { + return err; + } + *mediaSource = mSurfaceMediaSource; + } else { + return INVALID_OPERATION; + } + return OK; +} + +// setupSurfaceMediaSource creates a source with the given +// width and height and framerate. +// TODO: This could go in a static function inside SurfaceMediaSource +// similar to that in CameraSource +status_t StagefrightRecorder::setupSurfaceMediaSource() { + status_t err = OK; + mSurfaceMediaSource = new SurfaceMediaSource(mVideoWidth, mVideoHeight); + if (mSurfaceMediaSource == NULL) { + return NO_INIT; + } + + if (mFrameRate == -1) { + int32_t frameRate = 0; + CHECK (mSurfaceMediaSource->getFormat()->findInt32( + kKeyFrameRate, &frameRate)); + LOGI("Frame rate is not explicitly set. Use the current frame " + "rate (%d fps)", frameRate); + mFrameRate = frameRate; + } else { + err = mSurfaceMediaSource->setFrameRate(mFrameRate); + } + CHECK(mFrameRate != -1); + + mIsMetaDataStoredInVideoBuffers = + mSurfaceMediaSource->isMetaDataStoredInVideoBuffers(); + return err; +} + status_t StagefrightRecorder::setupCameraSource( sp<CameraSource> *cameraSource) { status_t err = OK; @@ -1465,29 +1528,37 @@ status_t StagefrightRecorder::setupMPEG4Recording( status_t err = OK; sp<MediaWriter> writer = new MPEG4Writer(outputFd); - if (mVideoSource == VIDEO_SOURCE_DEFAULT - || mVideoSource == VIDEO_SOURCE_CAMERA) { + if (mVideoSource < VIDEO_SOURCE_LIST_END) { - sp<MediaSource> cameraMediaSource; + sp<MediaSource> mediaSource; if (useSplitCameraSource) { + // TODO: Check if there is a better way to handle this + if (mVideoSource == VIDEO_SOURCE_GRALLOC_BUFFER) { + LOGE("Cannot use split camera when encoding frames"); + return INVALID_OPERATION; + } LOGV("Using Split camera source"); - cameraMediaSource = mCameraSourceSplitter->createClient(); + mediaSource = mCameraSourceSplitter->createClient(); } else { - sp<CameraSource> cameraSource; - err = setupCameraSource(&cameraSource); - cameraMediaSource = cameraSource; + err = setupMediaSource(&mediaSource); } + if ((videoWidth != mVideoWidth) || (videoHeight != mVideoHeight)) { + // TODO: Might be able to handle downsampling even if using GRAlloc + if (mVideoSource == VIDEO_SOURCE_GRALLOC_BUFFER) { + LOGE("Cannot change size or Downsample when encoding frames"); + return INVALID_OPERATION; + } // Use downsampling from the original source. - cameraMediaSource = - new VideoSourceDownSampler(cameraMediaSource, videoWidth, videoHeight); + mediaSource = + new VideoSourceDownSampler(mediaSource, videoWidth, videoHeight); } if (err != OK) { return err; } sp<MediaSource> encoder; - err = setupVideoEncoder(cameraMediaSource, videoBitRate, &encoder); + err = setupVideoEncoder(mediaSource, videoBitRate, &encoder); if (err != OK) { return err; } diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h index 034b373..1618b92 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.h +++ b/media/libmediaplayerservice/StagefrightRecorder.h @@ -36,6 +36,8 @@ struct MediaWriter; class MetaData; struct AudioSource; class MediaProfiles; +class ISurfaceTexture; +class SurfaceMediaSource; struct StagefrightRecorder : public MediaRecorderBase { StagefrightRecorder(); @@ -64,6 +66,8 @@ struct StagefrightRecorder : public MediaRecorderBase { virtual status_t reset(); virtual status_t getMaxAmplitude(int *max); virtual status_t dump(int fd, const Vector<String16>& args) const; + // Querying a SurfaceMediaSourcer + virtual sp<ISurfaceTexture> querySurfaceMediaSource() const; private: sp<ICamera> mCamera; @@ -109,12 +113,18 @@ private: sp<MediaSourceSplitter> mCameraSourceSplitter; sp<CameraSourceTimeLapse> mCameraSourceTimeLapse; + String8 mParams; bool mIsMetaDataStoredInVideoBuffers; MediaProfiles *mEncoderProfiles; bool mStarted; + // Needed when GLFrames are encoded. + // An <ISurfaceTexture> pointer + // will be sent to the client side using which the + // frame buffers will be queued and dequeued + sp<SurfaceMediaSource> mSurfaceMediaSource; status_t setupMPEG4Recording( bool useSplitCameraSource, @@ -134,7 +144,14 @@ private: sp<MediaSource> createAudioSource(); status_t checkVideoEncoderCapabilities(); status_t checkAudioEncoderCapabilities(); + // Generic MediaSource set-up. Returns the appropriate + // source (CameraSource or SurfaceMediaSource) + // depending on the videosource type + status_t setupMediaSource(sp<MediaSource> *mediaSource); status_t setupCameraSource(sp<CameraSource> *cameraSource); + // setup the surfacemediasource for the encoder + status_t setupSurfaceMediaSource(); + status_t setupAudioEncoder(const sp<MediaWriter>& writer); status_t setupVideoEncoder( sp<MediaSource> cameraSource, @@ -176,6 +193,7 @@ private: void clipNumberOfAudioChannels(); void setDefaultProfileIfNecessary(); + StagefrightRecorder(const StagefrightRecorder &); StagefrightRecorder &operator=(const StagefrightRecorder &); }; diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk index e17e1e8..3a3c082 100644 --- a/media/libstagefright/Android.mk +++ b/media/libstagefright/Android.mk @@ -42,6 +42,7 @@ LOCAL_SRC_FILES:= \ SampleTable.cpp \ StagefrightMediaScanner.cpp \ StagefrightMetadataRetriever.cpp \ + SurfaceMediaSource.cpp \ ThrottledSource.cpp \ TimeSource.cpp \ TimedEventQueue.cpp \ diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp index 1bc2fb9..de66d99 100755 --- a/media/libstagefright/CameraSource.cpp +++ b/media/libstagefright/CameraSource.cpp @@ -179,9 +179,6 @@ status_t CameraSource::isCameraAvailable( if (camera == 0) { mCamera = Camera::connect(cameraId); if (mCamera == 0) return -EBUSY; - // If proxy is not passed in by applications, still use the proxy of - // our own Camera to simplify the code. - mCameraRecordingProxy = mCamera->getRecordingProxy(); mCameraFlags &= ~FLAGS_HOT_CAMERA; } else { // We get the proxy from Camera, not ICamera. We need to get the proxy @@ -192,12 +189,12 @@ status_t CameraSource::isCameraAvailable( if (mCamera == 0) return -EBUSY; mCameraRecordingProxy = proxy; mCameraFlags |= FLAGS_HOT_CAMERA; + mDeathNotifier = new DeathNotifier(); + // isBinderAlive needs linkToDeath to work. + mCameraRecordingProxy->asBinder()->linkToDeath(mDeathNotifier); } mCamera->lock(); - mDeathNotifier = new DeathNotifier(); - // isBinderAlive needs linkToDeath to work. - mCameraRecordingProxy->asBinder()->linkToDeath(mDeathNotifier); return OK; } @@ -292,7 +289,7 @@ status_t CameraSource::configureCamera( CameraParameters* params, int32_t width, int32_t height, int32_t frameRate) { - + LOGV("configureCamera"); Vector<Size> sizes; bool isSetVideoSizeSupportedByCamera = true; getSupportedVideoSizes(*params, &isSetVideoSizeSupportedByCamera, sizes); @@ -368,6 +365,7 @@ status_t CameraSource::checkVideoSize( const CameraParameters& params, int32_t width, int32_t height) { + LOGV("checkVideoSize"); // The actual video size is the same as the preview size // if the camera hal does not support separate video and // preview output. In this case, we retrieve the video @@ -419,6 +417,7 @@ status_t CameraSource::checkFrameRate( const CameraParameters& params, int32_t frameRate) { + LOGV("checkFrameRate"); int32_t frameRateActual = params.getPreviewFrameRate(); if (frameRateActual < 0) { LOGE("Failed to retrieve preview frame rate (%d)", frameRateActual); @@ -464,6 +463,7 @@ status_t CameraSource::init( int32_t frameRate, bool storeMetaDataInVideoBuffers) { + LOGV("init"); status_t err = OK; int64_t token = IPCThreadState::self()->clearCallingIdentity(); err = initWithCameraAccess(camera, proxy, cameraId, @@ -480,6 +480,7 @@ status_t CameraSource::initWithCameraAccess( Size videoSize, int32_t frameRate, bool storeMetaDataInVideoBuffers) { + LOGV("initWithCameraAccess"); status_t err = OK; if ((err = isCameraAvailable(camera, proxy, cameraId)) != OK) { @@ -552,17 +553,25 @@ CameraSource::~CameraSource() { } void CameraSource::startCameraRecording() { + LOGV("startCameraRecording"); // Reset the identity to the current thread because media server owns the // camera and recording is started by the applications. The applications // will connect to the camera in ICameraRecordingProxy::startRecording. int64_t token = IPCThreadState::self()->clearCallingIdentity(); - mCamera->unlock(); - mCamera.clear(); + if (mCameraFlags & FLAGS_HOT_CAMERA) { + mCamera->unlock(); + mCamera.clear(); + CHECK_EQ(OK, mCameraRecordingProxy->startRecording(new ProxyListener(this))); + } else { + mCamera->setListener(new CameraSourceListener(this)); + mCamera->startRecording(); + CHECK(mCamera->recordingEnabled()); + } IPCThreadState::self()->restoreCallingIdentity(token); - CHECK_EQ(OK, mCameraRecordingProxy->startRecording(new ProxyListener(this))); } status_t CameraSource::start(MetaData *meta) { + LOGV("start"); CHECK(!mStarted); if (mInitCheck != OK) { LOGE("CameraSource is not initialized yet"); @@ -588,7 +597,13 @@ status_t CameraSource::start(MetaData *meta) { } void CameraSource::stopCameraRecording() { - mCameraRecordingProxy->stopRecording(); + LOGV("stopCameraRecording"); + if (mCameraFlags & FLAGS_HOT_CAMERA) { + mCameraRecordingProxy->stopRecording(); + } else { + mCamera->setListener(NULL); + mCamera->stopRecording(); + } } void CameraSource::releaseCamera() { @@ -599,11 +614,10 @@ void CameraSource::releaseCamera() { LOGV("Camera was cold when we started, stopping preview"); mCamera->stopPreview(); mCamera->disconnect(); - } else { - // Unlock the camera so the application can lock it back. - mCamera->unlock(); } + mCamera->unlock(); mCamera.clear(); + mCamera = 0; IPCThreadState::self()->restoreCallingIdentity(token); } if (mCameraRecordingProxy != 0) { @@ -646,8 +660,13 @@ status_t CameraSource::stop() { } void CameraSource::releaseRecordingFrame(const sp<IMemory>& frame) { + LOGV("releaseRecordingFrame"); if (mCameraRecordingProxy != NULL) { mCameraRecordingProxy->releaseRecordingFrame(frame); + } else { + int64_t token = IPCThreadState::self()->clearCallingIdentity(); + mCamera->releaseRecordingFrame(frame); + IPCThreadState::self()->restoreCallingIdentity(token); } } @@ -707,7 +726,8 @@ status_t CameraSource::read( while (mStarted && mFramesReceived.empty()) { if (NO_ERROR != mFrameAvailableCondition.waitRelative(mLock, 1000000000LL)) { - if (!mCameraRecordingProxy->asBinder()->isBinderAlive()) { + if (mCameraRecordingProxy != 0 && + !mCameraRecordingProxy->asBinder()->isBinderAlive()) { LOGW("camera recording proxy is gone"); return ERROR_END_OF_STREAM; } diff --git a/media/libstagefright/NuCachedSource2.cpp b/media/libstagefright/NuCachedSource2.cpp index 77a6602..4edb613 100644 --- a/media/libstagefright/NuCachedSource2.cpp +++ b/media/libstagefright/NuCachedSource2.cpp @@ -185,7 +185,8 @@ NuCachedSource2::NuCachedSource2(const sp<DataSource> &source) mFinalStatus(OK), mLastAccessPos(0), mFetching(true), - mLastFetchTimeUs(-1) { + mLastFetchTimeUs(-1), + mNumRetriesLeft(kMaxNumRetries) { mLooper->setName("NuCachedSource2"); mLooper->registerHandler(mReflector); mLooper->start(); @@ -254,7 +255,27 @@ void NuCachedSource2::onMessageReceived(const sp<AMessage> &msg) { void NuCachedSource2::fetchInternal() { LOGV("fetchInternal"); - CHECK_EQ(mFinalStatus, (status_t)OK); + { + Mutex::Autolock autoLock(mLock); + CHECK(mFinalStatus == OK || mNumRetriesLeft > 0); + + if (mFinalStatus != OK) { + --mNumRetriesLeft; + + status_t err = + mSource->reconnectAtOffset(mCacheOffset + mCache->totalSize()); + + if (err == ERROR_UNSUPPORTED) { + mNumRetriesLeft = 0; + return; + } else if (err != OK) { + LOGI("The attempt to reconnect failed, %d retries remaining", + mNumRetriesLeft); + + return; + } + } + } PageCache::Page *page = mCache->acquirePage(); @@ -264,14 +285,23 @@ void NuCachedSource2::fetchInternal() { Mutex::Autolock autoLock(mLock); if (n < 0) { - LOGE("source returned error %ld", n); + LOGE("source returned error %ld, %d retries left", n, mNumRetriesLeft); mFinalStatus = n; mCache->releasePage(page); } else if (n == 0) { LOGI("ERROR_END_OF_STREAM"); + + mNumRetriesLeft = 0; mFinalStatus = ERROR_END_OF_STREAM; + mCache->releasePage(page); } else { + if (mFinalStatus != OK) { + LOGI("retrying a previously failed read succeeded."); + } + mNumRetriesLeft = kMaxNumRetries; + mFinalStatus = OK; + page->mSize = n; mCache->appendPage(page); } @@ -280,7 +310,7 @@ void NuCachedSource2::fetchInternal() { void NuCachedSource2::onFetch() { LOGV("onFetch"); - if (mFinalStatus != OK) { + if (mFinalStatus != OK && mNumRetriesLeft == 0) { LOGV("EOS reached, done prefetching for now"); mFetching = false; } @@ -308,8 +338,19 @@ void NuCachedSource2::onFetch() { restartPrefetcherIfNecessary_l(); } - (new AMessage(kWhatFetchMore, mReflector->id()))->post( - mFetching ? 0 : 100000ll); + int64_t delayUs; + if (mFetching) { + if (mFinalStatus != OK && mNumRetriesLeft > 0) { + // We failed this time and will try again in 3 seconds. + delayUs = 3000000ll; + } else { + delayUs = 0; + } + } else { + delayUs = 100000ll; + } + + (new AMessage(kWhatFetchMore, mReflector->id()))->post(delayUs); } void NuCachedSource2::onRead(const sp<AMessage> &msg) { @@ -345,7 +386,7 @@ void NuCachedSource2::restartPrefetcherIfNecessary_l( bool ignoreLowWaterThreshold, bool force) { static const size_t kGrayArea = 1024 * 1024; - if (mFetching || mFinalStatus != OK) { + if (mFetching || (mFinalStatus != OK && mNumRetriesLeft == 0)) { return; } @@ -427,6 +468,12 @@ size_t NuCachedSource2::approxDataRemaining(status_t *finalStatus) { size_t NuCachedSource2::approxDataRemaining_l(status_t *finalStatus) { *finalStatus = mFinalStatus; + + if (mFinalStatus != OK && mNumRetriesLeft > 0) { + // Pretend that everything is fine until we're out of retries. + *finalStatus = OK; + } + off64_t lastBytePosCached = mCacheOffset + mCache->totalSize(); if (mLastAccessPos < lastBytePosCached) { return lastBytePosCached - mLastAccessPos; diff --git a/media/libstagefright/StagefrightMediaScanner.cpp b/media/libstagefright/StagefrightMediaScanner.cpp index 89faff7..571e8be 100644 --- a/media/libstagefright/StagefrightMediaScanner.cpp +++ b/media/libstagefright/StagefrightMediaScanner.cpp @@ -52,13 +52,13 @@ static bool FileHasAcceptableExtension(const char *extension) { return false; } -static status_t HandleMIDI( +static MediaScanResult HandleMIDI( const char *filename, MediaScannerClient *client) { // get the library configuration and do sanity check const S_EAS_LIB_CONFIG* pLibConfig = EAS_Config(); if ((pLibConfig == NULL) || (LIB_VERSION != pLibConfig->libVersion)) { LOGE("EAS library/header mismatch\n"); - return UNKNOWN_ERROR; + return MEDIA_SCAN_RESULT_ERROR; } EAS_I32 temp; @@ -88,34 +88,41 @@ static status_t HandleMIDI( } if (result != EAS_SUCCESS) { - return UNKNOWN_ERROR; + return MEDIA_SCAN_RESULT_SKIPPED; } char buffer[20]; sprintf(buffer, "%ld", temp); - if (!client->addStringTag("duration", buffer)) return UNKNOWN_ERROR; - - return OK; + status_t status = client->addStringTag("duration", buffer); + if (status) { + return MEDIA_SCAN_RESULT_ERROR; + } + return MEDIA_SCAN_RESULT_OK; } -status_t StagefrightMediaScanner::processFile( +MediaScanResult StagefrightMediaScanner::processFile( const char *path, const char *mimeType, MediaScannerClient &client) { LOGV("processFile '%s'.", path); client.setLocale(locale()); client.beginFile(); + MediaScanResult result = processFileInternal(path, mimeType, client); + client.endFile(); + return result; +} +MediaScanResult StagefrightMediaScanner::processFileInternal( + const char *path, const char *mimeType, + MediaScannerClient &client) { const char *extension = strrchr(path, '.'); if (!extension) { - return UNKNOWN_ERROR; + return MEDIA_SCAN_RESULT_SKIPPED; } if (!FileHasAcceptableExtension(extension)) { - client.endFile(); - - return UNKNOWN_ERROR; + return MEDIA_SCAN_RESULT_SKIPPED; } if (!strcasecmp(extension, ".mid") @@ -127,53 +134,57 @@ status_t StagefrightMediaScanner::processFile( || !strcasecmp(extension, ".rtx") || !strcasecmp(extension, ".ota") || !strcasecmp(extension, ".mxmf")) { - status_t status = HandleMIDI(path, &client); - if (status != OK) { - return status; + return HandleMIDI(path, &client); + } + + sp<MediaMetadataRetriever> mRetriever(new MediaMetadataRetriever); + + status_t status = mRetriever->setDataSource(path); + if (status) { + return MEDIA_SCAN_RESULT_ERROR; + } + + const char *value; + if ((value = mRetriever->extractMetadata( + METADATA_KEY_MIMETYPE)) != NULL) { + status = client.setMimeType(value); + if (status) { + return MEDIA_SCAN_RESULT_ERROR; } - } else { - sp<MediaMetadataRetriever> mRetriever(new MediaMetadataRetriever); - - if (mRetriever->setDataSource(path) == OK) { - const char *value; - if ((value = mRetriever->extractMetadata( - METADATA_KEY_MIMETYPE)) != NULL) { - client.setMimeType(value); - } + } - struct KeyMap { - const char *tag; - int key; - }; - static const KeyMap kKeyMap[] = { - { "tracknumber", METADATA_KEY_CD_TRACK_NUMBER }, - { "discnumber", METADATA_KEY_DISC_NUMBER }, - { "album", METADATA_KEY_ALBUM }, - { "artist", METADATA_KEY_ARTIST }, - { "albumartist", METADATA_KEY_ALBUMARTIST }, - { "composer", METADATA_KEY_COMPOSER }, - { "genre", METADATA_KEY_GENRE }, - { "title", METADATA_KEY_TITLE }, - { "year", METADATA_KEY_YEAR }, - { "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]); - - for (size_t i = 0; i < kNumEntries; ++i) { - const char *value; - if ((value = mRetriever->extractMetadata(kKeyMap[i].key)) != NULL) { - client.addStringTag(kKeyMap[i].tag, value); - } + struct KeyMap { + const char *tag; + int key; + }; + static const KeyMap kKeyMap[] = { + { "tracknumber", METADATA_KEY_CD_TRACK_NUMBER }, + { "discnumber", METADATA_KEY_DISC_NUMBER }, + { "album", METADATA_KEY_ALBUM }, + { "artist", METADATA_KEY_ARTIST }, + { "albumartist", METADATA_KEY_ALBUMARTIST }, + { "composer", METADATA_KEY_COMPOSER }, + { "genre", METADATA_KEY_GENRE }, + { "title", METADATA_KEY_TITLE }, + { "year", METADATA_KEY_YEAR }, + { "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]); + + for (size_t i = 0; i < kNumEntries; ++i) { + const char *value; + if ((value = mRetriever->extractMetadata(kKeyMap[i].key)) != NULL) { + status = client.addStringTag(kKeyMap[i].tag, value); + if (status) { + return MEDIA_SCAN_RESULT_ERROR; } } } - client.endFile(); - - return OK; + return MEDIA_SCAN_RESULT_OK; } char *StagefrightMediaScanner::extractAlbumArt(int fd) { diff --git a/media/libstagefright/SurfaceMediaSource.cpp b/media/libstagefright/SurfaceMediaSource.cpp new file mode 100644 index 0000000..ff4b08f --- /dev/null +++ b/media/libstagefright/SurfaceMediaSource.cpp @@ -0,0 +1,756 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// #define LOG_NDEBUG 0 +#define LOG_TAG "SurfaceMediaSource" + +#include <media/stagefright/SurfaceMediaSource.h> +#include <ui/GraphicBuffer.h> +#include <media/stagefright/MetaData.h> +#include <media/stagefright/MediaDefs.h> +#include <media/stagefright/MediaDebug.h> +#include <media/stagefright/openmax/OMX_IVCommon.h> + +#include <surfaceflinger/ISurfaceComposer.h> +#include <surfaceflinger/SurfaceComposerClient.h> +#include <surfaceflinger/IGraphicBufferAlloc.h> +#include <OMX_Component.h> + +#include <utils/Log.h> +#include <utils/String8.h> + +namespace android { + +SurfaceMediaSource::SurfaceMediaSource(uint32_t bufW, uint32_t bufH) : + mDefaultWidth(bufW), + mDefaultHeight(bufH), + mPixelFormat(0), + mBufferCount(MIN_ASYNC_BUFFER_SLOTS), + mClientBufferCount(0), + mServerBufferCount(MIN_ASYNC_BUFFER_SLOTS), + mCurrentSlot(INVALID_BUFFER_SLOT), + mCurrentTimestamp(0), + mSynchronousMode(true), + mConnectedApi(NO_CONNECTED_API), + mFrameRate(30), + mStarted(false) { + LOGV("SurfaceMediaSource::SurfaceMediaSource"); + sp<ISurfaceComposer> composer(ComposerService::getComposerService()); + mGraphicBufferAlloc = composer->createGraphicBufferAlloc(); +} + +SurfaceMediaSource::~SurfaceMediaSource() { + LOGV("SurfaceMediaSource::~SurfaceMediaSource"); + if (mStarted) { + stop(); + } + freeAllBuffers(); +} + +size_t SurfaceMediaSource::getQueuedCount() const { + Mutex::Autolock lock(mMutex); + return mQueue.size(); +} + +status_t SurfaceMediaSource::setBufferCountServerLocked(int bufferCount) { + if (bufferCount > NUM_BUFFER_SLOTS) + return BAD_VALUE; + + // special-case, nothing to do + if (bufferCount == mBufferCount) + return OK; + + if (!mClientBufferCount && + bufferCount >= mBufferCount) { + // easy, we just have more buffers + mBufferCount = bufferCount; + mServerBufferCount = bufferCount; + mDequeueCondition.signal(); + } else { + // we're here because we're either + // - reducing the number of available buffers + // - or there is a client-buffer-count in effect + + // less than 2 buffers is never allowed + if (bufferCount < 2) + return BAD_VALUE; + + // when there is non client-buffer-count in effect, the client is not + // allowed to dequeue more than one buffer at a time, + // so the next time they dequeue a buffer, we know that they don't + // own one. the actual resizing will happen during the next + // dequeueBuffer. + + mServerBufferCount = bufferCount; + } + return OK; +} + +// Called from the consumer side +status_t SurfaceMediaSource::setBufferCountServer(int bufferCount) { + Mutex::Autolock lock(mMutex); + return setBufferCountServerLocked(bufferCount); +} + +status_t SurfaceMediaSource::setBufferCount(int bufferCount) { + LOGV("SurfaceMediaSource::setBufferCount"); + if (bufferCount > NUM_BUFFER_SLOTS) { + LOGE("setBufferCount: bufferCount is larger than the number of buffer slots"); + return BAD_VALUE; + } + + Mutex::Autolock lock(mMutex); + // Error out if the user has dequeued buffers + for (int i = 0 ; i < mBufferCount ; i++) { + if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) { + LOGE("setBufferCount: client owns some buffers"); + return INVALID_OPERATION; + } + } + + if (bufferCount == 0) { + const int minBufferSlots = mSynchronousMode ? + MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS; + mClientBufferCount = 0; + bufferCount = (mServerBufferCount >= minBufferSlots) ? + mServerBufferCount : minBufferSlots; + return setBufferCountServerLocked(bufferCount); + } + + // We don't allow the client to set a buffer-count less than + // MIN_ASYNC_BUFFER_SLOTS (3), there is no reason for it. + if (bufferCount < MIN_ASYNC_BUFFER_SLOTS) { + return BAD_VALUE; + } + + // here we're guaranteed that the client doesn't have dequeued buffers + // and will release all of its buffer references. + freeAllBuffers(); + mBufferCount = bufferCount; + mClientBufferCount = bufferCount; + mCurrentSlot = INVALID_BUFFER_SLOT; + mQueue.clear(); + mDequeueCondition.signal(); + return OK; +} + +status_t SurfaceMediaSource::requestBuffer(int slot, sp<GraphicBuffer>* buf) { + LOGV("SurfaceMediaSource::requestBuffer"); + Mutex::Autolock lock(mMutex); + if (slot < 0 || mBufferCount <= slot) { + LOGE("requestBuffer: slot index out of range [0, %d]: %d", + mBufferCount, slot); + return BAD_VALUE; + } + mSlots[slot].mRequestBufferCalled = true; + *buf = mSlots[slot].mGraphicBuffer; + return NO_ERROR; +} + +status_t SurfaceMediaSource::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h, + uint32_t format, uint32_t usage) { + LOGV("dequeueBuffer"); + + + // Check for the buffer size- the client should just use the + // default width and height, and not try to set those. + // This is needed since + // the getFormat() returns mDefaultWidth/ Height for the OMX. It is + // queried by OMX in the beginning and not every time a frame comes. + // Not sure if there is a way to update the + // frame size while recording. So as of now, the client side + // sets the default values via the constructor, and the encoder is + // setup to encode frames of that size + // The design might need to change in the future. + // TODO: Currently just uses mDefaultWidth/Height. In the future + // we might declare mHeight and mWidth and check against those here. + if ((w != 0) || (h != 0)) { + LOGE("dequeuebuffer: invalid buffer size! Req: %dx%d, Found: %dx%d", + mDefaultWidth, mDefaultHeight, w, h); + return BAD_VALUE; + } + + Mutex::Autolock lock(mMutex); + + status_t returnFlags(OK); + + int found, foundSync; + int dequeuedCount = 0; + bool tryAgain = true; + while (tryAgain) { + // We need to wait for the FIFO to drain if the number of buffer + // needs to change. + // + // The condition "number of buffer needs to change" is true if + // - the client doesn't care about how many buffers there are + // - AND the actual number of buffer is different from what was + // set in the last setBufferCountServer() + // - OR - + // setBufferCountServer() was set to a value incompatible with + // the synchronization mode (for instance because the sync mode + // changed since) + // + // As long as this condition is true AND the FIFO is not empty, we + // wait on mDequeueCondition. + + int minBufferCountNeeded = mSynchronousMode ? + MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS; + + if (!mClientBufferCount && + ((mServerBufferCount != mBufferCount) || + (mServerBufferCount < minBufferCountNeeded))) { + // wait for the FIFO to drain + while (!mQueue.isEmpty()) { + LOGV("Waiting for the FIFO to drain"); + mDequeueCondition.wait(mMutex); + } + // need to check again since the mode could have changed + // while we were waiting + minBufferCountNeeded = mSynchronousMode ? + MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS; + } + + if (!mClientBufferCount && + ((mServerBufferCount != mBufferCount) || + (mServerBufferCount < minBufferCountNeeded))) { + // here we're guaranteed that mQueue is empty + freeAllBuffers(); + mBufferCount = mServerBufferCount; + if (mBufferCount < minBufferCountNeeded) + mBufferCount = minBufferCountNeeded; + mCurrentSlot = INVALID_BUFFER_SLOT; + returnFlags |= ISurfaceTexture::RELEASE_ALL_BUFFERS; + } + + // look for a free buffer to give to the client + found = INVALID_BUFFER_SLOT; + foundSync = INVALID_BUFFER_SLOT; + dequeuedCount = 0; + for (int i = 0; i < mBufferCount; i++) { + const int state = mSlots[i].mBufferState; + if (state == BufferSlot::DEQUEUED) { + dequeuedCount++; + continue; // won't be continuing if could + // dequeue a non 'FREE' current slot like + // that in SurfaceTexture + } + // In case of Encoding, we do not deque the mCurrentSlot buffer + // since we follow synchronous mode (unlike possibly in + // SurfaceTexture that could be using the asynch mode + // or has some mechanism in GL to be able to wait till the + // currentslot is done using the data) + // Here, we have to wait for the MPEG4Writer(or equiv) + // to tell us when it's done using the current buffer + if (state == BufferSlot::FREE) { + foundSync = i; + // Unlike that in SurfaceTexture, + // We don't need to worry if it is the + // currentslot or not as it is in state FREE + found = i; + break; + } + } + + // clients are not allowed to dequeue more than one buffer + // if they didn't set a buffer count. + if (!mClientBufferCount && dequeuedCount) { + return -EINVAL; + } + + // See whether a buffer has been queued since the last setBufferCount so + // we know whether to perform the MIN_UNDEQUEUED_BUFFERS check below. + bool bufferHasBeenQueued = mCurrentSlot != INVALID_BUFFER_SLOT; + if (bufferHasBeenQueued) { + // make sure the client is not trying to dequeue more buffers + // than allowed. + const int avail = mBufferCount - (dequeuedCount+1); + if (avail < (MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode))) { + LOGE("dequeueBuffer: MIN_UNDEQUEUED_BUFFERS=%d exceeded (dequeued=%d)", + MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode), + dequeuedCount); + return -EBUSY; + } + } + + // we're in synchronous mode and didn't find a buffer, we need to wait + // for for some buffers to be consumed + tryAgain = mSynchronousMode && (foundSync == INVALID_BUFFER_SLOT); + if (tryAgain) { + LOGW("Waiting..In synchronous mode and no buffer to dQ"); + mDequeueCondition.wait(mMutex); + } + } + + if (mSynchronousMode && found == INVALID_BUFFER_SLOT) { + // foundSync guaranteed to be != INVALID_BUFFER_SLOT + found = foundSync; + } + + if (found == INVALID_BUFFER_SLOT) { + return -EBUSY; + } + + const int buf = found; + *outBuf = found; + + const bool useDefaultSize = !w && !h; + if (useDefaultSize) { + // use the default size + w = mDefaultWidth; + h = mDefaultHeight; + } + + const bool updateFormat = (format != 0); + if (!updateFormat) { + // keep the current (or default) format + format = mPixelFormat; + } + + // buffer is now in DEQUEUED (but can also be current at the same time, + // if we're in synchronous mode) + mSlots[buf].mBufferState = BufferSlot::DEQUEUED; + + const sp<GraphicBuffer>& buffer(mSlots[buf].mGraphicBuffer); + if ((buffer == NULL) || + (uint32_t(buffer->width) != w) || + (uint32_t(buffer->height) != h) || + (uint32_t(buffer->format) != format) || + ((uint32_t(buffer->usage) & usage) != usage)) { + usage |= GraphicBuffer::USAGE_HW_TEXTURE; + status_t error; + sp<GraphicBuffer> graphicBuffer( + mGraphicBufferAlloc->createGraphicBuffer( + w, h, format, usage, &error)); + if (graphicBuffer == 0) { + LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer failed"); + return error; + } + if (updateFormat) { + mPixelFormat = format; + } + mSlots[buf].mGraphicBuffer = graphicBuffer; + mSlots[buf].mRequestBufferCalled = false; + returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION; + } + return returnFlags; +} + +status_t SurfaceMediaSource::setSynchronousMode(bool enabled) { + Mutex::Autolock lock(mMutex); + + status_t err = OK; + if (!enabled) { + // going to asynchronous mode, drain the queue + while (mSynchronousMode != enabled && !mQueue.isEmpty()) { + mDequeueCondition.wait(mMutex); + } + } + + if (mSynchronousMode != enabled) { + // - if we're going to asynchronous mode, the queue is guaranteed to be + // empty here + // - if the client set the number of buffers, we're guaranteed that + // we have at least 3 (because we don't allow less) + mSynchronousMode = enabled; + mDequeueCondition.signal(); + } + return err; +} + +status_t SurfaceMediaSource::connect(int api) { + LOGV("SurfaceMediaSource::connect"); + Mutex::Autolock lock(mMutex); + status_t err = NO_ERROR; + switch (api) { + case NATIVE_WINDOW_API_EGL: + case NATIVE_WINDOW_API_CPU: + case NATIVE_WINDOW_API_MEDIA: + case NATIVE_WINDOW_API_CAMERA: + if (mConnectedApi != NO_CONNECTED_API) { + err = -EINVAL; + } else { + mConnectedApi = api; + } + break; + default: + err = -EINVAL; + break; + } + return err; +} + +status_t SurfaceMediaSource::disconnect(int api) { + LOGV("SurfaceMediaSource::disconnect"); + Mutex::Autolock lock(mMutex); + status_t err = NO_ERROR; + switch (api) { + case NATIVE_WINDOW_API_EGL: + case NATIVE_WINDOW_API_CPU: + case NATIVE_WINDOW_API_MEDIA: + case NATIVE_WINDOW_API_CAMERA: + if (mConnectedApi == api) { + mConnectedApi = NO_CONNECTED_API; + } else { + err = -EINVAL; + } + break; + default: + err = -EINVAL; + break; + } + return err; +} + +status_t SurfaceMediaSource::queueBuffer(int buf, int64_t timestamp, + uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) { + LOGV("queueBuffer"); + + Mutex::Autolock lock(mMutex); + if (buf < 0 || buf >= mBufferCount) { + LOGE("queueBuffer: slot index out of range [0, %d]: %d", + mBufferCount, buf); + return -EINVAL; + } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) { + LOGE("queueBuffer: slot %d is not owned by the client (state=%d)", + buf, mSlots[buf].mBufferState); + return -EINVAL; + } else if (!mSlots[buf].mRequestBufferCalled) { + LOGE("queueBuffer: slot %d was enqueued without requesting a " + "buffer", buf); + return -EINVAL; + } + + if (mSynchronousMode) { + // in synchronous mode we queue all buffers in a FIFO + mQueue.push_back(buf); + LOGV("Client queued buffer on slot: %d, Q size = %d", + buf, mQueue.size()); + } else { + // in asynchronous mode we only keep the most recent buffer + if (mQueue.empty()) { + mQueue.push_back(buf); + } else { + Fifo::iterator front(mQueue.begin()); + // buffer currently queued is freed + mSlots[*front].mBufferState = BufferSlot::FREE; + // and we record the new buffer index in the queued list + *front = buf; + } + } + + mSlots[buf].mBufferState = BufferSlot::QUEUED; + mSlots[buf].mTimestamp = timestamp; + // TODO: (Confirm) Don't want to signal dequeue here. + // May be just in asynchronous mode? + // mDequeueCondition.signal(); + + // Once the queuing is done, we need to let the listener + // and signal the buffer consumer (encoder) know that a + // buffer is available + onFrameReceivedLocked(); + + *outWidth = mDefaultWidth; + *outHeight = mDefaultHeight; + *outTransform = 0; + + return OK; +} + + +// onFrameReceivedLocked informs the buffer consumers (StageFrightRecorder) +// or listeners that a frame has been received +// It is supposed to be called only from queuebuffer. +// The buffer is NOT made available for dequeueing immediately. We need to +// wait to hear from StageFrightRecorder to set the buffer FREE +// Make sure this is called when the mutex is locked +status_t SurfaceMediaSource::onFrameReceivedLocked() { + LOGV("On Frame Received"); + // Signal the encoder that a new frame has arrived + mFrameAvailableCondition.signal(); + + // call back the listener + // TODO: The listener may not be needed in SurfaceMediaSource at all. + // This can be made a SurfaceTexture specific thing + sp<FrameAvailableListener> listener; + if (mSynchronousMode || mQueue.empty()) { + listener = mFrameAvailableListener; + } + + if (listener != 0) { + listener->onFrameAvailable(); + } + return OK; +} + + +void SurfaceMediaSource::cancelBuffer(int buf) { + LOGV("SurfaceMediaSource::cancelBuffer"); + Mutex::Autolock lock(mMutex); + if (buf < 0 || buf >= mBufferCount) { + LOGE("cancelBuffer: slot index out of range [0, %d]: %d", + mBufferCount, buf); + return; + } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) { + LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)", + buf, mSlots[buf].mBufferState); + return; + } + mSlots[buf].mBufferState = BufferSlot::FREE; + mDequeueCondition.signal(); +} + +nsecs_t SurfaceMediaSource::getTimestamp() { + LOGV("SurfaceMediaSource::getTimestamp"); + Mutex::Autolock lock(mMutex); + return mCurrentTimestamp; +} + + +void SurfaceMediaSource::setFrameAvailableListener( + const sp<FrameAvailableListener>& listener) { + LOGV("SurfaceMediaSource::setFrameAvailableListener"); + Mutex::Autolock lock(mMutex); + mFrameAvailableListener = listener; +} + +void SurfaceMediaSource::freeAllBuffers() { + LOGV("freeAllBuffers"); + for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { + mSlots[i].mGraphicBuffer = 0; + mSlots[i].mBufferState = BufferSlot::FREE; + } +} + +sp<GraphicBuffer> SurfaceMediaSource::getCurrentBuffer() const { + Mutex::Autolock lock(mMutex); + return mCurrentBuf; +} + +int SurfaceMediaSource::query(int what, int* outValue) +{ + LOGV("query"); + Mutex::Autolock lock(mMutex); + int value; + switch (what) { + case NATIVE_WINDOW_WIDTH: + value = mDefaultWidth; + if (!mDefaultWidth && !mDefaultHeight && mCurrentBuf != 0) + value = mCurrentBuf->width; + break; + case NATIVE_WINDOW_HEIGHT: + value = mDefaultHeight; + if (!mDefaultWidth && !mDefaultHeight && mCurrentBuf != 0) + value = mCurrentBuf->height; + break; + case NATIVE_WINDOW_FORMAT: + value = mPixelFormat; + break; + case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS: + value = mSynchronousMode ? + (MIN_UNDEQUEUED_BUFFERS-1) : MIN_UNDEQUEUED_BUFFERS; + break; + default: + return BAD_VALUE; + } + outValue[0] = value; + return NO_ERROR; +} + +void SurfaceMediaSource::dump(String8& result) const +{ + char buffer[1024]; + dump(result, "", buffer, 1024); +} + +void SurfaceMediaSource::dump(String8& result, const char* prefix, + char* buffer, size_t SIZE) const +{ + Mutex::Autolock _l(mMutex); + snprintf(buffer, SIZE, + "%smBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], " + "mPixelFormat=%d, \n", + prefix, mBufferCount, mSynchronousMode, mDefaultWidth, mDefaultHeight, + mPixelFormat); + result.append(buffer); + + String8 fifo; + int fifoSize = 0; + Fifo::const_iterator i(mQueue.begin()); + while (i != mQueue.end()) { + snprintf(buffer, SIZE, "%02d ", *i++); + fifoSize++; + fifo.append(buffer); + } + + result.append(buffer); + + struct { + const char * operator()(int state) const { + switch (state) { + case BufferSlot::DEQUEUED: return "DEQUEUED"; + case BufferSlot::QUEUED: return "QUEUED"; + case BufferSlot::FREE: return "FREE"; + default: return "Unknown"; + } + } + } stateName; + + for (int i = 0; i < mBufferCount; i++) { + const BufferSlot& slot(mSlots[i]); + snprintf(buffer, SIZE, + "%s%s[%02d] state=%-8s, " + "timestamp=%lld\n", + prefix, (i==mCurrentSlot)?">":" ", i, stateName(slot.mBufferState), + slot.mTimestamp + ); + result.append(buffer); + } +} + +status_t SurfaceMediaSource::setFrameRate(int32_t fps) +{ + Mutex::Autolock lock(mMutex); + const int MAX_FRAME_RATE = 60; + if (fps < 0 || fps > MAX_FRAME_RATE) { + return BAD_VALUE; + } + mFrameRate = fps; + return OK; +} + +bool SurfaceMediaSource::isMetaDataStoredInVideoBuffers() const { + LOGV("isMetaDataStoredInVideoBuffers"); + return true; +} + +int32_t SurfaceMediaSource::getFrameRate( ) const { + Mutex::Autolock lock(mMutex); + return mFrameRate; +} + +status_t SurfaceMediaSource::start(MetaData *params) +{ + LOGV("start"); + Mutex::Autolock lock(mMutex); + CHECK(!mStarted); + mStarted = true; + return OK; +} + + +status_t SurfaceMediaSource::stop() +{ + LOGV("Stop"); + + Mutex::Autolock lock(mMutex); + // TODO: Add waiting on mFrameCompletedCondition here? + mStarted = false; + mFrameAvailableCondition.signal(); + + return OK; +} + +sp<MetaData> SurfaceMediaSource::getFormat() +{ + LOGV("getFormat"); + Mutex::Autolock autoLock(mMutex); + sp<MetaData> meta = new MetaData; + + meta->setInt32(kKeyWidth, mDefaultWidth); + meta->setInt32(kKeyHeight, mDefaultHeight); + // The encoder format is set as an opaque colorformat + // The encoder will later find out the actual colorformat + // from the GL Frames itself. + meta->setInt32(kKeyColorFormat, OMX_COLOR_FormatAndroidOpaque); + meta->setInt32(kKeyStride, mDefaultWidth); + meta->setInt32(kKeySliceHeight, mDefaultHeight); + meta->setInt32(kKeyFrameRate, mFrameRate); + meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW); + return meta; +} + +status_t SurfaceMediaSource::read( MediaBuffer **buffer, + const ReadOptions *options) +{ + LOGV("Read. Size of queued buffer: %d", mQueue.size()); + *buffer = NULL; + + Mutex::Autolock autoLock(mMutex) ; + // If the recording has started and the queue is empty, then just + // wait here till the frames come in from the client side + while (mStarted && mQueue.empty()) { + LOGV("NO FRAMES! Recorder waiting for FrameAvailableCondition"); + mFrameAvailableCondition.wait(mMutex); + } + + // If the loop was exited as a result of stopping the recording, + // it is OK + if (!mStarted) { + return OK; + } + + // Update the current buffer info + // TODO: mCurrentSlot can be made a bufferstate since there + // can be more than one "current" slots. + Fifo::iterator front(mQueue.begin()); + mCurrentSlot = *front; + mCurrentBuf = mSlots[mCurrentSlot].mGraphicBuffer; + mCurrentTimestamp = mSlots[mCurrentSlot].mTimestamp; + + // Pass the data to the MediaBuffer + // TODO: Change later to pass in only the metadata + *buffer = new MediaBuffer(mCurrentBuf); + (*buffer)->setObserver(this); + (*buffer)->add_ref(); + (*buffer)->meta_data()->setInt64(kKeyTime, mCurrentTimestamp); + + return OK; +} + +void SurfaceMediaSource::signalBufferReturned(MediaBuffer *buffer) { + LOGV("signalBufferReturned"); + + bool foundBuffer = false; + Mutex::Autolock autoLock(mMutex); + + if (!mStarted) { + LOGV("started = false. Nothing to do"); + return; + } + + for (Fifo::iterator it = mQueue.begin(); it != mQueue.end(); ++it) { + if (mSlots[*it].mGraphicBuffer == buffer->graphicBuffer()) { + LOGV("Buffer %d returned. Setting it 'FREE'. New Queue size = %d", + *it, mQueue.size()-1); + mSlots[*it].mBufferState = BufferSlot::FREE; + mQueue.erase(it); + buffer->setObserver(0); + buffer->release(); + mDequeueCondition.signal(); + mFrameCompleteCondition.signal(); + foundBuffer = true; + break; + } + } + + if (!foundBuffer) { + CHECK_EQ(0, "signalBufferReturned: bogus buffer"); + } +} + + + +} // end of namespace android diff --git a/media/libstagefright/WAVExtractor.cpp b/media/libstagefright/WAVExtractor.cpp index bf978d7..c406964 100644 --- a/media/libstagefright/WAVExtractor.cpp +++ b/media/libstagefright/WAVExtractor.cpp @@ -370,7 +370,9 @@ status_t WAVSource::read( int16_t *dst = (int16_t *)tmp->data(); const uint8_t *src = (const uint8_t *)buffer->data(); - while (n-- > 0) { + ssize_t numBytes = n; + + while (numBytes-- > 0) { *dst++ = ((int16_t)(*src) - 128) * 256; ++src; } diff --git a/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp b/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp index 588a74d..07a9eb8 100644 --- a/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp +++ b/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp @@ -25,6 +25,8 @@ #include "support.h" +#include <cutils/properties.h> // for property_get + namespace android { ChromiumHTTPDataSource::ChromiumHTTPDataSource(uint32_t flags) @@ -111,7 +113,7 @@ void ChromiumHTTPDataSource::onConnectionFailed(status_t err) { mState = DISCONNECTED; mCondition.broadcast(); - mURI.clear(); + // mURI.clear(); mIOResult = err; @@ -150,8 +152,18 @@ ssize_t ChromiumHTTPDataSource::readAt(off64_t offset, void *data, size_t size) Mutex::Autolock autoLock(mLock); if (mState != CONNECTED) { - return ERROR_NOT_CONNECTED; + return INVALID_OPERATION; + } + +#if 0 + char value[PROPERTY_VALUE_MAX]; + if (property_get("media.stagefright.disable-net", value, 0) + && (!strcasecmp(value, "true") || !strcmp(value, "1"))) { + LOG_PRI(ANDROID_LOG_INFO, LOG_TAG, "Simulating that the network is down."); + disconnect_l(); + return ERROR_IO; } +#endif if (offset != mCurrentOffset) { AString tmp = mURI; @@ -236,7 +248,7 @@ void ChromiumHTTPDataSource::onDisconnectComplete() { CHECK_EQ((int)mState, (int)DISCONNECTING); mState = DISCONNECTED; - mURI.clear(); + // mURI.clear(); mCondition.broadcast(); @@ -299,5 +311,21 @@ void ChromiumHTTPDataSource::clearDRMState_l() { } } +status_t ChromiumHTTPDataSource::reconnectAtOffset(off64_t offset) { + Mutex::Autolock autoLock(mLock); + + if (mURI.empty()) { + return INVALID_OPERATION; + } + + LOG_PRI(ANDROID_LOG_INFO, LOG_TAG, "Reconnecting..."); + status_t err = connect_l(mURI.c_str(), &mHeaders, offset); + if (err != OK) { + LOG_PRI(ANDROID_LOG_INFO, LOG_TAG, "Reconnect failed w/ err 0x%08x", err); + } + + return err; +} + } // namespace android diff --git a/media/libstagefright/include/ChromiumHTTPDataSource.h b/media/libstagefright/include/ChromiumHTTPDataSource.h index d833e2e..18f8913 100644 --- a/media/libstagefright/include/ChromiumHTTPDataSource.h +++ b/media/libstagefright/include/ChromiumHTTPDataSource.h @@ -51,6 +51,8 @@ struct ChromiumHTTPDataSource : public HTTPBase { virtual String8 getMIMEType() const; + virtual status_t reconnectAtOffset(off64_t offset); + protected: virtual ~ChromiumHTTPDataSource(); diff --git a/media/libstagefright/include/NuCachedSource2.h b/media/libstagefright/include/NuCachedSource2.h index 2d6cb84..22b2855 100644 --- a/media/libstagefright/include/NuCachedSource2.h +++ b/media/libstagefright/include/NuCachedSource2.h @@ -77,6 +77,10 @@ private: kWhatRead = 'read', }; + enum { + kMaxNumRetries = 10, + }; + sp<DataSource> mSource; sp<AHandlerReflector<NuCachedSource2> > mReflector; sp<ALooper> mLooper; @@ -93,6 +97,8 @@ private: bool mFetching; int64_t mLastFetchTimeUs; + int32_t mNumRetriesLeft; + void onMessageReceived(const sp<AMessage> &msg); void onFetch(); void onRead(const sp<AMessage> &msg); diff --git a/media/libstagefright/tests/Android.mk b/media/libstagefright/tests/Android.mk new file mode 100644 index 0000000..3ea8f39 --- /dev/null +++ b/media/libstagefright/tests/Android.mk @@ -0,0 +1,53 @@ +# Build the unit tests. +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +ifneq ($(TARGET_SIMULATOR),true) + +LOCAL_MODULE := SurfaceMediaSource_test + +LOCAL_MODULE_TAGS := tests + +LOCAL_SRC_FILES := \ + SurfaceMediaSource_test.cpp \ + DummyRecorder.cpp \ + +LOCAL_SHARED_LIBRARIES := \ + libEGL \ + libGLESv2 \ + libandroid \ + libbinder \ + libcutils \ + libgui \ + libstlport \ + libui \ + libutils \ + libstagefright \ + libstagefright_omx \ + libstagefright_foundation \ + +LOCAL_STATIC_LIBRARIES := \ + libgtest \ + libgtest_main \ + +LOCAL_C_INCLUDES := \ + bionic \ + bionic/libstdc++/include \ + external/gtest/include \ + external/stlport/stlport \ + frameworks/base/media/libstagefright \ + frameworks/base/media/libstagefright/include \ + $(TOP)/frameworks/base/include/media/stagefright/openmax \ + +include $(BUILD_EXECUTABLE) + +endif + +# Include subdirectory makefiles +# ============================================================ + +# If we're building with ONE_SHOT_MAKEFILE (mm, mmm), then what the framework +# team really wants is to build the stuff defined by this makefile. +ifeq (,$(ONE_SHOT_MAKEFILE)) +include $(call first-makefiles-under,$(LOCAL_PATH)) +endif diff --git a/media/libstagefright/tests/DummyRecorder.cpp b/media/libstagefright/tests/DummyRecorder.cpp new file mode 100644 index 0000000..8d75d6b --- /dev/null +++ b/media/libstagefright/tests/DummyRecorder.cpp @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "DummyRecorder" +// #define LOG_NDEBUG 0 + +#include <media/stagefright/MediaBuffer.h> +#include <media/stagefright/MediaSource.h> +#include "DummyRecorder.h" + +#include <utils/Log.h> + +namespace android { + +// static +void *DummyRecorder::threadWrapper(void *pthis) { + LOGV("ThreadWrapper: %p", pthis); + DummyRecorder *writer = static_cast<DummyRecorder *>(pthis); + writer->readFromSource(); + return NULL; +} + + +status_t DummyRecorder::start() { + LOGV("Start"); + mStarted = true; + + mSource->start(); + + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + int err = pthread_create(&mThread, &attr, threadWrapper, this); + pthread_attr_destroy(&attr); + + if (err) { + LOGE("Error creating thread!"); + return -ENODEV; + } + return OK; +} + + +status_t DummyRecorder::stop() { + LOGV("Stop"); + mStarted = false; + + mSource->stop(); + void *dummy; + pthread_join(mThread, &dummy); + status_t err = (status_t) dummy; + + LOGV("Ending the reading thread"); + return err; +} + +// pretend to read the source buffers +void DummyRecorder::readFromSource() { + LOGV("ReadFromSource"); + if (!mStarted) { + return; + } + + status_t err = OK; + MediaBuffer *buffer; + LOGV("A fake writer accessing the frames"); + while (mStarted && (err = mSource->read(&buffer)) == OK){ + // if not getting a valid buffer from source, then exit + if (buffer == NULL) { + return; + } + buffer->release(); + buffer = NULL; + } +} + + +} // end of namespace android diff --git a/media/libstagefright/tests/DummyRecorder.h b/media/libstagefright/tests/DummyRecorder.h new file mode 100644 index 0000000..1cbea1b --- /dev/null +++ b/media/libstagefright/tests/DummyRecorder.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DUMMY_RECORDER_H_ +#define DUMMY_RECORDER_H_ + +#include <pthread.h> +#include <utils/String8.h> +#include <media/stagefright/foundation/ABase.h> + + +namespace android { + +class MediaSource; +class MediaBuffer; + +class DummyRecorder { + public: + // The media source from which this will receive frames + sp<MediaSource> mSource; + bool mStarted; + pthread_t mThread; + + status_t start(); + status_t stop(); + + // actual entry point for the thread + void readFromSource(); + + // static function to wrap the actual thread entry point + static void *threadWrapper(void *pthis); + + DummyRecorder(const sp<MediaSource> &source) : mSource(source) + , mStarted(false) {} + ~DummyRecorder( ) {} + + private: + + DISALLOW_EVIL_CONSTRUCTORS(DummyRecorder); +}; + +} // end of namespace android +#endif + + diff --git a/media/libstagefright/tests/SurfaceMediaSource_test.cpp b/media/libstagefright/tests/SurfaceMediaSource_test.cpp new file mode 100644 index 0000000..ce10812 --- /dev/null +++ b/media/libstagefright/tests/SurfaceMediaSource_test.cpp @@ -0,0 +1,349 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "SurfaceMediaSource_test" +// #define LOG_NDEBUG 0 + +#include <gtest/gtest.h> +#include <utils/String8.h> +#include <utils/Errors.h> + +#include <media/stagefright/SurfaceMediaSource.h> + +#include <gui/SurfaceTextureClient.h> +#include <ui/GraphicBuffer.h> +#include <surfaceflinger/ISurfaceComposer.h> +#include <surfaceflinger/Surface.h> +#include <surfaceflinger/SurfaceComposerClient.h> + +#include <binder/ProcessState.h> +#include <ui/FramebufferNativeWindow.h> + +#include <media/stagefright/MediaDebug.h> +#include <media/stagefright/MediaDefs.h> +#include <media/stagefright/MetaData.h> +#include <media/stagefright/MPEG4Writer.h> +#include <media/stagefright/OMXClient.h> +#include <media/stagefright/OMXCodec.h> +#include <OMX_Component.h> + +#include "DummyRecorder.h" + +namespace android { + + +class SurfaceMediaSourceTest : public ::testing::Test { +public: + + SurfaceMediaSourceTest( ): mYuvTexWidth(64), mYuvTexHeight(66) { } + sp<MPEG4Writer> setUpWriter(OMXClient &client ); + void oneBufferPass(int width, int height ); + static void fillYV12Buffer(uint8_t* buf, int w, int h, int stride) ; + static void fillYV12BufferRect(uint8_t* buf, int w, int h, + int stride, const android_native_rect_t& rect) ; +protected: + + virtual void SetUp() { + mSMS = new SurfaceMediaSource(mYuvTexWidth, mYuvTexHeight); + mSMS->setSynchronousMode(true); + mSTC = new SurfaceTextureClient(mSMS); + mANW = mSTC; + + } + + + virtual void TearDown() { + mSMS.clear(); + mSTC.clear(); + mANW.clear(); + } + + const int mYuvTexWidth;// = 64; + const int mYuvTexHeight;// = 66; + + sp<SurfaceMediaSource> mSMS; + sp<SurfaceTextureClient> mSTC; + sp<ANativeWindow> mANW; + +}; + +void SurfaceMediaSourceTest::oneBufferPass(int width, int height ) { + LOGV("One Buffer Pass"); + ANativeWindowBuffer* anb; + ASSERT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb)); + ASSERT_TRUE(anb != NULL); + + sp<GraphicBuffer> buf(new GraphicBuffer(anb, false)); + ASSERT_EQ(NO_ERROR, mANW->lockBuffer(mANW.get(), buf->getNativeBuffer())); + + // Fill the buffer with the a checkerboard pattern + uint8_t* img = NULL; + buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); + SurfaceMediaSourceTest::fillYV12Buffer(img, width, height, buf->getStride()); + buf->unlock(); + + ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer())); +} + +sp<MPEG4Writer> SurfaceMediaSourceTest::setUpWriter(OMXClient &client ) { + // Writing to a file + const char *fileName = "/sdcard/outputSurfEnc.mp4"; + sp<MetaData> enc_meta = new MetaData; + enc_meta->setInt32(kKeyBitRate, 300000); + enc_meta->setInt32(kKeyFrameRate, 30); + + enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4); + + sp<MetaData> meta = mSMS->getFormat(); + + int32_t width, height, stride, sliceHeight, colorFormat; + CHECK(meta->findInt32(kKeyWidth, &width)); + CHECK(meta->findInt32(kKeyHeight, &height)); + CHECK(meta->findInt32(kKeyStride, &stride)); + CHECK(meta->findInt32(kKeySliceHeight, &sliceHeight)); + CHECK(meta->findInt32(kKeyColorFormat, &colorFormat)); + + enc_meta->setInt32(kKeyWidth, width); + enc_meta->setInt32(kKeyHeight, height); + enc_meta->setInt32(kKeyIFramesInterval, 1); + enc_meta->setInt32(kKeyStride, stride); + enc_meta->setInt32(kKeySliceHeight, sliceHeight); + // TODO: overwriting the colorformat since the format set by GRAlloc + // could be wrong or not be read by OMX + enc_meta->setInt32(kKeyColorFormat, OMX_COLOR_FormatYUV420Planar); + // colorFormat); + + + sp<MediaSource> encoder = + OMXCodec::Create( + client.interface(), enc_meta, true /* createEncoder */, mSMS); + + sp<MPEG4Writer> writer = new MPEG4Writer(fileName); + writer->addSource(encoder); + + return writer; +} + +// Fill a YV12 buffer with a multi-colored checkerboard pattern +void SurfaceMediaSourceTest::fillYV12Buffer(uint8_t* buf, int w, int h, int stride) { + const int blockWidth = w > 16 ? w / 16 : 1; + const int blockHeight = h > 16 ? h / 16 : 1; + const int yuvTexOffsetY = 0; + int yuvTexStrideY = stride; + int yuvTexOffsetV = yuvTexStrideY * h; + int yuvTexStrideV = (yuvTexStrideY/2 + 0xf) & ~0xf; + int yuvTexOffsetU = yuvTexOffsetV + yuvTexStrideV * h/2; + int yuvTexStrideU = yuvTexStrideV; + for (int x = 0; x < w; x++) { + for (int y = 0; y < h; y++) { + int parityX = (x / blockWidth) & 1; + int parityY = (y / blockHeight) & 1; + unsigned char intensity = (parityX ^ parityY) ? 63 : 191; + buf[yuvTexOffsetY + (y * yuvTexStrideY) + x] = intensity; + if (x < w / 2 && y < h / 2) { + buf[yuvTexOffsetU + (y * yuvTexStrideU) + x] = intensity; + if (x * 2 < w / 2 && y * 2 < h / 2) { + buf[yuvTexOffsetV + (y*2 * yuvTexStrideV) + x*2 + 0] = + buf[yuvTexOffsetV + (y*2 * yuvTexStrideV) + x*2 + 1] = + buf[yuvTexOffsetV + ((y*2+1) * yuvTexStrideV) + x*2 + 0] = + buf[yuvTexOffsetV + ((y*2+1) * yuvTexStrideV) + x*2 + 1] = + intensity; + } + } + } + } +} + +// Fill a YV12 buffer with red outside a given rectangle and green inside it. +void SurfaceMediaSourceTest::fillYV12BufferRect(uint8_t* buf, int w, + int h, int stride, const android_native_rect_t& rect) { + const int yuvTexOffsetY = 0; + int yuvTexStrideY = stride; + int yuvTexOffsetV = yuvTexStrideY * h; + int yuvTexStrideV = (yuvTexStrideY/2 + 0xf) & ~0xf; + int yuvTexOffsetU = yuvTexOffsetV + yuvTexStrideV * h/2; + int yuvTexStrideU = yuvTexStrideV; + for (int x = 0; x < w; x++) { + for (int y = 0; y < h; y++) { + bool inside = rect.left <= x && x < rect.right && + rect.top <= y && y < rect.bottom; + buf[yuvTexOffsetY + (y * yuvTexStrideY) + x] = inside ? 240 : 64; + if (x < w / 2 && y < h / 2) { + bool inside = rect.left <= 2*x && 2*x < rect.right && + rect.top <= 2*y && 2*y < rect.bottom; + buf[yuvTexOffsetU + (y * yuvTexStrideU) + x] = 16; + buf[yuvTexOffsetV + (y * yuvTexStrideV) + x] = + inside ? 16 : 255; + } + } + } +} ///////// End of class SurfaceMediaSourceTest + +/////////////////////////////////////////////////////////////////// +// Class to imitate the recording ///////////////////////////// +// //////////////////////////////////////////////////////////////// +struct SimpleDummyRecorder { + sp<MediaSource> mSource; + + SimpleDummyRecorder + (const sp<MediaSource> &source): mSource(source) {} + + status_t start() { return mSource->start();} + status_t stop() { return mSource->stop();} + + // fakes reading from a media source + status_t readFromSource() { + MediaBuffer *buffer; + status_t err = mSource->read(&buffer); + if (err != OK) { + return err; + } + buffer->release(); + buffer = NULL; + return OK; + } +}; + +/////////////////////////////////////////////////////////////////// +// TESTS +// Just pass one buffer from the native_window to the SurfaceMediaSource +TEST_F(SurfaceMediaSourceTest, EncodingFromCpuFilledYV12BufferNpotOneBufferPass) { + LOGV("Testing OneBufferPass ******************************"); + + ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(), + 0, 0, HAL_PIXEL_FORMAT_YV12)); + // OMX_COLOR_FormatYUV420Planar)); // )); + ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(), + GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN)); + + oneBufferPass(mYuvTexWidth, mYuvTexHeight); +} + +// Pass the buffer with the wrong height and weight and should not be accepted +TEST_F(SurfaceMediaSourceTest, EncodingFromCpuFilledYV12BufferNpotWrongSizeBufferPass) { + LOGV("Testing Wrong size BufferPass ******************************"); + + // setting the client side buffer size different than the server size + ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(), + 10, 10, HAL_PIXEL_FORMAT_YV12)); + // OMX_COLOR_FormatYUV420Planar)); // )); + ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(), + GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN)); + + ANativeWindowBuffer* anb; + + // make sure we get an error back when dequeuing! + ASSERT_NE(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb)); +} + + +// pass multiple buffers from the native_window the SurfaceMediaSource +// A dummy writer is used to simulate actual MPEG4Writer +TEST_F(SurfaceMediaSourceTest, EncodingFromCpuFilledYV12BufferNpotMultiBufferPass) { + LOGV("Testing MultiBufferPass, Dummy Recorder *********************"); + ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(), + 0, 0, HAL_PIXEL_FORMAT_YV12)); + ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(), + GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN)); + SimpleDummyRecorder writer(mSMS); + writer.start(); + + int32_t nFramesCount = 0; + while (nFramesCount < 300) { + oneBufferPass(mYuvTexWidth, mYuvTexHeight); + + ASSERT_EQ(NO_ERROR, writer.readFromSource()); + + nFramesCount++; + } + writer.stop(); +} + +// Delayed pass of multiple buffers from the native_window the SurfaceMediaSource +// A dummy writer is used to simulate actual MPEG4Writer +TEST_F(SurfaceMediaSourceTest, EncodingFromCpuFilledYV12BufferNpotMultiBufferPassLag) { + LOGV("Testing MultiBufferPass, Dummy Recorder Lagging **************"); + ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(), + 0, 0, HAL_PIXEL_FORMAT_YV12)); + ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(), + GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN)); + SimpleDummyRecorder writer(mSMS); + writer.start(); + + int32_t nFramesCount = 1; + const int FRAMES_LAG = mSMS->getBufferCount() - 1; + while (nFramesCount <= 300) { + oneBufferPass(mYuvTexWidth, mYuvTexHeight); + // Forcing the writer to lag behind a few frames + if (nFramesCount > FRAMES_LAG) { + ASSERT_EQ(NO_ERROR, writer.readFromSource()); + } + nFramesCount++; + } + writer.stop(); +} + +// pass multiple buffers from the native_window the SurfaceMediaSource +// A dummy writer (MULTITHREADED) is used to simulate actual MPEG4Writer +TEST_F(SurfaceMediaSourceTest, EncodingFromCpuFilledYV12BufferNpotMultiBufferPassThreaded) { + LOGV("Testing MultiBufferPass, Dummy Recorder Multi-Threaded **********"); + ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(), + 0, 0, HAL_PIXEL_FORMAT_YV12)); + ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(), + GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN)); + + DummyRecorder writer(mSMS); + writer.start(); + + int32_t nFramesCount = 0; + while (nFramesCount <= 300) { + oneBufferPass(mYuvTexWidth, mYuvTexHeight); + + nFramesCount++; + } + writer.stop(); +} + +// Test to examine the actual encoding. Temporarily disabled till the +// colorformat and encoding from GRAlloc data is resolved +TEST_F(SurfaceMediaSourceTest, DISABLED_EncodingFromCpuFilledYV12BufferNpotWrite) { + LOGV("Testing the whole pipeline with actual Recorder"); + ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(), + 0, 0, HAL_PIXEL_FORMAT_YV12)); // OMX_COLOR_FormatYUV420Planar)); // )); + ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(), + GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN)); + + OMXClient client; + CHECK_EQ(OK, client.connect()); + + sp<MPEG4Writer> writer = setUpWriter(client); + int64_t start = systemTime(); + CHECK_EQ(OK, writer->start()); + + int32_t nFramesCount = 0; + while (nFramesCount <= 300) { + oneBufferPass(mYuvTexWidth, mYuvTexHeight); + nFramesCount++; + } + + CHECK_EQ(OK, writer->stop()); + writer.clear(); + int64_t end = systemTime(); + client.disconnect(); +} + + +} // namespace android diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java index afe4246..a5022e9 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java @@ -63,7 +63,7 @@ public class DatabaseHelper extends SQLiteOpenHelper { // database gets upgraded properly. At a minimum, please confirm that 'upgradeVersion' // is properly propagated through your change. Not doing so will result in a loss of user // settings. - private static final int DATABASE_VERSION = 66; + private static final int DATABASE_VERSION = 67; private Context mContext; @@ -861,6 +861,36 @@ public class DatabaseHelper extends SQLiteOpenHelper { upgradeVersion = 66; } + if (upgradeVersion == 66) { + // This upgrade makes sure that MODE_RINGER_STREAMS_AFFECTED and + // NOTIFICATIONS_USE_RING_VOLUME settings are set according to device voice capability + db.beginTransaction(); + try { + int ringerModeAffectedStreams = (1 << AudioManager.STREAM_RING) | + (1 << AudioManager.STREAM_NOTIFICATION) | + (1 << AudioManager.STREAM_SYSTEM) | + (1 << AudioManager.STREAM_SYSTEM_ENFORCED); + if (!mContext.getResources().getBoolean( + com.android.internal.R.bool.config_voice_capable)) { + ringerModeAffectedStreams |= (1 << AudioManager.STREAM_MUSIC); + + db.execSQL("DELETE FROM system WHERE name='" + + Settings.System.NOTIFICATIONS_USE_RING_VOLUME + "'"); + db.execSQL("INSERT INTO system ('name', 'value') values ('" + + Settings.System.NOTIFICATIONS_USE_RING_VOLUME + "', '1')"); + } + db.execSQL("DELETE FROM system WHERE name='" + + Settings.System.MODE_RINGER_STREAMS_AFFECTED + "'"); + db.execSQL("INSERT INTO system ('name', 'value') values ('" + + Settings.System.MODE_RINGER_STREAMS_AFFECTED + "', '" + + String.valueOf(ringerModeAffectedStreams) + "')"); + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + } + upgradeVersion = 67; + } + // *** Remember to update DATABASE_VERSION above! if (upgradeVersion != currentVersion) { @@ -1121,12 +1151,22 @@ public class DatabaseHelper extends SQLiteOpenHelper { loadVibrateSetting(db, false); - // By default, only the ring/notification, system and music streams are affected + // By default: + // - ringtones, notification, system and music streams are affected by ringer mode + // on non voice capable devices (tablets) + // - ringtones, notification and system streams are affected by ringer mode + // on voice capable devices (phones) + int ringerModeAffectedStreams = (1 << AudioManager.STREAM_RING) | + (1 << AudioManager.STREAM_NOTIFICATION) | + (1 << AudioManager.STREAM_SYSTEM) | + (1 << AudioManager.STREAM_SYSTEM_ENFORCED); + if (!mContext.getResources().getBoolean( + com.android.internal.R.bool.config_voice_capable)) { + ringerModeAffectedStreams |= (1 << AudioManager.STREAM_MUSIC); + } loadSetting(stmt, Settings.System.MODE_RINGER_STREAMS_AFFECTED, - (1 << AudioManager.STREAM_RING) | (1 << AudioManager.STREAM_NOTIFICATION) | - (1 << AudioManager.STREAM_SYSTEM) | (1 << AudioManager.STREAM_SYSTEM_ENFORCED) | - (1 << AudioManager.STREAM_MUSIC)); - + ringerModeAffectedStreams); + loadSetting(stmt, Settings.System.MUTE_STREAMS_AFFECTED, ((1 << AudioManager.STREAM_MUSIC) | (1 << AudioManager.STREAM_RING) | @@ -1232,8 +1272,13 @@ public class DatabaseHelper extends SQLiteOpenHelper { R.bool.def_vibrate_in_silent); // Set notification volume to follow ringer volume by default - loadBooleanSetting(stmt, Settings.System.NOTIFICATIONS_USE_RING_VOLUME, - R.bool.def_notifications_use_ring_volume); + if (mContext.getResources().getBoolean( + com.android.internal.R.bool.config_voice_capable)) { + loadBooleanSetting(stmt, Settings.System.NOTIFICATIONS_USE_RING_VOLUME, + R.bool.def_notifications_use_ring_volume); + } else { + loadSetting(stmt, Settings.System.NOTIFICATIONS_USE_RING_VOLUME, "1"); + } loadIntegerSetting(stmt, Settings.System.POINTER_SPEED, R.integer.def_pointer_speed); diff --git a/packages/SystemUI/res/layout-sw600dp/compat_mode_help.xml b/packages/SystemUI/res/layout-sw600dp/compat_mode_help.xml index d29e495..a354336 100644 --- a/packages/SystemUI/res/layout-sw600dp/compat_mode_help.xml +++ b/packages/SystemUI/res/layout-sw600dp/compat_mode_help.xml @@ -43,6 +43,7 @@ android:layout_height="wrap_content" android:layout_centerInParent="true" android:src="@drawable/compat_mode_help_diagram" + android:contentDescription="@string/accessibility_compatibility_zoom_example" /> <RelativeLayout android:orientation="horizontal" @@ -61,6 +62,7 @@ android:layout_alignParentRight="true" android:layout_centerVertical="true" android:src="@drawable/compat_mode_help_icon" + android:contentDescription="@string/accessibility_compatibility_zoom_button" /> <TextView android:id="@+id/explanation" diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar.xml b/packages/SystemUI/res/layout-sw600dp/status_bar.xml index d9f3f23..a2a6473 100644 --- a/packages/SystemUI/res/layout-sw600dp/status_bar.xml +++ b/packages/SystemUI/res/layout-sw600dp/status_bar.xml @@ -49,6 +49,7 @@ android:src="@drawable/ic_sysbar_back" android:layout_alignParentLeft="true" systemui:keyCode="4" + android:contentDescription="@string/accessibility_back" /> <LinearLayout android:id="@+id/navigationArea" @@ -62,11 +63,13 @@ android:layout_height="match_parent" android:src="@drawable/ic_sysbar_home" systemui:keyCode="3" + android:contentDescription="@string/accessibility_home" /> <ImageView android:id="@+id/recent_apps" android:layout_width="80dip" android:layout_height="match_parent" android:src="@drawable/ic_sysbar_recent" + android:contentDescription="@string/accessibility_menu" /> <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/menu" android:layout_width="80dip" @@ -74,6 +77,7 @@ android:src="@drawable/ic_sysbar_menu" systemui:keyCode="82" android:visibility="invisible" + android:contentDescription="@string/accessibility_menu" /> </LinearLayout> diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar_input_methods_item.xml b/packages/SystemUI/res/layout-sw600dp/status_bar_input_methods_item.xml index 3fef7e0..41a20fb 100644 --- a/packages/SystemUI/res/layout-sw600dp/status_bar_input_methods_item.xml +++ b/packages/SystemUI/res/layout-sw600dp/status_bar_input_methods_item.xml @@ -53,7 +53,8 @@ android:id="@+id/item_icon" android:layout_width="@android:dimen/app_icon_size" android:layout_height="wrap_content" - android:scaleType="fitCenter" /> + android:scaleType="fitCenter" + android:contentDescription="@null" /> <LinearLayout android:orientation="vertical" android:layout_width="0px" @@ -94,7 +95,8 @@ android:visibility="visible" android:clickable="true" android:focusable="true" - android:background="?android:attr/selectableItemBackground" /> + android:background="?android:attr/selectableItemBackground" + android:contentDescription="@string/accessibility_settings_button" /> </LinearLayout> <View android:layout_width="match_parent" diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar_notification_area.xml b/packages/SystemUI/res/layout-sw600dp/status_bar_notification_area.xml index fecfe7f..1e3099d 100644 --- a/packages/SystemUI/res/layout-sw600dp/status_bar_notification_area.xml +++ b/packages/SystemUI/res/layout-sw600dp/status_bar_notification_area.xml @@ -16,7 +16,7 @@ --> <!-- notification icons & panel access --> -<LinearLayout +<com.android.systemui.statusbar.tablet.NotificationArea xmlns:android="http://schemas.android.com/apk/res/android" xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui" android:id="@+id/notificationArea" @@ -40,6 +40,7 @@ android:layout_marginLeft="8dip" android:src="@drawable/ic_sysbar_ime_default" android:visibility="gone" + android:contentDescription="@string/accessibility_ime_switch_button" /> <com.android.systemui.statusbar.policy.CompatModeButton @@ -49,6 +50,7 @@ android:layout_marginLeft="8dip" android:src="@drawable/ic_sysbar_zoom" android:visibility="gone" + android:contentDescription="@string/accessibility_compatibility_zoom_button" /> <com.android.systemui.statusbar.tablet.NotificationIconArea @@ -152,4 +154,4 @@ /> </LinearLayout> </LinearLayout> -</LinearLayout> +</com.android.systemui.statusbar.tablet.NotificationArea> diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar_notification_panel_title.xml b/packages/SystemUI/res/layout-sw600dp/status_bar_notification_panel_title.xml index 543f4ed..bbb2bc6 100644 --- a/packages/SystemUI/res/layout-sw600dp/status_bar_notification_panel_title.xml +++ b/packages/SystemUI/res/layout-sw600dp/status_bar_notification_panel_title.xml @@ -14,15 +14,17 @@ limitations under the License. --> -<RelativeLayout +<com.android.systemui.statusbar.tablet.NotificationPanelTitle xmlns:android="http://schemas.android.com/apk/res/android" xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui" android:id="@+id/title_area" - android:layout_width="0dp" - android:layout_height="0dp" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:clickable="true" android:orientation="vertical" android:background="@drawable/notify_panel_clock_bg" > + <LinearLayout android:id="@+id/icons" android:layout_width="wrap_content" @@ -34,6 +36,7 @@ android:layout_marginTop="16dp" android:layout_marginBottom="16dp" > + <ImageView android:id="@+id/bluetooth" android:layout_height="32dp" @@ -41,6 +44,7 @@ android:scaleType="centerInside" android:baseline="22dp" android:visibility="gone" + android:contentDescription="@null" /> <FrameLayout @@ -49,21 +53,28 @@ android:layout_width="32dp" android:layout_marginRight="4dp" > + <ImageView android:id="@+id/network_signal" android:layout_height="match_parent" android:layout_width="match_parent" + android:contentDescription="@null" /> + <ImageView android:id="@+id/network_type" android:layout_height="match_parent" android:layout_width="match_parent" + android:contentDescription="@null" /> + <ImageView android:id="@+id/network_direction" android:layout_height="match_parent" android:layout_width="match_parent" + android:contentDescription="@null" /> + </FrameLayout> <TextView @@ -86,6 +97,7 @@ android:layout_toRightOf="@id/network_text" android:layout_alignBaseline="@id/network_signal" android:baseline="22dp" + android:contentDescription="@null" /> <TextView @@ -110,6 +122,7 @@ android:paddingRight="16dp" android:src="@drawable/ic_sysbar_quicksettings" android:baseline="21dp" + android:contentDescription="@string/accessibility_settings_button" /> <ImageView @@ -122,6 +135,7 @@ android:src="@drawable/ic_notification_open" android:baseline="21dp" android:visibility="invisible" + android:contentDescription="@string/accessibility_notifications_button" /> <View @@ -138,7 +152,7 @@ <com.android.systemui.statusbar.tablet.HoloClock android:id="@+id/clock" android:layout_height="wrap_content" - android:layout_width="match_parent" + android:layout_width="wrap_content" android:layout_alignParentRight="true" android:layout_above="@id/title_divider" android:layout_marginRight="6dip" @@ -164,19 +178,11 @@ android:id="@+id/date" style="@style/StatusBarNotificationText" android:layout_height="wrap_content" - android:layout_width="120dp" + android:layout_width="wrap_content" android:layout_alignBottom="@id/clock" android:layout_alignParentLeft="true" android:gravity="left" android:layout_marginLeft="32dp" /> - <view - class="com.android.systemui.statusbar.tablet.NotificationPanel$ModeToggle" - android:id="@+id/mode_toggle" - android:background="@null" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:clickable="true" - /> -</RelativeLayout> +</com.android.systemui.statusbar.tablet.NotificationPanelTitle> diff --git a/packages/SystemUI/res/layout/navigation_bar.xml b/packages/SystemUI/res/layout/navigation_bar.xml index 51e7d97..5d7e8de 100644 --- a/packages/SystemUI/res/layout/navigation_bar.xml +++ b/packages/SystemUI/res/layout/navigation_bar.xml @@ -54,6 +54,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" + android:contentDescription="@string/accessibility_back" /> <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/home" android:layout_width="80dp" @@ -66,6 +67,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" + android:contentDescription="@string/accessibility_home" /> <ImageView android:id="@+id/recent_apps" android:layout_width="80dp" @@ -80,6 +82,7 @@ systemui:keyCode="82" android:layout_weight="0" android:visibility="invisible" + android:contentDescription="@string/accessibility_menu" /> </LinearLayout> @@ -124,6 +127,7 @@ android:layout_height="match_parent" android:layout_width="match_parent" android:layout_weight="1" + android:contentDescription="@string/accessibility_menu" /> <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/home" android:layout_height="80dp" @@ -131,11 +135,13 @@ android:src="@drawable/ic_sysbar_home_default_land" systemui:keyCode="3" android:layout_weight="0" + android:contentDescription="@string/accessibility_home" /> <View android:layout_height="match_parent" android:layout_width="match_parent" android:layout_weight="1" + android:contentDescription="@string/accessibility_back" /> <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back" android:layout_height="80dp" @@ -148,6 +154,7 @@ android:layout_height="40dp" android:layout_width="match_parent" android:layout_weight="0" + android:contentDescription="@string/accessibility_menu" /> </LinearLayout> diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index 5298f2e..d7d7817 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -34,7 +34,7 @@ <string name="config_systemBarComponent" translatable="false">com.android.systemui.statusbar.tablet.TabletStatusBar</string> <!-- Whether or not we show the number in the bar. --> - <bool name="config_statusBarShowNumber">true</bool> + <bool name="config_statusBarShowNumber">false</bool> <!-- How many icons may be shown at once in the system bar. Includes any slots that may be reused for things like IME control. --> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 01cf2dc..082dab3 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -169,4 +169,135 @@ <string name="screenshot_saving_toast">Screenshot saved to Gallery</string> <!-- toast message displayed when we fail to take a screenshot. --> <string name="screenshot_failed_toast">Could not save screenshot</string> + + <!-- 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> + + <!-- Content description of the back button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_back">Back</string> + <!-- Content description of the home button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_home">Home</string> + <!-- Content description of the menu button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_menu">Menu</string> + + <!-- Content description of the switch input method button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_ime_switch_button">Switch input method button.</string> + <!-- Content description of the compatibility zoom button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_compatibility_zoom_button">Compatibility zoom button.</string> + + <!-- Content description of picture of the compatibility zoom example for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_compatibility_zoom_example">Zoom smaller to larger screen.</string> + + <!-- Content description of the bluetooth icon when connected for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_bluetooth_connected">Bluetooth connected.</string> + <!-- Content description of the bluetooth icon when connecting for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_bluetooth_disconnected">Bluetooth disconnected.</string> + + <!-- Content description of the battery when no battery for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_no_battery">No battery.</string> + <!-- Content description of the battery when it is one bar for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_battery_one_bar">Battery one bar.</string> + <!-- Content description of the battery when it is two bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_battery_two_bars">Battery two bars.</string> + <!-- Content description of the battery when it is three bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_battery_three_bars">Battery three bars.</string> + <!-- Content description of the battery when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_battery_full">Battery full.</string> + + <!-- Content description of the phone signal when no signal for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_no_phone">No phone.</string> + <!-- Content description of the phone signal when it is one bar for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_phone_one_bar">Phone one bar.</string> + <!-- Content description of the phone signal when it is two bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_phone_two_bars">Phone two bars.</string> + <!-- Content description of the phone signal when it is three bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_phone_three_bars">Phone three bars.</string> + <!-- Content description of the phone signal when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_phone_signal_full">Phone signal full.</string> + + <!-- Content description of the data signal when no signal for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_no_data">No data.</string> + <!-- Content description of the data signal when it is one bar for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_data_one_bar">Data one bar.</string> + <!-- Content description of the data signal when it is two bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_data_two_bars">Data two bars.</string> + <!-- Content description of the data signal when it is three bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_data_three_bars">Data three bars.</string> + <!-- Content description of the data signal when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_data_signal_full">Data signal full.</string> + + <!-- Content description of the WIFI signal when no signal for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_no_wifi">No WiFi.</string> + <!-- Content description of the WIFI signal when it is one bar for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_wifi_one_bar">WiFi one bar.</string> + <!-- Content description of the WIFI signal when it is two bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_wifi_two_bars">WiFi two bars.</string> + <!-- Content description of the WIFI signal when it is three bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_wifi_three_bars">WiFi three bars.</string> + <!-- Content description of the WIFI signal when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_wifi_signal_full">WiFi signal full.</string> + + <!-- Content description of the data connection type GPRS for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_data_connection_gprs">GPRS</string> + + <!-- Content description of the data connection type 3G for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_data_connection_3g">3G</string> + + <!-- Content description of the data connection type 3.5G for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_data_connection_3.5g">3.5G</string> + + <!-- Content description of the data connection type 4G for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_data_connection_4g">4G</string> + + <!-- Content description of the data connection type CDMA for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_data_connection_cdma">CDMA</string> + + <!-- Content description of the data connection type Edge for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_data_connection_edge">Edge</string> + + <!-- Content description of the data connection type WiFi for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_data_connection_wifi">WiFi</string> + + <!-- Content description of the data connection with no SIM for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_no_sim">No SIM.</string> + + <!-- Content description of the bluetooth tethering icon for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_bluetooth_tether">Bluetooth tethering.</string> + + <!-- Content description of the airplane mode icon for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_airplane_mode">Airplane mode.</string> + + <!-- Content description of the battery level icon for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_battery_level">Battery <xliff:g id="number">%d</xliff:g> percent.</string> + + <!-- Content description of the button for showing a settings panel in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_settings_button">Settings button.</string> + + <!-- Content description of the button for showing a notifications panel in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_notifications_button">Notifications button.</string> + + <!-- Content description of the button for removing a notification in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_remove_notification">Remove notification.</string> + + <!-- Content description of the enabled GPS icon in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_gps_enabled">GPS enabled.</string> + + <!-- Content description of the acquiring GPS icon in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_gps_acquiring">GPS acquiring.</string> + + <!-- Content description of the TeleTypewriter(TTY) enabled icon in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_tty_enabled">TeleTypewriter enabled.</string> + + <!-- Content description of the ringer vibrate icon in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_ringer_vibrate">Ringer vibrate.</string> + + <!-- Content description of the ringer silent icon in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_ringer_silent">Ringer silent.</string> + </resources> diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java index bc0a508..ea54445 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java @@ -22,7 +22,6 @@ import java.util.List; import android.animation.Animator; import android.animation.LayoutTransition; import android.app.ActivityManager; -import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; @@ -48,6 +47,7 @@ import android.util.DisplayMetrics; import android.util.Log; import android.view.LayoutInflater; import android.view.MenuItem; +import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; @@ -112,7 +112,7 @@ public class RecentsPanelView extends RelativeLayout position = _pos; packageName = _packageName; } - }; + } private final class OnLongClickDelegate implements View.OnLongClickListener { View mOtherView; @@ -252,6 +252,19 @@ public class RecentsPanelView extends RelativeLayout mChoreo.setPanelHeight(mRecentsContainer.getHeight()); } + @Override + public boolean dispatchHoverEvent(MotionEvent event) { + // Ignore hover events outside of this panel bounds since such events + // generate spurious accessibility events with the panel content when + // tapping outside of it, thus confusing the user. + final int x = (int) event.getX(); + final int y = (int) event.getY(); + if (x >= 0 && x < getWidth() && y >= 0 && y < getHeight()) { + return super.dispatchHoverEvent(event); + } + return true; + } + /** * Whether the panel is showing, or, if it's animating, whether it will be * when the animation is done. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LatestItemView.java b/packages/SystemUI/src/com/android/systemui/statusbar/LatestItemView.java index 64ec063..6419777 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/LatestItemView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/LatestItemView.java @@ -18,8 +18,8 @@ package com.android.systemui.statusbar; import android.content.Context; import android.util.AttributeSet; -import android.util.Slog; -import android.view.MotionEvent; +import android.view.View; +import android.view.accessibility.AccessibilityEvent; import android.widget.FrameLayout; public class LatestItemView extends FrameLayout { @@ -27,7 +27,22 @@ public class LatestItemView extends FrameLayout { super(context, attrs); } + @Override public void setOnClickListener(OnClickListener l) { super.setOnClickListener(l); } + + @Override + public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) { + if (super.onRequestSendAccessibilityEvent(child, event)) { + // Add a record for the entire layout since its content is somehow small. + // The event comes from a leaf view that is interacted with. + AccessibilityEvent record = AccessibilityEvent.obtain(); + onInitializeAccessibilityEvent(record); + dispatchPopulateAccessibilityEvent(record); + event.appendRecord(record); + return true; + } + return false; + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java index d9d9c06..be4b395 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java @@ -16,6 +16,7 @@ package com.android.systemui.statusbar; +import android.app.Notification; import android.content.Context; import android.content.pm.PackageManager; import android.content.res.Resources; @@ -23,11 +24,11 @@ import android.graphics.drawable.Drawable; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Rect; +import android.text.TextUtils; import android.util.Slog; import android.util.Log; -import android.view.View; import android.view.ViewDebug; -import android.widget.FrameLayout; +import android.view.accessibility.AccessibilityEvent; import java.text.NumberFormat; @@ -45,8 +46,9 @@ public class StatusBarIconView extends AnimatedImageView { private int mNumberX; private int mNumberY; private String mNumberText; + private Notification mNotification; - public StatusBarIconView(Context context, String slot) { + public StatusBarIconView(Context context, String slot, Notification notification) { super(context); final Resources res = context.getResources(); mSlot = slot; @@ -54,6 +56,8 @@ public class StatusBarIconView extends AnimatedImageView { mNumberPain.setTextAlign(Paint.Align.CENTER); mNumberPain.setColor(res.getColor(R.drawable.notification_number_text_color)); mNumberPain.setAntiAlias(true); + mNotification = notification; + setContentDescription(notification); } private static boolean streq(String a, String b) { @@ -83,6 +87,7 @@ public class StatusBarIconView extends AnimatedImageView { final boolean numberEquals = mIcon != null && mIcon.number == icon.number; mIcon = icon.clone(); + setContentDescription(icon.contentDescription); if (!iconEquals) { Drawable drawable = getIcon(icon); if (drawable == null) { @@ -159,6 +164,15 @@ public class StatusBarIconView extends AnimatedImageView { return mIcon; } + @Override + public void onInitializeAccessibilityEvent(AccessibilityEvent event) { + super.onInitializeAccessibilityEvent(event); + if (mNotification != null) { + event.setParcelableData(mNotification); + } + } + + @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); if (mNumberBackground != null) { @@ -166,6 +180,7 @@ public class StatusBarIconView extends AnimatedImageView { } } + @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); @@ -175,6 +190,7 @@ public class StatusBarIconView extends AnimatedImageView { } } + @Override protected void debug(int depth) { super.debug(depth); Log.d("View", debugIndent(depth) + "slot=" + mSlot); @@ -213,4 +229,13 @@ public class StatusBarIconView extends AnimatedImageView { mNumberY = h-r.bottom-((dh-r.top-th-r.bottom)/2); mNumberBackground.setBounds(w-dw, h-dh, w, h); } + + private void setContentDescription(Notification notification) { + if (notification != null) { + CharSequence tickerText = notification.tickerText; + if (!TextUtils.isEmpty(tickerText)) { + setContentDescription(tickerText); + } + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/IconMerger.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/IconMerger.java index e1d17a8..f6aa159 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/IconMerger.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/IconMerger.java @@ -33,7 +33,8 @@ public class IconMerger extends LinearLayout { private int mIconSize; private StatusBarIconView mMoreView; - private StatusBarIcon mMoreIcon = new StatusBarIcon(null, R.drawable.stat_notify_more, 0); + private StatusBarIcon mMoreIcon = new StatusBarIcon(null, R.drawable.stat_notify_more, 0, 0, + null); public IconMerger(Context context, AttributeSet attrs) { super(context, attrs); @@ -41,7 +42,7 @@ public class IconMerger extends LinearLayout { mIconSize = context.getResources().getDimensionPixelSize( com.android.internal.R.dimen.status_bar_icon_size); - mMoreView = new StatusBarIconView(context, "more"); + mMoreView = new StatusBarIconView(context, "more", null); mMoreView.set(mMoreIcon); addView(mMoreView, 0, new LinearLayout.LayoutParams(mIconSize, mIconSize)); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index b50fd81..b93ad68 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -472,7 +472,7 @@ public class PhoneStatusBar extends StatusBar { public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon) { if (SPEW) Slog.d(TAG, "addIcon slot=" + slot + " index=" + index + " viewIndex=" + viewIndex + " icon=" + icon); - StatusBarIconView view = new StatusBarIconView(mContext, slot); + StatusBarIconView view = new StatusBarIconView(mContext, slot, null); view.set(icon); mStatusIcons.addView(view, viewIndex, new LinearLayout.LayoutParams(mIconSize, mIconSize)); } @@ -565,27 +565,33 @@ public class PhoneStatusBar extends StatusBar { final RemoteViews contentView = notification.notification.contentView; - if (false) { + if (DEBUG) { Slog.d(TAG, "old notification: when=" + oldNotification.notification.when + " ongoing=" + oldNotification.isOngoing() + " expanded=" + oldEntry.expanded - + " contentView=" + oldContentView); + + " contentView=" + oldContentView + + " rowParent=" + oldEntry.row.getParent()); Slog.d(TAG, "new notification: when=" + notification.notification.when + " ongoing=" + oldNotification.isOngoing() + " contentView=" + contentView); } + // Can we just reapply the RemoteViews in place? If when didn't change, the order // didn't change. - if (notification.notification.when == oldNotification.notification.when - && notification.isOngoing() == oldNotification.isOngoing() - && oldEntry.expanded != null + boolean contentsUnchanged = oldEntry.expanded != null && contentView != null && oldContentView != null && contentView.getPackage() != null && oldContentView.getPackage() != null && oldContentView.getPackage().equals(contentView.getPackage()) - && oldContentView.getLayoutId() == contentView.getLayoutId()) { - if (SPEW) Slog.d(TAG, "reusing notification"); + && oldContentView.getLayoutId() == contentView.getLayoutId(); + ViewGroup rowParent = (ViewGroup) oldEntry.row.getParent(); + boolean orderUnchanged = notification.notification.when==oldNotification.notification.when + && notification.priority == oldNotification.priority; + // priority now encompasses isOngoing() + boolean isLastAnyway = rowParent.indexOfChild(oldEntry.row) == rowParent.getChildCount()-1; + if (contentsUnchanged && (orderUnchanged || isLastAnyway)) { + if (DEBUG) Slog.d(TAG, "reusing notification for key: " + key); oldEntry.notification = notification; try { // Reapply the RemoteViews @@ -601,7 +607,7 @@ public class PhoneStatusBar extends StatusBar { // Update the icon. final StatusBarIcon ic = new StatusBarIcon(notification.pkg, notification.notification.icon, notification.notification.iconLevel, - notification.notification.number); + notification.notification.number, notification.notification.tickerText); if (!oldEntry.icon.set(ic)) { handleNotificationError(key, notification, "Couldn't update icon: " + ic); return; @@ -759,9 +765,11 @@ public class PhoneStatusBar extends StatusBar { final View expanded = views[2]; // Construct the icon. final StatusBarIconView iconView = new StatusBarIconView(mContext, - notification.pkg + "/0x" + Integer.toHexString(notification.id)); + notification.pkg + "/0x" + Integer.toHexString(notification.id), + notification.notification); final StatusBarIcon ic = new StatusBarIcon(notification.pkg, notification.notification.icon, - notification.notification.iconLevel, notification.notification.number); + notification.notification.iconLevel, notification.notification.number, + notification.notification.tickerText); if (!iconView.set(ic)) { handleNotificationError(key, notification, "Coulding create icon: " + ic); return null; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java index af5c72d..7b50985 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java @@ -18,25 +18,17 @@ package com.android.systemui.statusbar.phone; import android.app.StatusBarManager; import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothProfile; -import android.bluetooth.BluetoothPbap; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.content.res.TypedArray; -import android.graphics.PixelFormat; -import android.graphics.Typeface; -import android.graphics.drawable.Drawable; import android.location.LocationManager; import android.media.AudioManager; import android.net.ConnectivityManager; import android.net.NetworkInfo; -import android.net.Uri; import android.net.wifi.WifiManager; import android.os.Binder; import android.os.Handler; -import android.os.Message; import android.os.RemoteException; import android.os.storage.StorageManager; import android.provider.Settings; @@ -44,18 +36,7 @@ import android.telephony.PhoneStateListener; import android.telephony.ServiceState; import android.telephony.SignalStrength; import android.telephony.TelephonyManager; -import android.text.format.DateFormat; -import android.text.style.CharacterStyle; -import android.text.style.RelativeSizeSpan; -import android.text.style.ForegroundColorSpan; -import android.text.style.StyleSpan; -import android.text.Spannable; -import android.text.SpannableStringBuilder; import android.util.Slog; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.LinearLayout; import com.android.internal.app.IBatteryStats; import com.android.internal.telephony.IccCard; @@ -63,7 +44,6 @@ import com.android.internal.telephony.TelephonyIntents; import com.android.internal.telephony.cdma.EriInfo; import com.android.internal.telephony.cdma.TtyIntent; import com.android.server.am.BatteryStatsService; - import com.android.systemui.R; /** @@ -447,6 +427,32 @@ public class PhoneStatusBarPolicy { R.drawable.stat_sys_data_fully_inandout_1x } }; + // Accessibility; + + private static final int[] sPhoneSignalStrength = { + R.string.accessibility_no_phone, + R.string.accessibility_phone_one_bar, + R.string.accessibility_phone_two_bars, + R.string.accessibility_phone_three_bars, + R.string.accessibility_phone_signal_full + }; + + private static final int[] sDataConnectionStrength = { + R.string.accessibility_no_data, + R.string.accessibility_data_one_bar, + R.string.accessibility_data_two_bars, + R.string.accessibility_data_three_bars, + R.string.accessibility_data_signal_full + }; + + private static final int[] sWifiConnectionStrength = { + R.string.accessibility_no_wifi, + R.string.accessibility_wifi_one_bar, + R.string.accessibility_wifi_two_bars, + R.string.accessibility_wifi_three_bars, + R.string.accessibility_wifi_signal_full + }; + // Assume it's all good unless we hear otherwise. We don't always seem // to get broadcasts that it *is* there. IccCard.State mSimState = IccCard.State.READY; @@ -546,12 +552,13 @@ public class PhoneStatusBarPolicy { new com.android.systemui.usb.StorageNotification(context)); // battery - mService.setIcon("battery", com.android.internal.R.drawable.stat_sys_battery_unknown, 0); + mService.setIcon("battery", com.android.internal.R.drawable.stat_sys_battery_unknown, 0, + null); // phone_signal mPhone = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE); mPhoneSignalIconId = R.drawable.stat_sys_signal_null; - mService.setIcon("phone_signal", mPhoneSignalIconId, 0); + mService.setIcon("phone_signal", mPhoneSignalIconId, 0, null); // register for phone state notifications. ((TelephonyManager)mContext.getSystemService(Context.TELEPHONY_SERVICE)) @@ -563,24 +570,24 @@ public class PhoneStatusBarPolicy { | PhoneStateListener.LISTEN_DATA_ACTIVITY); // data_connection - mService.setIcon("data_connection", R.drawable.stat_sys_data_connected_g, 0); + mService.setIcon("data_connection", R.drawable.stat_sys_data_connected_g, 0, null); mService.setIconVisibility("data_connection", false); // wifi - mService.setIcon("wifi", sWifiSignalImages[0][0], 0); + mService.setIcon("wifi", sWifiSignalImages[0][0], 0, null); mService.setIconVisibility("wifi", false); // wifi will get updated by the sticky intents // TTY status - mService.setIcon("tty", R.drawable.stat_sys_tty_mode, 0); + mService.setIcon("tty", R.drawable.stat_sys_tty_mode, 0, null); mService.setIconVisibility("tty", false); // Cdma Roaming Indicator, ERI - mService.setIcon("cdma_eri", R.drawable.stat_sys_roaming_cdma_0, 0); + mService.setIcon("cdma_eri", R.drawable.stat_sys_roaming_cdma_0, 0, null); mService.setIconVisibility("cdma_eri", false); // bluetooth status - mService.setIcon("bluetooth", R.drawable.stat_sys_data_bluetooth, 0); + mService.setIcon("bluetooth", R.drawable.stat_sys_data_bluetooth, 0, null); BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); if (adapter != null) { mBluetoothEnabled = adapter.isEnabled(); @@ -590,21 +597,23 @@ public class PhoneStatusBarPolicy { mService.setIconVisibility("bluetooth", mBluetoothEnabled); // Gps status - mService.setIcon("gps", R.drawable.stat_sys_gps_acquiring_anim, 0); + mService.setIcon("gps", R.drawable.stat_sys_gps_acquiring_anim, 0, null); mService.setIconVisibility("gps", false); // Alarm clock - mService.setIcon("alarm_clock", R.drawable.stat_notify_alarm, 0); + mService.setIcon("alarm_clock", R.drawable.stat_notify_alarm, 0, null); mService.setIconVisibility("alarm_clock", false); // Sync state - mService.setIcon("sync_active", com.android.internal.R.drawable.stat_notify_sync_anim0, 0); - mService.setIcon("sync_failing", com.android.internal.R.drawable.stat_notify_sync_error, 0); + mService.setIcon("sync_active", com.android.internal.R.drawable.stat_notify_sync_anim0, + 0, null); + mService.setIcon("sync_failing", com.android.internal.R.drawable.stat_notify_sync_error, + 0, null); mService.setIconVisibility("sync_active", false); mService.setIconVisibility("sync_failing", false); // volume - mService.setIcon("volume", R.drawable.stat_sys_ringer_silent, 0); + mService.setIcon("volume", R.drawable.stat_sys_ringer_silent, 0, null); mService.setIconVisibility("volume", false); updateVolume(); @@ -655,7 +664,8 @@ public class PhoneStatusBarPolicy { private final void updateBattery(Intent intent) { final int id = intent.getIntExtra("icon-small", 0); int level = intent.getIntExtra("level", 0); - mService.setIcon("battery", id, level); + String contentDescription = mContext.getString(R.string.accessibility_battery_level, level); + mService.setIcon("battery", id, level, contentDescription); } private void updateConnectivity(Intent intent) { @@ -677,12 +687,16 @@ public class PhoneStatusBarPolicy { if (info.isConnected()) { mIsWifiConnected = true; int iconId; + String contentDescription = null; if (mLastWifiSignalLevel == -1) { iconId = sWifiSignalImages[mInetCondition][0]; + contentDescription = mContext.getString(sWifiConnectionStrength[0]); } else { iconId = sWifiSignalImages[mInetCondition][mLastWifiSignalLevel]; - } - mService.setIcon("wifi", iconId, 0); + contentDescription = mContext.getString( + sWifiConnectionStrength[mLastWifiSignalLevel]); + } + mService.setIcon("wifi", iconId, 0, contentDescription); // Show the icon since wi-fi is connected mService.setIconVisibility("wifi", true); } else { @@ -690,7 +704,8 @@ public class PhoneStatusBarPolicy { mIsWifiConnected = false; int iconId = sWifiSignalImages[0][0]; - mService.setIcon("wifi", iconId, 0); + String contentDescription = mContext.getString(R.string.accessibility_no_wifi); + mService.setIcon("wifi", iconId, 0, contentDescription); // Hide the icon since we're not connected mService.setIconVisibility("wifi", false); } @@ -781,6 +796,7 @@ public class PhoneStatusBarPolicy { private final void updateSignalStrength() { int[] iconList; + String contentDescription = null; // Display signal strength while in "emergency calls only" mode if (mServiceState == null || (!hasService() && !mServiceState.isEmergencyOnly())) { @@ -788,10 +804,12 @@ public class PhoneStatusBarPolicy { if (Settings.System.getInt(mContext.getContentResolver(), Settings.System.AIRPLANE_MODE_ON, 0) == 1) { mPhoneSignalIconId = R.drawable.stat_sys_signal_flightmode; + contentDescription = mContext.getString(R.string.accessibility_airplane_mode); } else { mPhoneSignalIconId = R.drawable.stat_sys_signal_null; + contentDescription = mContext.getString(R.string.accessibility_no_phone); } - mService.setIcon("phone_signal", mPhoneSignalIconId, 0); + mService.setIcon("phone_signal", mPhoneSignalIconId, 0, contentDescription); return; } @@ -805,8 +823,11 @@ public class PhoneStatusBarPolicy { } else { iconList = sSignalImages[mInetCondition]; } - mPhoneSignalIconId = iconList[mSignalStrength.getLevel()]; - mService.setIcon("phone_signal", mPhoneSignalIconId, 0); + + final int signalLevel = mSignalStrength.getLevel(); + mPhoneSignalIconId = iconList[signalLevel]; + contentDescription = mContext.getString(sPhoneSignalStrength[signalLevel]); + mService.setIcon("phone_signal", mPhoneSignalIconId, 0, contentDescription); } private final void updateDataNetType(int net) { @@ -850,6 +871,7 @@ public class PhoneStatusBarPolicy { private final void updateDataIcon() { int iconId; + String contentDescription = null; boolean visible = true; if (!isCdma()) { @@ -870,13 +892,15 @@ public class PhoneStatusBarPolicy { iconId = mDataIconList[0]; break; } - mService.setIcon("data_connection", iconId, 0); + contentDescription = mContext.getString(sDataConnectionStrength[mDataActivity]); + mService.setIcon("data_connection", iconId, 0, contentDescription); } else { visible = false; } } else { iconId = R.drawable.stat_sys_no_sim; - mService.setIcon("data_connection", iconId, 0); + contentDescription = mContext.getString(R.string.accessibility_no_sim); + mService.setIcon("data_connection", iconId, 0, contentDescription); } } else { // CDMA case, mDataActivity can be also DATA_ACTIVITY_DORMANT @@ -896,7 +920,7 @@ public class PhoneStatusBarPolicy { iconId = mDataIconList[0]; break; } - mService.setIcon("data_connection", iconId, 0); + mService.setIcon("data_connection", iconId, 0, null); } else { visible = false; } @@ -921,12 +945,19 @@ public class PhoneStatusBarPolicy { final int ringerMode = audioManager.getRingerMode(); final boolean visible = ringerMode == AudioManager.RINGER_MODE_SILENT || ringerMode == AudioManager.RINGER_MODE_VIBRATE; - final int iconId = audioManager.shouldVibrate(AudioManager.VIBRATE_TYPE_RINGER) - ? R.drawable.stat_sys_ringer_vibrate - : R.drawable.stat_sys_ringer_silent; + + final int iconId; + String contentDescription = null; + if (audioManager.shouldVibrate(AudioManager.VIBRATE_TYPE_RINGER)) { + iconId = R.drawable.stat_sys_ringer_vibrate; + contentDescription = mContext.getString(R.string.accessibility_ringer_vibrate); + } else { + iconId = R.drawable.stat_sys_ringer_silent; + contentDescription = mContext.getString(R.string.accessibility_ringer_silent); + } if (visible) { - mService.setIcon("volume", iconId, 0); + mService.setIcon("volume", iconId, 0, contentDescription); } if (visible != mVolumeVisible) { mService.setIconVisibility("volume", visible); @@ -936,6 +967,7 @@ public class PhoneStatusBarPolicy { private final void updateBluetooth(Intent intent) { int iconId = R.drawable.stat_sys_data_bluetooth; + String contentDescription = null; String action = intent.getAction(); if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) { int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR); @@ -945,12 +977,16 @@ public class PhoneStatusBarPolicy { BluetoothAdapter.STATE_DISCONNECTED); if (state == BluetoothAdapter.STATE_CONNECTED) { iconId = R.drawable.stat_sys_data_bluetooth_connected; + contentDescription = mContext.getString(R.string.accessibility_bluetooth_connected); + } else { + contentDescription = mContext.getString( + R.string.accessibility_bluetooth_disconnected); } } else { return; } - mService.setIcon("bluetooth", iconId, 0); + mService.setIcon("bluetooth", iconId, 0, contentDescription); mService.setIconVisibility("bluetooth", mBluetoothEnabled); } @@ -974,6 +1010,7 @@ public class PhoneStatusBarPolicy { } } else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) { int iconId; + String contentDescription = null; final int newRssi = intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200); int newSignalLevel = WifiManager.calculateSignalLevel(newRssi, sWifiSignalImages[0].length); @@ -981,10 +1018,13 @@ public class PhoneStatusBarPolicy { mLastWifiSignalLevel = newSignalLevel; if (mIsWifiConnected) { iconId = sWifiSignalImages[mInetCondition][newSignalLevel]; + contentDescription = mContext.getString( + sWifiConnectionStrength[newSignalLevel]); } else { iconId = sWifiTemporarilyNotConnectedImage; + contentDescription = mContext.getString(R.string.accessibility_no_wifi); } - mService.setIcon("wifi", iconId, 0); + mService.setIcon("wifi", iconId, 0, contentDescription); } } } @@ -995,14 +1035,16 @@ public class PhoneStatusBarPolicy { if (action.equals(LocationManager.GPS_FIX_CHANGE_ACTION) && enabled) { // GPS is getting fixes - mService.setIcon("gps", com.android.internal.R.drawable.stat_sys_gps_on, 0); + mService.setIcon("gps", com.android.internal.R.drawable.stat_sys_gps_on, 0, + mContext.getString(R.string.accessibility_gps_enabled)); mService.setIconVisibility("gps", true); } else if (action.equals(LocationManager.GPS_ENABLED_CHANGE_ACTION) && !enabled) { // GPS is off mService.setIconVisibility("gps", false); } else { // GPS is on, but not receiving fixes - mService.setIcon("gps", R.drawable.stat_sys_gps_acquiring_anim, 0); + mService.setIcon("gps", R.drawable.stat_sys_gps_acquiring_anim, 0, + mContext.getString(R.string.accessibility_gps_acquiring)); mService.setIconVisibility("gps", true); } } @@ -1016,7 +1058,8 @@ public class PhoneStatusBarPolicy { if (enabled) { // TTY is on if (false) Slog.v(TAG, "updateTTY: set TTY on"); - mService.setIcon("tty", R.drawable.stat_sys_tty_mode, 0); + mService.setIcon("tty", R.drawable.stat_sys_tty_mode, 0, + mContext.getString(R.string.accessibility_tty_enabled)); mService.setIconVisibility("tty", true); } else { // TTY is off @@ -1058,15 +1101,15 @@ public class PhoneStatusBarPolicy { switch (iconMode) { case EriInfo.ROAMING_ICON_MODE_NORMAL: - mService.setIcon("cdma_eri", iconList[iconIndex], 0); + mService.setIcon("cdma_eri", iconList[iconIndex], 0, null); mService.setIconVisibility("cdma_eri", true); break; case EriInfo.ROAMING_ICON_MODE_FLASH: - mService.setIcon("cdma_eri", R.drawable.stat_sys_roaming_cdma_flash, 0); + mService.setIcon("cdma_eri", R.drawable.stat_sys_roaming_cdma_flash, 0, null); mService.setIconVisibility("cdma_eri", true); break; } - mService.setIcon("phone_signal", mPhoneSignalIconId, 0); + mService.setIcon("phone_signal", mPhoneSignalIconId, 0, null); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java index 84c524a..c2390e8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java @@ -26,6 +26,7 @@ import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.ViewParent; +import android.view.accessibility.AccessibilityEvent; import android.widget.FrameLayout; import com.android.systemui.R; @@ -203,5 +204,19 @@ public class PhoneStatusBarView extends FrameLayout { return mService.interceptTouchEvent(event) ? true : super.onInterceptTouchEvent(event); } -} + @Override + public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) { + if (super.onRequestSendAccessibilityEvent(child, event)) { + // The status bar is very small so augment the view that the user is touching + // with the content of the status bar a whole. This way an accessibility service + // may announce the current item as well as the entire content if appropriate. + AccessibilityEvent record = AccessibilityEvent.obtain(); + onInitializeAccessibilityEvent(record); + dispatchPopulateAccessibilityEvent(record); + event.appendRecord(record); + return true; + } + return false; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/Ticker.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/Ticker.java index 8ee12de..e76fe51 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/Ticker.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/Ticker.java @@ -183,7 +183,8 @@ public abstract class Ticker { } final Drawable icon = StatusBarIconView.getIcon(mContext, - new StatusBarIcon(n.pkg, n.notification.icon, n.notification.iconLevel, 0)); + new StatusBarIcon(n.pkg, n.notification.icon, n.notification.iconLevel, 0, + n.notification.tickerText)); final Segment newSegment = new Segment(n, icon, n.notification.tickerText); // If there's already a notification schedule for this package and id, remove it. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java new file mode 100644 index 0000000..13fb03e --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java @@ -0,0 +1,37 @@ +// Copyright 2011 Google Inc. All Rights Reserved. + +package com.android.systemui.statusbar.policy; + +import com.android.systemui.R; + +/** + * Content descriptions for accessibility support. + */ +public class AccessibilityContentDescriptions { + + private AccessibilityContentDescriptions() {} + + static final int[] PHONE_SIGNAL_STRENGTH = { + R.string.accessibility_no_phone, + R.string.accessibility_phone_one_bar, + R.string.accessibility_phone_two_bars, + R.string.accessibility_phone_three_bars, + R.string.accessibility_phone_signal_full + }; + + static final int[] DATA_CONNECTION_STRENGTH = { + R.string.accessibility_no_data, + R.string.accessibility_data_one_bar, + R.string.accessibility_data_two_bars, + R.string.accessibility_data_three_bars, + R.string.accessibility_data_signal_full + }; + + static final int[] WIFI_CONNECTION_STRENGTH = { + R.string.accessibility_no_wifi, + R.string.accessibility_wifi_one_bar, + R.string.accessibility_wifi_two_bars, + R.string.accessibility_wifi_three_bars, + R.string.accessibility_wifi_signal_full + }; +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java index ae2b6b2..3957c1b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java @@ -62,12 +62,15 @@ public class BatteryController extends BroadcastReceiver { ImageView v = mIconViews.get(i); v.setImageResource(icon); v.setImageLevel(level); + v.setContentDescription(mContext.getString(R.string.accessibility_battery_level, + level)); } N = mLabelViews.size(); for (int i=0; i<N; i++) { //final boolean plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0; TextView v = mLabelViews.get(i); - v.setText(mContext.getString(R.string.status_bar_settings_battery_meter_format, level)); + v.setText(mContext.getString(R.string.status_bar_settings_battery_meter_format, + level)); } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothController.java index 0525054..c6f416f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothController.java @@ -19,12 +19,10 @@ package com.android.systemui.statusbar.policy; import java.util.ArrayList; import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothDevice; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.util.Slog; import android.view.View; import android.widget.ImageView; @@ -54,26 +52,24 @@ public class BluetoothController extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) { - int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR); - mEnabled = state == BluetoothAdapter.STATE_ON; - } else if (action.equals(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED)) { - int state = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE, + int state = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE, BluetoothAdapter.STATE_DISCONNECTED); - if (state == BluetoothAdapter.STATE_CONNECTED) { - mIconId = R.drawable.stat_sys_data_bluetooth_connected; - } else { - mIconId = R.drawable.stat_sys_data_bluetooth; - } - } + int contentDescriptionResId = 0; + if (state == BluetoothAdapter.STATE_CONNECTED) { + mIconId = R.drawable.stat_sys_data_bluetooth_connected; + contentDescriptionResId = R.string.accessibility_bluetooth_connected; + } else { + mIconId = R.drawable.stat_sys_data_bluetooth; + contentDescriptionResId = R.string.accessibility_bluetooth_disconnected; + } int N = mIconViews.size(); for (int i=0; i<N; i++) { ImageView v = mIconViews.get(i); v.setImageResource(mIconId); v.setVisibility(mEnabled ? View.VISIBLE : View.GONE); + v.setContentDescription(mContext.getString(contentDescriptionResId)); } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java index 3175a99..829855b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java @@ -28,14 +28,11 @@ import android.content.IntentFilter; import android.content.res.Resources; import android.net.ConnectivityManager; import android.net.NetworkInfo; -import android.net.wifi.SupplicantState; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.os.Binder; import android.os.Handler; -import android.os.HandlerThread; -import android.os.Looper; import android.os.Message; import android.os.Messenger; import android.os.RemoteException; @@ -87,6 +84,11 @@ public class NetworkController extends BroadcastReceiver { int mDataTypeIconId; boolean mDataActive; + String mContentDescriptionPhoneSignal; + String mContentDescriptionWifi; + String mContentDescriptionCombinedSignal; + String mContentDescriptionDataType; + // wifi final WifiManager mWifiManager; AsyncChannel mWifiChannel; @@ -366,6 +368,8 @@ public class NetworkController extends BroadcastReceiver { if (mSignalStrength == null) { mPhoneSignalIconId = R.drawable.stat_sys_signal_null; mDataSignalIconId = R.drawable.stat_sys_signal_0; // note we use 0 instead of null + mContentDescriptionPhoneSignal = mContext.getString( + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0]); } else { int iconLevel; int[] iconList; @@ -385,6 +389,9 @@ public class NetworkController extends BroadcastReceiver { } } mPhoneSignalIconId = iconList[iconLevel]; + mContentDescriptionPhoneSignal = mContext.getString( + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[iconLevel]); + mDataSignalIconId = TelephonyIcons.DATA_SIGNAL_STRENGTH[mInetCondition][iconLevel]; } } @@ -395,14 +402,20 @@ public class NetworkController extends BroadcastReceiver { case TelephonyManager.NETWORK_TYPE_UNKNOWN: mDataIconList = TelephonyIcons.DATA_G[mInetCondition]; mDataTypeIconId = 0; + mContentDescriptionDataType = mContext.getString( + R.string.accessibility_data_connection_gprs); break; case TelephonyManager.NETWORK_TYPE_EDGE: mDataIconList = TelephonyIcons.DATA_E[mInetCondition]; mDataTypeIconId = R.drawable.stat_sys_signal_edge; + mContentDescriptionDataType = mContext.getString( + R.string.accessibility_data_connection_edge); break; case TelephonyManager.NETWORK_TYPE_UMTS: mDataIconList = TelephonyIcons.DATA_3G[mInetCondition]; mDataTypeIconId = R.drawable.stat_sys_signal_3g; + mContentDescriptionDataType = mContext.getString( + R.string.accessibility_data_connection_3g); break; case TelephonyManager.NETWORK_TYPE_HSDPA: case TelephonyManager.NETWORK_TYPE_HSUPA: @@ -410,19 +423,27 @@ public class NetworkController extends BroadcastReceiver { if (mHspaDataDistinguishable) { mDataIconList = TelephonyIcons.DATA_H[mInetCondition]; mDataTypeIconId = R.drawable.stat_sys_signal_hsdpa; + mContentDescriptionDataType = mContext.getString( + R.string.accessibility_data_connection_3_5g); } else { mDataIconList = TelephonyIcons.DATA_3G[mInetCondition]; mDataTypeIconId = R.drawable.stat_sys_signal_3g; + mContentDescriptionDataType = mContext.getString( + R.string.accessibility_data_connection_3g); } break; case TelephonyManager.NETWORK_TYPE_CDMA: // display 1xRTT for IS95A/B mDataIconList = TelephonyIcons.DATA_1X[mInetCondition]; mDataTypeIconId = R.drawable.stat_sys_signal_1x; + mContentDescriptionDataType = mContext.getString( + R.string.accessibility_data_connection_cdma); break; case TelephonyManager.NETWORK_TYPE_1xRTT: mDataIconList = TelephonyIcons.DATA_1X[mInetCondition]; mDataTypeIconId = R.drawable.stat_sys_signal_1x; + mContentDescriptionDataType = mContext.getString( + R.string.accessibility_data_connection_cdma); break; case TelephonyManager.NETWORK_TYPE_EVDO_0: //fall through case TelephonyManager.NETWORK_TYPE_EVDO_A: @@ -430,14 +451,20 @@ public class NetworkController extends BroadcastReceiver { case TelephonyManager.NETWORK_TYPE_EHRPD: mDataIconList = TelephonyIcons.DATA_3G[mInetCondition]; mDataTypeIconId = R.drawable.stat_sys_signal_3g; + mContentDescriptionDataType = mContext.getString( + R.string.accessibility_data_connection_3g); break; case TelephonyManager.NETWORK_TYPE_LTE: mDataIconList = TelephonyIcons.DATA_4G[mInetCondition]; mDataTypeIconId = R.drawable.stat_sys_signal_4g; + mContentDescriptionDataType = mContext.getString( + R.string.accessibility_data_connection_4g); break; default: mDataIconList = TelephonyIcons.DATA_G[mInetCondition]; mDataTypeIconId = R.drawable.stat_sys_signal_gprs; + mContentDescriptionDataType = mContext.getString( + R.string.accessibility_data_connection_gprs); break; } if ((isCdma() && isCdmaEri()) || mPhone.isNetworkRoaming()) { @@ -618,8 +645,11 @@ public class NetworkController extends BroadcastReceiver { private void updateWifiIcons() { if (mWifiConnected) { mWifiIconId = WifiIcons.WIFI_SIGNAL_STRENGTH[mInetCondition][mWifiLevel]; + mContentDescriptionWifi = mContext.getString( + AccessibilityContentDescriptions.WIFI_CONNECTION_STRENGTH[mWifiLevel]); } else { mWifiIconId = WifiIcons.WIFI_SIGNAL_STRENGTH[0][0]; + mContentDescriptionWifi = mContext.getString(R.string.accessibility_no_wifi); } } @@ -704,6 +734,7 @@ public class NetworkController extends BroadcastReceiver { } } combinedSignalIconId = mWifiIconId; + mContentDescriptionCombinedSignal = mContentDescriptionWifi; dataTypeIconId = 0; } else if (mDataConnected) { label = mNetworkName; @@ -723,22 +754,29 @@ public class NetworkController extends BroadcastReceiver { break; } combinedSignalIconId = mDataSignalIconId; + mContentDescriptionCombinedSignal = mContentDescriptionDataType; dataTypeIconId = mDataTypeIconId; } else if (mBluetoothTethered) { label = mContext.getString(R.string.bluetooth_tethered); combinedSignalIconId = mBluetoothTetherIconId; + mContentDescriptionCombinedSignal = mContext.getString( + R.string.accessibility_bluetooth_tether); dataTypeIconId = 0; } else if (mAirplaneMode && (mServiceState == null || (!hasService() && !mServiceState.isEmergencyOnly()))) { // Only display the flight-mode icon if not in "emergency calls only" mode. label = context.getString(R.string.status_bar_settings_signal_meter_disconnected); combinedSignalIconId = R.drawable.stat_sys_signal_flightmode; + mContentDescriptionCombinedSignal = mContext.getString( + R.string.accessibility_airplane_mode); dataTypeIconId = 0; } else { label = context.getString(R.string.status_bar_settings_signal_meter_disconnected); // On devices without mobile radios, we want to show the wifi icon combinedSignalIconId = hasMobileDataFeature() ? mDataSignalIconId : mWifiIconId; + mContentDescriptionCombinedSignal = hasMobileDataFeature() + ? mContentDescriptionDataType : mContentDescriptionWifi; dataTypeIconId = 0; } @@ -764,6 +802,7 @@ public class NetworkController extends BroadcastReceiver { for (int i=0; i<N; i++) { final ImageView v = mPhoneSignalIconViews.get(i); v.setImageResource(mPhoneSignalIconId); + v.setContentDescription(mContentDescriptionPhoneSignal); } } @@ -774,6 +813,7 @@ public class NetworkController extends BroadcastReceiver { for (int i=0; i<N; i++) { final ImageView v = mDataDirectionIconViews.get(i); v.setImageResource(mDataDirectionIconId); + v.setContentDescription(mContentDescriptionDataType); } } @@ -784,6 +824,7 @@ public class NetworkController extends BroadcastReceiver { for (int i=0; i<N; i++) { final ImageView v = mWifiIconViews.get(i); v.setImageResource(mWifiIconId); + v.setContentDescription(mContentDescriptionWifi); } } @@ -794,6 +835,7 @@ public class NetworkController extends BroadcastReceiver { for (int i=0; i<N; i++) { final ImageView v = mCombinedSignalIconViews.get(i); v.setImageResource(combinedSignalIconId); + v.setContentDescription(mContentDescriptionCombinedSignal); } } @@ -808,6 +850,7 @@ public class NetworkController extends BroadcastReceiver { } else { v.setVisibility(View.VISIBLE); v.setImageResource(dataTypeIconId); + v.setContentDescription(mContentDescriptionDataType); } } } @@ -826,6 +869,7 @@ public class NetworkController extends BroadcastReceiver { } else { v.setVisibility(View.VISIBLE); v.setImageResource(dataDirectionOverlayIconId); + v.setContentDescription(mContentDescriptionDataType); } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java index b4d2a14..d5885bb 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java @@ -148,6 +148,11 @@ public class NotificationRowLayout extends ViewGroup { "now sliding child %d: %s (touchY=%.1f, rowHeight=%d, count=%d)", childIdx, mSlidingChild, mInitialTouchY, mRowHeight, count)); } + + + // We need to prevent the surrounding ScrollView from intercepting us now; + // the scroll position will be locked while we swipe + requestDisallowInterceptTouchEvent(true); } } break; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/CompatModePanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/CompatModePanel.java index c62c4ad..8c4ae19 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/CompatModePanel.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/CompatModePanel.java @@ -22,6 +22,7 @@ import android.content.res.TypedArray; import android.os.RemoteException; import android.util.AttributeSet; import android.util.Slog; +import android.view.MotionEvent; import android.view.View; import android.widget.FrameLayout; import android.widget.ImageView; @@ -90,6 +91,19 @@ public class CompatModePanel extends FrameLayout implements StatusBarPanel, return false; } + @Override + public boolean dispatchHoverEvent(MotionEvent event) { + // Ignore hover events outside of this panel bounds since such events + // generate spurious accessibility events with the panel content when + // tapping outside of it, thus confusing the user. + final int x = (int) event.getX(); + final int y = (int) event.getY(); + if (x >= 0 && x < getWidth() && y >= 0 && y < getHeight()) { + return super.dispatchHoverEvent(event); + } + return true; + } + public void setTrigger(View v) { mTrigger = v; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java index 339e3f3..1e417ac 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java @@ -30,6 +30,7 @@ import android.text.TextUtils; import android.util.AttributeSet; import android.util.Log; import android.util.Pair; +import android.view.MotionEvent; import android.view.View; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodManager; @@ -160,6 +161,19 @@ public class InputMethodsPanel extends LinearLayout implements StatusBarPanel, } } + @Override + public boolean dispatchHoverEvent(MotionEvent event) { + // Ignore hover events outside of this panel bounds since such events + // generate spurious accessibility events with the panel content when + // tapping outside of it, thus confusing the user. + final int x = (int) event.getX(); + final int y = (int) event.getY(); + if (x >= 0 && x < getWidth() && y >= 0 && y < getHeight()) { + return super.dispatchHoverEvent(event); + } + return true; + } + private void updateHardKeyboardEnabled() { if (mHardKeyboardAvailable) { final boolean checked = mHardKeyboardSwitch.isChecked(); @@ -222,6 +236,7 @@ public class InputMethodsPanel extends LinearLayout implements StatusBarPanel, itemSubtitle.setText(imiName); } subtypeIcon.setImageDrawable(icon); + subtypeIcon.setContentDescription(itemTitle.getText()); final String settingsActivity = imi.getSettingsActivity(); if (!TextUtils.isEmpty(settingsActivity)) { settingsIcon.setOnClickListener(new View.OnClickListener() { @@ -463,4 +478,5 @@ public class InputMethodsPanel extends LinearLayout implements StatusBarPanel, public interface OnHardKeyboardEnabledChangeListener { public void onHardKeyboardEnabledChange(boolean enabled); } + } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationArea.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationArea.java new file mode 100644 index 0000000..42bdf3d --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationArea.java @@ -0,0 +1,45 @@ +/* + * 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.statusbar.tablet; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.view.accessibility.AccessibilityEvent; +import android.widget.LinearLayout; + +public class NotificationArea extends LinearLayout { + + public NotificationArea(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) { + if (super.onRequestSendAccessibilityEvent(child, event)) { + // The event is coming from a descendant like battery but append + // the content of the entire notification area so accessibility + // services can choose how to present the content to the user. + AccessibilityEvent record = AccessibilityEvent.obtain(); + onInitializeAccessibilityEvent(record); + dispatchPopulateAccessibilityEvent(record); + event.appendRecord(record); + return true; + } + return false; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java index 64a4f16..a316e4b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java @@ -20,27 +20,15 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; -import android.animation.ValueAnimator; import android.content.Context; -import android.content.res.Resources; -import android.graphics.Canvas; import android.graphics.Rect; -import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.util.Slog; -import android.view.accessibility.AccessibilityEvent; import android.view.LayoutInflater; import android.view.MotionEvent; -import android.view.SoundEffectConstants; import android.view.View; import android.view.ViewGroup; -import android.view.animation.AccelerateInterpolator; -import android.widget.FrameLayout; -import android.widget.FrameLayout; -import android.widget.ImageView; -import android.widget.LinearLayout; import android.widget.RelativeLayout; -import android.widget.TextView; import com.android.systemui.R; @@ -53,8 +41,7 @@ public class NotificationPanel extends RelativeLayout implements StatusBarPanel, boolean mShowing; int mNotificationCount = 0; - View mTitleArea; - ModeToggle mModeToggle; + NotificationPanelTitle mTitleArea; View mSettingsButton; View mNotificationButton; View mNotificationScroller; @@ -68,48 +55,6 @@ public class NotificationPanel extends RelativeLayout implements StatusBarPanel, Choreographer mChoreo = new Choreographer(); - static class ModeToggle extends View { - NotificationPanel mPanel; - View mTitle; - public ModeToggle(Context context, AttributeSet attrs) { - super(context, attrs); - } - public void setPanel(NotificationPanel p) { - mPanel = p; - } - public void setTitleArea(View v) { - mTitle = v; - } - @Override - public boolean onTouchEvent(MotionEvent e) { - final int x = (int)e.getX(); - final int y = (int)e.getY(); - switch (e.getAction()) { - case MotionEvent.ACTION_DOWN: - mTitle.setPressed(true); - break; - case MotionEvent.ACTION_MOVE: - mTitle.setPressed(x >= 0 - && x < getWidth() - && y >= 0 - && y < getHeight()); - break; - case MotionEvent.ACTION_CANCEL: - mTitle.setPressed(false); - break; - case MotionEvent.ACTION_UP: - if (mTitle.isPressed()) { - sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED); - playSoundEffect(SoundEffectConstants.CLICK); - mPanel.swapPanels(); - mTitle.setPressed(false); - } - break; - } - return true; - } - } - public NotificationPanel(Context context, AttributeSet attrs) { this(context, attrs, 0); } @@ -126,14 +71,11 @@ public class NotificationPanel extends RelativeLayout implements StatusBarPanel, mContentParent = (ViewGroup)findViewById(R.id.content_parent); mContentParent.bringToFront(); - mTitleArea = findViewById(R.id.title_area); - mModeToggle = (ModeToggle) findViewById(R.id.mode_toggle); - mModeToggle.setOnClickListener(this); - mModeToggle.setPanel(this); - mModeToggle.setTitleArea(mTitleArea); + mTitleArea = (NotificationPanelTitle) findViewById(R.id.title_area); + mTitleArea.setPanel(this); - mSettingsButton = (ImageView)findViewById(R.id.settings_button); - mNotificationButton = (ImageView)findViewById(R.id.notification_button); + mSettingsButton = findViewById(R.id.settings_button); + mNotificationButton = findViewById(R.id.notification_button); mNotificationScroller = findViewById(R.id.notification_scroller); mContentFrame = (ViewGroup)findViewById(R.id.content_frame); @@ -185,6 +127,19 @@ public class NotificationPanel extends RelativeLayout implements StatusBarPanel, } } + @Override + public boolean dispatchHoverEvent(MotionEvent event) { + // Ignore hover events outside of this panel bounds since such events + // generate spurious accessibility events with the panel content when + // tapping outside of it, thus confusing the user. + final int x = (int) event.getX(); + final int y = (int) event.getY(); + if (x >= 0 && x < getWidth() && y >= 0 && y < getHeight()) { + return super.dispatchHoverEvent(event); + } + return true; + } + /* @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { @@ -205,7 +160,7 @@ public class NotificationPanel extends RelativeLayout implements StatusBarPanel, */ public void onClick(View v) { - if (v == mModeToggle) { + if (v == mTitleArea) { swapPanels(); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanelTitle.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanelTitle.java new file mode 100644 index 0000000..689bc36 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanelTitle.java @@ -0,0 +1,82 @@ +/* + * 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.statusbar.tablet; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.SoundEffectConstants; +import android.view.View; +import android.view.accessibility.AccessibilityEvent; +import android.widget.RelativeLayout; + +public class NotificationPanelTitle extends RelativeLayout implements View.OnClickListener { + private NotificationPanel mPanel; + + public NotificationPanelTitle(Context context, AttributeSet attrs) { + super(context, attrs); + setOnClickListener(this); + } + + public void setPanel(NotificationPanel p) { + mPanel = p; + } + + @Override + public boolean onTouchEvent(MotionEvent e) { + switch (e.getAction()) { + case MotionEvent.ACTION_DOWN: + setPressed(true); + break; + case MotionEvent.ACTION_MOVE: + final int x = (int) e.getX(); + final int y = (int) e.getY(); + setPressed(x > 0 && x < getWidth() && y > 0 && y < getHeight()); + break; + case MotionEvent.ACTION_UP: + if (isPressed()) { + playSoundEffect(SoundEffectConstants.CLICK); + mPanel.swapPanels(); + setPressed(false); + } + break; + case MotionEvent.ACTION_CANCEL: + setPressed(false); + break; + } + return true; + } + + @Override + public void onClick(View v) { + if (v == this) { + mPanel.swapPanels(); + } + } + + @Override + public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) { + if (super.onRequestSendAccessibilityEvent(child, event)) { + AccessibilityEvent record = AccessibilityEvent.obtain(); + onInitializeAccessibilityEvent(record); + dispatchPopulateAccessibilityEvent(record); + event.appendRecord(record); + return true; + } + return false; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPeekPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPeekPanel.java index 8b68240..ba28306 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPeekPanel.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPeekPanel.java @@ -18,12 +18,9 @@ package com.android.systemui.statusbar.tablet; import android.content.Context; import android.util.AttributeSet; -import android.util.Slog; import android.view.MotionEvent; import android.widget.RelativeLayout; -import com.android.systemui.R; - public class NotificationPeekPanel extends RelativeLayout implements StatusBarPanel { TabletStatusBar mBar; @@ -54,5 +51,17 @@ public class NotificationPeekPanel extends RelativeLayout implements StatusBarPa mBar.resetNotificationPeekFadeTimer(); return false; } -} + @Override + public boolean dispatchHoverEvent(MotionEvent event) { + // Ignore hover events outside of this panel bounds since such events + // generate spurious accessibility events with the panel content when + // tapping outside of it, thus confusing the user. + final int x = (int) event.getX(); + final int y = (int) event.getY(); + if (x >= 0 && x < getWidth() && y >= 0 && y < getHeight()) { + return super.dispatchHoverEvent(event); + } + return true; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java index df09f84..13846ed 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java @@ -808,7 +808,8 @@ public class TabletStatusBar extends StatusBar implements // Update the icon. final StatusBarIcon ic = new StatusBarIcon(notification.pkg, notification.notification.icon, notification.notification.iconLevel, - notification.notification.number); + notification.notification.number, + notification.notification.tickerText); if (!oldEntry.icon.set(ic)) { handleNotificationError(key, notification, "Couldn't update icon: " + ic); return; @@ -1012,10 +1013,7 @@ public class TabletStatusBar extends StatusBar implements mCompatModeButton.refresh(); if (mCompatModeButton.getVisibility() == View.VISIBLE) { - if (DEBUG_COMPAT_HELP - || ! Prefs.read(mContext).getBoolean(Prefs.SHOWN_COMPAT_MODE_HELP, false)) { showCompatibilityHelp(); - } } else { hideCompatibilityHelp(); mCompatModePanel.closePanel(); @@ -1451,13 +1449,15 @@ public class TabletStatusBar extends StatusBar implements } // Construct the icon. final StatusBarIconView iconView = new StatusBarIconView(mContext, - notification.pkg + "/0x" + Integer.toHexString(notification.id)); + notification.pkg + "/0x" + Integer.toHexString(notification.id), + notification.notification); iconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); final StatusBarIcon ic = new StatusBarIcon(notification.pkg, notification.notification.icon, notification.notification.iconLevel, - notification.notification.number); + notification.notification.number, + notification.notification.tickerText); if (!iconView.set(ic)) { handleNotificationError(key, notification, "Couldn't attach StatusBarIcon: " + ic); return null; @@ -1501,11 +1501,6 @@ public class TabletStatusBar extends StatusBar implements // alternate behavior in DND mode if (mNotificationDNDMode) { if (mIconLayout.getChildCount() == 0) { - final StatusBarIconView iconView = new StatusBarIconView(mContext, "_dnd"); - iconView.setImageResource(R.drawable.ic_notification_dnd); - iconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); - iconView.setPadding(mIconHPadding, 0, mIconHPadding, 0); - final Notification dndNotification = new Notification.Builder(mContext) .setContentTitle(mContext.getText(R.string.notifications_off_title)) .setContentText(mContext.getText(R.string.notifications_off_text)) @@ -1513,6 +1508,12 @@ public class TabletStatusBar extends StatusBar implements .setOngoing(true) .getNotification(); + final StatusBarIconView iconView = new StatusBarIconView(mContext, "_dnd", + dndNotification); + iconView.setImageResource(R.drawable.ic_notification_dnd); + iconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); + iconView.setPadding(mIconHPadding, 0, mIconHPadding, 0); + mNotificationDNDDummyEntry = new NotificationData.Entry( null, new StatusBarNotification("", 0, "", 0, 0, dndNotification), @@ -1634,19 +1635,24 @@ public class TabletStatusBar extends StatusBar implements } else { if ((sbn.notification.flags & Notification.FLAG_ONGOING_EVENT) == 0) { vetoButton.setVisibility(View.INVISIBLE); + vetoButton.setContentDescription("VETO"); } else { vetoButton.setVisibility(View.GONE); } } + vetoButton.setContentDescription(mContext.getString( + R.string.accessibility_remove_notification)); // the large icon ImageView largeIcon = (ImageView)row.findViewById(R.id.large_icon); if (sbn.notification.largeIcon != null) { largeIcon.setImageBitmap(sbn.notification.largeIcon); + largeIcon.setContentDescription(sbn.notification.tickerText); } else { largeIcon.getLayoutParams().width = 0; largeIcon.setVisibility(View.INVISIBLE); } + largeIcon.setContentDescription(sbn.notification.tickerText); // bind the click event to the content area ViewGroup content = (ViewGroup)row.findViewById(R.id.content); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java index a8f4262..6045e31 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java @@ -284,7 +284,7 @@ public class TabletTicker } else if (n.tickerText != null) { group = (ViewGroup)inflater.inflate(R.layout.status_bar_ticker_compat, mWindow, false); final Drawable icon = StatusBarIconView.getIcon(mContext, - new StatusBarIcon(notification.pkg, n.icon, n.iconLevel, 0)); + new StatusBarIcon(notification.pkg, n.icon, n.iconLevel, 0, n.tickerText)); ImageView iv = (ImageView)group.findViewById(iconId); iv.setImageDrawable(icon); iv.setVisibility(View.VISIBLE); diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java index 935f4ad..47d34b3 100644 --- a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java +++ b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java @@ -35,7 +35,6 @@ import android.media.Ringtone; import android.media.RingtoneManager; import android.net.Uri; import android.os.Handler; -import android.os.IBinder; import android.os.LocalPowerManager; import android.os.Message; import android.os.PowerManager; @@ -43,7 +42,6 @@ import android.os.RemoteException; import android.os.SystemClock; import android.os.SystemProperties; import android.provider.Settings; -import android.provider.Settings.SettingNotFoundException; import android.telephony.TelephonyManager; import android.util.EventLog; import android.util.Log; @@ -1117,8 +1115,11 @@ public class KeyguardViewMediator implements KeyguardViewCallback, // Give feedback to user when secure keyguard is active and engaged if (mShowing && isSecure()) { if (!mShowingLockIcon) { + String contentDescription = mContext.getString( + com.android.internal.R.string.status_bar_device_locked); mStatusBarManager.setIcon("secure", - com.android.internal.R.drawable.stat_sys_secure, 0); + com.android.internal.R.drawable.stat_sys_secure, 0, + contentDescription); mShowingLockIcon = true; } } else { diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java index b963b13..e0debf7 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java @@ -388,6 +388,11 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { st.isHandled = false; mPreparedPanel = st; + if (st.frozenActionViewState != null) { + st.menu.restoreActionViewStates(st.frozenActionViewState); + st.frozenActionViewState = null; + } + return true; } @@ -652,7 +657,13 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { @Override public void invalidatePanelMenu(int featureId) { PanelFeatureState st = getPanelState(featureId, true); + Bundle savedActionViewStates = null; if (st.menu != null) { + savedActionViewStates = new Bundle(); + st.menu.saveActionViewStates(savedActionViewStates); + if (savedActionViewStates.size() > 0) { + st.frozenActionViewState = savedActionViewStates; + } st.menu.clear(); } st.refreshMenuContent = true; @@ -3024,6 +3035,12 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { */ Bundle frozenMenuState; + /** + * Contains the state of associated action views when told to freeze. + * These are saved across invalidations. + */ + Bundle frozenActionViewState; + PanelFeatureState(int featureId) { this.featureId = featureId; diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index ad6cebb..ae13ab5 100755 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -166,22 +166,22 @@ public class PhoneWindowManager implements WindowManagerPolicy { static final int SYSTEM_DIALOG_LAYER = 6; // toasts and the plugged-in battery thing static final int TOAST_LAYER = 7; - static final int STATUS_BAR_LAYER = 8; - static final int STATUS_BAR_PANEL_LAYER = 9; // SIM errors and unlock. Not sure if this really should be in a high layer. - static final int PRIORITY_PHONE_LAYER = 10; + static final int PRIORITY_PHONE_LAYER = 8; // like the ANR / app crashed dialogs - static final int SYSTEM_ALERT_LAYER = 11; + static final int SYSTEM_ALERT_LAYER = 9; // system-level error dialogs - static final int SYSTEM_ERROR_LAYER = 12; + static final int SYSTEM_ERROR_LAYER = 10; // on-screen keyboards and other such input method user interfaces go here. - static final int INPUT_METHOD_LAYER = 13; + static final int INPUT_METHOD_LAYER = 11; // on-screen keyboards and other such input method user interfaces go here. - static final int INPUT_METHOD_DIALOG_LAYER = 14; + static final int INPUT_METHOD_DIALOG_LAYER = 12; // the keyguard; nothing on top of these can take focus, since they are // responsible for power management when displayed. - static final int KEYGUARD_LAYER = 15; - static final int KEYGUARD_DIALOG_LAYER = 16; + static final int KEYGUARD_LAYER = 13; + static final int KEYGUARD_DIALOG_LAYER = 14; + static final int STATUS_BAR_LAYER = 15; + static final int STATUS_BAR_PANEL_LAYER = 16; // the navigation bar, if available, shows atop most things static final int NAVIGATION_BAR_LAYER = 17; // the drag layer: input for drag-and-drop is associated with this window, @@ -1703,7 +1703,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } } - if (DEBUG_LAYOUT) Log.i(TAG, "mNavigationBar frame: " + navr); + if (DEBUG_LAYOUT) { + Log.i(TAG, "mNavigationBar frame: " + navr); + Log.i(TAG, String.format("mDock rect: (%d,%d - %d,%d)", + mDockLeft, mDockTop, mDockRight, mDockBottom)); + } // apply navigation bar insets pf.left = df.left = vf.left = mDockLeft; @@ -1713,6 +1717,25 @@ public class PhoneWindowManager implements WindowManagerPolicy { mStatusBar.computeFrameLw(pf, df, vf, vf); + // now, let's consider the navigation bar; if it exists, it must be removed from the + // available screen real estate (like an un-hideable status bar) + if (navr != null) { + if (navr.top == 0) { + // Navigation bar is vertical + if (mRestrictedScreenLeft == navr.left) { + mRestrictedScreenLeft = navr.right; + mRestrictedScreenWidth -= (navr.right - navr.left); + } else if ((mRestrictedScreenLeft+mRestrictedScreenWidth) == navr.right) { + mRestrictedScreenWidth -= (navr.right - navr.left); + } + } else { + // Navigation bar horizontal, at bottom + if ((mRestrictedScreenHeight+mRestrictedScreenTop) == navr.bottom) { + mRestrictedScreenHeight -= (navr.bottom-navr.top); + } + } + } + if (mStatusBar.isVisibleLw()) { // If the status bar is hidden, we don't want to cause // windows behind it to scroll. @@ -1745,23 +1768,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { mRestrictedScreenHeight -= (r.bottom-r.top); } - if (navr != null) { - if (navr.top == 0) { - // Navigation bar is vertical - if (mRestrictedScreenLeft == navr.left) { - mRestrictedScreenLeft = navr.right; - mRestrictedScreenWidth -= (navr.right - navr.left); - } else if ((mRestrictedScreenLeft+mRestrictedScreenWidth) == navr.right) { - mRestrictedScreenWidth -= (navr.right - navr.left); - } - } else { - // Navigation bar horizontal, at bottom - if ((mRestrictedScreenHeight-mRestrictedScreenTop) == r.bottom) { - mRestrictedScreenHeight -= (navr.bottom-navr.top); - } - } - } - mContentTop = mCurTop = mDockTop = mRestrictedScreenTop; mContentBottom = mCurBottom = mDockBottom = mRestrictedScreenTop + mRestrictedScreenHeight; @@ -1873,19 +1879,22 @@ public class PhoneWindowManager implements WindowManagerPolicy { // permission, so they have the same privileges as the status // bar itself. // - // However, they should still dodge the navigation bar if it exists. A - // straightforward way to do this is to only allow the status bar panels to - // extend to the extrema of the allowable region for the IME dock. + // However, they should still dodge the navigation bar if it exists. pf.left = df.left = hasNavBar ? mDockLeft : mUnrestrictedScreenLeft; pf.top = df.top = mUnrestrictedScreenTop; pf.right = df.right = hasNavBar - ? mDockRight + ? mRestrictedScreenLeft+mRestrictedScreenWidth : mUnrestrictedScreenLeft+mUnrestrictedScreenWidth; pf.bottom = df.bottom = hasNavBar - ? mDockBottom + ? mRestrictedScreenTop+mRestrictedScreenHeight : mUnrestrictedScreenTop+mUnrestrictedScreenHeight; + if (DEBUG_LAYOUT) { + Log.v(TAG, String.format( + "Laying out status bar window: (%d,%d - %d,%d)", + pf.left, pf.top, pf.right, pf.bottom)); + } } else { pf.left = df.left = mRestrictedScreenLeft; pf.top = df.top = mRestrictedScreenTop; @@ -1922,12 +1931,23 @@ public class PhoneWindowManager implements WindowManagerPolicy { pf.left = df.left = cf.left = hasNavBar ? mDockLeft : mUnrestrictedScreenLeft; pf.top = df.top = cf.top = mUnrestrictedScreenTop; pf.right = df.right = cf.right = hasNavBar - ? mDockRight + ? mRestrictedScreenLeft+mRestrictedScreenWidth : mUnrestrictedScreenLeft+mUnrestrictedScreenWidth; pf.bottom = df.bottom = cf.bottom = hasNavBar - ? mDockBottom + ? mRestrictedScreenTop+mRestrictedScreenHeight : mUnrestrictedScreenTop+mUnrestrictedScreenHeight; + } else if (attrs.type == TYPE_NAVIGATION_BAR) { + // The navigation bar has Real Ultimate Power. + pf.left = df.left = mUnrestrictedScreenLeft; + pf.top = df.top = mUnrestrictedScreenTop; + pf.right = df.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth; + pf.bottom = df.bottom = mUnrestrictedScreenTop+mUnrestrictedScreenHeight; + if (DEBUG_LAYOUT) { + Log.v(TAG, String.format( + "Laying out navigation bar window: (%d,%d - %d,%d)", + pf.left, pf.top, pf.right, pf.bottom)); + } } else { pf.left = df.left = cf.left = mRestrictedScreenLeft; pf.top = df.top = cf.top = mRestrictedScreenTop; diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index 86d4cc3..0323fe0 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -81,6 +81,8 @@ static const int kDumpLockSleep = 20000; static const nsecs_t kWarningThrottle = seconds(5); +// RecordThread loop sleep time upon application overrun or audio HAL read error +static const int kRecordThreadSleepUs = 5000; // ---------------------------------------------------------------------------- @@ -417,7 +419,7 @@ sp<IAudioTrack> AudioFlinger::createTrack( lSessionId = *sessionId; } else { // if no audio session id is provided, create one here - lSessionId = nextUniqueId_l(); + lSessionId = nextUniqueId(); if (sessionId != NULL) { *sessionId = lSessionId; } @@ -725,6 +727,15 @@ status_t AudioFlinger::setParameters(int ioHandle, const String8& keyValuePairs) thread = checkPlaybackThread_l(ioHandle); if (thread == NULL) { thread = checkRecordThread_l(ioHandle); + } else if (thread.get() == primaryPlaybackThread_l()) { + // indicate output device change to all input threads for pre processing + AudioParameter param = AudioParameter(keyValuePairs); + int value; + if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) { + for (size_t i = 0; i < mRecordThreads.size(); i++) { + mRecordThreads.valueAt(i)->setParameters(keyValuePairs); + } + } } } if (thread != NULL) { @@ -873,10 +884,10 @@ void AudioFlinger::removeClient_l(pid_t pid) // ---------------------------------------------------------------------------- -AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, int id) +AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, int id, uint32_t device) : Thread(false), mAudioFlinger(audioFlinger), mSampleRate(0), mFrameCount(0), mChannelCount(0), - mFrameSize(1), mFormat(0), mStandby(false), mId(id), mExiting(false) + mFrameSize(1), mFormat(0), mStandby(false), mId(id), mExiting(false), mDevice(device) { } @@ -1032,14 +1043,15 @@ status_t AudioFlinger::ThreadBase::dumpBase(int fd, const Vector<String16>& args return NO_ERROR; } - // ---------------------------------------------------------------------------- -AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device) - : ThreadBase(audioFlinger, id), +AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger, + AudioStreamOut* output, + int id, + uint32_t device) + : ThreadBase(audioFlinger, id, device), mMixBuffer(0), mSuspended(0), mBytesWritten(0), mOutput(output), - mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false), - mDevice(device) + mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false) { readOutputParameters(); @@ -1199,9 +1211,9 @@ sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTra } } - if (mOutput == 0) { + lStatus = initCheck(); + if (lStatus != NO_ERROR) { LOGE("Audio driver not initialized."); - lStatus = NO_INIT; goto Exit; } @@ -1423,7 +1435,7 @@ status_t AudioFlinger::PlaybackThread::getRenderPosition(uint32_t *halFrames, ui if (halFrames == 0 || dspFrames == 0) { return BAD_VALUE; } - if (mOutput == 0) { + if (initCheck() != NO_ERROR) { return INVALID_OPERATION; } *halFrames = mBytesWritten / audio_stream_frame_size(&mOutput->stream->common); @@ -1468,34 +1480,6 @@ uint32_t AudioFlinger::PlaybackThread::getStrategyForSession_l(int sessionId) return AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC); } -sp<AudioFlinger::EffectChain> AudioFlinger::PlaybackThread::getEffectChain(int sessionId) -{ - Mutex::Autolock _l(mLock); - return getEffectChain_l(sessionId); -} - -sp<AudioFlinger::EffectChain> AudioFlinger::PlaybackThread::getEffectChain_l(int sessionId) -{ - sp<EffectChain> chain; - - size_t size = mEffectChains.size(); - for (size_t i = 0; i < size; i++) { - if (mEffectChains[i]->sessionId() == sessionId) { - chain = mEffectChains[i]; - break; - } - } - return chain; -} - -void AudioFlinger::PlaybackThread::setMode(uint32_t mode) -{ - Mutex::Autolock _l(mLock); - size_t size = mEffectChains.size(); - for (size_t i = 0; i < size; i++) { - mEffectChains[i]->setMode_l(mode); - } -} // ---------------------------------------------------------------------------- @@ -1503,7 +1487,7 @@ AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, Aud : PlaybackThread(audioFlinger, output, id, device), mAudioMixer(0) { - mType = PlaybackThread::MIXER; + mType = ThreadBase::MIXER; mAudioMixer = new AudioMixer(mFrameCount, mSampleRate); // FIXME - Current mixer implementation only supports stereo output @@ -2072,7 +2056,7 @@ uint32_t AudioFlinger::MixerThread::suspendSleepTimeUs() AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device) : PlaybackThread(audioFlinger, output, id, device) { - mType = PlaybackThread::DIRECT; + mType = ThreadBase::DIRECT; } AudioFlinger::DirectOutputThread::~DirectOutputThread() @@ -2551,7 +2535,7 @@ uint32_t AudioFlinger::DirectOutputThread::suspendSleepTimeUs() AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger, AudioFlinger::MixerThread* mainThread, int id) : MixerThread(audioFlinger, mainThread->getOutput(), id, mainThread->device()), mWaitTimeMs(UINT_MAX) { - mType = PlaybackThread::DUPLICATING; + mType = ThreadBase::DUPLICATING; addOutputTrack(mainThread); } @@ -2970,7 +2954,7 @@ AudioFlinger::PlaybackThread::Track::Track( mStreamType = streamType; // NOTE: audio_track_cblk_t::frameSize for 8 bit PCM data is based on a sample size of // 16 bit because data is converted to 16 bit before being stored in buffer by AudioTrack - mCblk->frameSize = audio_is_linear_pcm(format) ? mChannelCount * audio_bytes_per_sample(format) : sizeof(uint8_t); + mCblk->frameSize = audio_is_linear_pcm(format) ? mChannelCount * sizeof(int16_t) : sizeof(uint8_t); } } @@ -3751,21 +3735,26 @@ sp<IAudioRecord> AudioFlinger::openRecord( if (sessionId != NULL && *sessionId != AUDIO_SESSION_OUTPUT_MIX) { lSessionId = *sessionId; } else { - lSessionId = nextUniqueId_l(); + lSessionId = nextUniqueId(); if (sessionId != NULL) { *sessionId = lSessionId; } } // create new record track. The record track uses one track in mHardwareMixerThread by convention. - recordTrack = new RecordThread::RecordTrack(thread, client, sampleRate, - format, channelMask, frameCount, flags, lSessionId); - } - if (recordTrack->getCblk() == NULL) { + recordTrack = thread->createRecordTrack_l(client, + sampleRate, + format, + channelMask, + frameCount, + flags, + lSessionId, + &lStatus); + } + if (lStatus != NO_ERROR) { // remove local strong reference to Client before deleting the RecordTrack so that the Client // destructor is called by the TrackBase destructor with mLock held client.clear(); recordTrack.clear(); - lStatus = NO_MEMORY; goto Exit; } @@ -3814,10 +3803,16 @@ status_t AudioFlinger::RecordHandle::onTransact( // ---------------------------------------------------------------------------- -AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger, AudioStreamIn *input, uint32_t sampleRate, uint32_t channels, int id) : - ThreadBase(audioFlinger, id), - mInput(input), mResampler(0), mRsmpOutBuffer(0), mRsmpInBuffer(0) +AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger, + AudioStreamIn *input, + uint32_t sampleRate, + uint32_t channels, + int id, + uint32_t device) : + ThreadBase(audioFlinger, id, device), + mInput(input), mTrack(NULL), mResampler(0), mRsmpOutBuffer(0), mRsmpInBuffer(0) { + mType = ThreadBase::RECORD; mReqChannelCount = popcount(channels); mReqSampleRate = sampleRate; readInputParameters(); @@ -3847,6 +3842,7 @@ bool AudioFlinger::RecordThread::threadLoop() { AudioBufferProvider::Buffer buffer; sp<RecordTrack> activeTrack; + Vector< sp<EffectChain> > effectChains; nsecs_t lastWarning = 0; @@ -3897,14 +3893,22 @@ bool AudioFlinger::RecordThread::threadLoop() mStandby = false; } } + lockEffectChains_l(effectChains); } if (mActiveTrack != 0) { if (mActiveTrack->mState != TrackBase::ACTIVE && mActiveTrack->mState != TrackBase::RESUMING) { - usleep(5000); + unlockEffectChains(effectChains); + usleep(kRecordThreadSleepUs); continue; } + for (size_t i = 0; i < effectChains.size(); i ++) { + effectChains[i]->process_l(); + } + // enable changes in effect chain + unlockEffectChains(effectChains); + buffer.frameCount = mFrameCount; if (LIKELY(mActiveTrack->getNextBuffer(&buffer) == NO_ERROR)) { size_t framesOut = buffer.frameCount; @@ -3953,7 +3957,7 @@ bool AudioFlinger::RecordThread::threadLoop() // Force input into standby so that it tries to // recover at next read attempt mInput->stream->common.standby(&mInput->stream->common); - usleep(5000); + usleep(kRecordThreadSleepUs); } mRsmpInIndex = mFrameCount; framesOut = 0; @@ -4001,9 +4005,12 @@ bool AudioFlinger::RecordThread::threadLoop() // Release the processor for a while before asking for a new buffer. // This will give the application more chance to read from the buffer and // clear the overflow. - usleep(5000); + usleep(kRecordThreadSleepUs); } + } else { + unlockEffectChains(effectChains); } + effectChains.clear(); } if (!mStandby) { @@ -4017,6 +4024,49 @@ bool AudioFlinger::RecordThread::threadLoop() return false; } + +sp<AudioFlinger::RecordThread::RecordTrack> AudioFlinger::RecordThread::createRecordTrack_l( + const sp<AudioFlinger::Client>& client, + uint32_t sampleRate, + int format, + int channelMask, + int frameCount, + uint32_t flags, + int sessionId, + status_t *status) +{ + sp<RecordTrack> track; + status_t lStatus; + + lStatus = initCheck(); + if (lStatus != NO_ERROR) { + LOGE("Audio driver not initialized."); + goto Exit; + } + + { // scope for mLock + Mutex::Autolock _l(mLock); + + track = new RecordTrack(this, client, sampleRate, + format, channelMask, frameCount, flags, sessionId); + + if (track->getCblk() == NULL) { + lStatus = NO_MEMORY; + goto Exit; + } + + mTrack = track.get(); + + } + lStatus = NO_ERROR; + +Exit: + if (status) { + *status = lStatus; + } + return track; +} + status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrack) { LOGV("RecordThread::start"); @@ -4146,7 +4196,7 @@ status_t AudioFlinger::RecordThread::getNextBuffer(AudioBufferProvider::Buffer* // Force input into standby so that it tries to // recover at next read attempt mInput->stream->common.standby(&mInput->stream->common); - usleep(5000); + usleep(kRecordThreadSleepUs); } buffer->raw = 0; buffer->frameCount = 0; @@ -4211,6 +4261,23 @@ bool AudioFlinger::RecordThread::checkForNewParameters_l() reconfig = true; } } + if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) { + // forward device change to effects that have requested to be + // aware of attached audio device. + for (size_t i = 0; i < mEffectChains.size(); i++) { + mEffectChains[i]->setDevice_l(value); + } + // store input device and output device but do not forward output device to audio HAL. + // Note that status is ignored by the caller for output device + // (see AudioFlinger::setParameters() + if (value & AUDIO_DEVICE_OUT_ALL) { + mDevice &= (uint32_t)~(value & AUDIO_DEVICE_OUT_ALL); + status = BAD_VALUE; + } else { + mDevice &= (uint32_t)~(value & AUDIO_DEVICE_IN_ALL); + } + mDevice |= (uint32_t)value; + } if (status == NO_ERROR) { status = mInput->stream->common.set_parameters(&mInput->stream->common, keyValuePair.string()); if (status == INVALID_OPERATION) { @@ -4320,6 +4387,21 @@ unsigned int AudioFlinger::RecordThread::getInputFramesLost() return mInput->stream->get_input_frames_lost(mInput->stream); } +uint32_t AudioFlinger::RecordThread::hasAudioSession(int sessionId) +{ + Mutex::Autolock _l(mLock); + uint32_t result = 0; + if (getEffectChain_l(sessionId) != 0) { + result = EFFECT_SESSION; + } + + if (mTrack != NULL && sessionId == mTrack->sessionId()) { + result |= TRACK_SESSION; + } + + return result; +} + // ---------------------------------------------------------------------------- int AudioFlinger::openOutput(uint32_t *pDevices, @@ -4368,7 +4450,7 @@ int AudioFlinger::openOutput(uint32_t *pDevices, mHardwareStatus = AUDIO_HW_IDLE; if (outStream != NULL) { AudioStreamOut *output = new AudioStreamOut(outHwDev, outStream); - int id = nextUniqueId_l(); + int id = nextUniqueId(); if ((flags & AUDIO_POLICY_OUTPUT_FLAG_DIRECT) || (format != AUDIO_FORMAT_PCM_16_BIT) || @@ -4405,7 +4487,7 @@ int AudioFlinger::openDuplicateOutput(int output1, int output2) return 0; } - int id = nextUniqueId_l(); + int id = nextUniqueId(); DuplicatingThread *thread = new DuplicatingThread(this, thread1, id); thread->addOutputTrack(thread2); mPlaybackThreads.add(id, thread); @@ -4428,9 +4510,9 @@ status_t AudioFlinger::closeOutput(int output) LOGV("closeOutput() %d", output); - if (thread->type() == PlaybackThread::MIXER) { + if (thread->type() == ThreadBase::MIXER) { for (size_t i = 0; i < mPlaybackThreads.size(); i++) { - if (mPlaybackThreads.valueAt(i)->type() == PlaybackThread::DUPLICATING) { + if (mPlaybackThreads.valueAt(i)->type() == ThreadBase::DUPLICATING) { DuplicatingThread *dupThread = (DuplicatingThread *)mPlaybackThreads.valueAt(i).get(); dupThread->removeOutputTrack((MixerThread *)thread.get()); } @@ -4442,7 +4524,7 @@ status_t AudioFlinger::closeOutput(int output) } thread->exit(); - if (thread->type() != PlaybackThread::DUPLICATING) { + if (thread->type() != ThreadBase::DUPLICATING) { AudioStreamOut *out = thread->getOutput(); out->hwDev->close_output_stream(out->hwDev, out->stream); delete out; @@ -4537,9 +4619,17 @@ int AudioFlinger::openInput(uint32_t *pDevices, if (inStream != NULL) { AudioStreamIn *input = new AudioStreamIn(inHwDev, inStream); - int id = nextUniqueId_l(); - // Start record thread - thread = new RecordThread(this, input, reqSamplingRate, reqChannels, id); + int id = nextUniqueId(); + // Start record thread + // RecorThread require both input and output device indication to forward to audio + // pre processing modules + uint32_t device = (*pDevices) | primaryOutputDevice_l(); + thread = new RecordThread(this, + input, + reqSamplingRate, + reqChannels, + id, + device); mRecordThreads.add(id, thread); LOGV("openInput() created record thread: ID %d thread %p", id, thread); if (pSamplingRate) *pSamplingRate = reqSamplingRate; @@ -4597,7 +4687,7 @@ status_t AudioFlinger::setStreamOutput(uint32_t stream, int output) for (size_t i = 0; i < mPlaybackThreads.size(); i++) { PlaybackThread *thread = mPlaybackThreads.valueAt(i).get(); if (thread != dstThread && - thread->type() != PlaybackThread::DIRECT) { + thread->type() != ThreadBase::DIRECT) { MixerThread *srcThread = (MixerThread *)thread; srcThread->invalidateTracks(stream); } @@ -4609,8 +4699,7 @@ status_t AudioFlinger::setStreamOutput(uint32_t stream, int output) int AudioFlinger::newAudioSessionId() { - AutoMutex _l(mLock); - return nextUniqueId_l(); + return nextUniqueId(); } // checkPlaybackThread_l() must be called with AudioFlinger::mLock held @@ -4628,7 +4717,7 @@ AudioFlinger::MixerThread *AudioFlinger::checkMixerThread_l(int output) const { PlaybackThread *thread = checkPlaybackThread_l(output); if (thread != NULL) { - if (thread->type() == PlaybackThread::DIRECT) { + if (thread->type() == ThreadBase::DIRECT) { thread = NULL; } } @@ -4645,12 +4734,34 @@ AudioFlinger::RecordThread *AudioFlinger::checkRecordThread_l(int input) const return thread; } -// nextUniqueId_l() must be called with AudioFlinger::mLock held -int AudioFlinger::nextUniqueId_l() +uint32_t AudioFlinger::nextUniqueId() +{ + return android_atomic_inc(&mNextUniqueId); +} + +AudioFlinger::PlaybackThread *AudioFlinger::primaryPlaybackThread_l() { - return mNextUniqueId++; + for (size_t i = 0; i < mPlaybackThreads.size(); i++) { + PlaybackThread *thread = mPlaybackThreads.valueAt(i).get(); + if (thread->getOutput()->hwDev == mPrimaryHardwareDev) { + return thread; + } + } + return NULL; +} + +uint32_t AudioFlinger::primaryOutputDevice_l() +{ + PlaybackThread *thread = primaryPlaybackThread_l(); + + if (thread == NULL) { + return 0; + } + + return thread->device(); } + // ---------------------------------------------------------------------------- // Effect management // ---------------------------------------------------------------------------- @@ -4683,7 +4794,7 @@ sp<IEffect> AudioFlinger::createEffect(pid_t pid, effect_descriptor_t *pDesc, const sp<IEffectClient>& effectClient, int32_t priority, - int output, + int io, int sessionId, status_t *status, int *id, @@ -4695,8 +4806,8 @@ sp<IEffect> AudioFlinger::createEffect(pid_t pid, sp<Client> client; wp<Client> wclient; - LOGV("createEffect pid %d, client %p, priority %d, sessionId %d, output %d", - pid, effectClient.get(), priority, sessionId, output); + LOGV("createEffect pid %d, client %p, priority %d, sessionId %d, io %d", + pid, effectClient.get(), priority, sessionId, io); if (pDesc == NULL) { lStatus = BAD_VALUE; @@ -4724,7 +4835,7 @@ sp<IEffect> AudioFlinger::createEffect(pid_t pid, goto Exit; } - if (output == 0) { + if (io == 0) { if (sessionId == AUDIO_SESSION_OUTPUT_STAGE) { // output must be specified by AudioPolicyManager when using session // AUDIO_SESSION_OUTPUT_STAGE @@ -4732,9 +4843,9 @@ sp<IEffect> AudioFlinger::createEffect(pid_t pid, goto Exit; } else if (sessionId == AUDIO_SESSION_OUTPUT_MIX) { // if the output returned by getOutputForEffect() is removed before we lock the - // mutex below, the call to checkPlaybackThread_l(output) below will detect it + // mutex below, the call to checkPlaybackThread_l(io) below will detect it // and we will exit safely - output = AudioSystem::getOutputForEffect(&desc); + io = AudioSystem::getOutputForEffect(&desc); } } @@ -4811,31 +4922,41 @@ sp<IEffect> AudioFlinger::createEffect(pid_t pid, // output threads. // If output is 0 here, sessionId is neither SESSION_OUTPUT_STAGE nor SESSION_OUTPUT_MIX // because of code checking output when entering the function. - if (output == 0) { + // Note: io is never 0 when creating an effect on an input + if (io == 0) { // look for the thread where the specified audio session is present for (size_t i = 0; i < mPlaybackThreads.size(); i++) { if (mPlaybackThreads.valueAt(i)->hasAudioSession(sessionId) != 0) { - output = mPlaybackThreads.keyAt(i); + io = mPlaybackThreads.keyAt(i); break; } } + if (io == 0) { + for (size_t i = 0; i < mRecordThreads.size(); i++) { + if (mRecordThreads.valueAt(i)->hasAudioSession(sessionId) != 0) { + io = mRecordThreads.keyAt(i); + break; + } + } + } // If no output thread contains the requested session ID, default to // first output. The effect chain will be moved to the correct output // thread when a track with the same session ID is created - if (output == 0 && mPlaybackThreads.size()) { - output = mPlaybackThreads.keyAt(0); + if (io == 0 && mPlaybackThreads.size()) { + io = mPlaybackThreads.keyAt(0); } + LOGV("createEffect() got io %d for effect %s", io, desc.name); } - LOGV("createEffect() got output %d for effect %s", output, desc.name); - PlaybackThread *thread = checkPlaybackThread_l(output); + ThreadBase *thread = checkRecordThread_l(io); if (thread == NULL) { - LOGE("createEffect() unknown output thread"); - lStatus = BAD_VALUE; - goto Exit; + thread = checkPlaybackThread_l(io); + if (thread == NULL) { + LOGE("createEffect() unknown output thread"); + lStatus = BAD_VALUE; + goto Exit; + } } - // TODO: allow attachment of effect to inputs - wclient = mClients.valueFor(pid); if (wclient != NULL) { @@ -4943,8 +5064,9 @@ status_t AudioFlinger::moveEffectChain_l(int session, return NO_ERROR; } + // PlaybackThread::createEffect_l() must be called with AudioFlinger::mLock held -sp<AudioFlinger::EffectHandle> AudioFlinger::PlaybackThread::createEffect_l( +sp<AudioFlinger::EffectHandle> AudioFlinger::ThreadBase::createEffect_l( const sp<AudioFlinger::Client>& client, const sp<IEffectClient>& effectClient, int32_t priority, @@ -4957,24 +5079,14 @@ sp<AudioFlinger::EffectHandle> AudioFlinger::PlaybackThread::createEffect_l( sp<EffectModule> effect; sp<EffectHandle> handle; status_t lStatus; - sp<Track> track; sp<EffectChain> chain; bool chainCreated = false; bool effectCreated = false; bool effectRegistered = false; - if (mOutput == 0) { + lStatus = initCheck(); + if (lStatus != NO_ERROR) { LOGW("createEffect_l() Audio driver not initialized."); - lStatus = NO_INIT; - goto Exit; - } - - // Do not allow auxiliary effect on session other than 0 - if ((desc->flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY && - sessionId != AUDIO_SESSION_OUTPUT_MIX) { - LOGW("createEffect_l() Cannot add auxiliary effect %s to session %d", - desc->name, sessionId); - lStatus = BAD_VALUE; goto Exit; } @@ -4986,6 +5098,16 @@ sp<AudioFlinger::EffectHandle> AudioFlinger::PlaybackThread::createEffect_l( lStatus = BAD_VALUE; goto Exit; } + // Only Pre processor effects are allowed on input threads and only on input threads + if ((mType == RECORD && + (desc->flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_PRE_PROC) || + (mType != RECORD && + (desc->flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC)) { + LOGW("createEffect_l() effect %s (flags %08x) created on wrong thread type %d", + desc->name, desc->flags, mType); + lStatus = BAD_VALUE; + goto Exit; + } LOGV("createEffect_l() thread %p effect %s on session %d", this, desc->name, sessionId); @@ -5008,7 +5130,7 @@ sp<AudioFlinger::EffectHandle> AudioFlinger::PlaybackThread::createEffect_l( LOGV("createEffect_l() got effect %p on chain %p", effect == 0 ? 0 : effect.get(), chain.get()); if (effect == 0) { - int id = mAudioFlinger->nextUniqueId_l(); + int id = mAudioFlinger->nextUniqueId(); // Check CPU and memory usage lStatus = AudioSystem::registerEffect(desc, mId, chain->strategy(), sessionId, id); if (lStatus != NO_ERROR) { @@ -5059,9 +5181,20 @@ Exit: return handle; } +sp<AudioFlinger::EffectModule> AudioFlinger::ThreadBase::getEffect_l(int sessionId, int effectId) +{ + sp<EffectModule> effect; + + sp<EffectChain> chain = getEffectChain_l(sessionId); + if (chain != 0) { + effect = chain->getEffectFromId_l(effectId); + } + return effect; +} + // PlaybackThread::addEffect_l() must be called with AudioFlinger::mLock and // PlaybackThread::mLock held -status_t AudioFlinger::PlaybackThread::addEffect_l(const sp<EffectModule>& effect) +status_t AudioFlinger::ThreadBase::addEffect_l(const sp<EffectModule>& effect) { // check for existing effect chain with the requested audio session int sessionId = effect->sessionId(); @@ -5097,7 +5230,7 @@ status_t AudioFlinger::PlaybackThread::addEffect_l(const sp<EffectModule>& effec return NO_ERROR; } -void AudioFlinger::PlaybackThread::removeEffect_l(const sp<EffectModule>& effect) { +void AudioFlinger::ThreadBase::removeEffect_l(const sp<EffectModule>& effect) { LOGV("removeEffect_l() %p effect %p", this, effect.get()); effect_descriptor_t desc = effect->desc(); @@ -5116,7 +5249,53 @@ void AudioFlinger::PlaybackThread::removeEffect_l(const sp<EffectModule>& effect } } -void AudioFlinger::PlaybackThread::disconnectEffect(const sp<EffectModule>& effect, +void AudioFlinger::ThreadBase::lockEffectChains_l( + Vector<sp <AudioFlinger::EffectChain> >& effectChains) +{ + effectChains = mEffectChains; + for (size_t i = 0; i < mEffectChains.size(); i++) { + mEffectChains[i]->lock(); + } +} + +void AudioFlinger::ThreadBase::unlockEffectChains( + Vector<sp <AudioFlinger::EffectChain> >& effectChains) +{ + for (size_t i = 0; i < effectChains.size(); i++) { + effectChains[i]->unlock(); + } +} + +sp<AudioFlinger::EffectChain> AudioFlinger::ThreadBase::getEffectChain(int sessionId) +{ + Mutex::Autolock _l(mLock); + return getEffectChain_l(sessionId); +} + +sp<AudioFlinger::EffectChain> AudioFlinger::ThreadBase::getEffectChain_l(int sessionId) +{ + sp<EffectChain> chain; + + size_t size = mEffectChains.size(); + for (size_t i = 0; i < size; i++) { + if (mEffectChains[i]->sessionId() == sessionId) { + chain = mEffectChains[i]; + break; + } + } + return chain; +} + +void AudioFlinger::ThreadBase::setMode(uint32_t mode) +{ + Mutex::Autolock _l(mLock); + size_t size = mEffectChains.size(); + for (size_t i = 0; i < size; i++) { + mEffectChains[i]->setMode_l(mode); + } +} + +void AudioFlinger::ThreadBase::disconnectEffect(const sp<EffectModule>& effect, const wp<EffectHandle>& handle) { Mutex::Autolock _l(mLock); LOGV("disconnectEffect() %p effect %p", this, effect.get()); @@ -5222,35 +5401,6 @@ size_t AudioFlinger::PlaybackThread::removeEffectChain_l(const sp<EffectChain>& return mEffectChains.size(); } -void AudioFlinger::PlaybackThread::lockEffectChains_l( - Vector<sp <AudioFlinger::EffectChain> >& effectChains) -{ - effectChains = mEffectChains; - for (size_t i = 0; i < mEffectChains.size(); i++) { - mEffectChains[i]->lock(); - } -} - -void AudioFlinger::PlaybackThread::unlockEffectChains( - Vector<sp <AudioFlinger::EffectChain> >& effectChains) -{ - for (size_t i = 0; i < effectChains.size(); i++) { - effectChains[i]->unlock(); - } -} - - -sp<AudioFlinger::EffectModule> AudioFlinger::PlaybackThread::getEffect_l(int sessionId, int effectId) -{ - sp<EffectModule> effect; - - sp<EffectChain> chain = getEffectChain_l(sessionId); - if (chain != 0) { - effect = chain->getEffectFromId_l(effectId); - } - return effect; -} - status_t AudioFlinger::PlaybackThread::attachAuxEffect( const sp<AudioFlinger::PlaybackThread::Track> track, int EffectId) { @@ -5291,6 +5441,34 @@ void AudioFlinger::PlaybackThread::detachAuxEffect_l(int effectId) } } +status_t AudioFlinger::RecordThread::addEffectChain_l(const sp<EffectChain>& chain) +{ + // only one chain per input thread + if (mEffectChains.size() != 0) { + return INVALID_OPERATION; + } + LOGV("addEffectChain_l() %p on thread %p", chain.get(), this); + + chain->setInBuffer(NULL); + chain->setOutBuffer(NULL); + + mEffectChains.add(chain); + + return NO_ERROR; +} + +size_t AudioFlinger::RecordThread::removeEffectChain_l(const sp<EffectChain>& chain) +{ + LOGV("removeEffectChain_l() %p from thread %p", chain.get(), this); + LOGW_IF(mEffectChains.size() != 1, + "removeEffectChain_l() %p invalid chain size %d on thread %p", + chain.get(), mEffectChains.size(), this); + if (mEffectChains.size() == 1) { + mEffectChains.removeAt(0); + } + return 0; +} + // ---------------------------------------------------------------------------- // EffectModule implementation // ---------------------------------------------------------------------------- @@ -5312,12 +5490,11 @@ AudioFlinger::EffectModule::EffectModule(const wp<ThreadBase>& wThread, if (thread == 0) { return; } - PlaybackThread *p = (PlaybackThread *)thread.get(); memcpy(&mDescriptor, desc, sizeof(effect_descriptor_t)); // create effect engine from effect factory - mStatus = EffectCreate(&desc->uuid, sessionId, p->id(), &mEffectInterface); + mStatus = EffectCreate(&desc->uuid, sessionId, thread->id(), &mEffectInterface); if (mStatus != NO_ERROR) { return; @@ -5340,6 +5517,13 @@ AudioFlinger::EffectModule::~EffectModule() { LOGV("Destructor %p", this); if (mEffectInterface != NULL) { + if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC || + (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) { + sp<ThreadBase> thread = mThread.promote(); + if (thread != 0) { + thread->stream()->remove_audio_effect(thread->stream(), mEffectInterface); + } + } // release effect engine EffectRelease(mEffectInterface); } @@ -5415,8 +5599,7 @@ void AudioFlinger::EffectModule::disconnect(const wp<EffectHandle>& handle) { sp<ThreadBase> thread = mThread.promote(); if (thread != 0) { - PlaybackThread *playbackThread = (PlaybackThread *)thread.get(); - playbackThread->disconnectEffect(keep, handle); + thread->disconnectEffect(keep, handle); } } } @@ -5626,6 +5809,14 @@ status_t AudioFlinger::EffectModule::start_l() if (status == 0) { status = cmdStatus; } + if (status == 0 && + ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC || + (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC)) { + sp<ThreadBase> thread = mThread.promote(); + if (thread != 0) { + thread->stream()->add_audio_effect(thread->stream(), mEffectInterface); + } + } return status; } @@ -5645,6 +5836,14 @@ status_t AudioFlinger::EffectModule::stop_l() if (status == 0) { status = cmdStatus; } + if (status == 0 && + ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC || + (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC)) { + sp<ThreadBase> thread = mThread.promote(); + if (thread != 0) { + thread->stream()->remove_audio_effect(thread->stream(), mEffectInterface); + } + } return status; } @@ -5784,17 +5983,41 @@ status_t AudioFlinger::EffectModule::setDevice(uint32_t device) { Mutex::Autolock _l(mLock); status_t status = NO_ERROR; - if ((mDescriptor.flags & EFFECT_FLAG_DEVICE_MASK) == EFFECT_FLAG_DEVICE_IND) { - status_t cmdStatus; - uint32_t size = sizeof(status_t); - status = (*mEffectInterface)->command(mEffectInterface, - EFFECT_CMD_SET_DEVICE, - sizeof(uint32_t), - &device, - &size, - &cmdStatus); - if (status == NO_ERROR) { - status = cmdStatus; + if (device && (mDescriptor.flags & EFFECT_FLAG_DEVICE_MASK) == EFFECT_FLAG_DEVICE_IND) { + // audio pre processing modules on RecordThread can receive both output and + // input device indication in the same call + uint32_t dev = device & AUDIO_DEVICE_OUT_ALL; + if (dev) { + status_t cmdStatus; + uint32_t size = sizeof(status_t); + + status = (*mEffectInterface)->command(mEffectInterface, + EFFECT_CMD_SET_DEVICE, + sizeof(uint32_t), + &dev, + &size, + &cmdStatus); + if (status == NO_ERROR) { + status = cmdStatus; + } + } + dev = device & AUDIO_DEVICE_IN_ALL; + if (dev) { + status_t cmdStatus; + uint32_t size = sizeof(status_t); + + status_t status2 = (*mEffectInterface)->command(mEffectInterface, + EFFECT_CMD_SET_INPUT_DEVICE, + sizeof(uint32_t), + &dev, + &size, + &cmdStatus); + if (status2 == NO_ERROR) { + status2 = cmdStatus; + } + if (status == NO_ERROR) { + status = status2; + } } } return status; @@ -6168,7 +6391,6 @@ void AudioFlinger::EffectChain::process_l() LOGW("process_l(): cannot promote mixer thread"); return; } - PlaybackThread *playbackThread = (PlaybackThread *)thread.get(); bool isGlobalSession = (mSessionId == AUDIO_SESSION_OUTPUT_MIX) || (mSessionId == AUDIO_SESSION_OUTPUT_STAGE); bool tracksOnSession = false; @@ -6180,7 +6402,7 @@ void AudioFlinger::EffectChain::process_l() // will not do it if (tracksOnSession && activeTrackCnt() == 0) { - size_t numSamples = playbackThread->frameCount() * playbackThread->channelCount(); + size_t numSamples = thread->frameCount() * thread->channelCount(); memset(mInBuffer, 0, numSamples * sizeof(int16_t)); } diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h index 1fad987..fff4f06 100644 --- a/services/audioflinger/AudioFlinger.h +++ b/services/audioflinger/AudioFlinger.h @@ -157,7 +157,7 @@ public: effect_descriptor_t *pDesc, const sp<IEffectClient>& effectClient, int32_t priority, - int output, + int io, int sessionId, status_t *status, int *id, @@ -273,9 +273,17 @@ private: class ThreadBase : public Thread { public: - ThreadBase (const sp<AudioFlinger>& audioFlinger, int id); + ThreadBase (const sp<AudioFlinger>& audioFlinger, int id, uint32_t device); virtual ~ThreadBase(); + + enum type { + MIXER, // Thread class is MixerThread + DIRECT, // Thread class is DirectOutputThread + DUPLICATING, // Thread class is DuplicatingThread + RECORD // Thread class is RecordThread + }; + status_t dumpBase(int fd, const Vector<String16>& args); // base for record and playback @@ -377,6 +385,8 @@ private: int mParam; }; + virtual status_t initCheck() const = 0; + int type() const { return mType; } uint32_t sampleRate() const; int channelCount() const; uint32_t format() const; @@ -392,6 +402,60 @@ private: void processConfigEvents(); int id() const { return mId;} bool standby() { return mStandby; } + uint32_t device() { return mDevice; } + virtual audio_stream_t* stream() = 0; + + sp<EffectHandle> createEffect_l( + const sp<AudioFlinger::Client>& client, + const sp<IEffectClient>& effectClient, + int32_t priority, + int sessionId, + effect_descriptor_t *desc, + int *enabled, + status_t *status); + void disconnectEffect(const sp< EffectModule>& effect, + const wp<EffectHandle>& handle); + + // return values for hasAudioSession (bit field) + enum effect_state { + EFFECT_SESSION = 0x1, // the audio session corresponds to at least one + // effect + TRACK_SESSION = 0x2 // the audio session corresponds to at least one + // track + }; + + // get effect chain corresponding to session Id. + sp<EffectChain> getEffectChain(int sessionId); + // same as getEffectChain() but must be called with ThreadBase mutex locked + sp<EffectChain> getEffectChain_l(int sessionId); + // add an effect chain to the chain list (mEffectChains) + virtual status_t addEffectChain_l(const sp<EffectChain>& chain) = 0; + // remove an effect chain from the chain list (mEffectChains) + virtual size_t removeEffectChain_l(const sp<EffectChain>& chain) = 0; + // lock mall effect chains Mutexes. Must be called before releasing the + // ThreadBase mutex before processing the mixer and effects. This guarantees the + // integrity of the chains during the process. + void lockEffectChains_l(Vector<sp <EffectChain> >& effectChains); + // unlock effect chains after process + void unlockEffectChains(Vector<sp <EffectChain> >& effectChains); + // set audio mode to all effect chains + void setMode(uint32_t mode); + // get effect module with corresponding ID on specified audio session + sp<AudioFlinger::EffectModule> getEffect_l(int sessionId, int effectId); + // add and effect module. Also creates the effect chain is none exists for + // the effects audio session + status_t addEffect_l(const sp< EffectModule>& effect); + // remove and effect module. Also removes the effect chain is this was the last + // effect + void removeEffect_l(const sp< EffectModule>& effect); + // detach all tracks connected to an auxiliary effect + virtual void detachAuxEffect_l(int effectId) {} + // returns either EFFECT_SESSION if effects on this audio session exist in one + // chain, or TRACK_SESSION if tracks on this audio session exist, or both + virtual uint32_t hasAudioSession(int sessionId) = 0; + // the value returned by default implementation is not important as the + // strategy is only meaningful for PlaybackThread which implements this method + virtual uint32_t getStrategyForSession_l(int sessionId) { return 0; } mutable Mutex mLock; @@ -406,6 +470,7 @@ private: friend class RecordThread; friend class RecordTrack; + int mType; Condition mWaitWorkCV; sp<AudioFlinger> mAudioFlinger; uint32_t mSampleRate; @@ -421,18 +486,15 @@ private: bool mStandby; int mId; bool mExiting; + Vector< sp<EffectChain> > mEffectChains; + uint32_t mDevice; // output device for PlaybackThread + // input + output devices for RecordThread }; // --- PlaybackThread --- class PlaybackThread : public ThreadBase { public: - enum type { - MIXER, - DIRECT, - DUPLICATING - }; - enum mixer_state { MIXER_IDLE, MIXER_TRACKS_ENABLED, @@ -569,6 +631,8 @@ private: virtual status_t readyToRun(); virtual void onFirstRef(); + virtual status_t initCheck() const { return (mOutput == 0) ? NO_INIT : NO_ERROR; } + virtual uint32_t latency() const; virtual status_t setMasterVolume(float value); @@ -595,8 +659,8 @@ private: status_t *status); AudioStreamOut* getOutput() { return mOutput; } + virtual audio_stream_t* stream() { return &mOutput->stream->common; } - virtual int type() const { return mType; } void suspend() { mSuspended++; } void restore() { if (mSuspended) mSuspended--; } bool isSuspended() { return (mSuspended != 0); } @@ -605,45 +669,16 @@ private: virtual status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames); int16_t *mixBuffer() { return mMixBuffer; }; - sp<EffectHandle> createEffect_l( - const sp<AudioFlinger::Client>& client, - const sp<IEffectClient>& effectClient, - int32_t priority, - int sessionId, - effect_descriptor_t *desc, - int *enabled, - status_t *status); - void disconnectEffect(const sp< EffectModule>& effect, - const wp<EffectHandle>& handle); - - // return values for hasAudioSession (bit field) - enum effect_state { - EFFECT_SESSION = 0x1, // the audio session corresponds to at least one - // effect - TRACK_SESSION = 0x2 // the audio session corresponds to at least one - // track - }; - - uint32_t hasAudioSession(int sessionId); - sp<EffectChain> getEffectChain(int sessionId); - sp<EffectChain> getEffectChain_l(int sessionId); - status_t addEffectChain_l(const sp<EffectChain>& chain); - size_t removeEffectChain_l(const sp<EffectChain>& chain); - void lockEffectChains_l(Vector<sp <EffectChain> >& effectChains); - void unlockEffectChains(Vector<sp <EffectChain> >& effectChains); - - sp<AudioFlinger::EffectModule> getEffect_l(int sessionId, int effectId); - void detachAuxEffect_l(int effectId); + virtual void detachAuxEffect_l(int effectId); status_t attachAuxEffect(const sp<AudioFlinger::PlaybackThread::Track> track, int EffectId); status_t attachAuxEffect_l(const sp<AudioFlinger::PlaybackThread::Track> track, int EffectId); - void setMode(uint32_t mode); - status_t addEffect_l(const sp< EffectModule>& effect); - void removeEffect_l(const sp< EffectModule>& effect); - - uint32_t getStrategyForSession_l(int sessionId); + virtual status_t addEffectChain_l(const sp<EffectChain>& chain); + virtual size_t removeEffectChain_l(const sp<EffectChain>& chain); + virtual uint32_t hasAudioSession(int sessionId); + virtual uint32_t getStrategyForSession_l(int sessionId); struct stream_type_t { stream_type_t() @@ -656,7 +691,6 @@ private: }; protected: - int mType; int16_t* mMixBuffer; int mSuspended; int mBytesWritten; @@ -688,8 +722,6 @@ private: void readOutputParameters(); - uint32_t device() { return mDevice; } - virtual status_t dumpInternals(int fd, const Vector<String16>& args); status_t dumpTracks(int fd, const Vector<String16>& args); status_t dumpEffectChains(int fd, const Vector<String16>& args); @@ -703,8 +735,6 @@ private: int mNumWrites; int mNumDelayedWrites; bool mInWrite; - Vector< sp<EffectChain> > mEffectChains; - uint32_t mDevice; }; class MixerThread : public PlaybackThread { @@ -788,11 +818,13 @@ private: float streamVolumeInternal(int stream) const { return mStreamTypes[stream].volume; } void audioConfigChanged_l(int event, int ioHandle, void *param2); - int nextUniqueId_l(); + uint32_t nextUniqueId(); status_t moveEffectChain_l(int session, AudioFlinger::PlaybackThread *srcThread, AudioFlinger::PlaybackThread *dstThread, bool reRegister); + PlaybackThread *primaryPlaybackThread_l(); + uint32_t primaryOutputDevice_l(); friend class AudioBuffer; @@ -864,18 +896,33 @@ private: AudioStreamIn *input, uint32_t sampleRate, uint32_t channels, - int id); + int id, + uint32_t device); ~RecordThread(); virtual bool threadLoop(); virtual status_t readyToRun() { return NO_ERROR; } virtual void onFirstRef(); + virtual status_t initCheck() const { return (mInput == 0) ? NO_INIT : NO_ERROR; } + sp<AudioFlinger::RecordThread::RecordTrack> createRecordTrack_l( + const sp<AudioFlinger::Client>& client, + uint32_t sampleRate, + int format, + int channelMask, + int frameCount, + uint32_t flags, + int sessionId, + status_t *status); + status_t start(RecordTrack* recordTrack); void stop(RecordTrack* recordTrack); status_t dump(int fd, const Vector<String16>& args); AudioStreamIn* getInput() { return mInput; } + virtual audio_stream_t* stream() { return &mInput->stream->common; } + + void setTrack(RecordTrack *recordTrack) { mTrack = recordTrack; } virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer); virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer); virtual bool checkForNewParameters_l(); @@ -884,9 +931,14 @@ private: void readInputParameters(); virtual unsigned int getInputFramesLost(); + virtual status_t addEffectChain_l(const sp<EffectChain>& chain); + virtual size_t removeEffectChain_l(const sp<EffectChain>& chain); + virtual uint32_t hasAudioSession(int sessionId); + private: RecordThread(); AudioStreamIn *mInput; + RecordTrack* mTrack; sp<RecordTrack> mActiveTrack; Condition mStartStopCond; AudioResampler *mResampler; @@ -1103,9 +1155,8 @@ private: status_t addEffect_l(const sp<EffectModule>& handle); size_t removeEffect_l(const sp<EffectModule>& handle); - int sessionId() { - return mSessionId; - } + int sessionId() { return mSessionId; } + void setSessionId(int sessionId) { mSessionId = sessionId; } sp<EffectModule> getEffectFromDesc_l(effect_descriptor_t *descriptor); sp<EffectModule> getEffectFromId_l(int id); diff --git a/services/audioflinger/AudioPolicyService.cpp b/services/audioflinger/AudioPolicyService.cpp index 8e16d94..dd1e153 100644 --- a/services/audioflinger/AudioPolicyService.cpp +++ b/services/audioflinger/AudioPolicyService.cpp @@ -33,11 +33,14 @@ #include <cutils/properties.h> #include <dlfcn.h> #include <hardware_legacy/power.h> +#include <media/AudioEffect.h> +#include <media/EffectsFactoryApi.h> #include <hardware/hardware.h> #include <system/audio.h> #include <system/audio_policy.h> #include <hardware/audio_policy.h> +#include <audio_effects/audio_effects_conf.h> namespace android { @@ -101,6 +104,13 @@ AudioPolicyService::AudioPolicyService() mpAudioPolicy->set_can_mute_enforced_audible(mpAudioPolicy, !forced_val); LOGI("Loaded audio policy from %s (%s)", module->name, module->id); + + // load audio pre processing modules + if (access(AUDIO_EFFECT_VENDOR_CONFIG_FILE, R_OK) == 0) { + loadPreProcessorConfig(AUDIO_EFFECT_VENDOR_CONFIG_FILE); + } else if (access(AUDIO_EFFECT_DEFAULT_CONFIG_FILE, R_OK) == 0) { + loadPreProcessorConfig(AUDIO_EFFECT_DEFAULT_CONFIG_FILE); + } } AudioPolicyService::~AudioPolicyService() @@ -110,6 +120,31 @@ AudioPolicyService::~AudioPolicyService() mAudioCommandThread->exit(); mAudioCommandThread.clear(); + + // release audio pre processing resources + for (size_t i = 0; i < mInputSources.size(); i++) { + InputSourceDesc *source = mInputSources.valueAt(i); + Vector <EffectDesc *> effects = source->mEffects; + for (size_t j = 0; j < effects.size(); j++) { + delete effects[j]->mName; + Vector <effect_param_t *> params = effects[j]->mParams; + for (size_t k = 0; k < params.size(); k++) { + delete params[k]; + } + params.clear(); + delete effects[j]; + } + effects.clear(); + delete source; + } + mInputSources.clear(); + + for (size_t i = 0; i < mInputs.size(); i++) { + mInputs.valueAt(i)->mEffects.clear(); + delete mInputs.valueAt(i); + } + mInputs.clear(); + if (mpAudioPolicy && mpAudioPolicyDev) mpAudioPolicyDev->destroy_audio_policy(mpAudioPolicyDev, mpAudioPolicy); if (mpAudioPolicyDev) @@ -276,13 +311,51 @@ audio_io_handle_t AudioPolicyService::getInput(int inputSource, uint32_t samplingRate, uint32_t format, uint32_t channels, - audio_in_acoustics_t acoustics) + audio_in_acoustics_t acoustics, + int audioSession) { if (mpAudioPolicy == NULL) { return 0; } Mutex::Autolock _l(mLock); - return mpAudioPolicy->get_input(mpAudioPolicy, inputSource, samplingRate, format, channels, acoustics); + audio_io_handle_t input = mpAudioPolicy->get_input(mpAudioPolicy, inputSource, samplingRate, + format, channels, acoustics); + + if (input == 0) { + return input; + } + // create audio pre processors according to input source + ssize_t index = mInputSources.indexOfKey((audio_source_t)inputSource); + if (index < 0) { + return input; + } + ssize_t idx = mInputs.indexOfKey(input); + InputDesc *inputDesc; + if (idx < 0) { + inputDesc = new InputDesc(); + inputDesc->mSessionId = audioSession; + mInputs.add(input, inputDesc); + } else { + inputDesc = mInputs.valueAt(idx); + } + + Vector <EffectDesc *> effects = mInputSources.valueAt(index)->mEffects; + for (size_t i = 0; i < effects.size(); i++) { + EffectDesc *effect = effects[i]; + sp<AudioEffect> fx = new AudioEffect(NULL, &effect->mUuid, -1, 0, 0, audioSession, input); + status_t status = fx->initCheck(); + if (status != NO_ERROR && status != ALREADY_EXISTS) { + LOGW("Failed to create Fx %s on input %d", effect->mName, input); + // fx goes out of scope and strong ref on AudioEffect is released + continue; + } + for (size_t j = 0; j < effect->mParams.size(); j++) { + fx->setParameter(effect->mParams[j]); + } + inputDesc->mEffects.add(fx); + } + setPreProcessorEnabled(inputDesc, true); + return input; } status_t AudioPolicyService::startInput(audio_io_handle_t input) @@ -291,6 +364,7 @@ status_t AudioPolicyService::startInput(audio_io_handle_t input) return NO_INIT; } Mutex::Autolock _l(mLock); + return mpAudioPolicy->start_input(mpAudioPolicy, input); } @@ -300,6 +374,7 @@ status_t AudioPolicyService::stopInput(audio_io_handle_t input) return NO_INIT; } Mutex::Autolock _l(mLock); + return mpAudioPolicy->stop_input(mpAudioPolicy, input); } @@ -310,6 +385,16 @@ void AudioPolicyService::releaseInput(audio_io_handle_t input) } Mutex::Autolock _l(mLock); mpAudioPolicy->release_input(mpAudioPolicy, input); + + ssize_t index = mInputs.indexOfKey(input); + if (index < 0) { + return; + } + InputDesc *inputDesc = mInputs.valueAt(index); + setPreProcessorEnabled(inputDesc, false); + inputDesc->mEffects.clear(); + delete inputDesc; + mInputs.removeItemsAt(index); } status_t AudioPolicyService::initStreamVolume(audio_stream_type_t stream, @@ -384,7 +469,7 @@ audio_io_handle_t AudioPolicyService::getOutputForEffect(effect_descriptor_t *de } status_t AudioPolicyService::registerEffect(effect_descriptor_t *desc, - audio_io_handle_t output, + audio_io_handle_t io, uint32_t strategy, int session, int id) @@ -392,7 +477,7 @@ status_t AudioPolicyService::registerEffect(effect_descriptor_t *desc, if (mpAudioPolicy == NULL) { return NO_INIT; } - return mpAudioPolicy->register_effect(mpAudioPolicy, desc, output, strategy, session, id); + return mpAudioPolicy->register_effect(mpAudioPolicy, desc, io, strategy, session, id); } status_t AudioPolicyService::unregisterEffect(int id) @@ -489,6 +574,15 @@ status_t AudioPolicyService::dumpPermissionDenial(int fd) return NO_ERROR; } +void AudioPolicyService::setPreProcessorEnabled(InputDesc *inputDesc, bool enabled) +{ + Vector<sp<AudioEffect> > fxVector = inputDesc->mEffects; + for (size_t i = 0; i < fxVector.size(); i++) { + sp<AudioEffect> fx = fxVector.itemAt(i); + fx->setEnabled(enabled); + } +} + status_t AudioPolicyService::onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { @@ -918,6 +1012,300 @@ int AudioPolicyService::setVoiceVolume(float volume, int delayMs) return (int)mAudioCommandThread->voiceVolumeCommand(volume, delayMs); } +// ---------------------------------------------------------------------------- +// Audio pre-processing configuration +// ---------------------------------------------------------------------------- + +const char *AudioPolicyService::kInputSourceNames[AUDIO_SOURCE_CNT -1] = { + MIC_SRC_TAG, + VOICE_UL_SRC_TAG, + VOICE_DL_SRC_TAG, + VOICE_CALL_SRC_TAG, + CAMCORDER_SRC_TAG, + VOICE_REC_SRC_TAG, + VOICE_COMM_SRC_TAG +}; + +// returns the audio_source_t enum corresponding to the input source name or +// AUDIO_SOURCE_CNT is no match found +audio_source_t AudioPolicyService::inputSourceNameToEnum(const char *name) +{ + int i; + for (i = AUDIO_SOURCE_MIC; i < AUDIO_SOURCE_CNT; i++) { + if (strcmp(name, kInputSourceNames[i - AUDIO_SOURCE_MIC]) == 0) { + LOGV("inputSourceNameToEnum found source %s %d", name, i); + break; + } + } + return (audio_source_t)i; +} + +size_t AudioPolicyService::growParamSize(char *param, + size_t size, + size_t *curSize, + size_t *totSize) +{ + // *curSize is at least sizeof(effect_param_t) + 2 * sizeof(int) + size_t pos = ((*curSize - 1 ) / size + 1) * size; + + if (pos + size > *totSize) { + while (pos + size > *totSize) { + *totSize += ((*totSize + 7) / 8) * 4; + } + param = (char *)realloc(param, *totSize); + } + *curSize = pos + size; + return pos; +} + +size_t AudioPolicyService::readParamValue(cnode *node, + char *param, + size_t *curSize, + size_t *totSize) +{ + if (strncmp(node->name, SHORT_TAG, sizeof(SHORT_TAG) + 1) == 0) { + size_t pos = growParamSize(param, sizeof(short), curSize, totSize); + *(short *)((char *)param + pos) = (short)atoi(node->value); + LOGV("readParamValue() reading short %d", *(short *)((char *)param + pos)); + return sizeof(short); + } else if (strncmp(node->name, INT_TAG, sizeof(INT_TAG) + 1) == 0) { + size_t pos = growParamSize(param, sizeof(int), curSize, totSize); + *(int *)((char *)param + pos) = atoi(node->value); + LOGV("readParamValue() reading int %d", *(int *)((char *)param + pos)); + return sizeof(int); + } else if (strncmp(node->name, FLOAT_TAG, sizeof(FLOAT_TAG) + 1) == 0) { + size_t pos = growParamSize(param, sizeof(float), curSize, totSize); + *(float *)((char *)param + pos) = (float)atof(node->value); + LOGV("readParamValue() reading float %f",*(float *)((char *)param + pos)); + return sizeof(float); + } else if (strncmp(node->name, BOOL_TAG, sizeof(BOOL_TAG) + 1) == 0) { + size_t pos = growParamSize(param, sizeof(bool), curSize, totSize); + if (strncmp(node->value, "false", strlen("false") + 1) == 0) { + *(bool *)((char *)param + pos) = false; + } else { + *(bool *)((char *)param + pos) = true; + } + LOGV("readParamValue() reading bool %s",*(bool *)((char *)param + pos) ? "true" : "false"); + return sizeof(bool); + } else if (strncmp(node->name, STRING_TAG, sizeof(STRING_TAG) + 1) == 0) { + size_t len = strnlen(node->value, EFFECT_STRING_LEN_MAX); + if (*curSize + len + 1 > *totSize) { + *totSize = *curSize + len + 1; + param = (char *)realloc(param, *totSize); + } + strncpy(param + *curSize, node->value, len); + *curSize += len; + param[*curSize] = '\0'; + LOGV("readParamValue() reading string %s", param + *curSize - len); + return len; + } + LOGW("readParamValue() unknown param type %s", node->name); + return 0; +} + +effect_param_t *AudioPolicyService::loadEffectParameter(cnode *root) +{ + cnode *param; + cnode *value; + size_t curSize = sizeof(effect_param_t); + size_t totSize = sizeof(effect_param_t) + 2 * sizeof(int); + effect_param_t *fx_param = (effect_param_t *)malloc(totSize); + + param = config_find(root, PARAM_TAG); + value = config_find(root, VALUE_TAG); + if (param == NULL && value == NULL) { + // try to parse simple parameter form {int int} + param = root->first_child; + if (param) { + // Note: that a pair of random strings is read as 0 0 + int *ptr = (int *)fx_param->data; + int *ptr2 = (int *)((char *)param + sizeof(effect_param_t)); + LOGW("loadEffectParameter() ptr %p ptr2 %p", ptr, ptr2); + *ptr++ = atoi(param->name); + *ptr = atoi(param->value); + fx_param->psize = sizeof(int); + fx_param->vsize = sizeof(int); + return fx_param; + } + } + if (param == NULL || value == NULL) { + LOGW("loadEffectParameter() invalid parameter description %s", root->name); + goto error; + } + + fx_param->psize = 0; + param = param->first_child; + while (param) { + LOGV("loadEffectParameter() reading param of type %s", param->name); + size_t size = readParamValue(param, (char *)fx_param, &curSize, &totSize); + if (size == 0) { + goto error; + } + fx_param->psize += size; + param = param->next; + } + + // align start of value field on 32 bit boundary + curSize = ((curSize - 1 ) / sizeof(int) + 1) * sizeof(int); + + fx_param->vsize = 0; + value = value->first_child; + while (value) { + LOGV("loadEffectParameter() reading value of type %s", value->name); + size_t size = readParamValue(value, (char *)fx_param, &curSize, &totSize); + if (size == 0) { + goto error; + } + fx_param->vsize += size; + value = value->next; + } + + return fx_param; + +error: + delete fx_param; + return NULL; +} + +void AudioPolicyService::loadEffectParameters(cnode *root, Vector <effect_param_t *>& params) +{ + cnode *node = root->first_child; + while (node) { + LOGV("loadEffectParameters() loading param %s", node->name); + effect_param_t *param = loadEffectParameter(node); + if (param == NULL) { + node = node->next; + continue; + } + params.add(param); + node = node->next; + } +} + +AudioPolicyService::InputSourceDesc *AudioPolicyService::loadInputSource( + cnode *root, + const Vector <EffectDesc *>& effects) +{ + cnode *node = root->first_child; + if (node == NULL) { + LOGW("loadInputSource() empty element %s", root->name); + return NULL; + } + InputSourceDesc *source = new InputSourceDesc(); + while (node) { + size_t i; + for (i = 0; i < effects.size(); i++) { + if (strncmp(effects[i]->mName, node->name, EFFECT_STRING_LEN_MAX) == 0) { + LOGV("loadInputSource() found effect %s in list", node->name); + break; + } + } + if (i == effects.size()) { + LOGV("loadInputSource() effect %s not in list", node->name); + node = node->next; + continue; + } + EffectDesc *effect = new EffectDesc(*effects[i]); + loadEffectParameters(node, effect->mParams); + LOGV("loadInputSource() adding effect %s uuid %08x", effect->mName, effect->mUuid.timeLow); + source->mEffects.add(effect); + node = node->next; + } + if (source->mEffects.size() == 0) { + LOGW("loadInputSource() no valid effects found in source %s", root->name); + delete source; + return NULL; + } + return source; +} + +status_t AudioPolicyService::loadInputSources(cnode *root, const Vector <EffectDesc *>& effects) +{ + cnode *node = config_find(root, PREPROCESSING_TAG); + if (node == NULL) { + return -ENOENT; + } + node = node->first_child; + while (node) { + audio_source_t source = inputSourceNameToEnum(node->name); + if (source == AUDIO_SOURCE_CNT) { + LOGW("loadInputSources() invalid input source %s", node->name); + node = node->next; + continue; + } + LOGV("loadInputSources() loading input source %s", node->name); + InputSourceDesc *desc = loadInputSource(node, effects); + if (desc == NULL) { + node = node->next; + continue; + } + mInputSources.add(source, desc); + node = node->next; + } + return NO_ERROR; +} + +AudioPolicyService::EffectDesc *AudioPolicyService::loadEffect(cnode *root) +{ + cnode *node = config_find(root, UUID_TAG); + if (node == NULL) { + return NULL; + } + effect_uuid_t uuid; + if (AudioEffect::stringToGuid(node->value, &uuid) != NO_ERROR) { + LOGW("loadEffect() invalid uuid %s", node->value); + return NULL; + } + EffectDesc *effect = new EffectDesc(); + effect->mName = strdup(root->name); + memcpy(&effect->mUuid, &uuid, sizeof(effect_uuid_t)); + + return effect; +} + +status_t AudioPolicyService::loadEffects(cnode *root, Vector <EffectDesc *>& effects) +{ + cnode *node = config_find(root, EFFECTS_TAG); + if (node == NULL) { + return -ENOENT; + } + node = node->first_child; + while (node) { + LOGV("loadEffects() loading effect %s", node->name); + EffectDesc *effect = loadEffect(node); + if (effect == NULL) { + node = node->next; + continue; + } + effects.add(effect); + node = node->next; + } + return NO_ERROR; +} + +status_t AudioPolicyService::loadPreProcessorConfig(const char *path) +{ + cnode *root; + char *data; + + data = (char *)load_file(path, NULL); + if (data == NULL) { + return -ENODEV; + } + root = config_node("", ""); + config_load(root, data); + + Vector <EffectDesc *> effects; + loadEffects(root, effects); + loadInputSources(root, effects); + + config_free(root); + free(root); + free(data); + + return NO_ERROR; +} + /* implementation of the interface to the policy manager */ extern "C" { diff --git a/services/audioflinger/AudioPolicyService.h b/services/audioflinger/AudioPolicyService.h index b830120..62ad29e 100644 --- a/services/audioflinger/AudioPolicyService.h +++ b/services/audioflinger/AudioPolicyService.h @@ -17,14 +17,17 @@ #ifndef ANDROID_AUDIOPOLICYSERVICE_H #define ANDROID_AUDIOPOLICYSERVICE_H -#include <media/IAudioPolicyService.h> -#include <media/ToneGenerator.h> +#include <cutils/misc.h> +#include <cutils/config_utils.h> #include <utils/Vector.h> +#include <utils/SortedVector.h> #include <binder/BinderService.h> - #include <system/audio.h> #include <system/audio_policy.h> #include <hardware/audio_policy.h> +#include <media/IAudioPolicyService.h> +#include <media/ToneGenerator.h> +#include <media/AudioEffect.h> namespace android { @@ -78,7 +81,8 @@ public: uint32_t format = AUDIO_FORMAT_DEFAULT, uint32_t channels = 0, audio_in_acoustics_t acoustics = - (audio_in_acoustics_t)0); + (audio_in_acoustics_t)0, + int audioSession = 0); virtual status_t startInput(audio_io_handle_t input); virtual status_t stopInput(audio_io_handle_t input); virtual void releaseInput(audio_io_handle_t input); @@ -93,7 +97,7 @@ public: virtual audio_io_handle_t getOutputForEffect(effect_descriptor_t *desc); virtual status_t registerEffect(effect_descriptor_t *desc, - audio_io_handle_t output, + audio_io_handle_t io, uint32_t strategy, int session, int id); @@ -218,6 +222,51 @@ private: String8 mName; // string used by wake lock fo delayed commands }; + class EffectDesc { + public: + EffectDesc() {} + virtual ~EffectDesc() {} + char *mName; + effect_uuid_t mUuid; + Vector <effect_param_t *> mParams; + }; + + class InputSourceDesc { + public: + InputSourceDesc() {} + virtual ~InputSourceDesc() {} + Vector <EffectDesc *> mEffects; + }; + + + class InputDesc { + public: + InputDesc() {} + virtual ~InputDesc() {} + int mSessionId; + Vector< sp<AudioEffect> >mEffects; + }; + + static const char *kInputSourceNames[AUDIO_SOURCE_CNT -1]; + + void setPreProcessorEnabled(InputDesc *inputDesc, bool enabled); + status_t loadPreProcessorConfig(const char *path); + status_t loadEffects(cnode *root, Vector <EffectDesc *>& effects); + EffectDesc *loadEffect(cnode *root); + status_t loadInputSources(cnode *root, const Vector <EffectDesc *>& effects); + audio_source_t inputSourceNameToEnum(const char *name); + InputSourceDesc *loadInputSource(cnode *root, const Vector <EffectDesc *>& effects); + void loadEffectParameters(cnode *root, Vector <effect_param_t *>& params); + effect_param_t *loadEffectParameter(cnode *root); + size_t readParamValue(cnode *node, + char *param, + size_t *curSize, + size_t *totSize); + size_t growParamSize(char *param, + size_t size, + size_t *curSize, + size_t *totSize); + // Internal dump utilities. status_t dumpPermissionDenial(int fd); @@ -226,9 +275,10 @@ private: // device connection state or routing sp <AudioCommandThread> mAudioCommandThread; // audio commands thread sp <AudioCommandThread> mTonePlaybackThread; // tone playback thread - struct audio_policy_device *mpAudioPolicyDev; struct audio_policy *mpAudioPolicy; + KeyedVector< audio_source_t, InputSourceDesc* > mInputSources; + KeyedVector< audio_io_handle_t, InputDesc* > mInputs; }; }; // namespace android diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp index 1cac502..039b003 100644 --- a/services/input/InputDispatcher.cpp +++ b/services/input/InputDispatcher.cpp @@ -215,14 +215,6 @@ InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& polic mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) { mLooper = new Looper(false); - mInboundQueue.headSentinel.refCount = -1; - mInboundQueue.headSentinel.type = EventEntry::TYPE_SENTINEL; - mInboundQueue.headSentinel.eventTime = LONG_LONG_MIN; - - mInboundQueue.tailSentinel.refCount = -1; - mInboundQueue.tailSentinel.type = EventEntry::TYPE_SENTINEL; - mInboundQueue.tailSentinel.eventTime = LONG_LONG_MAX; - mKeyRepeatState.lastKeyEntry = NULL; policy->getDispatcherConfiguration(&mConfig); @@ -319,7 +311,7 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) { } } else { // Inbound queue has at least one entry. - EventEntry* entry = mInboundQueue.headSentinel.next; + EventEntry* entry = mInboundQueue.head; // Throttle the entry if it is a move event and there are no // other events behind it in the queue. Due to movement batching, additional @@ -335,7 +327,7 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) { int32_t deviceId = motionEntry->deviceId; uint32_t source = motionEntry->source; if (! isAppSwitchDue - && motionEntry->next == & mInboundQueue.tailSentinel // exactly one event + && !motionEntry->next // exactly one event, no successors && (motionEntry->action == AMOTION_EVENT_ACTION_MOVE || motionEntry->action == AMOTION_EVENT_ACTION_HOVER_MOVE) && deviceId == mThrottleState.lastDeviceId @@ -641,13 +633,13 @@ bool InputDispatcher::runCommandsLockedInterruptible() { (this->*command)(commandEntry); // commands are implicitly 'LockedInterruptible' commandEntry->connection.clear(); - mAllocator.releaseCommandEntry(commandEntry); + delete commandEntry; } while (! mCommandQueue.isEmpty()); return true; } InputDispatcher::CommandEntry* InputDispatcher::postCommandLocked(Command command) { - CommandEntry* commandEntry = mAllocator.obtainCommandEntry(command); + CommandEntry* commandEntry = new CommandEntry(command); mCommandQueue.enqueueAtTail(commandEntry); return commandEntry; } @@ -674,12 +666,12 @@ void InputDispatcher::releaseInboundEventLocked(EventEntry* entry) { #endif setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED); } - mAllocator.releaseEventEntry(entry); + entry->release(); } void InputDispatcher::resetKeyRepeatLocked() { if (mKeyRepeatState.lastKeyEntry) { - mAllocator.releaseKeyEntry(mKeyRepeatState.lastKeyEntry); + mKeyRepeatState.lastKeyEntry->release(); mKeyRepeatState.lastKeyEntry = NULL; } } @@ -691,18 +683,18 @@ InputDispatcher::KeyEntry* InputDispatcher::synthesizeKeyRepeatLocked(nsecs_t cu uint32_t policyFlags = (entry->policyFlags & POLICY_FLAG_RAW_MASK) | POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_TRUSTED; if (entry->refCount == 1) { - mAllocator.recycleKeyEntry(entry); + entry->recycle(); entry->eventTime = currentTime; entry->policyFlags = policyFlags; entry->repeatCount += 1; } else { - KeyEntry* newEntry = mAllocator.obtainKeyEntry(currentTime, + KeyEntry* newEntry = new KeyEntry(currentTime, entry->deviceId, entry->source, policyFlags, entry->action, entry->flags, entry->keyCode, entry->scanCode, entry->metaState, entry->repeatCount + 1, entry->downTime); mKeyRepeatState.lastKeyEntry = newEntry; - mAllocator.releaseKeyEntry(entry); + entry->release(); entry = newEntry; } @@ -887,7 +879,7 @@ bool InputDispatcher::dispatchMotionLocked( uint32_t originalSampleCount = entry->countSamples(); #endif MotionSample* nextSample = splitBatchAfterSample->next; - MotionEntry* nextEntry = mAllocator.obtainMotionEntry(nextSample->eventTime, + MotionEntry* nextEntry = new MotionEntry(nextSample->eventTime, entry->deviceId, entry->source, entry->policyFlags, entry->action, entry->flags, entry->metaState, entry->buttonState, entry->edgeFlags, @@ -897,7 +889,7 @@ bool InputDispatcher::dispatchMotionLocked( nextEntry->firstSample.next = nextSample->next; nextEntry->lastSample = entry->lastSample; } - mAllocator.freeMotionSample(nextSample); + delete nextSample; entry->lastSample = const_cast<MotionSample*>(splitBatchAfterSample); entry->lastSample->next = NULL; @@ -1992,7 +1984,7 @@ void InputDispatcher::enqueueDispatchEntryLocked( // This is a new event. // Enqueue a new dispatch entry onto the outbound queue for this connection. - DispatchEntry* dispatchEntry = mAllocator.obtainDispatchEntry(eventEntry, // increments ref + DispatchEntry* dispatchEntry = new DispatchEntry(eventEntry, // increments ref inputTargetFlags, inputTarget->xOffset, inputTarget->yOffset, inputTarget->scaleFactor); if (dispatchEntry->hasForegroundTarget()) { @@ -2087,7 +2079,7 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime, LOG_ASSERT(connection->status == Connection::STATUS_NORMAL); LOG_ASSERT(! connection->outboundQueue.isEmpty()); - DispatchEntry* dispatchEntry = connection->outboundQueue.headSentinel.next; + DispatchEntry* dispatchEntry = connection->outboundQueue.head; LOG_ASSERT(! dispatchEntry->inProgress); // Mark the dispatch entry as in progress. @@ -2276,7 +2268,7 @@ void InputDispatcher::startNextDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection) { // Start the next dispatch cycle for this connection. while (! connection->outboundQueue.isEmpty()) { - DispatchEntry* dispatchEntry = connection->outboundQueue.headSentinel.next; + DispatchEntry* dispatchEntry = connection->outboundQueue.head; if (dispatchEntry->inProgress) { // Finish or resume current event in progress. if (dispatchEntry->tailMotionSample) { @@ -2293,7 +2285,7 @@ void InputDispatcher::startNextDispatchCycleLocked(nsecs_t currentTime, if (dispatchEntry->hasForegroundTarget()) { decrementPendingForegroundDispatchesLocked(dispatchEntry->eventEntry); } - mAllocator.releaseDispatchEntry(dispatchEntry); + delete dispatchEntry; } else { // If the head is not in progress, then we must have already dequeued the in // progress event, which means we actually aborted it. @@ -2333,7 +2325,7 @@ void InputDispatcher::drainOutboundQueueLocked(Connection* connection) { if (dispatchEntry->hasForegroundTarget()) { decrementPendingForegroundDispatchesLocked(dispatchEntry->eventEntry); } - mAllocator.releaseDispatchEntry(dispatchEntry); + delete dispatchEntry; } deactivateConnectionLocked(connection); @@ -2407,7 +2399,7 @@ void InputDispatcher::synthesizeCancelationEventsForConnectionLocked( nsecs_t currentTime = now(); mTempCancelationEvents.clear(); - connection->inputState.synthesizeCancelationEvents(currentTime, & mAllocator, + connection->inputState.synthesizeCancelationEvents(currentTime, mTempCancelationEvents, options); if (! mTempCancelationEvents.isEmpty() @@ -2448,10 +2440,10 @@ void InputDispatcher::synthesizeCancelationEventsForConnectionLocked( enqueueDispatchEntryLocked(connection, cancelationEventEntry, // increments ref &target, false, InputTarget::FLAG_DISPATCH_AS_IS); - mAllocator.releaseEventEntry(cancelationEventEntry); + cancelationEventEntry->release(); } - if (!connection->outboundQueue.headSentinel.next->inProgress) { + if (!connection->outboundQueue.head->inProgress) { startDispatchCycleLocked(currentTime, connection); } } @@ -2523,7 +2515,7 @@ InputDispatcher::splitMotionEvent(const MotionEntry* originalMotionEntry, BitSet } } - MotionEntry* splitMotionEntry = mAllocator.obtainMotionEntry( + MotionEntry* splitMotionEntry = new MotionEntry( originalMotionEntry->eventTime, originalMotionEntry->deviceId, originalMotionEntry->source, @@ -2547,8 +2539,7 @@ InputDispatcher::splitMotionEvent(const MotionEntry* originalMotionEntry, BitSet originalMotionSample->pointerCoords[originalPointerIndex]); } - mAllocator.appendMotionSample(splitMotionEntry, originalMotionSample->eventTime, - splitPointerCoords); + splitMotionEntry->appendSample(originalMotionSample->eventTime, splitPointerCoords); } if (originalMotionEntry->injectionState) { @@ -2568,7 +2559,7 @@ void InputDispatcher::notifyConfigurationChanged(nsecs_t eventTime) { { // acquire lock AutoMutex _l(mLock); - ConfigurationChangedEntry* newEntry = mAllocator.obtainConfigurationChangedEntry(eventTime); + ConfigurationChangedEntry* newEntry = new ConfigurationChangedEntry(eventTime); needWake = enqueueInboundEventLocked(newEntry); } // release lock @@ -2638,7 +2629,7 @@ void InputDispatcher::notifyKey(nsecs_t eventTime, int32_t deviceId, uint32_t so } int32_t repeatCount = 0; - KeyEntry* newEntry = mAllocator.obtainKeyEntry(eventTime, + KeyEntry* newEntry = new KeyEntry(eventTime, deviceId, source, policyFlags, action, flags, keyCode, scanCode, metaState, repeatCount, downTime); @@ -2718,8 +2709,7 @@ void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, uint32_t // Try to append a move sample to the tail of the inbound queue for this device. // Give up if we encounter a non-move motion event for this device since that // means we cannot append any new samples until a new motion event has started. - for (EventEntry* entry = mInboundQueue.tailSentinel.prev; - entry != & mInboundQueue.headSentinel; entry = entry->prev) { + for (EventEntry* entry = mInboundQueue.tail; entry; entry = entry->prev) { if (entry->type != EventEntry::TYPE_MOTION) { // Keep looking for motion events. continue; @@ -2798,7 +2788,7 @@ void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, uint32_t continue; } - DispatchEntry* dispatchEntry = connection->outboundQueue.headSentinel.next; + DispatchEntry* dispatchEntry = connection->outboundQueue.head; if (! dispatchEntry->inProgress || dispatchEntry->eventEntry->type != EventEntry::TYPE_MOTION || dispatchEntry->isSplit()) { @@ -2844,7 +2834,7 @@ void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, uint32_t // Hurray! This foreground target is currently dispatching a move event // that we can stream onto. Append the motion sample and resume dispatch. - mAllocator.appendMotionSample(motionEntry, eventTime, pointerCoords); + motionEntry->appendSample(eventTime, pointerCoords); #if DEBUG_BATCHING LOGD("Appended motion sample onto batch for most recently dispatched " "motion event for this device and source in the outbound queues. " @@ -2864,7 +2854,7 @@ NoBatchingOrStreaming:; } // Just enqueue a new motion event. - MotionEntry* newEntry = mAllocator.obtainMotionEntry(eventTime, + MotionEntry* newEntry = new MotionEntry(eventTime, deviceId, source, policyFlags, action, flags, metaState, buttonState, edgeFlags, xPrecision, yPrecision, downTime, pointerCount, pointerProperties, pointerCoords); @@ -2901,7 +2891,7 @@ void InputDispatcher::batchMotionLocked(MotionEntry* entry, nsecs_t eventTime, } // Append the sample. - mAllocator.appendMotionSample(entry, eventTime, pointerCoords); + entry->appendSample(eventTime, pointerCoords); #if DEBUG_BATCHING LOGD("Appended motion sample onto batch for %s, events were %0.3f ms apart", eventDescription, interval * 0.000001f); @@ -2958,7 +2948,7 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event, } mLock.lock(); - injectedEntry = mAllocator.obtainKeyEntry(keyEvent->getEventTime(), + injectedEntry = new KeyEntry(keyEvent->getEventTime(), keyEvent->getDeviceId(), keyEvent->getSource(), policyFlags, action, flags, keyEvent->getKeyCode(), keyEvent->getScanCode(), keyEvent->getMetaState(), @@ -2983,7 +2973,7 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event, mLock.lock(); const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes(); const PointerCoords* samplePointerCoords = motionEvent->getSamplePointerCoords(); - MotionEntry* motionEntry = mAllocator.obtainMotionEntry(*sampleEventTimes, + MotionEntry* motionEntry = new MotionEntry(*sampleEventTimes, motionEvent->getDeviceId(), motionEvent->getSource(), policyFlags, action, motionEvent->getFlags(), motionEvent->getMetaState(), motionEvent->getButtonState(), @@ -2994,7 +2984,7 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event, for (size_t i = motionEvent->getHistorySize(); i > 0; i--) { sampleEventTimes += 1; samplePointerCoords += pointerCount; - mAllocator.appendMotionSample(motionEntry, *sampleEventTimes, samplePointerCoords); + motionEntry->appendSample(*sampleEventTimes, samplePointerCoords); } injectedEntry = motionEntry; break; @@ -3005,7 +2995,7 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event, return INPUT_EVENT_INJECTION_FAILED; } - InjectionState* injectionState = mAllocator.obtainInjectionState(injectorPid, injectorUid); + InjectionState* injectionState = new InjectionState(injectorPid, injectorUid); if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) { injectionState->injectionIsAsync = true; } @@ -3068,7 +3058,7 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event, } } - mAllocator.releaseInjectionState(injectionState); + injectionState->release(); } // release lock #if DEBUG_INJECTION @@ -3704,7 +3694,7 @@ void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible( entry->interceptKeyResult = consumed ? KeyEntry::INTERCEPT_KEY_RESULT_SKIP : KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE; - mAllocator.releaseKeyEntry(entry); + entry->release(); } void InputDispatcher::doDispatchCycleFinishedLockedInterruptible( @@ -3714,7 +3704,7 @@ void InputDispatcher::doDispatchCycleFinishedLockedInterruptible( bool skipNext = false; if (!connection->outboundQueue.isEmpty()) { - DispatchEntry* dispatchEntry = connection->outboundQueue.headSentinel.next; + DispatchEntry* dispatchEntry = connection->outboundQueue.head; if (dispatchEntry->inProgress) { if (dispatchEntry->eventEntry->type == EventEntry::TYPE_KEY) { KeyEntry* keyEntry = static_cast<KeyEntry*>(dispatchEntry->eventEntry); @@ -3796,7 +3786,7 @@ bool InputDispatcher::afterKeyEventLockedInterruptible(const sp<Connection>& con return true; // skip next cycle } - LOG_ASSERT(connection->outboundQueue.headSentinel.next == dispatchEntry); + LOG_ASSERT(connection->outboundQueue.head == dispatchEntry); // Latch the fallback keycode for this key on an initial down. // The fallback keycode cannot change at any other point in the lifecycle. @@ -3929,230 +3919,137 @@ void InputDispatcher::dump(String8& dump) { template <typename T> uint32_t InputDispatcher::Queue<T>::count() const { uint32_t result = 0; - for (const T* entry = headSentinel.next; entry != & tailSentinel; entry = entry->next) { + for (const T* entry = head; entry; entry = entry->next) { result += 1; } return result; } -// --- InputDispatcher::Allocator --- +// --- InputDispatcher::InjectionState --- -InputDispatcher::Allocator::Allocator() { +InputDispatcher::InjectionState::InjectionState(int32_t injectorPid, int32_t injectorUid) : + refCount(1), + injectorPid(injectorPid), injectorUid(injectorUid), + injectionResult(INPUT_EVENT_INJECTION_PENDING), injectionIsAsync(false), + pendingForegroundDispatches(0) { } -InputDispatcher::InjectionState* -InputDispatcher::Allocator::obtainInjectionState(int32_t injectorPid, int32_t injectorUid) { - InjectionState* injectionState = mInjectionStatePool.alloc(); - injectionState->refCount = 1; - injectionState->injectorPid = injectorPid; - injectionState->injectorUid = injectorUid; - injectionState->injectionIsAsync = false; - injectionState->injectionResult = INPUT_EVENT_INJECTION_PENDING; - injectionState->pendingForegroundDispatches = 0; - return injectionState; +InputDispatcher::InjectionState::~InjectionState() { } -void InputDispatcher::Allocator::initializeEventEntry(EventEntry* entry, int32_t type, - nsecs_t eventTime, uint32_t policyFlags) { - entry->type = type; - entry->refCount = 1; - entry->dispatchInProgress = false; - entry->eventTime = eventTime; - entry->policyFlags = policyFlags; - entry->injectionState = NULL; -} - -void InputDispatcher::Allocator::releaseEventEntryInjectionState(EventEntry* entry) { - if (entry->injectionState) { - releaseInjectionState(entry->injectionState); - entry->injectionState = NULL; +void InputDispatcher::InjectionState::release() { + refCount -= 1; + if (refCount == 0) { + delete this; + } else { + LOG_ASSERT(refCount > 0); } } -InputDispatcher::ConfigurationChangedEntry* -InputDispatcher::Allocator::obtainConfigurationChangedEntry(nsecs_t eventTime) { - ConfigurationChangedEntry* entry = mConfigurationChangeEntryPool.alloc(); - initializeEventEntry(entry, EventEntry::TYPE_CONFIGURATION_CHANGED, eventTime, 0); - return entry; -} -InputDispatcher::KeyEntry* InputDispatcher::Allocator::obtainKeyEntry(nsecs_t eventTime, - int32_t deviceId, uint32_t source, uint32_t policyFlags, int32_t action, - int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState, - int32_t repeatCount, nsecs_t downTime) { - KeyEntry* entry = mKeyEntryPool.alloc(); - initializeEventEntry(entry, EventEntry::TYPE_KEY, eventTime, policyFlags); - - entry->deviceId = deviceId; - entry->source = source; - entry->action = action; - entry->flags = flags; - entry->keyCode = keyCode; - entry->scanCode = scanCode; - entry->metaState = metaState; - entry->repeatCount = repeatCount; - entry->downTime = downTime; - entry->syntheticRepeat = false; - entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN; - return entry; -} +// --- InputDispatcher::EventEntry --- -InputDispatcher::MotionEntry* InputDispatcher::Allocator::obtainMotionEntry(nsecs_t eventTime, - int32_t deviceId, uint32_t source, uint32_t policyFlags, int32_t action, int32_t flags, - int32_t metaState, int32_t buttonState, - int32_t edgeFlags, float xPrecision, float yPrecision, - nsecs_t downTime, uint32_t pointerCount, - const PointerProperties* pointerProperties, const PointerCoords* pointerCoords) { - MotionEntry* entry = mMotionEntryPool.alloc(); - initializeEventEntry(entry, EventEntry::TYPE_MOTION, eventTime, policyFlags); - - entry->eventTime = eventTime; - entry->deviceId = deviceId; - entry->source = source; - entry->action = action; - entry->flags = flags; - entry->metaState = metaState; - entry->buttonState = buttonState; - entry->edgeFlags = edgeFlags; - entry->xPrecision = xPrecision; - entry->yPrecision = yPrecision; - entry->downTime = downTime; - entry->pointerCount = pointerCount; - entry->firstSample.eventTime = eventTime; - entry->firstSample.eventTimeBeforeCoalescing = eventTime; - entry->firstSample.next = NULL; - entry->lastSample = & entry->firstSample; - for (uint32_t i = 0; i < pointerCount; i++) { - entry->pointerProperties[i].copyFrom(pointerProperties[i]); - entry->firstSample.pointerCoords[i].copyFrom(pointerCoords[i]); - } - return entry; +InputDispatcher::EventEntry::EventEntry(int32_t type, nsecs_t eventTime, uint32_t policyFlags) : + refCount(1), type(type), eventTime(eventTime), policyFlags(policyFlags), + injectionState(NULL), dispatchInProgress(false) { } -InputDispatcher::DispatchEntry* InputDispatcher::Allocator::obtainDispatchEntry( - EventEntry* eventEntry, - int32_t targetFlags, float xOffset, float yOffset, float scaleFactor) { - DispatchEntry* entry = mDispatchEntryPool.alloc(); - entry->eventEntry = eventEntry; - eventEntry->refCount += 1; - entry->targetFlags = targetFlags; - entry->xOffset = xOffset; - entry->yOffset = yOffset; - entry->scaleFactor = scaleFactor; - entry->inProgress = false; - entry->headMotionSample = NULL; - entry->tailMotionSample = NULL; - return entry; +InputDispatcher::EventEntry::~EventEntry() { + releaseInjectionState(); } -InputDispatcher::CommandEntry* InputDispatcher::Allocator::obtainCommandEntry(Command command) { - CommandEntry* entry = mCommandEntryPool.alloc(); - entry->command = command; - return entry; -} - -void InputDispatcher::Allocator::releaseInjectionState(InjectionState* injectionState) { - injectionState->refCount -= 1; - if (injectionState->refCount == 0) { - mInjectionStatePool.free(injectionState); +void InputDispatcher::EventEntry::release() { + refCount -= 1; + if (refCount == 0) { + delete this; } else { - LOG_ASSERT(injectionState->refCount > 0); + LOG_ASSERT(refCount > 0); } } -void InputDispatcher::Allocator::releaseEventEntry(EventEntry* entry) { - switch (entry->type) { - case EventEntry::TYPE_CONFIGURATION_CHANGED: - releaseConfigurationChangedEntry(static_cast<ConfigurationChangedEntry*>(entry)); - break; - case EventEntry::TYPE_KEY: - releaseKeyEntry(static_cast<KeyEntry*>(entry)); - break; - case EventEntry::TYPE_MOTION: - releaseMotionEntry(static_cast<MotionEntry*>(entry)); - break; - default: - LOG_ASSERT(false); - break; +void InputDispatcher::EventEntry::releaseInjectionState() { + if (injectionState) { + injectionState->release(); + injectionState = NULL; } } -void InputDispatcher::Allocator::releaseConfigurationChangedEntry( - ConfigurationChangedEntry* entry) { - entry->refCount -= 1; - if (entry->refCount == 0) { - releaseEventEntryInjectionState(entry); - mConfigurationChangeEntryPool.free(entry); - } else { - LOG_ASSERT(entry->refCount > 0); - } -} -void InputDispatcher::Allocator::releaseKeyEntry(KeyEntry* entry) { - entry->refCount -= 1; - if (entry->refCount == 0) { - releaseEventEntryInjectionState(entry); - mKeyEntryPool.free(entry); - } else { - LOG_ASSERT(entry->refCount > 0); - } -} +// --- InputDispatcher::ConfigurationChangedEntry --- -void InputDispatcher::Allocator::releaseMotionEntry(MotionEntry* entry) { - entry->refCount -= 1; - if (entry->refCount == 0) { - releaseEventEntryInjectionState(entry); - for (MotionSample* sample = entry->firstSample.next; sample != NULL; ) { - MotionSample* next = sample->next; - mMotionSamplePool.free(sample); - sample = next; - } - mMotionEntryPool.free(entry); - } else { - LOG_ASSERT(entry->refCount > 0); - } +InputDispatcher::ConfigurationChangedEntry::ConfigurationChangedEntry(nsecs_t eventTime) : + EventEntry(TYPE_CONFIGURATION_CHANGED, eventTime, 0) { } -void InputDispatcher::Allocator::freeMotionSample(MotionSample* sample) { - mMotionSamplePool.free(sample); +InputDispatcher::ConfigurationChangedEntry::~ConfigurationChangedEntry() { } -void InputDispatcher::Allocator::releaseDispatchEntry(DispatchEntry* entry) { - releaseEventEntry(entry->eventEntry); - mDispatchEntryPool.free(entry); + +// --- InputDispatcher::KeyEntry --- + +InputDispatcher::KeyEntry::KeyEntry(nsecs_t eventTime, + int32_t deviceId, uint32_t source, uint32_t policyFlags, int32_t action, + int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState, + int32_t repeatCount, nsecs_t downTime) : + EventEntry(TYPE_KEY, eventTime, policyFlags), + deviceId(deviceId), source(source), action(action), flags(flags), + keyCode(keyCode), scanCode(scanCode), metaState(metaState), + repeatCount(repeatCount), downTime(downTime), + syntheticRepeat(false), interceptKeyResult(KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) { } -void InputDispatcher::Allocator::releaseCommandEntry(CommandEntry* entry) { - mCommandEntryPool.free(entry); +InputDispatcher::KeyEntry::~KeyEntry() { } -void InputDispatcher::Allocator::appendMotionSample(MotionEntry* motionEntry, - nsecs_t eventTime, const PointerCoords* pointerCoords) { - MotionSample* sample = mMotionSamplePool.alloc(); - sample->eventTime = eventTime; - sample->eventTimeBeforeCoalescing = eventTime; - uint32_t pointerCount = motionEntry->pointerCount; - for (uint32_t i = 0; i < pointerCount; i++) { - sample->pointerCoords[i].copyFrom(pointerCoords[i]); - } +void InputDispatcher::KeyEntry::recycle() { + releaseInjectionState(); - sample->next = NULL; - motionEntry->lastSample->next = sample; - motionEntry->lastSample = sample; + dispatchInProgress = false; + syntheticRepeat = false; + interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN; } -void InputDispatcher::Allocator::recycleKeyEntry(KeyEntry* keyEntry) { - releaseEventEntryInjectionState(keyEntry); - keyEntry->dispatchInProgress = false; - keyEntry->syntheticRepeat = false; - keyEntry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN; +// --- InputDispatcher::MotionSample --- + +InputDispatcher::MotionSample::MotionSample(nsecs_t eventTime, + const PointerCoords* pointerCoords, uint32_t pointerCount) : + next(NULL), eventTime(eventTime), eventTimeBeforeCoalescing(eventTime) { + for (uint32_t i = 0; i < pointerCount; i++) { + this->pointerCoords[i].copyFrom(pointerCoords[i]); + } } // --- InputDispatcher::MotionEntry --- +InputDispatcher::MotionEntry::MotionEntry(nsecs_t eventTime, + int32_t deviceId, uint32_t source, uint32_t policyFlags, int32_t action, int32_t flags, + int32_t metaState, int32_t buttonState, + int32_t edgeFlags, float xPrecision, float yPrecision, + nsecs_t downTime, uint32_t pointerCount, + const PointerProperties* pointerProperties, const PointerCoords* pointerCoords) : + EventEntry(TYPE_MOTION, eventTime, policyFlags), + deviceId(deviceId), source(source), action(action), flags(flags), + metaState(metaState), buttonState(buttonState), edgeFlags(edgeFlags), + xPrecision(xPrecision), yPrecision(yPrecision), + downTime(downTime), pointerCount(pointerCount), + firstSample(eventTime, pointerCoords, pointerCount), + lastSample(&firstSample) { + for (uint32_t i = 0; i < pointerCount; i++) { + this->pointerProperties[i].copyFrom(pointerProperties[i]); + } +} + +InputDispatcher::MotionEntry::~MotionEntry() { + for (MotionSample* sample = firstSample.next; sample != NULL; ) { + MotionSample* next = sample->next; + delete sample; + sample = next; + } +} + uint32_t InputDispatcher::MotionEntry::countSamples() const { uint32_t count = 1; for (MotionSample* sample = firstSample.next; sample != NULL; sample = sample->next) { @@ -4176,6 +4073,31 @@ bool InputDispatcher::MotionEntry::canAppendSamples(int32_t action, uint32_t poi return true; } +void InputDispatcher::MotionEntry::appendSample( + nsecs_t eventTime, const PointerCoords* pointerCoords) { + MotionSample* sample = new MotionSample(eventTime, pointerCoords, pointerCount); + + lastSample->next = sample; + lastSample = sample; +} + + +// --- InputDispatcher::DispatchEntry --- + +InputDispatcher::DispatchEntry::DispatchEntry(EventEntry* eventEntry, + int32_t targetFlags, float xOffset, float yOffset, float scaleFactor) : + eventEntry(eventEntry), targetFlags(targetFlags), + xOffset(xOffset), yOffset(yOffset), scaleFactor(scaleFactor), + inProgress(false), + resolvedAction(0), resolvedFlags(0), + headMotionSample(NULL), tailMotionSample(NULL) { + eventEntry->refCount += 1; +} + +InputDispatcher::DispatchEntry::~DispatchEntry() { + eventEntry->release(); +} + // --- InputDispatcher::InputState --- @@ -4380,12 +4302,11 @@ void InputDispatcher::InputState::MotionMemento::setPointers(const MotionEntry* } void InputDispatcher::InputState::synthesizeCancelationEvents(nsecs_t currentTime, - Allocator* allocator, Vector<EventEntry*>& outEvents, - const CancelationOptions& options) { + Vector<EventEntry*>& outEvents, const CancelationOptions& options) { for (size_t i = 0; i < mKeyMementos.size(); i++) { const KeyMemento& memento = mKeyMementos.itemAt(i); if (shouldCancelKey(memento, options)) { - outEvents.push(allocator->obtainKeyEntry(currentTime, + outEvents.push(new KeyEntry(currentTime, memento.deviceId, memento.source, 0, AKEY_EVENT_ACTION_UP, memento.flags | AKEY_EVENT_FLAG_CANCELED, memento.keyCode, memento.scanCode, 0, 0, memento.downTime)); @@ -4395,7 +4316,7 @@ void InputDispatcher::InputState::synthesizeCancelationEvents(nsecs_t currentTim for (size_t i = 0; i < mMotionMementos.size(); i++) { const MotionMemento& memento = mMotionMementos.itemAt(i); if (shouldCancelMotion(memento, options)) { - outEvents.push(allocator->obtainMotionEntry(currentTime, + outEvents.push(new MotionEntry(currentTime, memento.deviceId, memento.source, 0, memento.hovering ? AMOTION_EVENT_ACTION_HOVER_EXIT @@ -4516,8 +4437,8 @@ const char* InputDispatcher::Connection::getStatusLabel() const { InputDispatcher::DispatchEntry* InputDispatcher::Connection::findQueuedDispatchEntryForEvent( const EventEntry* eventEntry) const { - for (DispatchEntry* dispatchEntry = outboundQueue.tailSentinel.prev; - dispatchEntry != & outboundQueue.headSentinel; dispatchEntry = dispatchEntry->prev) { + for (DispatchEntry* dispatchEntry = outboundQueue.tail; dispatchEntry; + dispatchEntry = dispatchEntry->prev) { if (dispatchEntry->eventEntry == eventEntry) { return dispatchEntry; } @@ -4528,8 +4449,8 @@ InputDispatcher::DispatchEntry* InputDispatcher::Connection::findQueuedDispatchE // --- InputDispatcher::CommandEntry --- -InputDispatcher::CommandEntry::CommandEntry() : - keyEntry(NULL) { +InputDispatcher::CommandEntry::CommandEntry(Command command) : + command(command), eventTime(0), keyEntry(NULL), userActivityEventType(0), handled(false) { } InputDispatcher::CommandEntry::~CommandEntry() { diff --git a/services/input/InputDispatcher.h b/services/input/InputDispatcher.h index 15fd274..1d39b2e 100644 --- a/services/input/InputDispatcher.h +++ b/services/input/InputDispatcher.h @@ -26,7 +26,6 @@ #include <utils/RefBase.h> #include <utils/String8.h> #include <utils/Looper.h> -#include <utils/Pool.h> #include <utils/BitSet.h> #include <stddef.h> @@ -434,11 +433,16 @@ private: int32_t injectionResult; // initially INPUT_EVENT_INJECTION_PENDING bool injectionIsAsync; // set to true if injection is not waiting for the result int32_t pendingForegroundDispatches; // the number of foreground dispatches in progress + + InjectionState(int32_t injectorPid, int32_t injectorUid); + void release(); + + private: + ~InjectionState(); }; struct EventEntry : Link<EventEntry> { enum { - TYPE_SENTINEL, TYPE_CONFIGURATION_CHANGED, TYPE_KEY, TYPE_MOTION @@ -453,9 +457,20 @@ private: bool dispatchInProgress; // initially false, set to true while dispatching inline bool isInjected() const { return injectionState != NULL; } + + void release(); + + protected: + EventEntry(int32_t type, nsecs_t eventTime, uint32_t policyFlags); + virtual ~EventEntry(); + void releaseInjectionState(); }; struct ConfigurationChangedEntry : EventEntry { + ConfigurationChangedEntry(nsecs_t eventTime); + + protected: + virtual ~ConfigurationChangedEntry(); }; struct KeyEntry : EventEntry { @@ -477,6 +492,15 @@ private: INTERCEPT_KEY_RESULT_CONTINUE, }; InterceptKeyResult interceptKeyResult; // set based on the interception result + + KeyEntry(nsecs_t eventTime, + int32_t deviceId, uint32_t source, uint32_t policyFlags, int32_t action, + int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState, + int32_t repeatCount, nsecs_t downTime); + void recycle(); + + protected: + virtual ~KeyEntry(); }; struct MotionSample { @@ -485,6 +509,9 @@ private: nsecs_t eventTime; // may be updated during coalescing nsecs_t eventTimeBeforeCoalescing; // not updated during coalescing PointerCoords pointerCoords[MAX_POINTERS]; + + MotionSample(nsecs_t eventTime, const PointerCoords* pointerCoords, + uint32_t pointerCount); }; struct MotionEntry : EventEntry { @@ -505,11 +532,23 @@ private: MotionSample firstSample; MotionSample* lastSample; + MotionEntry(nsecs_t eventTime, + int32_t deviceId, uint32_t source, uint32_t policyFlags, int32_t action, + int32_t flags, int32_t metaState, int32_t buttonState, int32_t edgeFlags, + float xPrecision, float yPrecision, + nsecs_t downTime, uint32_t pointerCount, + const PointerProperties* pointerProperties, const PointerCoords* pointerCoords); + uint32_t countSamples() const; // Checks whether we can append samples, assuming the device id and source are the same. bool canAppendSamples(int32_t action, uint32_t pointerCount, const PointerProperties* pointerProperties) const; + + void appendSample(nsecs_t eventTime, const PointerCoords* pointerCoords); + + protected: + virtual ~MotionEntry(); }; // Tracks the progress of dispatching a particular event to a particular connection. @@ -540,6 +579,10 @@ private: // will be set to NULL. MotionSample* tailMotionSample; + DispatchEntry(EventEntry* eventEntry, + int32_t targetFlags, float xOffset, float yOffset, float scaleFactor); + ~DispatchEntry(); + inline bool hasForegroundTarget() const { return targetFlags & InputTarget::FLAG_FOREGROUND; } @@ -570,7 +613,7 @@ private: class Connection; struct CommandEntry : Link<CommandEntry> { - CommandEntry(); + CommandEntry(Command command); ~CommandEntry(); Command command; @@ -588,99 +631,65 @@ private: // Generic queue implementation. template <typename T> struct Queue { - T headSentinel; - T tailSentinel; - - inline Queue() { - headSentinel.prev = NULL; - headSentinel.next = & tailSentinel; - tailSentinel.prev = & headSentinel; - tailSentinel.next = NULL; + T* head; + T* tail; + + inline Queue() : head(NULL), tail(NULL) { } inline bool isEmpty() const { - return headSentinel.next == & tailSentinel; + return !head; } inline void enqueueAtTail(T* entry) { - T* last = tailSentinel.prev; - last->next = entry; - entry->prev = last; - entry->next = & tailSentinel; - tailSentinel.prev = entry; + entry->prev = tail; + if (tail) { + tail->next = entry; + } else { + head = entry; + } + entry->next = NULL; + tail = entry; } inline void enqueueAtHead(T* entry) { - T* first = headSentinel.next; - headSentinel.next = entry; - entry->prev = & headSentinel; - entry->next = first; - first->prev = entry; + entry->next = head; + if (head) { + head->prev = entry; + } else { + tail = entry; + } + entry->prev = NULL; + head = entry; } inline void dequeue(T* entry) { - entry->prev->next = entry->next; - entry->next->prev = entry->prev; + if (entry->prev) { + entry->prev->next = entry->next; + } else { + head = entry->next; + } + if (entry->next) { + entry->next->prev = entry->prev; + } else { + tail = entry->prev; + } } inline T* dequeueAtHead() { - T* first = headSentinel.next; - dequeue(first); - return first; + T* entry = head; + head = entry->next; + if (head) { + head->prev = NULL; + } else { + tail = NULL; + } + return entry; } uint32_t count() const; }; - /* Allocates queue entries and performs reference counting as needed. */ - class Allocator { - public: - Allocator(); - - InjectionState* obtainInjectionState(int32_t injectorPid, int32_t injectorUid); - ConfigurationChangedEntry* obtainConfigurationChangedEntry(nsecs_t eventTime); - KeyEntry* obtainKeyEntry(nsecs_t eventTime, - int32_t deviceId, uint32_t source, uint32_t policyFlags, int32_t action, - int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState, - int32_t repeatCount, nsecs_t downTime); - MotionEntry* obtainMotionEntry(nsecs_t eventTime, - int32_t deviceId, uint32_t source, uint32_t policyFlags, int32_t action, - int32_t flags, int32_t metaState, int32_t buttonState, int32_t edgeFlags, - float xPrecision, float yPrecision, - nsecs_t downTime, uint32_t pointerCount, - const PointerProperties* pointerProperties, const PointerCoords* pointerCoords); - DispatchEntry* obtainDispatchEntry(EventEntry* eventEntry, - int32_t targetFlags, float xOffset, float yOffset, float scaleFactor); - CommandEntry* obtainCommandEntry(Command command); - - void releaseInjectionState(InjectionState* injectionState); - void releaseEventEntry(EventEntry* entry); - void releaseConfigurationChangedEntry(ConfigurationChangedEntry* entry); - void releaseKeyEntry(KeyEntry* entry); - void releaseMotionEntry(MotionEntry* entry); - void freeMotionSample(MotionSample* sample); - void releaseDispatchEntry(DispatchEntry* entry); - void releaseCommandEntry(CommandEntry* entry); - - void recycleKeyEntry(KeyEntry* entry); - - void appendMotionSample(MotionEntry* motionEntry, - nsecs_t eventTime, const PointerCoords* pointerCoords); - - private: - Pool<InjectionState> mInjectionStatePool; - Pool<ConfigurationChangedEntry> mConfigurationChangeEntryPool; - Pool<KeyEntry> mKeyEntryPool; - Pool<MotionEntry> mMotionEntryPool; - Pool<MotionSample> mMotionSamplePool; - Pool<DispatchEntry> mDispatchEntryPool; - Pool<CommandEntry> mCommandEntryPool; - - void initializeEventEntry(EventEntry* entry, int32_t type, nsecs_t eventTime, - uint32_t policyFlags); - void releaseEventEntryInjectionState(EventEntry* entry); - }; - /* Specifies which events are to be canceled and why. */ struct CancelationOptions { enum Mode { @@ -728,7 +737,7 @@ private: bool trackMotion(const MotionEntry* entry, int32_t action, int32_t flags); // Synthesizes cancelation events for the current state and resets the tracked state. - void synthesizeCancelationEvents(nsecs_t currentTime, Allocator* allocator, + void synthesizeCancelationEvents(nsecs_t currentTime, Vector<EventEntry*>& outEvents, const CancelationOptions& options); // Clears the current state. @@ -856,7 +865,6 @@ private: Mutex mLock; - Allocator mAllocator; sp<Looper> mLooper; EventEntry* mPendingEvent; diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java index 438883e..a679ca7 100644 --- a/services/java/com/android/server/AppWidgetService.java +++ b/services/java/com/android/server/AppWidgetService.java @@ -230,8 +230,14 @@ class AppWidgetService extends IAppWidgetService.Stub pw.println(':'); pw.print(" min=("); pw.print(info.minWidth); pw.print("x"); pw.print(info.minHeight); + pw.print(") minResize=("); pw.print(info.minResizeWidth); + pw.print("x"); pw.print(info.minResizeHeight); pw.print(") updatePeriodMillis="); pw.print(info.updatePeriodMillis); + pw.print(" resizeMode="); + pw.print(info.resizeMode); + pw.print(" autoAdvanceViewId="); + pw.print(info.autoAdvanceViewId); pw.print(" initialLayout=#"); pw.print(Integer.toHexString(info.initialLayout)); pw.print(" zombie="); pw.println(p.zombie); diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java index b78424b..79c0675 100644 --- a/services/java/com/android/server/ConnectivityService.java +++ b/services/java/com/android/server/ConnectivityService.java @@ -155,7 +155,9 @@ public class ConnectivityService extends IConnectivityManager.Stub { private boolean mInetConditionChangeInFlight = false; private int mDefaultConnectionSequence = 0; + private Object mDnsLock = new Object(); private int mNumDnsEntries; + private boolean mDnsOverridden = false; private boolean mTestMode; private static ConnectivityService sServiceInstance; @@ -244,6 +246,13 @@ public class ConnectivityService extends IConnectivityManager.Stub { private static final int EVENT_SET_DEPENDENCY_MET = MAX_NETWORK_STATE_TRACKER_EVENT + 10; + /** + * used internally to restore DNS properties back to the + * default network + */ + private static final int EVENT_RESTORE_DNS = + MAX_NETWORK_STATE_TRACKER_EVENT + 11; + private Handler mHandler; // list of DeathRecipients used to make sure features are turned off when @@ -1081,7 +1090,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { try { InetAddress addr = InetAddress.getByAddress(hostAddress); LinkProperties lp = tracker.getLinkProperties(); - return addRoute(lp, RouteInfo.makeHostRoute(addr)); + return addRouteToAddress(lp, addr); } catch (UnknownHostException e) {} return false; } @@ -1094,6 +1103,31 @@ public class ConnectivityService extends IConnectivityManager.Stub { return modifyRoute(p.getInterfaceName(), p, r, 0, false); } + private boolean addRouteToAddress(LinkProperties lp, InetAddress addr) { + return modifyRouteToAddress(lp, addr, true); + } + + private boolean removeRouteToAddress(LinkProperties lp, InetAddress addr) { + return modifyRouteToAddress(lp, addr, false); + } + + private boolean modifyRouteToAddress(LinkProperties lp, InetAddress addr, boolean doAdd) { + RouteInfo bestRoute = RouteInfo.selectBestRoute(lp.getRoutes(), addr); + if (bestRoute == null) { + bestRoute = RouteInfo.makeHostRoute(addr); + } else { + if (bestRoute.getGateway().equals(addr)) { + // if there is no better route, add the implied hostroute for our gateway + bestRoute = RouteInfo.makeHostRoute(addr); + } else { + // if we will connect to this through another route, add a direct route + // to it's gateway + bestRoute = RouteInfo.makeHostRoute(addr, bestRoute.getGateway()); + } + } + return modifyRoute(lp.getInterfaceName(), lp, bestRoute, 0, doAdd); + } + private boolean modifyRoute(String ifaceName, LinkProperties lp, RouteInfo r, int cycleCount, boolean doAdd) { if ((ifaceName == null) || (lp == null) || (r == null)) return false; @@ -1704,49 +1738,50 @@ public class ConnectivityService extends IConnectivityManager.Stub { */ private void updateRoutes(LinkProperties newLp, LinkProperties curLp, boolean isLinkDefault) { Collection<RouteInfo> routesToAdd = null; - CompareResult<InetAddress> dnsDiff = null; - + CompareResult<InetAddress> dnsDiff = new CompareResult<InetAddress>(); + CompareResult<RouteInfo> routeDiff = new CompareResult<RouteInfo>(); if (curLp != null) { // check for the delta between the current set and the new - CompareResult<RouteInfo> routeDiff = curLp.compareRoutes(newLp); + routeDiff = curLp.compareRoutes(newLp); dnsDiff = curLp.compareDnses(newLp); - - for (RouteInfo r : routeDiff.removed) { - if (isLinkDefault || ! r.isDefaultRoute()) { - removeRoute(curLp, r); - } - } - routesToAdd = routeDiff.added; + } else if (newLp != null) { + routeDiff.added = newLp.getRoutes(); + dnsDiff.added = newLp.getDnses(); } - if (newLp != null) { - // if we didn't get a diff from cur -> new, then just use the new - if (routesToAdd == null) { - routesToAdd = newLp.getRoutes(); + for (RouteInfo r : routeDiff.removed) { + if (isLinkDefault || ! r.isDefaultRoute()) { + removeRoute(curLp, r); } + } - for (RouteInfo r : routesToAdd) { - if (isLinkDefault || ! r.isDefaultRoute()) { - addRoute(newLp, r); - } + for (RouteInfo r : routeDiff.added) { + if (isLinkDefault || ! r.isDefaultRoute()) { + addRoute(newLp, r); } } if (!isLinkDefault) { // handle DNS routes - Collection<InetAddress> dnsToAdd = null; - if (dnsDiff != null) { - dnsToAdd = dnsDiff.added; - for (InetAddress dnsAddress : dnsDiff.removed) { - removeRoute(curLp, RouteInfo.makeHostRoute(dnsAddress)); + if (routeDiff.removed.size() == 0 && routeDiff.added.size() == 0) { + // no change in routes, check for change in dns themselves + for (InetAddress oldDns : dnsDiff.removed) { + removeRouteToAddress(curLp, oldDns); } - } - if (newLp != null) { - if (dnsToAdd == null) { - dnsToAdd = newLp.getDnses(); + for (InetAddress newDns : dnsDiff.added) { + addRouteToAddress(newLp, newDns); } - for(InetAddress dnsAddress : dnsToAdd) { - addRoute(newLp, RouteInfo.makeHostRoute(dnsAddress)); + } else { + // routes changed - remove all old dns entries and add new + if (curLp != null) { + for (InetAddress oldDns : curLp.getDnses()) { + removeRouteToAddress(curLp, oldDns); + } + } + if (newLp != null) { + for (InetAddress newDns : newLp.getDnses()) { + addRouteToAddress(newLp, newDns); + } } } } @@ -1890,6 +1925,50 @@ public class ConnectivityService extends IConnectivityManager.Stub { mContext.sendBroadcast(intent); } + // Caller must grab mDnsLock. + private boolean updateDns(String network, Collection<InetAddress> dnses, String domains) { + boolean changed = false; + int last = 0; + if (dnses.size() == 0 && mDefaultDns != null) { + ++last; + String value = mDefaultDns.getHostAddress(); + if (!value.equals(SystemProperties.get("net.dns1"))) { + if (DBG) { + log("no dns provided for " + network + " - using " + value); + } + changed = true; + SystemProperties.set("net.dns1", value); + } + } else { + for (InetAddress dns : dnses) { + ++last; + String key = "net.dns" + last; + String value = dns.getHostAddress(); + if (!changed && value.equals(SystemProperties.get(key))) { + continue; + } + if (DBG) { + log("adding dns " + value + " for " + network); + } + changed = true; + SystemProperties.set(key, value); + } + } + for (int i = last + 1; i <= mNumDnsEntries; ++i) { + String key = "net.dns" + i; + if (DBG) log("erasing " + key); + changed = true; + SystemProperties.set(key, ""); + } + mNumDnsEntries = last; + + if (!domains.equals(SystemProperties.get("net.dns.search"))) { + SystemProperties.set("net.dns.search", domains); + changed = true; + } + return changed; + } + private void handleDnsConfigurationChange(int netType) { // add default net's dns entries NetworkStateTracker nt = mNetTrackers[netType]; @@ -1899,40 +1978,12 @@ public class ConnectivityService extends IConnectivityManager.Stub { Collection<InetAddress> dnses = p.getDnses(); boolean changed = false; if (mNetConfigs[netType].isDefault()) { - int j = 1; - if (dnses.size() == 0 && mDefaultDns != null) { - String dnsString = mDefaultDns.getHostAddress(); - if (!dnsString.equals(SystemProperties.get("net.dns1"))) { - if (DBG) { - log("no dns provided - using " + dnsString); - } - changed = true; - SystemProperties.set("net.dns1", dnsString); - } - j++; - } else { - for (InetAddress dns : dnses) { - String dnsString = dns.getHostAddress(); - if (!changed && dnsString.equals(SystemProperties.get("net.dns" + j))) { - j++; - continue; - } - if (DBG) { - log("adding dns " + dns + " for " + - nt.getNetworkInfo().getTypeName()); - } - changed = true; - SystemProperties.set("net.dns" + j++, dnsString); - } - } - for (int k=j ; k<mNumDnsEntries; k++) { - if (changed || !TextUtils.isEmpty(SystemProperties.get("net.dns" + k))) { - if (DBG) log("erasing net.dns" + k); - changed = true; - SystemProperties.set("net.dns" + k, ""); + String network = nt.getNetworkInfo().getTypeName(); + synchronized (mDnsLock) { + if (!mDnsOverridden) { + changed = updateDns(network, dnses, ""); } } - mNumDnsEntries = j; } else { // set per-pid dns for attached secondary nets List pids = mNetRequestersPids[netType]; @@ -2139,6 +2190,13 @@ public class ConnectivityService extends IConnectivityManager.Stub { handleSetDependencyMet(msg.arg2, met); break; } + case EVENT_RESTORE_DNS: + { + if (mActiveDefaultNetwork != -1) { + handleDnsConfigurationChange(mActiveDefaultNetwork); + } + break; + } } } } @@ -2204,6 +2262,15 @@ public class ConnectivityService extends IConnectivityManager.Stub { } } + public int setUsbTethering(boolean enable) { + enforceTetherAccessPermission(); + if (isTetheringSupported()) { + return mTethering.setUsbTethering(enable); + } else { + return ConnectivityManager.TETHER_ERROR_UNSUPPORTED; + } + } + // TODO - move iface listing, queries, etc to new module // javadoc from interface public String[] getTetherableIfaces() { @@ -2586,12 +2653,57 @@ public class ConnectivityService extends IConnectivityManager.Stub { private VpnCallback() { } - public synchronized void override(List<String> dnsServers, List<String> searchDomains) { - // TODO: override DNS servers and http proxy. + public void override(List<String> dnsServers, List<String> searchDomains) { + if (dnsServers == null) { + restore(); + return; + } + + // Convert DNS servers into addresses. + List<InetAddress> addresses = new ArrayList<InetAddress>(); + for (String address : dnsServers) { + // Double check the addresses and remove invalid ones. + try { + addresses.add(InetAddress.parseNumericAddress(address)); + } catch (Exception e) { + // ignore + } + } + if (addresses.isEmpty()) { + restore(); + return; + } + + // Concatenate search domains into a string. + StringBuilder buffer = new StringBuilder(); + if (searchDomains != null) { + for (String domain : searchDomains) { + buffer.append(domain).append(' '); + } + } + String domains = buffer.toString().trim(); + + // Apply DNS changes. + boolean changed = false; + synchronized (mDnsLock) { + changed = updateDns("VPN", addresses, domains); + mDnsOverridden = true; + } + if (changed) { + bumpDns(); + } + + // TODO: temporarily remove http proxy? } - public synchronized void restore() { - // TODO: restore VPN changes. + public void restore() { + synchronized (mDnsLock) { + if (!mDnsOverridden) { + return; + } + mDnsOverridden = false; + } + mHandler.sendEmptyMessage(EVENT_RESTORE_DNS); } } } diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java index 2597978..73d790a 100644 --- a/services/java/com/android/server/InputMethodManagerService.java +++ b/services/java/com/android/server/InputMethodManagerService.java @@ -50,6 +50,7 @@ import android.content.ServiceConnection; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.content.res.Configuration; @@ -165,7 +166,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub private final KeyguardManager mKeyguardManager; private final Notification mImeSwitcherNotification; private final PendingIntent mImeSwitchPendingIntent; - private final boolean mShowOngoingImeSwitcherForPhones; + private boolean mShowOngoingImeSwitcherForPhones; private boolean mNotificationShown; class SessionState { @@ -537,8 +538,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mImeSwitcherNotification.vibrate = null; Intent intent = new Intent(Settings.ACTION_SHOW_INPUT_METHOD_PICKER); mImeSwitchPendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0); - mShowOngoingImeSwitcherForPhones = mRes.getBoolean( - com.android.internal.R.bool.show_ongoing_ime_switcher); + + mShowOngoingImeSwitcherForPhones = false; synchronized (mMethodMap) { mFileManager = new InputMethodFileManager(mMethodMap); @@ -611,6 +612,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub synchronized (mMethodMap) { if (!mSystemReady) { mSystemReady = true; + mShowOngoingImeSwitcherForPhones = mRes.getBoolean( + com.android.internal.R.bool.show_ongoing_ime_switcher); try { startInputInnerLocked(); } catch (RuntimeException e) { @@ -1046,7 +1049,16 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mStatusBar.setIconVisibility("ime", false); } else if (packageName != null) { if (DEBUG) Slog.d(TAG, "show a small icon for the input method"); - mStatusBar.setIcon("ime", packageName, iconId, 0); + CharSequence contentDescription = null; + try { + PackageManager packageManager = mContext.getPackageManager(); + contentDescription = packageManager.getApplicationLabel( + packageManager.getApplicationInfo(packageName, 0)); + } catch (NameNotFoundException nnfe) { + /* ignore */ + } + mStatusBar.setIcon("ime", packageName, iconId, 0, + contentDescription != null ? contentDescription.toString() : null); mStatusBar.setIconVisibility("ime", true); } } @@ -1115,13 +1127,21 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mBackDisposition = backDisposition; mStatusBar.setImeWindowStatus(token, vis, backDisposition); final boolean iconVisibility = (vis & InputMethodService.IME_ACTIVE) != 0; - if (iconVisibility && needsToShowImeSwitchOngoingNotification()) { + final InputMethodInfo imi = mMethodMap.get(mCurMethodId); + if (imi != null && iconVisibility && needsToShowImeSwitchOngoingNotification()) { final PackageManager pm = mContext.getPackageManager(); - final CharSequence label = mMethodMap.get(mCurMethodId).loadLabel(pm); final CharSequence title = mRes.getText( com.android.internal.R.string.select_input_method); + final CharSequence imiLabel = imi.loadLabel(pm); + final CharSequence summary = mCurrentSubtype != null + ? TextUtils.concat(mCurrentSubtype.getDisplayName(mContext, + imi.getPackageName(), imi.getServiceInfo().applicationInfo), + (TextUtils.isEmpty(imiLabel) ? + "" : " (" + imiLabel + ")")) + : imiLabel; + mImeSwitcherNotification.setLatestEventInfo( - mContext, title, label, mImeSwitchPendingIntent); + mContext, title, summary, mImeSwitchPendingIntent); mNotificationManager.notify( com.android.internal.R.string.select_input_method, mImeSwitcherNotification); diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java index 41e8a31..17ad268 100644 --- a/services/java/com/android/server/NetworkManagementService.java +++ b/services/java/com/android/server/NetworkManagementService.java @@ -93,6 +93,7 @@ class NetworkManagementService extends INetworkManagementService.Stub { private static final String KEY_TX = "tx_bytes"; class NetdResponseCode { + /* Keep in sync with system/netd/ResponseCode.h */ public static final int InterfaceListResult = 110; public static final int TetherInterfaceListResult = 111; public static final int TetherDnsFwdTgtListResult = 112; @@ -108,6 +109,7 @@ class NetworkManagementService extends INetworkManagementService.Stub { public static final int InterfaceTxThrottleResult = 219; public static final int InterfaceChange = 600; + public static final int BandwidthControl = 601; } /** @@ -265,6 +267,20 @@ class NetworkManagementService extends INetworkManagementService.Stub { } /** + * Notify our observers of a limit reached. + */ + private void notifyLimitReached(String limitName, String iface) { + for (INetworkManagementEventObserver obs : mObservers) { + try { + obs.limitReached(limitName, iface); + Slog.d(TAG, "Observer notified limit reached for " + limitName + " " + iface); + } catch (Exception ex) { + Slog.w(TAG, "Observer notifier failed", ex); + } + } + } + + /** * Let us know the daemon is connected */ protected void onConnected() { @@ -286,33 +302,52 @@ class NetworkManagementService extends INetworkManagementService.Stub { }.start(); } public boolean onEvent(int code, String raw, String[] cooked) { - if (code == NetdResponseCode.InterfaceChange) { - /* - * a network interface change occured - * Format: "NNN Iface added <name>" - * "NNN Iface removed <name>" - * "NNN Iface changed <name> <up/down>" - * "NNN Iface linkstatus <name> <up/down>" - */ - if (cooked.length < 4 || !cooked[1].equals("Iface")) { + switch (code) { + case NetdResponseCode.InterfaceChange: + /* + * a network interface change occured + * Format: "NNN Iface added <name>" + * "NNN Iface removed <name>" + * "NNN Iface changed <name> <up/down>" + * "NNN Iface linkstatus <name> <up/down>" + */ + if (cooked.length < 4 || !cooked[1].equals("Iface")) { + throw new IllegalStateException( + String.format("Invalid event from daemon (%s)", raw)); + } + if (cooked[2].equals("added")) { + notifyInterfaceAdded(cooked[3]); + return true; + } else if (cooked[2].equals("removed")) { + notifyInterfaceRemoved(cooked[3]); + return true; + } else if (cooked[2].equals("changed") && cooked.length == 5) { + notifyInterfaceStatusChanged(cooked[3], cooked[4].equals("up")); + return true; + } else if (cooked[2].equals("linkstate") && cooked.length == 5) { + notifyInterfaceLinkStateChanged(cooked[3], cooked[4].equals("up")); + return true; + } throw new IllegalStateException( String.format("Invalid event from daemon (%s)", raw)); - } - if (cooked[2].equals("added")) { - notifyInterfaceAdded(cooked[3]); - return true; - } else if (cooked[2].equals("removed")) { - notifyInterfaceRemoved(cooked[3]); - return true; - } else if (cooked[2].equals("changed") && cooked.length == 5) { - notifyInterfaceStatusChanged(cooked[3], cooked[4].equals("up")); - return true; - } else if (cooked[2].equals("linkstate") && cooked.length == 5) { - notifyInterfaceLinkStateChanged(cooked[3], cooked[4].equals("up")); - return true; - } - throw new IllegalStateException( - String.format("Invalid event from daemon (%s)", raw)); + // break; + case NetdResponseCode.BandwidthControl: + /* + * Bandwidth control needs some attention + * Format: "NNN limit alert <alertName> <ifaceName>" + */ + if (cooked.length < 5 || !cooked[1].equals("limit")) { + throw new IllegalStateException( + String.format("Invalid event from daemon (%s)", raw)); + } + if (cooked[2].equals("alert")) { + notifyLimitReached(cooked[3], cooked[4]); + return true; + } + throw new IllegalStateException( + String.format("Invalid event from daemon (%s)", raw)); + // break; + default: break; } return false; } @@ -814,7 +849,6 @@ class NetworkManagementService extends INetworkManagementService.Stub { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.CHANGE_WIFI_STATE, "NetworkManagementService"); try { - mConnector.doCommand(String.format("softap stop " + wlanIface)); mConnector.doCommand(String.format("softap fwreload " + wlanIface + " AP")); mConnector.doCommand(String.format("softap start " + wlanIface)); if (wifiConfig == null) { @@ -862,13 +896,15 @@ class NetworkManagementService extends INetworkManagementService.Stub { } } - public void stopAccessPoint() throws IllegalStateException { + public void stopAccessPoint(String wlanIface) throws IllegalStateException { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); mContext.enforceCallingOrSelfPermission( android.Manifest.permission.CHANGE_WIFI_STATE, "NetworkManagementService"); try { mConnector.doCommand("softap stopap"); + mConnector.doCommand("softap stop " + wlanIface); + mConnector.doCommand(String.format("softap fwreload " + wlanIface + " STA")); } catch (NativeDaemonConnectorException e) { throw new IllegalStateException("Error communicating to native daemon to stop soft AP", e); diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java index 4ecdfed..5d7a48f 100755 --- a/services/java/com/android/server/NotificationManagerService.java +++ b/services/java/com/android/server/NotificationManagerService.java @@ -262,7 +262,7 @@ public class NotificationManagerService extends INotificationManager.Stub public void onNotificationClick(String pkg, String tag, int id) { cancelNotification(pkg, tag, id, Notification.FLAG_AUTO_CANCEL, - Notification.FLAG_FOREGROUND_SERVICE, true); + Notification.FLAG_FOREGROUND_SERVICE, false); } public void onNotificationClear(String pkg, String tag, int id) { diff --git a/services/java/com/android/server/StatusBarManagerService.java b/services/java/com/android/server/StatusBarManagerService.java index 286a937..4ced83c 100644 --- a/services/java/com/android/server/StatusBarManagerService.java +++ b/services/java/com/android/server/StatusBarManagerService.java @@ -22,10 +22,10 @@ import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.res.Resources; -import android.os.IBinder; -import android.os.RemoteException; import android.os.Binder; import android.os.Handler; +import android.os.IBinder; +import android.os.RemoteException; import android.util.Slog; import android.view.View; @@ -175,7 +175,8 @@ public class StatusBarManagerService extends IStatusBarService.Stub } } - public void setIcon(String slot, String iconPackage, int iconId, int iconLevel) { + public void setIcon(String slot, String iconPackage, int iconId, int iconLevel, + String contentDescription) { enforceStatusBar(); synchronized (mIcons) { @@ -184,7 +185,8 @@ public class StatusBarManagerService extends IStatusBarService.Stub throw new SecurityException("invalid status bar icon slot: " + slot); } - StatusBarIcon icon = new StatusBarIcon(iconPackage, iconId, iconLevel); + StatusBarIcon icon = new StatusBarIcon(iconPackage, iconId, iconLevel, 0, + contentDescription); //Slog.d(TAG, "setIcon slot=" + slot + " index=" + index + " icon=" + icon); mIcons.setIcon(index, icon); diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 8c7e279..f15eca6 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -37,6 +37,7 @@ import android.provider.Settings; import android.server.BluetoothA2dpService; import android.server.BluetoothService; import android.server.search.SearchManagerService; +import android.server.WifiP2pService; import android.util.DisplayMetrics; import android.util.EventLog; import android.util.Slog; @@ -108,6 +109,7 @@ class ServerThread extends Thread { NetworkStatsService networkStats = null; NetworkPolicyManagerService networkPolicy = null; ConnectivityService connectivity = null; + WifiP2pService wifiP2p = null; IPackageManager pm = null; Context context = null; WindowManagerService wm = null; @@ -230,6 +232,7 @@ class ServerThread extends Thread { WallpaperManagerService wallpaper = null; LocationManagerService location = null; CountryDetectorService countryDetector = null; + TextServicesManagerService tsms = null; if (factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) { try { @@ -273,6 +276,14 @@ class ServerThread extends Thread { } try { + Slog.i(TAG, "Text Service Manager Service"); + tsms = new TextServicesManagerService(context); + ServiceManager.addService(Context.TEXT_SERVICES_MANAGER_SERVICE, tsms); + } catch (Throwable e) { + Slog.e(TAG, "Failure starting Text Service Manager Service", e); + } + + try { Slog.i(TAG, "NetworkStats Service"); networkStats = new NetworkStatsService(context, networkManagement, alarm); ServiceManager.addService(Context.NETWORK_STATS_SERVICE, networkStats); @@ -290,6 +301,14 @@ class ServerThread extends Thread { Slog.e(TAG, "Failure starting NetworkPolicy Service", e); } + try { + Slog.i(TAG, "Wi-Fi P2pService"); + wifiP2p = new WifiP2pService(context); + ServiceManager.addService(Context.WIFI_P2P_SERVICE, wifiP2p); + } catch (Throwable e) { + Slog.e(TAG, "Failure starting Wi-Fi P2pService", e); + } + try { Slog.i(TAG, "Connectivity Service"); connectivity = new ConnectivityService(context, networkManagement, networkPolicy); @@ -538,6 +557,7 @@ class ServerThread extends Thread { final LocationManagerService locationF = location; final CountryDetectorService countryDetectorF = countryDetector; final NetworkTimeUpdateService networkTimeUpdaterF = networkTimeUpdater; + final TextServicesManagerService textServiceManagerServiceF = tsms; // We now tell the activity manager it is okay to run third party // code. It will call back into us once it has gotten to the state @@ -571,6 +591,7 @@ class ServerThread extends Thread { if (countryDetectorF != null) countryDetectorF.systemReady(); if (throttleF != null) throttleF.systemReady(); if (networkTimeUpdaterF != null) networkTimeUpdaterF.systemReady(); + if (textServiceManagerServiceF != null) textServiceManagerServiceF.systemReady(); } }); diff --git a/services/java/com/android/server/TextServicesManagerService.java b/services/java/com/android/server/TextServicesManagerService.java new file mode 100644 index 0000000..4a0c837 --- /dev/null +++ b/services/java/com/android/server/TextServicesManagerService.java @@ -0,0 +1,346 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server; + +import com.android.internal.content.PackageMonitor; +import com.android.internal.textservice.ISpellCheckerService; +import com.android.internal.textservice.ISpellCheckerSession; +import com.android.internal.textservice.ISpellCheckerSessionListener; +import com.android.internal.textservice.ITextServicesManager; +import com.android.internal.textservice.ITextServicesSessionListener; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.content.pm.ServiceInfo; +import android.os.IBinder; +import android.os.RemoteException; +import android.os.SystemClock; +import android.provider.Settings; +import android.text.TextUtils; +import android.service.textservice.SpellCheckerService; +import android.util.Log; +import android.util.Slog; +import android.view.textservice.SpellCheckerInfo; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; + +public class TextServicesManagerService extends ITextServicesManager.Stub { + private static final String TAG = TextServicesManagerService.class.getSimpleName(); + private static final boolean DBG = false; + + private final Context mContext; + private boolean mSystemReady; + private final TextServicesMonitor mMonitor; + private final HashMap<String, SpellCheckerInfo> mSpellCheckerMap = + new HashMap<String, SpellCheckerInfo>(); + private final ArrayList<SpellCheckerInfo> mSpellCheckerList = new ArrayList<SpellCheckerInfo>(); + private final HashMap<String, SpellCheckerBindGroup> mSpellCheckerBindGroups = + new HashMap<String, SpellCheckerBindGroup>(); + + public void systemReady() { + if (!mSystemReady) { + mSystemReady = true; + } + } + + public TextServicesManagerService(Context context) { + mSystemReady = false; + mContext = context; + mMonitor = new TextServicesMonitor(); + mMonitor.register(context, true); + synchronized (mSpellCheckerMap) { + buildSpellCheckerMapLocked(context, mSpellCheckerList, mSpellCheckerMap); + } + } + + private class TextServicesMonitor extends PackageMonitor { + @Override + public void onSomePackagesChanged() { + synchronized (mSpellCheckerMap) { + buildSpellCheckerMapLocked(mContext, mSpellCheckerList, mSpellCheckerMap); + // TODO: Update for each locale + SpellCheckerInfo sci = getCurrentSpellChecker(null); + if (sci == null) { + sci = findAvailSpellCheckerLocked(null, null); + if (sci == null) return; + // Set the current spell checker if there is one or more spell checkers + // available. In this case, "sci" is the first one in the available spell + // checkers. + setCurrentSpellChecker(sci); + } + final String packageName = sci.getPackageName(); + final int change = isPackageDisappearing(packageName); + if (change == PACKAGE_PERMANENT_CHANGE || change == PACKAGE_TEMPORARY_CHANGE) { + // Package disappearing + setCurrentSpellChecker(findAvailSpellCheckerLocked(null, packageName)); + } else if (isPackageModified(packageName)) { + // Package modified + setCurrentSpellChecker(findAvailSpellCheckerLocked(null, packageName)); + } + } + } + } + + private static void buildSpellCheckerMapLocked(Context context, + ArrayList<SpellCheckerInfo> list, HashMap<String, SpellCheckerInfo> map) { + list.clear(); + map.clear(); + final PackageManager pm = context.getPackageManager(); + List<ResolveInfo> services = pm.queryIntentServices( + new Intent(SpellCheckerService.SERVICE_INTERFACE), PackageManager.GET_META_DATA); + final int N = services.size(); + for (int i = 0; i < N; ++i) { + final ResolveInfo ri = services.get(i); + final ServiceInfo si = ri.serviceInfo; + final ComponentName compName = new ComponentName(si.packageName, si.name); + if (!android.Manifest.permission.BIND_TEXT_SERVICE.equals(si.permission)) { + Slog.w(TAG, "Skipping text service " + compName + + ": it does not require the permission " + + android.Manifest.permission.BIND_TEXT_SERVICE); + continue; + } + if (DBG) Slog.d(TAG, "Add: " + compName); + final SpellCheckerInfo sci = new SpellCheckerInfo(context, ri); + list.add(sci); + map.put(sci.getId(), sci); + } + } + + // TODO: find an appropriate spell checker for specified locale + private SpellCheckerInfo findAvailSpellCheckerLocked(String locale, String prefPackage) { + final int spellCheckersCount = mSpellCheckerList.size(); + if (spellCheckersCount == 0) { + Slog.w(TAG, "no available spell checker services found"); + return null; + } + if (prefPackage != null) { + for (int i = 0; i < spellCheckersCount; ++i) { + final SpellCheckerInfo sci = mSpellCheckerList.get(i); + if (prefPackage.equals(sci.getPackageName())) { + return sci; + } + } + } + if (spellCheckersCount > 1) { + Slog.w(TAG, "more than one spell checker service found, picking first"); + } + return mSpellCheckerList.get(0); + } + + // TODO: Save SpellCheckerService by supported languages. Currently only one spell + // checker is saved. + @Override + public SpellCheckerInfo getCurrentSpellChecker(String locale) { + synchronized (mSpellCheckerMap) { + final String curSpellCheckerId = + Settings.Secure.getString(mContext.getContentResolver(), + Settings.Secure.SPELL_CHECKER_SERVICE); + if (TextUtils.isEmpty(curSpellCheckerId)) { + return null; + } + return mSpellCheckerMap.get(curSpellCheckerId); + } + } + + @Override + public void getSpellCheckerService(SpellCheckerInfo info, String locale, + ITextServicesSessionListener tsListener, ISpellCheckerSessionListener scListener) { + if (!mSystemReady) { + return; + } + if (info == null || tsListener == null) { + Slog.e(TAG, "getSpellCheckerService: Invalid input."); + return; + } + final String sciId = info.getId(); + synchronized(mSpellCheckerMap) { + if (!mSpellCheckerMap.containsKey(sciId)) { + return; + } + if (mSpellCheckerBindGroups.containsKey(sciId)) { + mSpellCheckerBindGroups.get(sciId).addListener(tsListener, locale, scListener); + return; + } + final InternalServiceConnection connection = new InternalServiceConnection( + sciId, locale, scListener); + final Intent serviceIntent = new Intent(SpellCheckerService.SERVICE_INTERFACE); + serviceIntent.setComponent(info.getComponent()); + if (!mContext.bindService(serviceIntent, connection, Context.BIND_AUTO_CREATE)) { + Slog.e(TAG, "Failed to get a spell checker service."); + return; + } + final SpellCheckerBindGroup group = new SpellCheckerBindGroup( + connection, tsListener, locale, scListener); + mSpellCheckerBindGroups.put(sciId, group); + } + return; + } + + @Override + public void finishSpellCheckerService(ISpellCheckerSessionListener listener) { + synchronized(mSpellCheckerMap) { + for (SpellCheckerBindGroup group : mSpellCheckerBindGroups.values()) { + if (group == null) continue; + group.removeListener(listener); + } + } + } + + private void setCurrentSpellChecker(SpellCheckerInfo sci) { + if (sci == null || mSpellCheckerMap.containsKey(sci.getId())) return; + Settings.Secure.putString(mContext.getContentResolver(), + Settings.Secure.SPELL_CHECKER_SERVICE, sci == null ? "" : sci.getId()); + } + + // SpellCheckerBindGroup contains active text service session listeners. + // If there are no listeners anymore, the SpellCheckerBindGroup instance will be removed from + // mSpellCheckerBindGroups + private class SpellCheckerBindGroup { + final InternalServiceConnection mInternalConnection; + final ArrayList<InternalDeathRecipient> mListeners = + new ArrayList<InternalDeathRecipient>(); + + public SpellCheckerBindGroup(InternalServiceConnection connection, + ITextServicesSessionListener listener, String locale, + ISpellCheckerSessionListener scListener) { + mInternalConnection = connection; + addListener(listener, locale, scListener); + } + + public void onServiceConnected(ISpellCheckerService spellChecker) { + synchronized(mSpellCheckerMap) { + for (InternalDeathRecipient listener : mListeners) { + try { + final ISpellCheckerSession session = spellChecker.getISpellCheckerSession( + listener.mScLocale, listener.mScListener); + listener.mTsListener.onServiceConnected(session); + } catch (RemoteException e) { + } + } + } + } + + public void addListener(ITextServicesSessionListener tsListener, String locale, + ISpellCheckerSessionListener scListener) { + synchronized(mSpellCheckerMap) { + try { + final int size = mListeners.size(); + for (int i = 0; i < size; ++i) { + if (mListeners.get(i).hasSpellCheckerListener(scListener)) { + // do not add the lister if the group already contains this. + return; + } + } + final InternalDeathRecipient recipient = new InternalDeathRecipient( + this, tsListener, locale, scListener); + scListener.asBinder().linkToDeath(recipient, 0); + mListeners.add(new InternalDeathRecipient( + this, tsListener, locale, scListener)); + } catch(RemoteException e) { + // do nothing + } + cleanLocked(); + } + } + + public void removeListener(ISpellCheckerSessionListener listener) { + synchronized(mSpellCheckerMap) { + final int size = mListeners.size(); + final ArrayList<InternalDeathRecipient> removeList = + new ArrayList<InternalDeathRecipient>(); + for (int i = 0; i < size; ++i) { + final InternalDeathRecipient tempRecipient = mListeners.get(i); + if(tempRecipient.hasSpellCheckerListener(listener)) { + removeList.add(tempRecipient); + } + } + final int removeSize = removeList.size(); + for (int i = 0; i < removeSize; ++i) { + mListeners.remove(removeList.get(i)); + } + cleanLocked(); + } + } + + private void cleanLocked() { + if (mListeners.isEmpty()) { + mSpellCheckerBindGroups.remove(this); + // Unbind service when there is no active clients. + mContext.unbindService(mInternalConnection); + } + } + } + + private class InternalServiceConnection implements ServiceConnection { + private final ISpellCheckerSessionListener mListener; + private final String mSciId; + private final String mLocale; + public InternalServiceConnection( + String id, String locale, ISpellCheckerSessionListener listener) { + mSciId = id; + mLocale = locale; + mListener = listener; + } + + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + synchronized(mSpellCheckerMap) { + ISpellCheckerService spellChecker = ISpellCheckerService.Stub.asInterface(service); + final SpellCheckerBindGroup group = mSpellCheckerBindGroups.get(mSciId); + if (group != null) { + group.onServiceConnected(spellChecker); + } + } + } + + @Override + public void onServiceDisconnected(ComponentName name) { + mSpellCheckerBindGroups.remove(mSciId); + } + } + + private class InternalDeathRecipient implements IBinder.DeathRecipient { + public final ITextServicesSessionListener mTsListener; + public final ISpellCheckerSessionListener mScListener; + public final String mScLocale; + private final SpellCheckerBindGroup mGroup; + public InternalDeathRecipient(SpellCheckerBindGroup group, + ITextServicesSessionListener tsListener, String scLocale, + ISpellCheckerSessionListener scListener) { + mTsListener = tsListener; + mScListener = scListener; + mScLocale = scLocale; + mGroup = group; + } + + public boolean hasSpellCheckerListener(ISpellCheckerSessionListener listener) { + return mScListener.equals(listener); + } + + @Override + public void binderDied() { + mGroup.removeListener(mScListener); + } + } +} diff --git a/services/java/com/android/server/ThrottleService.java b/services/java/com/android/server/ThrottleService.java index b8890aa..cd649ce 100644 --- a/services/java/com/android/server/ThrottleService.java +++ b/services/java/com/android/server/ThrottleService.java @@ -194,6 +194,7 @@ public class ThrottleService extends IThrottleManager.Stub { } public void interfaceRemoved(String iface) {} + public void limitReached(String limitName, String iface) {} } diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java index 7112553..f9f63b1 100644 --- a/services/java/com/android/server/WifiService.java +++ b/services/java/com/android/server/WifiService.java @@ -1461,7 +1461,7 @@ public class WifiService extends IWifiManager.Stub { if (mMulticasters.size() != 0) { return; } else { - mWifiStateMachine.startPacketFiltering(); + mWifiStateMachine.startFilteringMulticastV4Packets(); } } } @@ -1472,11 +1472,11 @@ public class WifiService extends IWifiManager.Stub { synchronized (mMulticasters) { mMulticastEnabled++; mMulticasters.add(new Multicaster(tag, binder)); - // Note that we could call stopPacketFiltering only when + // Note that we could call stopFilteringMulticastV4Packets only when // our new size == 1 (first call), but this function won't // be called often and by making the stopPacket call each // time we're less fragile and self-healing. - mWifiStateMachine.stopPacketFiltering(); + mWifiStateMachine.stopFilteringMulticastV4Packets(); } int uid = Binder.getCallingUid(); @@ -1513,7 +1513,7 @@ public class WifiService extends IWifiManager.Stub { removed.unlinkDeathRecipient(); } if (mMulticasters.size() == 0) { - mWifiStateMachine.startPacketFiltering(); + mWifiStateMachine.startFilteringMulticastV4Packets(); } Long ident = Binder.clearCallingIdentity(); diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 0924b86..3389f33 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -3628,6 +3628,7 @@ public final class ActivityManagerService extends ActivityManagerNative app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE; app.forcingToForeground = null; app.foregroundServices = false; + app.hasShownUi = false; app.debugging = false; mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app); @@ -9218,6 +9219,7 @@ public final class ActivityManagerService extends ActivityManagerNative app.forcingToForeground = null; app.foregroundServices = false; app.foregroundActivities = false; + app.hasShownUi = false; killServicesLocked(app, true); @@ -9331,8 +9333,6 @@ public final class ActivityManagerService extends ActivityManagerNative // This app is persistent, so we need to keep its record around. // If it is not already on the pending app list, add it there // and start a new process for it. - app.forcingToForeground = null; - app.foregroundServices = false; if (mPersistentStartingProcesses.indexOf(app) < 0) { mPersistentStartingProcesses.add(app); restart = true; @@ -12728,21 +12728,31 @@ public final class ActivityManagerService extends ActivityManagerNative while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) { ServiceRecord s = jt.next(); if (s.startRequested) { - if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) { - // This service has seen some activity within - // recent memory, so we will keep its process ahead - // of the background processes. + if (app.hasShownUi) { + // If this process has shown some UI, let it immediately + // go to the LRU list because it may be pretty heavy with + // UI stuff. We'll tag it with a label just to help + // debug and understand what is going on. if (adj > SECONDARY_SERVER_ADJ) { - adj = SECONDARY_SERVER_ADJ; - app.adjType = "started-services"; - app.hidden = false; + app.adjType = "started-bg-ui-services"; + } + } else { + if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) { + // This service has seen some activity within + // recent memory, so we will keep its process ahead + // of the background processes. + if (adj > SECONDARY_SERVER_ADJ) { + adj = SECONDARY_SERVER_ADJ; + app.adjType = "started-services"; + app.hidden = false; + } + } + // If we have let the service slide into the background + // state, still have some text describing what it is doing + // even though the service no longer has an impact. + if (adj > SECONDARY_SERVER_ADJ) { + app.adjType = "started-bg-services"; } - } - // If we have let the service slide into the background - // state, still have some text describing what it is doing - // even though the service no longer has an impact. - if (adj > SECONDARY_SERVER_ADJ) { - app.adjType = "started-bg-services"; } // Don't kill this process because it is doing work; it // has said it is doing work. @@ -13351,15 +13361,15 @@ public final class ActivityManagerService extends ActivityManagerNative break; } } - } else if (app.curAdj >= PERCEPTIBLE_APP_ADJ) { - if (app.trimMemoryLevel < ComponentCallbacks.TRIM_MEMORY_INVISIBLE + } else if (app.curAdj == HEAVY_WEIGHT_APP_ADJ) { + if (app.trimMemoryLevel < ComponentCallbacks.TRIM_MEMORY_BACKGROUND && app.thread != null) { try { - app.thread.scheduleTrimMemory(ComponentCallbacks.TRIM_MEMORY_INVISIBLE); + app.thread.scheduleTrimMemory(ComponentCallbacks.TRIM_MEMORY_BACKGROUND); } catch (RemoteException e) { } } - app.trimMemoryLevel = ComponentCallbacks.TRIM_MEMORY_INVISIBLE; + app.trimMemoryLevel = ComponentCallbacks.TRIM_MEMORY_BACKGROUND; } else { app.trimMemoryLevel = 0; } @@ -13442,7 +13452,7 @@ public final class ActivityManagerService extends ActivityManagerNative } public boolean profileControl(String process, boolean start, - String path, ParcelFileDescriptor fd) throws RemoteException { + String path, ParcelFileDescriptor fd, int profileType) throws RemoteException { try { synchronized (this) { @@ -13487,7 +13497,7 @@ public final class ActivityManagerService extends ActivityManagerNative } } - proc.thread.profilerControl(start, path, fd); + proc.thread.profilerControl(start, path, fd, profileType); fd = null; return true; } diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java index 0d89081..cc58eaf 100644 --- a/services/java/com/android/server/am/ActivityStack.java +++ b/services/java/com/android/server/am/ActivityStack.java @@ -559,6 +559,7 @@ final class ActivityStack { r.forceNewConfig = false; showAskCompatModeDialogLocked(r); r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo); + app.hasShownUi = true; app.thread.scheduleLaunchActivity(new Intent(r.intent), r, System.identityHashCode(r), r.info, r.compat, r.icicle, results, newIntents, !andResume, diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java index 9e597aa..5b59363 100644 --- a/services/java/com/android/server/am/ProcessRecord.java +++ b/services/java/com/android/server/am/ProcessRecord.java @@ -66,6 +66,7 @@ class ProcessRecord { boolean setIsForeground; // Running foreground UI when last set? boolean foregroundServices; // Running any services that are foreground? boolean foregroundActivities; // Running any activities that are foreground? + boolean hasShownUi; // Has UI been shown in this process since it was started? boolean bad; // True if disabled in the bad process list boolean killedBackground; // True when proc has been killed due to too many bg String waitingToKill; // Process is waiting to be killed when in the bg; reason @@ -185,6 +186,7 @@ class ProcessRecord { pw.print(prefix); pw.print("curSchedGroup="); pw.print(curSchedGroup); pw.print(" setSchedGroup="); pw.print(setSchedGroup); pw.print(" trimMemoryLevel="); pw.println(trimMemoryLevel); + pw.print(" hasShownUi="); pw.println(hasShownUi); pw.print(prefix); pw.print("setIsForeground="); pw.print(setIsForeground); pw.print(" foregroundServices="); pw.print(foregroundServices); pw.print(" forcingToForeground="); pw.println(forcingToForeground); diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java index d7d4b03..a5a6d8e 100644 --- a/services/java/com/android/server/connectivity/Tethering.java +++ b/services/java/com/android/server/connectivity/Tethering.java @@ -36,7 +36,6 @@ import android.net.LinkProperties; import android.net.NetworkInfo; import android.net.NetworkUtils; import android.os.Binder; -import android.os.Environment; import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; @@ -76,10 +75,6 @@ public class Tethering extends INetworkManagementEventObserver.Stub { private final static String TAG = "Tethering"; private final static boolean DEBUG = true; - private boolean mBooted = false; - //used to remember if we got connected before boot finished - private boolean mDeferedUsbConnection = false; - // TODO - remove both of these - should be part of interface inspection/selection stuff private String[] mTetherableUsbRegexs; private String[] mTetherableWifiRegexs; @@ -126,10 +121,9 @@ public class Tethering extends INetworkManagementEventObserver.Stub { private Notification mTetheredNotification; - // whether we can tether is the && of these two - they come in as separate - // broadcasts so track them so we can decide what to do when either changes - private boolean mUsbMassStorageOff; // track the status of USB Mass Storage - private boolean mUsbConnected; // track the status of USB connection + private boolean mRndisEnabled; // track the RNDIS function enabled state + private boolean mUsbTetherRequested; // true if USB tethering should be started + // when RNDIS is enabled public Tethering(Context context, INetworkManagementService nmService, Looper looper) { mContext = context; @@ -149,7 +143,6 @@ public class Tethering extends INetworkManagementEventObserver.Stub { IntentFilter filter = new IntentFilter(); filter.addAction(UsbManager.ACTION_USB_STATE); filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); - filter.addAction(Intent.ACTION_BOOT_COMPLETED); mContext.registerReceiver(mStateReceiver, filter); filter = new IntentFilter(); @@ -158,9 +151,6 @@ public class Tethering extends INetworkManagementEventObserver.Stub { filter.addDataScheme("file"); mContext.registerReceiver(mStateReceiver, filter); - mUsbMassStorageOff = !Environment.MEDIA_SHARED.equals( - Environment.getExternalStorageState()); - mDhcpRange = context.getResources().getStringArray( com.android.internal.R.array.config_tether_dhcp_range); if ((mDhcpRange.length == 0) || (mDhcpRange.length % 2 ==1)) { @@ -221,6 +211,8 @@ public class Tethering extends INetworkManagementEventObserver.Stub { } public void interfaceLinkStateChanged(String iface, boolean up) { + if (DEBUG) Log.d(TAG, "interfaceLinkStateChanged " + iface + ", " + up); + interfaceStatusChanged(iface, up); } private boolean isUsb(String iface) { @@ -243,6 +235,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { } return false; } + public void interfaceAdded(String iface) { boolean found = false; boolean usb = false; @@ -288,6 +281,8 @@ public class Tethering extends INetworkManagementEventObserver.Stub { } } + public void limitReached(String limitName, String iface) {} + public int tether(String iface) { Log.d(TAG, "Tethering " + iface); TetherInterfaceSM sm = null; @@ -454,47 +449,28 @@ public class Tethering extends INetworkManagementEventObserver.Stub { } } - private void updateUsbStatus() { - boolean enable = mUsbConnected && mUsbMassStorageOff; - - if (mBooted) { - enableUsbIfaces(enable); - } - } - private class StateReceiver extends BroadcastReceiver { public void onReceive(Context content, Intent intent) { String action = intent.getAction(); if (action.equals(UsbManager.ACTION_USB_STATE)) { - mUsbConnected = intent.getExtras().getBoolean(UsbManager.USB_CONNECTED); - updateUsbStatus(); - } else if (action.equals(Intent.ACTION_MEDIA_SHARED)) { - mUsbMassStorageOff = false; - updateUsbStatus(); - } - else if (action.equals(Intent.ACTION_MEDIA_UNSHARED)) { - mUsbMassStorageOff = true; - updateUsbStatus(); + synchronized (Tethering.this) { + boolean usbConnected = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false); + mRndisEnabled = intent.getBooleanExtra(UsbManager.USB_FUNCTION_RNDIS, false); + // start tethering if we have a request pending + if (usbConnected && mRndisEnabled && mUsbTetherRequested) { + tetherUsb(true); + } + mUsbTetherRequested = false; + } } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { if (DEBUG) Log.d(TAG, "Tethering got CONNECTIVITY_ACTION"); mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED); - } else if (action.equals(Intent.ACTION_BOOT_COMPLETED)) { - mBooted = true; - updateUsbStatus(); } } } - // used on cable insert/remove - private void enableUsbIfaces(boolean enable) { - // add/remove USB interfaces when USB is connected/disconnected - for (String intf : mTetherableUsbRegexs) { - if (enable) { - interfaceAdded(intf); - } else { - interfaceRemoved(intf); - } - } + private void tetherUsb(boolean enable) { + if (DEBUG) Log.d(TAG, "tetherUsb " + enable); String[] ifaces = new String[0]; try { @@ -505,83 +481,50 @@ public class Tethering extends INetworkManagementEventObserver.Stub { } for (String iface : ifaces) { if (isUsb(iface)) { - if (enable) { - interfaceAdded(iface); - } else { - interfaceRemoved(iface); + int result = (enable ? tether(iface) : untether(iface)); + if (result == ConnectivityManager.TETHER_ERROR_NO_ERROR) { + return; } } } - } - - // toggled when we enter/leave the fully tethered state - private boolean enableUsbRndis(boolean enabled) { - if (DEBUG) Log.d(TAG, "enableUsbRndis(" + enabled + ")"); - - UsbManager usbManager = (UsbManager)mContext.getSystemService(Context.USB_SERVICE); - if (usbManager == null) { - Log.d(TAG, "could not get UsbManager"); - return false; - } - try { - if (enabled) { - usbManager.setCurrentFunction(UsbManager.USB_FUNCTION_RNDIS, false); - } else { - usbManager.setCurrentFunction(null, false); - } - } catch (Exception e) { - Log.e(TAG, "Error toggling usb RNDIS", e); - return false; - } - return true; + Log.e(TAG, "unable start or stop USB tethering"); } // configured when we start tethering and unconfig'd on error or conclusion private boolean configureUsbIface(boolean enabled) { if (DEBUG) Log.d(TAG, "configureUsbIface(" + enabled + ")"); - if (enabled) { - // must enable RNDIS first to create the interface - enableUsbRndis(enabled); - } - + // toggle the USB interfaces + String[] ifaces = new String[0]; try { - // bring toggle the interfaces - String[] ifaces = new String[0]; - try { - ifaces = mNMService.listInterfaces(); - } catch (Exception e) { - Log.e(TAG, "Error listing Interfaces", e); - return false; - } - for (String iface : ifaces) { - if (isUsb(iface)) { - InterfaceConfiguration ifcg = null; - try { - ifcg = mNMService.getInterfaceConfig(iface); - if (ifcg != null) { - InetAddress addr = NetworkUtils.numericToInetAddress(USB_NEAR_IFACE_ADDR); - ifcg.addr = new LinkAddress(addr, USB_PREFIX_LENGTH); - if (enabled) { - ifcg.interfaceFlags = ifcg.interfaceFlags.replace("down", "up"); - } else { - ifcg.interfaceFlags = ifcg.interfaceFlags.replace("up", "down"); - } - ifcg.interfaceFlags = ifcg.interfaceFlags.replace("running", ""); - ifcg.interfaceFlags = ifcg.interfaceFlags.replace(" "," "); - mNMService.setInterfaceConfig(iface, ifcg); + ifaces = mNMService.listInterfaces(); + } catch (Exception e) { + Log.e(TAG, "Error listing Interfaces", e); + return false; + } + for (String iface : ifaces) { + if (isUsb(iface)) { + InterfaceConfiguration ifcg = null; + try { + ifcg = mNMService.getInterfaceConfig(iface); + if (ifcg != null) { + InetAddress addr = NetworkUtils.numericToInetAddress(USB_NEAR_IFACE_ADDR); + ifcg.addr = new LinkAddress(addr, USB_PREFIX_LENGTH); + if (enabled) { + ifcg.interfaceFlags = ifcg.interfaceFlags.replace("down", "up"); + } else { + ifcg.interfaceFlags = ifcg.interfaceFlags.replace("up", "down"); } - } catch (Exception e) { - Log.e(TAG, "Error configuring interface " + iface, e); - return false; + ifcg.interfaceFlags = ifcg.interfaceFlags.replace("running", ""); + ifcg.interfaceFlags = ifcg.interfaceFlags.replace(" "," "); + mNMService.setInterfaceConfig(iface, ifcg); } + } catch (Exception e) { + Log.e(TAG, "Error configuring interface " + iface, e); + return false; } - } - } finally { - if (!enabled) { - enableUsbRndis(false); } - } + } return true; } @@ -598,6 +541,28 @@ public class Tethering extends INetworkManagementEventObserver.Stub { return mTetherableBluetoothRegexs; } + public int setUsbTethering(boolean enable) { + UsbManager usbManager = (UsbManager)mContext.getSystemService(Context.USB_SERVICE); + + synchronized (this) { + if (enable) { + if (mRndisEnabled) { + tetherUsb(true); + } else { + mUsbTetherRequested = true; + usbManager.setCurrentFunction(UsbManager.USB_FUNCTION_RNDIS, false); + } + } else { + tetherUsb(false); + if (mRndisEnabled) { + usbManager.setCurrentFunction(null, false); + } + mUsbTetherRequested = false; + } + } + return ConnectivityManager.TETHER_ERROR_NO_ERROR; + } + public int[] getUpstreamIfaceTypes() { int values[] = new int[mUpstreamIfaceTypes.size()]; Iterator<Integer> iterator = mUpstreamIfaceTypes.iterator(); diff --git a/services/java/com/android/server/connectivity/Vpn.java b/services/java/com/android/server/connectivity/Vpn.java index 05e95a7..9cb772e 100644 --- a/services/java/com/android/server/connectivity/Vpn.java +++ b/services/java/com/android/server/connectivity/Vpn.java @@ -248,6 +248,8 @@ public class Vpn extends INetworkManagementEventObserver.Stub { } } + public void limitReached(String limitName, String iface) {} + private void showNotification(VpnConfig config, String label, Bitmap icon) { NotificationManager nm = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); @@ -394,7 +396,7 @@ public class Vpn extends INetworkManagementEventObserver.Stub { if (mTimer == -1) { mTimer = now; Thread.sleep(1); - } else if (now - mTimer <= 30000) { + } else if (now - mTimer <= 60000) { Thread.sleep(yield ? 200 : 1); } else { mInfo.state = LegacyVpnInfo.STATE_TIMEOUT; diff --git a/services/java/com/android/server/usb/UsbDeviceManager.java b/services/java/com/android/server/usb/UsbDeviceManager.java index c80cd0a..f183f83 100644 --- a/services/java/com/android/server/usb/UsbDeviceManager.java +++ b/services/java/com/android/server/usb/UsbDeviceManager.java @@ -19,6 +19,7 @@ package com.android.server.usb; import android.app.PendingIntent; import android.app.Notification; import android.app.NotificationManager; +import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; @@ -80,6 +81,7 @@ public class UsbDeviceManager { private static final int MSG_ENABLE_ADB = 1; private static final int MSG_SET_CURRENT_FUNCTION = 2; private static final int MSG_SYSTEM_READY = 3; + private static final int MSG_BOOT_COMPLETED = 4; // Delay for debouncing USB disconnects. // We often get rapid connect/disconnect events when enabling USB functions, @@ -87,7 +89,7 @@ public class UsbDeviceManager { private static final int UPDATE_DELAY = 1000; private UsbHandler mHandler; - private boolean mSystemReady; + private boolean mBootCompleted; private final Context mContext; private final ContentResolver mContentResolver; @@ -141,10 +143,15 @@ public class UsbDeviceManager { Process.THREAD_PRIORITY_BACKGROUND); thread.start(); mHandler = new UsbHandler(thread.getLooper()); + + if (nativeIsStartRequested()) { + if (DEBUG) Slog.d(TAG, "accessory attached at boot"); + setCurrentFunction(UsbManager.USB_FUNCTION_ACCESSORY, false); + } } public void systemReady() { - mSystemReady = true; + if (DEBUG) Slog.d(TAG, "systemReady"); mNotificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); @@ -236,15 +243,22 @@ public class UsbDeviceManager { private String mCurrentFunctions; private String mDefaultFunctions; private UsbAccessory mCurrentAccessory; - private boolean mDeferAccessoryAttached; private int mUsbNotificationId; private boolean mAdbNotificationShown; + private final BroadcastReceiver mBootCompletedReceiver = new BroadcastReceiver() { + public void onReceive(Context context, Intent intent) { + if (DEBUG) Slog.d(TAG, "boot completed"); + mHandler.sendEmptyMessage(MSG_BOOT_COMPLETED); + } + }; + private static final int NOTIFICATION_NONE = 0; private static final int NOTIFICATION_MTP = 1; private static final int NOTIFICATION_PTP = 2; private static final int NOTIFICATION_INSTALLER = 3; - private static final int NOTIFICATION_ADB = 4; + private static final int NOTIFICATION_ACCESSORY = 4; + private static final int NOTIFICATION_ADB = 5; public UsbHandler(Looper looper) { super(looper); @@ -285,6 +299,9 @@ public class UsbDeviceManager { // Watch for USB configuration changes mUEventObserver.startObserving(USB_STATE_MATCH); mUEventObserver.startObserving(ACCESSORY_START_MATCH); + + mContext.registerReceiver(mBootCompletedReceiver, + new IntentFilter(Intent.ACTION_BOOT_COMPLETED)); } catch (Exception e) { Slog.e(TAG, "Error initializing UsbHandler", e); } @@ -406,11 +423,9 @@ public class UsbDeviceManager { mCurrentAccessory = new UsbAccessory(strings); Slog.d(TAG, "entering USB accessory mode: " + mCurrentAccessory); // defer accessoryAttached if system is not ready - if (mSystemReady) { + if (mBootCompleted) { mSettingsManager.accessoryAttached(mCurrentAccessory); - } else { - mDeferAccessoryAttached = true; - } + } // else handle in mBootCompletedReceiver } else { Slog.e(TAG, "nativeGetAccessoryStrings failed"); } @@ -421,7 +436,7 @@ public class UsbDeviceManager { setEnabledFunctions(mDefaultFunctions); if (mCurrentAccessory != null) { - if (mSystemReady) { + if (mBootCompleted) { mSettingsManager.accessoryDetached(mCurrentAccessory); } mCurrentAccessory = null; @@ -463,7 +478,7 @@ public class UsbDeviceManager { // restore defaults when USB is disconnected doSetCurrentFunctions(mDefaultFunctions); } - if (mSystemReady) { + if (mBootCompleted) { updateUsbState(); } break; @@ -497,7 +512,10 @@ public class UsbDeviceManager { updateUsbNotification(); updateAdbNotification(); updateUsbState(); - if (mCurrentAccessory != null && mDeferAccessoryAttached) { + break; + case MSG_BOOT_COMPLETED: + mBootCompleted = true; + if (mCurrentAccessory != null) { mSettingsManager.accessoryAttached(mCurrentAccessory); } break; @@ -527,6 +545,10 @@ public class UsbDeviceManager { title = r.getText( com.android.internal.R.string.usb_cd_installer_notification_title); id = NOTIFICATION_INSTALLER; + } else if (containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_ACCESSORY)) { + title = r.getText( + com.android.internal.R.string.usb_accessory_notification_title); + id = NOTIFICATION_ACCESSORY; } else { Slog.e(TAG, "No known USB function in updateUsbNotification"); } @@ -671,4 +693,5 @@ public class UsbDeviceManager { private native String[] nativeGetAccessoryStrings(); private native ParcelFileDescriptor nativeOpenAccessory(); + private native boolean nativeIsStartRequested(); } diff --git a/services/java/com/android/server/wm/BlackFrame.java b/services/java/com/android/server/wm/BlackFrame.java index d8fd7fe..36f5dcb 100644 --- a/services/java/com/android/server/wm/BlackFrame.java +++ b/services/java/com/android/server/wm/BlackFrame.java @@ -32,10 +32,12 @@ public class BlackFrame { final int top; final Surface surface; - BlackSurface(SurfaceSession session, int layer, int l, int t, int w, int h) + BlackSurface(SurfaceSession session, int layer, int l, int t, int r, int b) throws Surface.OutOfResourcesException { left = l; top = t; + int w = r-l; + int h = b-t; surface = new Surface(session, 0, "BlackSurface", -1, w, h, PixelFormat.OPAQUE, Surface.FX_SURFACE_DIM); if (WindowManagerService.SHOW_TRANSACTIONS || diff --git a/services/jni/com_android_server_UsbDeviceManager.cpp b/services/jni/com_android_server_UsbDeviceManager.cpp index 6954171..40f0dbd 100644 --- a/services/jni/com_android_server_UsbDeviceManager.cpp +++ b/services/jni/com_android_server_UsbDeviceManager.cpp @@ -99,11 +99,26 @@ static jobject android_server_UsbDeviceManager_openAccessory(JNIEnv *env, jobjec gParcelFileDescriptorOffsets.mConstructor, fileDescriptor); } +static jboolean android_server_UsbDeviceManager_isStartRequested(JNIEnv *env, jobject thiz) +{ + int fd = open(DRIVER_NAME, O_RDWR); + if (fd < 0) { + LOGE("could not open %s", DRIVER_NAME); + return false; + } + int result = ioctl(fd, ACCESSORY_IS_START_REQUESTED); + close(fd); + return (result == 1); +} + + static JNINativeMethod method_table[] = { { "nativeGetAccessoryStrings", "()[Ljava/lang/String;", (void*)android_server_UsbDeviceManager_getAccessoryStrings }, { "nativeOpenAccessory", "()Landroid/os/ParcelFileDescriptor;", (void*)android_server_UsbDeviceManager_openAccessory }, + { "nativeIsStartRequested", "()Z", + (void*)android_server_UsbDeviceManager_isStartRequested }, }; int register_android_server_UsbDeviceManager(JNIEnv *env) diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp index e0dce1f..5b74fb8 100644 --- a/services/sensorservice/SensorService.cpp +++ b/services/sensorservice/SensorService.cpp @@ -586,12 +586,12 @@ status_t SensorService::SensorEventConnection::sendEvents( if (size == -EAGAIN) { // the destination doesn't accept events anymore, it's probably // full. For now, we just drop the events on the floor. - LOGW("dropping %d events on the floor", count); + //LOGW("dropping %d events on the floor", count); return size; } - LOGE_IF(size<0, "dropping %d events on the floor (%s)", - count, strerror(-size)); + //LOGE_IF(size<0, "dropping %d events on the floor (%s)", + // count, strerror(-size)); return size < 0 ? status_t(size) : status_t(NO_ERROR); } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 680814c..4a27701 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1318,9 +1318,6 @@ sp<ISurface> SurfaceFlinger::createSurface( if (surfaceHandle != 0) { params->token = token; params->identity = layer->getIdentity(); - params->width = w; - params->height = h; - params->format = format; if (normalLayer != 0) { Mutex::Autolock _l(mStateLock); mLayerMap.add(layer->getSurfaceBinder(), normalLayer); diff --git a/services/surfaceflinger/SurfaceTextureLayer.cpp b/services/surfaceflinger/SurfaceTextureLayer.cpp index 11f61cc..91e010f 100644 --- a/services/surfaceflinger/SurfaceTextureLayer.cpp +++ b/services/surfaceflinger/SurfaceTextureLayer.cpp @@ -60,7 +60,11 @@ status_t SurfaceTextureLayer::queueBuffer(int buf, int64_t timestamp, sp<Layer> layer(mLayer.promote()); if (layer != NULL) { - *outTransform = layer->getOrientation(); + uint32_t orientation = layer->getOrientation(); + if (orientation & Transform::ROT_INVALID) { + orientation = 0; + } + *outTransform = orientation; } return res; diff --git a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java index 4f8b525..3bd78e0 100644 --- a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java +++ b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java @@ -36,6 +36,7 @@ import android.os.Messenger; import android.os.SystemProperties; import android.preference.PreferenceManager; import android.provider.Settings; +import android.telephony.ServiceState; import android.provider.Settings.SettingNotFoundException; import android.text.TextUtils; import android.util.Log; @@ -1031,6 +1032,27 @@ public abstract class DataConnectionTracker extends Handler { protected void onSetDependencyMet(String apnType, boolean met) { } + protected String getReryConfig(boolean forDefault) { + int rt = mPhone.getServiceState().getRadioTechnology(); + + if ((rt == ServiceState.RADIO_TECHNOLOGY_IS95A) || + (rt == ServiceState.RADIO_TECHNOLOGY_IS95B) || + (rt == ServiceState.RADIO_TECHNOLOGY_1xRTT) || + (rt == ServiceState.RADIO_TECHNOLOGY_EVDO_0) || + (rt == ServiceState.RADIO_TECHNOLOGY_EVDO_A) || + (rt == ServiceState.RADIO_TECHNOLOGY_EVDO_B) || + (rt == ServiceState.RADIO_TECHNOLOGY_EHRPD)) { + // CDMA variant + return SystemProperties.get("ro.cdma.data_retry_config"); + } else { + // Use GSM varient for all others. + if (forDefault) { + return SystemProperties.get("ro.gsm.data_retry_config"); + } else { + return SystemProperties.get("ro.gsm.2nd_data_retry_config"); + } + } + } protected void resetAllRetryCounts() { for (DataConnection dc : mDataConnections.values()) { diff --git a/telephony/java/com/android/internal/telephony/PhoneBase.java b/telephony/java/com/android/internal/telephony/PhoneBase.java index 40a70a8..a0961ca 100644 --- a/telephony/java/com/android/internal/telephony/PhoneBase.java +++ b/telephony/java/com/android/internal/telephony/PhoneBase.java @@ -806,10 +806,10 @@ public abstract class PhoneBase extends Handler implements Phone { mNotifier.notifyDataConnection(this, reason, apnType, getDataConnectionState(apnType)); } - public void notifyDataConnection() { + public void notifyDataConnection(String reason) { String types[] = getActiveApnTypes(); for (String apnType : types) { - mNotifier.notifyDataConnection(this, null, apnType, getDataConnectionState(apnType)); + mNotifier.notifyDataConnection(this, reason, apnType, getDataConnectionState(apnType)); } } diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java index 93fc9ce..facee5f 100644 --- a/telephony/java/com/android/internal/telephony/RILConstants.java +++ b/telephony/java/com/android/internal/telephony/RILConstants.java @@ -31,6 +31,8 @@ public interface RILConstants { // From the top of ril.cpp int RIL_ERRNO_INVALID_RESPONSE = -1; + int MAX_INT = 0x7FFFFFFF; + // from RIL_Errno int SUCCESS = 0; int RADIO_NOT_AVAILABLE = 1; /* If radio did not start or is resetting */ diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java index 0d551aa..d3bb6a5 100644 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java @@ -134,8 +134,6 @@ public class CdmaLteServiceStateTracker extends CdmaServiceStateTracker { } } - // Not sure if this is needed in CDMALTE phone. - // mDataRoaming = regCodeIsRoaming(regState); mLteSS.setRadioTechnology(type); mLteSS.setState(regCodeToServiceState(regState)); } else { @@ -249,10 +247,11 @@ public class CdmaLteServiceStateTracker extends CdmaServiceStateTracker { boolean hasLocationChanged = !newCellLoc.equals(cellLoc); boolean has4gHandoff = - ((networkType == ServiceState.RADIO_TECHNOLOGY_LTE) && - (newNetworkType == ServiceState.RADIO_TECHNOLOGY_EHRPD)) || - ((networkType == ServiceState.RADIO_TECHNOLOGY_EHRPD) && - (newNetworkType == ServiceState.RADIO_TECHNOLOGY_LTE)); + mNewDataConnectionState == ServiceState.STATE_IN_SERVICE && + (((networkType == ServiceState.RADIO_TECHNOLOGY_LTE) && + (newNetworkType == ServiceState.RADIO_TECHNOLOGY_EHRPD)) || + ((networkType == ServiceState.RADIO_TECHNOLOGY_EHRPD) && + (newNetworkType == ServiceState.RADIO_TECHNOLOGY_LTE))); boolean hasMultiApnSupport = (((newNetworkType == ServiceState.RADIO_TECHNOLOGY_LTE) || @@ -345,13 +344,14 @@ public class CdmaLteServiceStateTracker extends CdmaServiceStateTracker { } if (cm.getSimState().isSIMReady()) { - // SIM is found on the device. If ERI roaming is OFF, use operator name - // from CSIM record. + // SIM is found on the device. If ERI roaming is OFF and SID/NID matches + // one configfured in SIM, use operator name from CSIM record. boolean showSpn = ((CdmaLteUiccRecords)phone.mIccRecords).getCsimSpnDisplayCondition(); int iconIndex = ss.getCdmaEriIconIndex(); - if (showSpn && (iconIndex == EriInfo.ROAMING_INDICATOR_OFF)) { + if (showSpn && (iconIndex == EriInfo.ROAMING_INDICATOR_OFF) && + isInHomeSidNid(ss.getSystemId(), ss.getNetworkId())) { ss.setOperatorAlphaLong(phone.mIccRecords.getServiceProviderName()); } } @@ -392,7 +392,7 @@ public class CdmaLteServiceStateTracker extends CdmaServiceStateTracker { phone.notifyServiceStateChanged(ss); } - if (hasCdmaDataConnectionAttached) { + if (hasCdmaDataConnectionAttached || has4gHandoff) { mAttachedRegistrants.notifyRegistrants(); } @@ -401,7 +401,7 @@ public class CdmaLteServiceStateTracker extends CdmaServiceStateTracker { } if ((hasCdmaDataConnectionChanged || hasNetworkTypeChanged)) { - phone.notifyDataConnection(); + phone.notifyDataConnection(null); } if (hasRoamingOn) { @@ -469,6 +469,34 @@ public class CdmaLteServiceStateTracker extends CdmaServiceStateTracker { } /** + * Check whether the specified SID and NID pair appears in the HOME SID/NID list + * read from NV or SIM. + * + * @return true if provided sid/nid pair belongs to operator's home network. + */ + private boolean isInHomeSidNid(int sid, int nid) { + // if SID/NID is not available, assume this is home network. + if (isSidsAllZeros()) return true; + + // length of SID/NID shold be same + if (mHomeSystemId.length != mHomeNetworkId.length) return true; + + if (sid == 0) return true; + + for (int i = 0; i < mHomeSystemId.length; i++) { + // Use SID only if NID is a reserved value. + // SID 0 and NID 0 and 65535 are reserved. (C.0005 2.6.5.2) + if ((mHomeSystemId[i] == sid) && + ((mHomeNetworkId[i] == 0) || (mHomeNetworkId[i] == 65535) || + (nid == 0) || (nid == 65535) || (mHomeNetworkId[i] == nid))) { + return true; + } + } + // SID/NID are not in the list. So device is not in home network + return false; + } + + /** * Returns OTASP_NOT_NEEDED as its not needed for LTE */ @Override diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java index 24a468a..2cf4b88 100755 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java @@ -130,8 +130,8 @@ public class CdmaServiceStateTracker extends ServiceStateTracker { protected String mCurPlmn = null; protected String mMdn; - private int mHomeSystemId[] = null; - private int mHomeNetworkId[] = null; + protected int mHomeSystemId[] = null; + protected int mHomeNetworkId[] = null; protected String mMin; protected String mPrlVersion; protected boolean mIsMinInfoReady = false; @@ -999,7 +999,7 @@ public class CdmaServiceStateTracker extends ServiceStateTracker { } if (hasCdmaDataConnectionChanged || hasNetworkTypeChanged) { - phone.notifyDataConnection(); + phone.notifyDataConnection(null); } if (hasRoamingOn) { @@ -1481,7 +1481,7 @@ public class CdmaServiceStateTracker extends ServiceStateTracker { } } - private boolean isSidsAllZeros() { + protected boolean isSidsAllZeros() { if (mHomeSystemId != null) { for (int i=0; i < mHomeSystemId.length; i++) { if (mHomeSystemId[i] != 0) { diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java index ccdb0bf..be129d5 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java @@ -609,9 +609,20 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { for (DataConnectionAc dcac : mDataConnectionAsyncChannels.values()) { if (dcac.getReconnectIntentSync() != null) { cancelReconnectAlarm(dcac); - if (dcac.dataConnection != null) { - dcac.dataConnection.resetRetryCount(); + } + // update retry config for existing calls to match up + // ones for the new RAT. + if (dcac.dataConnection != null) { + Collection<ApnContext> apns = dcac.getApnListSync(); + + boolean hasDefault = false; + for (ApnContext apnContext : apns) { + if (apnContext.getApnType().equals(Phone.APN_TYPE_DEFAULT)) { + hasDefault = true; + break; + } } + configureRetry(dcac.dataConnection, hasDefault); } } @@ -973,7 +984,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { // configure retry count if no other Apn is using the same connection. if (refCount == 0) { - configureRetry(dc, apnContext.getApnType()); + configureRetry(dc, apn.canHandleType(Phone.APN_TYPE_DEFAULT)); } apnContext.setDataConnectionAc(dcac); apnContext.setDataConnection(dc); @@ -1834,7 +1845,11 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { retryOverride = ((DataConnection.CallSetupException)ar.exception).getRetryOverride(); } - startDelayedRetry(cause, apnContext, retryOverride); + if (retryOverride == RILConstants.MAX_INT) { + if (DBG) log("No retry is suggested."); + } else { + startDelayedRetry(cause, apnContext, retryOverride); + } } } else { if (DBG) log("onDataSetupComplete: Try next APN"); @@ -2022,20 +2037,18 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { return conn; } - private void configureRetry(DataConnection dc, String apnType) { - if ((dc == null) || (apnType == null)) return; + private void configureRetry(DataConnection dc, boolean forDefault) { + if (dc == null) return; - if (apnType.equals(Phone.APN_TYPE_DEFAULT)) { - if (!dc.configureRetry(SystemProperties.get("ro.gsm.data_retry_config"))) { + if (!dc.configureRetry(getReryConfig(forDefault))) { + if (forDefault) { if (!dc.configureRetry(DEFAULT_DATA_RETRY_CONFIG)) { // Should never happen, log an error and default to a simple linear sequence. loge("configureRetry: Could not configure using " + "DEFAULT_DATA_RETRY_CONFIG=" + DEFAULT_DATA_RETRY_CONFIG); dc.configureRetry(20, 2000, 1000); } - } - } else { - if (!dc.configureRetry(SystemProperties.get("ro.gsm.2nd_data_retry_config"))) { + } else { if (!dc.configureRetry(SECONDARY_DATA_RETRY_CONFIG)) { // Should never happen, log an error and default to a simple sequence. loge("configureRetry: Could note configure using " + diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java index 93f4b4e..d3645fa 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java @@ -915,7 +915,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker { } if (hasRadioTechnologyChanged) { - phone.notifyDataConnection(Phone.REASON_NW_TYPE_CHANGED, Phone.APN_TYPE_ALL); + phone.notifyDataConnection(Phone.REASON_NW_TYPE_CHANGED); } if (hasRoamingOn) { diff --git a/tests/BiDiTests/Android b/tests/BiDiTests/Android deleted file mode 100644 index e69de29..0000000 --- a/tests/BiDiTests/Android +++ /dev/null diff --git a/tests/BiDiTests/Android.mk b/tests/BiDiTests/Android-private.mk index ae29fc2..ae29fc2 100644 --- a/tests/BiDiTests/Android.mk +++ b/tests/BiDiTests/Android-private.mk diff --git a/tests/BiDiTests/new-attributes.txt b/tests/BiDiTests/new-attributes.txt new file mode 100644 index 0000000..57854cc --- /dev/null +++ b/tests/BiDiTests/new-attributes.txt @@ -0,0 +1,9 @@ + <public type="attr" name="layoutDirection" /> + + <public type="attr" name="layout_marginStart"/> + <public type="attr" name="layout_marginEnd"/> + + <public type="attr" name="paddingStart"/> + <public type="attr" name="paddingEnd"/> + + <public type="attr" name="textDirection"/> diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ListActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ListActivity.java index 1493ab9..13b6129 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/ListActivity.java +++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ListActivity.java @@ -93,12 +93,9 @@ public class ListActivity extends Activity { } public void startProfiling(View v) { - ViewDebug.startLooperProfiling(new File(Environment.getExternalStorageDirectory(), - "looper.trace")); } public void stopProfiling(View v) { - ViewDebug.stopLooperProfiling(); } @Override diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java index e776463..9aa70b0 100644 --- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java +++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java @@ -87,8 +87,6 @@ public class ImageProcessingActivity extends Activity mIsProcessing = false; } - // This is a hack to work around an invalidation bug - mBitmapOut.setPixel(0, 0, 0); mOutPixelsAllocation.copyTo(mBitmapOut); mDisplayView.invalidate(); } diff --git a/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java b/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java index b212533..e75a079 100644 --- a/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java +++ b/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java @@ -100,22 +100,22 @@ public class StatusBarTest extends TestActivity new Test("Double Remove") { public void run() { Log.d(TAG, "set 0"); - mStatusBarManager.setIcon("speakerphone", R.drawable.stat_sys_phone, 0); + mStatusBarManager.setIcon("speakerphone", R.drawable.stat_sys_phone, 0, null); Log.d(TAG, "remove 1"); mStatusBarManager.removeIcon("tty"); SystemClock.sleep(1000); Log.d(TAG, "set 1"); - mStatusBarManager.setIcon("tty", R.drawable.stat_sys_phone, 0); + mStatusBarManager.setIcon("tty", R.drawable.stat_sys_phone, 0, null); if (false) { Log.d(TAG, "set 2"); - mStatusBarManager.setIcon("tty", R.drawable.stat_sys_phone, 0); + mStatusBarManager.setIcon("tty", R.drawable.stat_sys_phone, 0, null); } Log.d(TAG, "remove 2"); mStatusBarManager.removeIcon("tty"); Log.d(TAG, "set 3"); - mStatusBarManager.setIcon("speakerphone", R.drawable.stat_sys_phone, 0); + mStatusBarManager.setIcon("speakerphone", R.drawable.stat_sys_phone, 0, null); } }, new Test("Hide (FLAG_FULLSCREEN)") { diff --git a/tests/TileBenchmark/AndroidManifest.xml b/tests/TileBenchmark/AndroidManifest.xml index 663cc0d..ab61a9e 100644 --- a/tests/TileBenchmark/AndroidManifest.xml +++ b/tests/TileBenchmark/AndroidManifest.xml @@ -7,14 +7,16 @@ android:label="@string/app_name" android:hardwareAccelerated="true"> <activity android:name=".ProfileActivity" - android:label="@string/profile_activity"> + android:label="@string/profile_activity" + android:theme="@android:style/Theme.Holo.NoActionBar"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".PlaybackActivity" - android:label="@string/playback_activity"> + android:label="@string/playback_activity" + android:theme="@android:style/Theme.Holo.NoActionBar"> </activity> </application> </manifest> diff --git a/tests/TileBenchmark/res/layout/main.xml b/tests/TileBenchmark/res/layout/main.xml index 4a81da6..577c466 100644 --- a/tests/TileBenchmark/res/layout/main.xml +++ b/tests/TileBenchmark/res/layout/main.xml @@ -23,11 +23,11 @@ android:layout_width="match_parent" android:layout_height="wrap_content" > - <Button - android:id="@+id/inspect" + <Spinner + android:id="@+id/movement" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="@string/inspect_log" + android:prompt="@string/movement_method" /> <Spinner android:id="@+id/velocity" @@ -36,6 +36,13 @@ android:gravity="center_horizontal" android:prompt="@string/desired_scroll_velocity" /> + <ToggleButton + android:id="@+id/capture" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textOn="@string/capture_stop" + android:textOff="@string/capture_start" + /> <EditText android:id="@+id/url" android:layout_width="0dip" @@ -44,6 +51,12 @@ android:imeOptions="actionGo" android:layout_weight="1" /> + <Button + android:id="@+id/inspect" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/inspect_log" + /> </LinearLayout> <com.test.tilebenchmark.ProfiledWebView android:id="@+id/web" diff --git a/tests/TileBenchmark/res/values/colors.xml b/tests/TileBenchmark/res/values/colors.xml index 3958083..dbb8e72 100644 --- a/tests/TileBenchmark/res/values/colors.xml +++ b/tests/TileBenchmark/res/values/colors.xml @@ -18,8 +18,17 @@ <color name="ready_tile">#ff4ac230</color> <!-- The color of tiles with stale / invalid textures --> <color name="unready_tile">#ff744400</color> - <!-- Background color for logged URLs --> - <color name="finished_url">#ff004000</color> - <!-- Background color for URLs with logging in progress --> - <color name="unfinished_url">#ff400000</color> + <!-- Viewport overlay in playback --> + <color name="view">#50000050</color> + <!-- Invalidated region overlay in playback - start color --> + <color name="inval_region_start">#80ff0000</color> + <!-- Invalidated region overlay in playback - stop color--> + <color name="inval_region_stop">#80ffffff</color> + + <!-- Background color for not testing --> + <color name="background_not_testing">#ff000000</color> + <!-- Background color for during testing --> + <color name="background_start_testing">#ff400000</color> + <!-- Background color for testing complete --> + <color name="background_stop_testing">#ff004000</color> </resources> diff --git a/tests/TileBenchmark/res/values/strings.xml b/tests/TileBenchmark/res/values/strings.xml index f70ee2c..66972ac 100644 --- a/tests/TileBenchmark/res/values/strings.xml +++ b/tests/TileBenchmark/res/values/strings.xml @@ -28,6 +28,10 @@ <string name="loadbutton">Load</string> <!-- Button, opens the playback activity [CHAR LIMIT=20] --> <string name="inspect_log">Inspect Log</string> + <!-- ToggleButton label when pressing starts capture [CHAR LIMIT=15] --> + <string name="capture_start">Start Capture</string> + <!-- ToggleButton label when pressing stops capture [CHAR LIMIT=15] --> + <string name="capture_stop">Stop Capture</string> <!-- The speed of auto-scrolling [CHAR LIMIT=30] --> <string name="desired_scroll_velocity">Choose Scroll Velocity</string> <!-- Pixels moved per frame [CHAR LIMIT=10] --> @@ -39,6 +43,21 @@ <item>200</item> <item>400</item> </string-array> + <!-- Drop down menu for selecting scrolling vs manual navigation for + capturing [CHAR LIMIT=15] --> + <string name="movement_method">Movement Method</string> + <!-- Drop down menu entry - automatically scroll to the end of the page + with scrollBy() [CHAR LIMIT=15] --> + <string name="movement_auto_scroll">Auto-scroll</string> + <!-- Drop down menu entry - [CHAR LIMIT=15] --> + <string name="movement_auto_fling">Auto-fling</string> + <!-- Drop down menu entry - manually navigate the page(s), hit 'capture' + button [CHAR LIMIT=15] --> + <string name="movement_manual">Manual</string> + + <!-- Error popup indicating log data couldn't be loaded [CHAR LIMIT=60] --> + <string name="error_no_data">Error: log data could not be loaded.</string> + <!-- 25th percentile - 25% of frames fall below this value [CHAR LIMIT=12] --> <string name="percentile_25">25%ile</string> @@ -56,7 +75,7 @@ <string name="format_stat">%4.4f</string> <!-- Format string for displaying aggregate stats+values (nr of valid tiles, etc.) [CHAR LIMIT=20] --> - <string name="format_stat_name">%1$9s %2$3d</string> + <string name="format_stat_name">%1$-20s %2$3d</string> <!-- Text hovering over canvas, number of tiles ready [CHAR LIMIT=15] --> <string name="ready_tiles">Ready Tiles</string> <!-- Text hovering over canvas, number tiles not ready [CHAR LIMIT=15] --> @@ -64,4 +83,7 @@ <!-- Text hovering over canvas, number of tiles that haven't been allocated to a place on the page [CHAR LIMIT=15] --> <string name="unplaced_tiles">Unplaced Tiles</string> + <!-- Text hovering over canvas, number of invalidated regions this frame + [CHAR LIMIT=15] --> + <string name="number_invalidates">Invalidates</string> </resources> diff --git a/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackActivity.java b/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackActivity.java index 5130f5d..36694a7 100644 --- a/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackActivity.java +++ b/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackActivity.java @@ -27,6 +27,7 @@ import android.widget.Button; import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; import android.widget.TextView; +import android.widget.Toast; import java.io.FileInputStream; import java.io.IOException; @@ -102,7 +103,10 @@ public class PlaybackActivity extends Activity { @Override protected void onPostExecute(TileData data[][]) { if (data == null) { - data = genTestPattern(); + Toast.makeText(getApplicationContext(), + getResources().getString(R.string.error_no_data), + Toast.LENGTH_LONG).show(); + return; } mPlaybackView.setData(data); @@ -166,23 +170,4 @@ public class PlaybackActivity extends Activity { new LoadFileTask().execute(ProfileActivity.TEMP_FILENAME); } - - private TileData[][] genTestPattern() { - final int XMAX = 5; - final int FRAMEMAX = 99; - - TileData example[][] = new TileData[FRAMEMAX][]; - for (int frame = 0; frame < FRAMEMAX; frame++) { - int numTiles = frame + 10; - - example[frame] = new TileData[numTiles]; - for (int t = 0; t < numTiles; t++) { - int x = t % XMAX; - int y = t / XMAX; - boolean isReady = y * 10 < frame; - example[frame][t] = new TileData(x, y, isReady, 0); - } - } - return example; - } } diff --git a/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackGraphs.java b/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackGraphs.java index db4a341..35b1563 100644 --- a/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackGraphs.java +++ b/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackGraphs.java @@ -28,19 +28,17 @@ import java.util.ArrayList; import java.util.Arrays; public class PlaybackGraphs { - private static final int BAR_WIDTH = PlaybackView.TILEX * 3; + private static final int BAR_WIDTH = PlaybackView.TILE_SCALE * 3; private static final float CANVAS_SCALE = 0.2f; private static final double IDEAL_FRAMES = 60; private static final int LABELOFFSET = 100; private static Paint whiteLabels; - private static double viewportCoverage(int l, int b, int r, int t, - int tileIndexX, - int tileIndexY) { - if (tileIndexX * PlaybackView.TILEX < r - && (tileIndexX + 1) * PlaybackView.TILEX >= l - && tileIndexY * PlaybackView.TILEY < t - && (tileIndexY + 1) * PlaybackView.TILEY >= b) { + private static double viewportCoverage(TileData view, TileData tile) { + if (tile.left < view.right + && tile.right >= view.left + && tile.top < view.bottom + && tile.bottom >= view.top) { return 1.0f; } return 0.0f; @@ -76,13 +74,10 @@ public class PlaybackGraphs { // coverage graph @Override public double getValue(TileData[] frame) { - int l = frame[0].x, b = frame[0].y; - int r = frame[1].x, t = frame[1].y; double total = 0, totalCount = 0; - for (int tileID = 2; tileID < frame.length; tileID++) { + for (int tileID = 1; tileID < frame.length; tileID++) { TileData data = frame[tileID]; - double coverage = viewportCoverage(l, b, r, t, data.x, - data.y); + double coverage = viewportCoverage(frame[0], data); total += coverage * (data.isReady ? 1 : 0); totalCount += coverage; } @@ -158,7 +153,7 @@ public class PlaybackGraphs { public PlaybackGraphs() { whiteLabels = new Paint(); whiteLabels.setColor(Color.WHITE); - whiteLabels.setTextSize(PlaybackView.TILEY / 3); + whiteLabels.setTextSize(PlaybackView.TILE_SCALE / 3); } private ArrayList<ShapeDrawable> mShapes = new ArrayList<ShapeDrawable>(); @@ -177,11 +172,13 @@ public class PlaybackGraphs { int lastBar = 0; for (int frameIndex = 0; frameIndex < tileProfilingData.length; frameIndex++) { TileData frame[] = tileProfilingData[frameIndex]; - int newBar = (frame[0].y + frame[1].y) / 2; + int newBar = (frame[0].top + frame[0].bottom) / 2; MetricGen s = Metrics[metricIndex]; double absoluteValue = s.getValue(frame); double relativeValue = absoluteValue / s.getMax(); + relativeValue = Math.min(1,relativeValue); + relativeValue = Math.max(0,relativeValue); int rightPos = (int) (-BAR_WIDTH * metricIndex); int leftPos = (int) (-BAR_WIDTH * (metricIndex + relativeValue)); @@ -207,7 +204,7 @@ public class PlaybackGraphs { ArrayList<ShapeDrawable> shapes) { // Shapes drawn here are drawn relative to the viewRect Rect viewRect = shapes.get(shapes.size() - 1).getBounds(); - canvas.translate(0, 5 * PlaybackView.TILEY - viewRect.top); + canvas.translate(0, 5 * PlaybackView.TILE_SCALE - viewRect.top); for (ShapeDrawable shape : mShapes) { shape.draw(canvas); @@ -234,13 +231,15 @@ public class PlaybackGraphs { int yPos = LABELOFFSET; canvas.drawText(label, xPos, yPos, whiteLabels); for (int statIndex = 0; statIndex < Stats.length; statIndex++) { - label = resources.getString(R.string.format_stat, mStats[metricIndex][statIndex]); - yPos = LABELOFFSET + (1 + statIndex) * PlaybackView.TILEY / 2; + label = resources.getString(R.string.format_stat, + mStats[metricIndex][statIndex]); + yPos = LABELOFFSET + (1 + statIndex) * PlaybackView.TILE_SCALE + / 2; canvas.drawText(label, xPos, yPos, whiteLabels); } } for (int stringIndex = 0; stringIndex < strings.length; stringIndex++) { - int yPos = LABELOFFSET + stringIndex * PlaybackView.TILEY / 2; + int yPos = LABELOFFSET + stringIndex * PlaybackView.TILE_SCALE / 2; canvas.drawText(strings[stringIndex], 0, yPos, whiteLabels); } } diff --git a/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackView.java b/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackView.java index f104eac..edc8643 100644 --- a/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackView.java +++ b/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackView.java @@ -16,6 +16,9 @@ package com.test.tilebenchmark; +import android.animation.ArgbEvaluator; +import android.animation.ObjectAnimator; +import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; @@ -30,8 +33,9 @@ import android.view.View; import java.util.ArrayList; public class PlaybackView extends View { - public static final int TILEX = 300; - public static final int TILEY = 300; + public static final int TILE_SCALE = 300; + private static final int INVAL_FLAG = -2; + private static final int INVAL_CYCLE = 250; private Paint levelPaint = null, coordPaint = null, goldPaint = null; private PlaybackGraphs mGraphs; @@ -39,28 +43,46 @@ public class PlaybackView extends View { private ArrayList<ShapeDrawable> mTempShapes = new ArrayList<ShapeDrawable>(); private TileData mProfData[][] = null; private GestureDetector mGestureDetector = null; - private String mRenderStrings[] = new String[3]; + private String mRenderStrings[] = new String[4]; private class TileDrawable extends ShapeDrawable { TileData tile; + String label; - public TileDrawable(TileData t) { - int tileColorId = t.isReady ? R.color.ready_tile - : R.color.unready_tile; - getPaint().setColor(getResources().getColor(tileColorId)); - - setBounds(t.x * TILEX, t.y * TILEY, (t.x + 1) * TILEX, (t.y + 1) - * TILEY); + public TileDrawable(TileData t, int colorId) { this.tile = t; + getPaint().setColor(getResources().getColor(colorId)); + if (colorId == R.color.ready_tile + || colorId == R.color.unready_tile) { + + label = (int) (t.left / TILE_SCALE) + ", " + + (int) (t.top / TILE_SCALE); + // ignore scale value for tiles + setBounds(t.left, t.top, + t.right, t.bottom); + } else { + setBounds((int) (t.left * t.scale), + (int) (t.top * t.scale), + (int) (t.right * t.scale), + (int) (t.bottom * t.scale)); + } + } + + @SuppressWarnings("unused") + public void setColor(int color) { + getPaint().setColor(color); } @Override public void draw(Canvas canvas) { super.draw(canvas); - canvas.drawText(Integer.toString(tile.level), getBounds().left, - getBounds().bottom, levelPaint); - canvas.drawText(tile.x + "," + tile.y, getBounds().left, - ((getBounds().bottom + getBounds().top) / 2), coordPaint); + if (label != null) { + canvas.drawText(Integer.toString(tile.level), getBounds().left, + getBounds().bottom, levelPaint); + canvas.drawText(label, getBounds().left, + ((getBounds().bottom + getBounds().top) / 2), + coordPaint); + } } } @@ -92,10 +114,10 @@ public class PlaybackView extends View { private void init() { levelPaint = new Paint(); levelPaint.setColor(Color.WHITE); - levelPaint.setTextSize(TILEY / 2); + levelPaint.setTextSize(TILE_SCALE / 2); coordPaint = new Paint(); coordPaint.setColor(Color.BLACK); - coordPaint.setTextSize(TILEY / 3); + coordPaint.setTextSize(TILE_SCALE / 3); goldPaint = new Paint(); goldPaint.setColor(0xffa0e010); mGraphs = new PlaybackGraphs(); @@ -110,6 +132,7 @@ public class PlaybackView extends View { } mGraphs.draw(canvas, mTempShapes, mRenderStrings, getResources()); + invalidate(); // may have animations, force redraw } public int setFrame(int frame) { @@ -117,35 +140,66 @@ public class PlaybackView extends View { return 0; } - int readyTiles = 0, unreadyTiles = 0, unplacedTiles = 0; + int readyTiles = 0, unreadyTiles = 0, unplacedTiles = 0, numInvals = 0; mTempShapes.clear(); - // draw actual tiles - for (int tileID = 2; tileID < mProfData[frame].length; tileID++) { - TileData t = mProfData[frame][tileID]; - mTempShapes.add(new TileDrawable(t)); - if (t.isReady) { - readyTiles++; + // create tile shapes (as they're drawn on bottom) + for (TileData t : mProfData[frame]) { + if (t.level != INVAL_FLAG && t != mProfData[frame][0]) { + int colorId; + if (t.isReady) { + readyTiles++; + colorId = R.color.ready_tile; + } else { + unreadyTiles++; + colorId = R.color.unready_tile; + } + if (t.left < 0 || t.top < 0) { + unplacedTiles++; + } + mTempShapes.add(new TileDrawable(t, colorId)); } else { - unreadyTiles++; + numInvals++; } - if (t.x < 0 || t.y < 0) { - unplacedTiles++; + } + + // create invalidate shapes (drawn above tiles) + int invalId = 0; + for (TileData t : mProfData[frame]) { + if (t.level == INVAL_FLAG && t != mProfData[frame][0]) { + TileDrawable invalShape = new TileDrawable(t, + R.color.inval_region_start); + ValueAnimator tileAnimator = ObjectAnimator.ofInt(invalShape, + "color", + getResources().getColor(R.color.inval_region_start), + getResources().getColor(R.color.inval_region_stop)); + tileAnimator.setDuration(numInvals * INVAL_CYCLE); + tileAnimator.setEvaluator(new ArgbEvaluator()); + tileAnimator.setRepeatCount(ValueAnimator.INFINITE); + tileAnimator.setRepeatMode(ValueAnimator.RESTART); + float delay = (float) (invalId) * INVAL_CYCLE; + tileAnimator.setStartDelay((int) delay); + invalId++; + tileAnimator.start(); + + mTempShapes.add(invalShape); } } + mRenderStrings[0] = getResources().getString(R.string.format_stat_name, getResources().getString(R.string.ready_tiles), readyTiles); mRenderStrings[1] = getResources().getString(R.string.format_stat_name, getResources().getString(R.string.unready_tiles), unreadyTiles); mRenderStrings[2] = getResources().getString(R.string.format_stat_name, - getResources().getString(R.string.unplaced_tiles), unplacedTiles); - - // draw view rect (using first two TileData objects) - ShapeDrawable viewShape = new ShapeDrawable(); - viewShape.getPaint().setColor(0xff0000ff); - viewShape.setAlpha(64); - viewShape.setBounds(mProfData[frame][0].x, mProfData[frame][0].y, - mProfData[frame][1].x, mProfData[frame][1].y); + getResources().getString(R.string.unplaced_tiles), + unplacedTiles); + mRenderStrings[3] = getResources().getString(R.string.format_stat_name, + getResources().getString(R.string.number_invalidates), + numInvals); + + // draw view rect (using first TileData object, on top) + TileDrawable viewShape = new TileDrawable(mProfData[frame][0], + R.color.view); mTempShapes.add(viewShape); this.invalidate(); return frame; diff --git a/tests/TileBenchmark/src/com/test/tilebenchmark/ProfileActivity.java b/tests/TileBenchmark/src/com/test/tilebenchmark/ProfileActivity.java index 23b6275..1521807 100644 --- a/tests/TileBenchmark/src/com/test/tilebenchmark/ProfileActivity.java +++ b/tests/TileBenchmark/src/com/test/tilebenchmark/ProfileActivity.java @@ -38,6 +38,7 @@ import android.widget.EditText; import android.widget.Spinner; import android.widget.TextView; import android.widget.TextView.OnEditorActionListener; +import android.widget.ToggleButton; import java.io.FileOutputStream; import java.io.IOException; @@ -58,11 +59,24 @@ public class ProfileActivity extends Activity { // before test Button mInspectButton; + ToggleButton mCaptureButton; Spinner mVelocitySpinner; + Spinner mMovementSpinner; EditText mUrl; ProfiledWebView mWeb; ProfileCallback mCallback; + LoggingWebViewClient mLoggingWebViewClient = new LoggingWebViewClient(); + AutoLoggingWebViewClient mAutoLoggingWebViewClient = new AutoLoggingWebViewClient(); + + private enum TestingState { + NOT_TESTING, + PRE_TESTING, + START_TESTING, + STOP_TESTING, + SAVED_TESTING + }; + private class VelocitySelectedListener implements OnItemSelectedListener { @Override public void onItemSelected(AdapterView<?> parent, View view, @@ -77,6 +91,31 @@ public class ProfileActivity extends Activity { } } + private class MovementSelectedListener implements OnItemSelectedListener { + @Override + public void onItemSelected(AdapterView<?> parent, View view, + int position, long id) { + String movementStr = parent.getItemAtPosition(position).toString(); + if (movementStr == getResources().getString( + R.string.movement_auto_scroll) + || movementStr == getResources().getString( + R.string.movement_auto_fling)) { + mWeb.setWebViewClient(mAutoLoggingWebViewClient); + mCaptureButton.setEnabled(false); + mVelocitySpinner.setEnabled(true); + } else if (movementStr == getResources().getString( + R.string.movement_manual)) { + mWeb.setWebViewClient(mLoggingWebViewClient); + mCaptureButton.setEnabled(true); + mVelocitySpinner.setEnabled(false); + } + } + + @Override + public void onNothingSelected(AdapterView<?> parent) { + } + } + private class LoggingWebViewClient extends WebViewClient { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { @@ -88,6 +127,9 @@ public class ProfileActivity extends Activity { super.onPageStarted(view, url, favicon); mUrl.setText(url); } + } + + private class AutoLoggingWebViewClient extends LoggingWebViewClient { @Override public void onPageFinished(WebView view, String url) { @@ -100,10 +142,16 @@ public class ProfileActivity extends Activity { @Override public void onFinish() { - mWeb.startScrollTest(mCallback); + startViewProfiling(true); } }.start(); } + + @Override + public void onPageStarted(WebView view, String url, Bitmap favicon) { + super.onPageStarted(view, url, favicon); + setTestingState(TestingState.PRE_TESTING); + } } private class StoreFileTask extends @@ -125,24 +173,65 @@ public class ProfileActivity extends Activity { @Override protected void onPostExecute(Void v) { - mUrl.setBackgroundResource(R.color.finished_url); + setTestingState(TestingState.SAVED_TESTING); } } + public void setTestingState(TestingState state) { + switch (state) { + case NOT_TESTING: + mUrl.setBackgroundResource(R.color.background_not_testing); + mInspectButton.setEnabled(true); + mMovementSpinner.setEnabled(true); + break; + case PRE_TESTING: + mInspectButton.setEnabled(false); + mMovementSpinner.setEnabled(false); + break; + case START_TESTING: + mUrl.setBackgroundResource(R.color.background_start_testing); + mInspectButton.setEnabled(false); + mMovementSpinner.setEnabled(false); + break; + case STOP_TESTING: + mUrl.setBackgroundResource(R.color.background_stop_testing); + break; + case SAVED_TESTING: + mInspectButton.setEnabled(true); + mMovementSpinner.setEnabled(true); + break; + } + } + + /** auto - automatically scroll. */ + private void startViewProfiling(boolean auto) { + if (!auto) { + // manual, toggle capture button to indicate capture state to user + mCaptureButton.setChecked(true); + } + mWeb.startScrollTest(mCallback, auto); + setTestingState(TestingState.START_TESTING); + } + /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mInspectButton = (Button) findViewById(R.id.inspect); + mCaptureButton = (ToggleButton) findViewById(R.id.capture); mVelocitySpinner = (Spinner) findViewById(R.id.velocity); + mMovementSpinner = (Spinner) findViewById(R.id.movement); mUrl = (EditText) findViewById(R.id.url); mWeb = (ProfiledWebView) findViewById(R.id.web); mCallback = new ProfileCallback() { @SuppressWarnings("unchecked") @Override public void profileCallback(TileData[][] data) { - new StoreFileTask().execute(new Pair<String, TileData[][]>(TEMP_FILENAME, data)); + new StoreFileTask().execute(new Pair<String, TileData[][]>( + TEMP_FILENAME, data)); + mCaptureButton.setChecked(false); + setTestingState(TestingState.STOP_TESTING); } }; @@ -166,6 +255,33 @@ public class ProfileActivity extends Activity { new VelocitySelectedListener()); mVelocitySpinner.setSelection(3); + // Movement spinner + String content[] = { + getResources().getString(R.string.movement_auto_scroll), + getResources().getString(R.string.movement_auto_fling), + getResources().getString(R.string.movement_manual) + }; + adapter = new ArrayAdapter<CharSequence>(this, + android.R.layout.simple_spinner_item, content); + adapter.setDropDownViewResource( + android.R.layout.simple_spinner_dropdown_item); + mMovementSpinner.setAdapter(adapter); + mMovementSpinner.setOnItemSelectedListener( + new MovementSelectedListener()); + mMovementSpinner.setSelection(0); + + // Capture toggle button + mCaptureButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + if (mCaptureButton.isChecked()) { + startViewProfiling(false); + } else { + mWeb.stopScrollTest(); + } + } + }); + // Custom profiling WebView WebSettings settings = mWeb.getSettings(); settings.setJavaScriptEnabled(true); @@ -180,12 +296,13 @@ public class ProfileActivity extends Activity { public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { String url = mUrl.getText().toString(); - mUrl.setBackgroundResource(R.color.unfinished_url); mWeb.loadUrl(url); mWeb.requestFocus(); return true; } }); + + setTestingState(TestingState.NOT_TESTING); } public void setCallback(ProfileCallback callback) { diff --git a/tests/TileBenchmark/src/com/test/tilebenchmark/ProfiledWebView.java b/tests/TileBenchmark/src/com/test/tilebenchmark/ProfiledWebView.java index 6560624..d3941be 100644 --- a/tests/TileBenchmark/src/com/test/tilebenchmark/ProfiledWebView.java +++ b/tests/TileBenchmark/src/com/test/tilebenchmark/ProfiledWebView.java @@ -59,12 +59,13 @@ public class ProfiledWebView extends WebView { } /* - * Called once the page is loaded to start scrolling for evaluating tiles + * Called once the page is loaded to start scrolling for evaluating tiles. + * If autoScrolling isn't set, stop must be called manually. */ - public void startScrollTest(ProfileCallback callback) { - isScrolling = true; + public void startScrollTest(ProfileCallback callback, boolean autoScrolling) { + isScrolling = autoScrolling; mCallback = callback; - super.tileProfilingStart(); + tileProfilingStart(); invalidate(); } @@ -72,19 +73,31 @@ public class ProfiledWebView extends WebView { * Called once the page has stopped scrolling */ public void stopScrollTest() { - float testRatio = super.tileProfilingStop(); + super.tileProfilingStop(); + + if (mCallback == null) { + tileProfilingClear(); + return; + } TileData data[][] = new TileData[super.tileProfilingNumFrames()][]; for (int frame = 0; frame < data.length; frame++) { data[frame] = new TileData[ - super.tileProfilingNumTilesInFrame(frame)]; + tileProfilingNumTilesInFrame(frame)]; for (int tile = 0; tile < data[frame].length; tile++) { - int x = super.tileProfilingGetX(frame, tile); - int y = super.tileProfilingGetY(frame, tile); - boolean isReady = super.tileProfilingGetReady(frame, tile); - int level = super.tileProfilingGetLevel(frame, tile); + int left = tileProfilingGetInt(frame, tile, "left"); + int top = tileProfilingGetInt(frame, tile, "top"); + int right = tileProfilingGetInt(frame, tile, "right"); + int bottom = tileProfilingGetInt(frame, tile, "bottom"); + + boolean isReady = super.tileProfilingGetInt( + frame, tile, "isReady") == 1; + int level = tileProfilingGetInt(frame, tile, "level"); + + float scale = tileProfilingGetFloat(frame, tile, "scale"); - data[frame][tile] = new TileData(x, y, isReady, level); + data[frame][tile] = new TileData(left, top, right, bottom, + isReady, level, scale); } } super.tileProfilingClear(); diff --git a/tests/TileBenchmark/src/com/test/tilebenchmark/TileData.java b/tests/TileBenchmark/src/com/test/tilebenchmark/TileData.java index 7d4bb9f..3e729a6 100644 --- a/tests/TileBenchmark/src/com/test/tilebenchmark/TileData.java +++ b/tests/TileBenchmark/src/com/test/tilebenchmark/TileData.java @@ -19,14 +19,24 @@ package com.test.tilebenchmark; import java.io.Serializable; public class TileData implements Serializable { - public int x, y; + int left, top, right, bottom; public boolean isReady; public int level; + public float scale; - public TileData(int x, int y, boolean isReady, int level) { - this.x = x; - this.y = y; + public TileData(int left, int top, int right, int bottom, boolean isReady, + int level, float scale) { + this.left = left; + this.right = right; + this.top = top; + this.bottom = bottom; this.isReady = isReady; this.level = level; + this.scale = scale; + } + + public String toString() { + return "Tile (" + left + "," + top + ")->(" + + right + "," + bottom + ")"; } } diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp index b35878a..d66cdf0 100644 --- a/tools/aapt/AaptAssets.cpp +++ b/tools/aapt/AaptAssets.cpp @@ -1852,7 +1852,7 @@ ssize_t AaptAssets::slurpFromArgs(Bundle* bundle) sp<AaptDir> assetAaptDir = makeDir(String8(kAssetDir)); AaptGroupEntry group; count = assetAaptDir->slurpFullTree(bundle, assetRoot, group, - String8(), mFullResPaths); + String8(), mFullAssetPaths); if (count < 0) { totalCount = count; goto bail; @@ -1926,7 +1926,7 @@ ssize_t AaptAssets::slurpFromArgs(Bundle* bundle) * guarantees about ordering, so we're okay with an inorder search * using whatever order the OS happens to hand back to us. */ - count = slurpFullTree(bundle, assetRoot, AaptGroupEntry(), String8(), mFullResPaths); + count = slurpFullTree(bundle, assetRoot, AaptGroupEntry(), String8(), mFullAssetPaths); if (count < 0) { /* failure; report error and remove archive */ totalCount = count; diff --git a/tools/aapt/AaptAssets.h b/tools/aapt/AaptAssets.h index a1c7c40..82dfd71 100644 --- a/tools/aapt/AaptAssets.h +++ b/tools/aapt/AaptAssets.h @@ -560,6 +560,10 @@ public: inline void setFullResPaths(sp<FilePathStore>& res) { mFullResPaths = res; } + inline sp<FilePathStore>& getFullAssetPaths() { return mFullAssetPaths; } + inline void + setFullAssetPaths(sp<FilePathStore>& res) { mFullAssetPaths = res; } + private: String8 mPackage; SortedVector<AaptGroupEntry> mGroupEntries; @@ -575,6 +579,7 @@ private: KeyedVector<String8, sp<ResourceTypeSet> >* mRes; sp<FilePathStore> mFullResPaths; + sp<FilePathStore> mFullAssetPaths; }; #endif // __AAPT_ASSETS_H diff --git a/tools/aapt/Android.mk b/tools/aapt/Android.mk index 094b7db..e507fb9 100644 --- a/tools/aapt/Android.mk +++ b/tools/aapt/Android.mk @@ -13,6 +13,8 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES := \ AaptAssets.cpp \ Command.cpp \ + CrunchCache.cpp \ + FileFinder.cpp \ Main.cpp \ Package.cpp \ StringPool.cpp \ diff --git a/tools/aapt/Bundle.h b/tools/aapt/Bundle.h index 56fe524..539c312 100644 --- a/tools/aapt/Bundle.h +++ b/tools/aapt/Bundle.h @@ -25,6 +25,7 @@ typedef enum Command { kCommandAdd, kCommandRemove, kCommandPackage, + kCommandCrunch, } Command; /* @@ -42,13 +43,14 @@ public: mManifestPackageNameOverride(NULL), mInstrumentationPackageNameOverride(NULL), mIsOverlayPackage(false), mAutoAddOverlay(false), mGenDependencies(false), - mAssetSourceDir(NULL), mProguardFile(NULL), + mAssetSourceDir(NULL), + mCrunchedOutputDir(NULL), mProguardFile(NULL), mAndroidManifestFile(NULL), mPublicOutputFile(NULL), mRClassDir(NULL), mResourceIntermediatesDir(NULL), mManifestMinSdkVersion(NULL), mMinSdkVersion(NULL), mTargetSdkVersion(NULL), mMaxSdkVersion(NULL), mVersionCode(NULL), mVersionName(NULL), mCustomPackage(NULL), mExtraPackages(NULL), mMaxResVersion(NULL), mDebugMode(false), mNonConstantId(false), mProduct(NULL), - mArgc(0), mArgv(NULL) + mUseCrunchCache(false), mArgc(0), mArgv(NULL) {} ~Bundle(void) {} @@ -106,6 +108,8 @@ public: */ const char* getAssetSourceDir() const { return mAssetSourceDir; } void setAssetSourceDir(const char* dir) { mAssetSourceDir = dir; } + const char* getCrunchedOutputDir() const { return mCrunchedOutputDir; } + void setCrunchedOutputDir(const char* dir) { mCrunchedOutputDir = dir; } const char* getProguardFile() const { return mProguardFile; } void setProguardFile(const char* file) { mProguardFile = file; } const android::Vector<const char*>& getResourceSourceDirs() const { return mResourceSourceDirs; } @@ -151,6 +155,8 @@ public: void setNonConstantId(bool val) { mNonConstantId = val; } const char* getProduct() const { return mProduct; } void setProduct(const char * val) { mProduct = val; } + void setUseCrunchCache(bool val) { mUseCrunchCache = val; } + bool getUseCrunchCache() { return mUseCrunchCache; } /* * Set and get the file specification. @@ -231,6 +237,7 @@ private: bool mAutoAddOverlay; bool mGenDependencies; const char* mAssetSourceDir; + const char* mCrunchedOutputDir; const char* mProguardFile; const char* mAndroidManifestFile; const char* mPublicOutputFile; @@ -254,6 +261,7 @@ private: bool mDebugMode; bool mNonConstantId; const char* mProduct; + bool mUseCrunchCache; /* file specification */ int mArgc; diff --git a/tools/aapt/CacheUpdater.h b/tools/aapt/CacheUpdater.h new file mode 100644 index 0000000..0e65589 --- /dev/null +++ b/tools/aapt/CacheUpdater.h @@ -0,0 +1,107 @@ +// +// Copyright 2011 The Android Open Source Project +// +// Abstraction of calls to system to make directories and delete files and +// wrapper to image processing. + +#ifndef CACHE_UPDATER_H +#define CACHE_UPDATER_H + +#include <utils/String8.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <stdio.h> +#include "Images.h" + +using namespace android; + +/** CacheUpdater + * This is a pure virtual class that declares abstractions of functions useful + * for managing a cache files. This manager is set up to be used in a + * mirror cache where the source tree is duplicated and filled with processed + * images. This class is abstracted to allow for dependency injection during + * unit testing. + * Usage: + * To update/add a file to the cache, call processImage + * To remove a file from the cache, call deleteFile + */ +class CacheUpdater { +public: + // Make sure all the directories along this path exist + virtual void ensureDirectoriesExist(String8 path) = 0; + + // Delete a file + virtual void deleteFile(String8 path) = 0; + + // Process an image from source out to dest + virtual void processImage(String8 source, String8 dest) = 0; +private: +}; + +/** SystemCacheUpdater + * This is an implementation of the above virtual cache updater specification. + * This implementations hits the filesystem to manage a cache and calls out to + * the PNG crunching in images.h to process images out to its cache components. + */ +class SystemCacheUpdater : public CacheUpdater { +public: + // Constructor to set bundle to pass to preProcessImage + SystemCacheUpdater (Bundle* b) + : bundle(b) { }; + + // Make sure all the directories along this path exist + virtual void ensureDirectoriesExist(String8 path) + { + // Check to see if we're dealing with a fully qualified path + String8 existsPath; + String8 toCreate; + String8 remains; + struct stat s; + + // Check optomistically to see if all directories exist. + // If something in the path doesn't exist, then walk the path backwards + // and find the place to start creating directories forward. + if (stat(path.string(),&s) == -1) { + // Walk backwards to find place to start creating directories + existsPath = path; + do { + // As we remove the end of existsPath add it to + // the string of paths to create. + toCreate = existsPath.getPathLeaf().appendPath(toCreate); + existsPath = existsPath.getPathDir(); + } while (stat(existsPath.string(),&s) == -1); + + // Walk forwards and build directories as we go + do { + // Advance to the next segment of the path + existsPath.appendPath(toCreate.walkPath(&remains)); + toCreate = remains; +#ifdef HAVE_MS_C_RUNTIME + _mkdir(existsPath.string()); +#else + mkdir(existsPath.string(), S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP); +#endif + } while (remains.length() > 0); + } //if + }; + + // Delete a file + virtual void deleteFile(String8 path) + { + if (remove(path.string()) != 0) + fprintf(stderr,"ERROR DELETING %s\n",path.string()); + }; + + // Process an image from source out to dest + virtual void processImage(String8 source, String8 dest) + { + // Make sure we're trying to write to a directory that is extant + ensureDirectoriesExist(dest.getPathDir()); + + preProcessImageToCache(bundle, source, dest); + }; +private: + Bundle* bundle; +}; + +#endif // CACHE_UPDATER_H
\ No newline at end of file diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp index 903c62c..daf53e0 100644 --- a/tools/aapt/Command.cpp +++ b/tools/aapt/Command.cpp @@ -1545,10 +1545,13 @@ int doPackage(Bundle* bundle) // Load the assets. assets = new AaptAssets(); - // Set up the resource gathering in assets if we're trying to make R.java + // Set up the resource gathering in assets if we're going to generate + // dependency files if (bundle->getGenDependencies()) { - sp<FilePathStore> pathStore = new FilePathStore; - assets->setFullResPaths(pathStore); + sp<FilePathStore> resPathStore = new FilePathStore; + assets->setFullResPaths(resPathStore); + sp<FilePathStore> assetPathStore = new FilePathStore; + assets->setFullAssetPaths(assetPathStore); } err = assets->slurpFromArgs(bundle); @@ -1575,9 +1578,16 @@ int doPackage(Bundle* bundle) } if (bundle->getGenDependencies()) { - dependencyFile = String8(bundle->getRClassDir()); + if (outputAPKFile) { + dependencyFile = String8(outputAPKFile); + // Strip the extension and add new one + dependencyFile = dependencyFile.getBasePath(); + dependencyFile.append(".d"); + } else { + dependencyFile = String8(bundle->getRClassDir()); + dependencyFile.appendPath("R.d"); + } // Make sure we have a clean dependency file to start with - dependencyFile.appendPath("R.d"); fp = fopen(dependencyFile, "w"); fclose(fp); } @@ -1615,19 +1625,6 @@ int doPackage(Bundle* bundle) } } - if (bundle->getGenDependencies()) { - // Now that writeResourceSymbols has taken care of writing the - // dependency targets to the dependencyFile, we'll write the - // pre-requisites. - fp = fopen(dependencyFile, "a+"); - fprintf(fp, " : "); - err = writeDependencyPreReqs(bundle, assets, fp); - - // Also manually add the AndroidManifeset since it's a non-asset - fprintf(fp, "%s \\\n", bundle->getAndroidManifestFile()); - fclose(fp); - } - // Write out the ProGuard file err = writeProguardFile(bundle, assets); if (err < 0) { @@ -1643,6 +1640,18 @@ int doPackage(Bundle* bundle) } } + if (bundle->getGenDependencies()) { + // Now that writeResourceSymbols or writeAPK has taken care of writing + // the targets to our dependency file, we'll write the prereqs + fp = fopen(dependencyFile, "a+"); + fprintf(fp, " : "); + bool includeRaw = (outputAPKFile != NULL); + err = writeDependencyPreReqs(bundle, assets, fp, includeRaw); + // Also manually add the AndroidManifeset since it's a non-asset + fprintf(fp, "%s \\\n", bundle->getAndroidManifestFile()); + fclose(fp); + } + retVal = 0; bail: if (SourcePos::hasErrors()) { @@ -1650,3 +1659,25 @@ bail: } return retVal; } + +/* + * Do PNG Crunching + * PRECONDITIONS + * -S flag points to a source directory containing drawable* folders + * -C flag points to destination directory. The folder structure in the + * source directory will be mirrored to the destination (cache) directory + * + * POSTCONDITIONS + * Destination directory will be updated to match the PNG files in + * the source directory. + */ +int doCrunch(Bundle* bundle) +{ + fprintf(stdout, "Crunching PNG Files in "); + fprintf(stdout, "source dir: %s\n", bundle->getResourceSourceDirs()[0]); + fprintf(stdout, "To destination dir: %s\n", bundle->getCrunchedOutputDir()); + + updatePreProcessedCache(bundle); + + return NO_ERROR; +} diff --git a/tools/aapt/CrunchCache.cpp b/tools/aapt/CrunchCache.cpp new file mode 100644 index 0000000..c4cf6bc --- /dev/null +++ b/tools/aapt/CrunchCache.cpp @@ -0,0 +1,104 @@ +// +// Copyright 2011 The Android Open Source Project +// +// Implementation file for CrunchCache +// This file defines functions laid out and documented in +// CrunchCache.h + +#include <utils/Vector.h> +#include <utils/String8.h> + +#include "DirectoryWalker.h" +#include "FileFinder.h" +#include "CacheUpdater.h" +#include "CrunchCache.h" + +using namespace android; + +CrunchCache::CrunchCache(String8 sourcePath, String8 destPath, FileFinder* ff) + : mSourcePath(sourcePath), mDestPath(destPath), mSourceFiles(0), mDestFiles(0), mFileFinder(ff) +{ + // We initialize the default value to return to 0 so if a file doesn't exist + // then all files are automatically "newer" than it. + + // Set file extensions to look for. Right now just pngs. + mExtensions.push(String8(".png")); + + // Load files into our data members + loadFiles(); +} + +size_t CrunchCache::crunch(CacheUpdater* cu, bool forceOverwrite) +{ + size_t numFilesUpdated = 0; + + // Iterate through the source files and compare to cache. + // After processing a file, remove it from the source files and + // from the dest files. + // We're done when we're out of files in source. + String8 relativePath; + while (mSourceFiles.size() > 0) { + // Get the full path to the source file, then convert to a c-string + // and offset our beginning pointer to the length of the sourcePath + // This efficiently strips the source directory prefix from our path. + // Also, String8 doesn't have a substring method so this is what we've + // got to work with. + const char* rPathPtr = mSourceFiles.keyAt(0).string()+mSourcePath.length(); + // Strip leading slash if present + int offset = 0; + if (rPathPtr[0] == OS_PATH_SEPARATOR) + offset = 1; + relativePath = String8(rPathPtr + offset); + + if (forceOverwrite || needsUpdating(relativePath)) { + cu->processImage(mSourcePath.appendPathCopy(relativePath), + mDestPath.appendPathCopy(relativePath)); + numFilesUpdated++; + // crunchFile(relativePath); + } + // Delete this file from the source files and (if it exists) from the + // dest files. + mSourceFiles.removeItemsAt(0); + mDestFiles.removeItem(mDestPath.appendPathCopy(relativePath)); + } + + // Iterate through what's left of destFiles and delete leftovers + while (mDestFiles.size() > 0) { + cu->deleteFile(mDestFiles.keyAt(0)); + mDestFiles.removeItemsAt(0); + } + + // Update our knowledge of the files cache + // both source and dest should be empty by now. + loadFiles(); + + return numFilesUpdated; +} + +void CrunchCache::loadFiles() +{ + // Clear out our data structures to avoid putting in duplicates + mSourceFiles.clear(); + mDestFiles.clear(); + + // Make a directory walker that points to the system. + DirectoryWalker* dw = new SystemDirectoryWalker(); + + // Load files in the source directory + mFileFinder->findFiles(mSourcePath, mExtensions, mSourceFiles,dw); + + // Load files in the destination directory + mFileFinder->findFiles(mDestPath,mExtensions,mDestFiles,dw); + + delete dw; +} + +bool CrunchCache::needsUpdating(String8 relativePath) const +{ + // Retrieve modification dates for this file entry under the source and + // cache directory trees. The vectors will return a modification date of 0 + // if the file doesn't exist. + time_t sourceDate = mSourceFiles.valueFor(mSourcePath.appendPathCopy(relativePath)); + time_t destDate = mDestFiles.valueFor(mDestPath.appendPathCopy(relativePath)); + return sourceDate > destDate; +}
\ No newline at end of file diff --git a/tools/aapt/CrunchCache.h b/tools/aapt/CrunchCache.h new file mode 100644 index 0000000..be3da5c --- /dev/null +++ b/tools/aapt/CrunchCache.h @@ -0,0 +1,102 @@ +// +// Copyright 2011 The Android Open Source Project +// +// Cache manager for pre-processed PNG files. +// Contains code for managing which PNG files get processed +// at build time. +// + +#ifndef CRUNCHCACHE_H +#define CRUNCHCACHE_H + +#include <utils/KeyedVector.h> +#include <utils/String8.h> +#include "FileFinder.h" +#include "CacheUpdater.h" + +using namespace android; + +/** CrunchCache + * This class is a cache manager which can pre-process PNG files and store + * them in a mirror-cache. It's capable of doing incremental updates to its + * cache. + * + * Usage: + * Create an instance initialized with the root of the source tree, the + * root location to store the cache files, and an instance of a file finder. + * Then update the cache by calling crunch. + */ +class CrunchCache { +public: + // Constructor + CrunchCache(String8 sourcePath, String8 destPath, FileFinder* ff); + + // Nobody should be calling the default constructor + // So this space is intentionally left blank + + // Default Copy Constructor and Destructor are fine + + /** crunch is the workhorse of this class. + * It goes through all the files found in the sourcePath and compares + * them to the cached versions in the destPath. If the optional + * argument forceOverwrite is set to true, then all source files are + * re-crunched even if they have not been modified recently. Otherwise, + * source files are only crunched when they needUpdating. Afterwards, + * we delete any leftover files in the cache that are no longer present + * in source. + * + * PRECONDITIONS: + * No setup besides construction is needed + * POSTCONDITIONS: + * The cache is updated to fully reflect all changes in source. + * The function then returns the number of files changed in cache + * (counting deletions). + */ + size_t crunch(CacheUpdater* cu, bool forceOverwrite=false); + +private: + /** loadFiles is a wrapper to the FileFinder that places matching + * files into mSourceFiles and mDestFiles. + * + * POSTCONDITIONS + * mDestFiles and mSourceFiles are refreshed to reflect the current + * state of the files in the source and dest directories. + * Any previous contents of mSourceFiles and mDestFiles are cleared. + */ + void loadFiles(); + + /** needsUpdating takes a file path + * and returns true if the file represented by this path is newer in the + * sourceFiles than in the cache (mDestFiles). + * + * PRECONDITIONS: + * mSourceFiles and mDestFiles must be initialized and filled. + * POSTCONDITIONS: + * returns true if and only if source file's modification time + * is greater than the cached file's mod-time. Otherwise returns false. + * + * USAGE: + * Should be used something like the following: + * if (needsUpdating(filePath)) + * // Recrunch sourceFile out to destFile. + * + */ + bool needsUpdating(String8 relativePath) const; + + // DATA MEMBERS ==================================================== + + String8 mSourcePath; + String8 mDestPath; + + Vector<String8> mExtensions; + + // Each vector of paths contains one entry per PNG file encountered. + // Each entry consists of a path pointing to that PNG. + DefaultKeyedVector<String8,time_t> mSourceFiles; + DefaultKeyedVector<String8,time_t> mDestFiles; + + // Pointer to a FileFinder to use + FileFinder* mFileFinder; +}; + +#endif // CRUNCHCACHE_H diff --git a/tools/aapt/DirectoryWalker.h b/tools/aapt/DirectoryWalker.h new file mode 100644 index 0000000..88031d0 --- /dev/null +++ b/tools/aapt/DirectoryWalker.h @@ -0,0 +1,98 @@ +// +// Copyright 2011 The Android Open Source Project +// +// Defines an abstraction for opening a directory on the filesystem and +// iterating through it. + +#ifndef DIRECTORYWALKER_H +#define DIRECTORYWALKER_H + +#include <dirent.h> +#include <sys/types.h> +#include <sys/param.h> +#include <sys/stat.h> +#include <unistd.h> +#include <utils/String8.h> + +#include <stdio.h> + +using namespace android; + +// Directory Walker +// This is an abstraction for walking through a directory and getting files +// and descriptions. + +class DirectoryWalker { +public: + virtual ~DirectoryWalker() {}; + virtual bool openDir(String8 path) = 0; + virtual bool openDir(const char* path) = 0; + // Advance to next directory entry + virtual struct dirent* nextEntry() = 0; + // Get the stats for the current entry + virtual struct stat* entryStats() = 0; + // Clean Up + virtual void closeDir() = 0; + // This class is able to replicate itself on the heap + virtual DirectoryWalker* clone() = 0; + + // DATA MEMBERS + // Current directory entry + struct dirent mEntry; + // Stats for that directory entry + struct stat mStats; + // Base path + String8 mBasePath; +}; + +// System Directory Walker +// This is an implementation of the above abstraction that calls +// real system calls and is fully functional. +// functions are inlined since they're very short and simple + +class SystemDirectoryWalker : public DirectoryWalker { + + // Default constructor, copy constructor, and destructor are fine +public: + virtual bool openDir(String8 path) { + mBasePath = path; + dir = NULL; + dir = opendir(mBasePath.string() ); + + if (dir == NULL) + return false; + + return true; + }; + virtual bool openDir(const char* path) { + String8 p(path); + openDir(p); + return true; + }; + // Advance to next directory entry + virtual struct dirent* nextEntry() { + struct dirent* entryPtr = readdir(dir); + if (entryPtr == NULL) + return NULL; + + mEntry = *entryPtr; + // Get stats + String8 fullPath = mBasePath.appendPathCopy(mEntry.d_name); + stat(fullPath.string(),&mStats); + return &mEntry; + }; + // Get the stats for the current entry + virtual struct stat* entryStats() { + return &mStats; + }; + virtual void closeDir() { + closedir(dir); + }; + virtual DirectoryWalker* clone() { + return new SystemDirectoryWalker(*this); + }; +private: + DIR* dir; +}; + +#endif // DIRECTORYWALKER_H diff --git a/tools/aapt/FileFinder.cpp b/tools/aapt/FileFinder.cpp new file mode 100644 index 0000000..580528d --- /dev/null +++ b/tools/aapt/FileFinder.cpp @@ -0,0 +1,113 @@ +// +// Copyright 2011 The Android Open Source Project +// + +// File Finder implementation. +// Implementation for the functions declared and documented in FileFinder.h + +#include <utils/Vector.h> +#include <utils/String8.h> +#include <utils/KeyedVector.h> + +#include <iostream> +#include <dirent.h> +#include <sys/stat.h> + +#include "DirectoryWalker.h" +#include "FileFinder.h" + +//#define DEBUG + +using android::String8; +using std::cout; +using std::endl; + +// Private function to check whether a file is a directory or not +bool isDirectory(const char* filename) { + struct stat fileStat; + if (stat(filename, &fileStat) == -1) { + return false; + } + return(S_ISDIR(fileStat.st_mode)); +} + + +// Private function to check whether a file is a regular file or not +bool isFile(const char* filename) { + struct stat fileStat; + if (stat(filename, &fileStat) == -1) { + return false; + } + return(S_ISREG(fileStat.st_mode)); +} + +bool SystemFileFinder::findFiles(String8 basePath, Vector<String8>& extensions, + KeyedVector<String8,time_t>& fileStore, + DirectoryWalker* dw) +{ + // Scan the directory pointed to by basePath + // check files and recurse into subdirectories. + if (!dw->openDir(basePath)) { + return false; + } +#ifdef DEBUG + cout << "FileFinder looking in " << basePath << endl; +#endif // DEBUG + /* + * Go through all directory entries. Check each file using checkAndAddFile + * and recurse into sub-directories. + */ + struct dirent* entry; + while ((entry = dw->nextEntry()) != NULL) { + String8 entryName(entry->d_name); + if (entry->d_name[0] == '.') // Skip hidden files and directories + continue; + + String8 fullPath = basePath.appendPathCopy(entryName); + // If this entry is a directory we'll recurse into it + if (isDirectory(fullPath.string()) ) { + DirectoryWalker* copy = dw->clone(); + findFiles(fullPath, extensions, fileStore,copy); + delete copy; + } + + // If this entry is a file, we'll pass it over to checkAndAddFile + if (isFile(fullPath.string()) ) { + checkAndAddFile(fullPath,dw->entryStats(),extensions,fileStore); + } + } + + // Clean up + dw->closeDir(); + + return true; +} + +void SystemFileFinder::checkAndAddFile(String8 path, const struct stat* stats, + Vector<String8>& extensions, + KeyedVector<String8,time_t>& fileStore) +{ +#ifdef DEBUG + cout << "Checking file " << path << "..."; +#endif // DEBUG + // Loop over the extensions, checking for a match + bool done = false; + String8 ext(path.getPathExtension()); + ext.toLower(); + for (size_t i = 0; i < extensions.size() && !done; ++i) { + String8 ext2 = extensions[i].getPathExtension(); + ext2.toLower(); + // Compare the extensions. If a match is found, add to storage. + if (ext == ext2) { +#ifdef DEBUG + cout << "Match"; +#endif // DEBUG + done = true; + fileStore.add(path,stats->st_mtime); + } + } +#ifdef DEBUG + cout << endl; +#endif //DEBUG +} + diff --git a/tools/aapt/FileFinder.h b/tools/aapt/FileFinder.h new file mode 100644 index 0000000..6974aee --- /dev/null +++ b/tools/aapt/FileFinder.h @@ -0,0 +1,80 @@ +// +// Copyright 2011 The Android Open Source Project +// + +// File Finder. +// This is a collection of useful functions for finding paths and modification +// times of files that match an extension pattern in a directory tree. +// and finding files in it. + +#ifndef FILEFINDER_H +#define FILEFINDER_H + +#include <utils/Vector.h> +#include <utils/KeyedVector.h> +#include <utils/String8.h> + +#include "DirectoryWalker.h" + +using namespace android; + +// Abstraction to allow for dependency injection. See MockFileFinder.h +// for the testing implementation. +class FileFinder { +public: + virtual bool findFiles(String8 basePath, Vector<String8>& extensions, + KeyedVector<String8,time_t>& fileStore, + DirectoryWalker* dw) = 0; + + virtual ~FileFinder() {}; +}; + +class SystemFileFinder : public FileFinder { +public: + + /* findFiles takes a path, a Vector of extensions, and a destination KeyedVector + * and places path/modification date key/values pointing to + * all files with matching extensions found into the KeyedVector + * PRECONDITIONS + * path is a valid system path + * extensions should include leading "." + * This is not necessary, but the comparison directly + * compares the end of the path string so if the "." + * is excluded there is a small chance you could have + * a false positive match. (For example: extension "png" + * would match a file called "blahblahpng") + * + * POSTCONDITIONS + * fileStore contains (in no guaranteed order) paths to all + * matching files encountered in subdirectories of path + * as keys in the KeyedVector. Each key has the modification time + * of the file as its value. + * + * Calls checkAndAddFile on each file encountered in the directory tree + * Recursively descends into subdirectories. + */ + virtual bool findFiles(String8 basePath, Vector<String8>& extensions, + KeyedVector<String8,time_t>& fileStore, + DirectoryWalker* dw); + +private: + /** + * checkAndAddFile looks at a single file path and stat combo + * to determine whether it is a matching file (by looking at + * the extension) + * + * PRECONDITIONS + * no setup is needed + * + * POSTCONDITIONS + * If the given file has a matching extension then a new entry + * is added to the KeyedVector with the path as the key and the modification + * time as the value. + * + */ + static void checkAndAddFile(String8 path, const struct stat* stats, + Vector<String8>& extensions, + KeyedVector<String8,time_t>& fileStore); + +}; +#endif // FILEFINDER_H diff --git a/tools/aapt/Images.cpp b/tools/aapt/Images.cpp index 3c471ca..311ceea 100644 --- a/tools/aapt/Images.cpp +++ b/tools/aapt/Images.cpp @@ -1080,7 +1080,128 @@ bail: return error; } +status_t preProcessImageToCache(Bundle* bundle, String8 source, String8 dest) +{ + png_structp read_ptr = NULL; + png_infop read_info = NULL; + + FILE* fp; + + image_info imageInfo; + + png_structp write_ptr = NULL; + png_infop write_info = NULL; + + status_t error = UNKNOWN_ERROR; + + // Get a file handler to read from + fp = fopen(source.string(),"rb"); + if (fp == NULL) { + fprintf(stderr, "%s ERROR: Unable to open PNG file\n", source.string()); + return error; + } + + // Call libpng to get a struct to read image data into + read_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!read_ptr) { + fclose(fp); + png_destroy_read_struct(&read_ptr, &read_info,NULL); + return error; + } + + // Call libpng to get a struct to read image info into + read_info = png_create_info_struct(read_ptr); + if (!read_info) { + fclose(fp); + png_destroy_read_struct(&read_ptr, &read_info,NULL); + return error; + } + + // Set a jump point for libpng to long jump back to on error + if (setjmp(png_jmpbuf(read_ptr))) { + fclose(fp); + png_destroy_read_struct(&read_ptr, &read_info,NULL); + return error; + } + + // Set up libpng to read from our file. + png_init_io(read_ptr,fp); + + // Actually read data from the file + read_png(source.string(), read_ptr, read_info, &imageInfo); + // We're done reading so we can clean up + // Find old file size before releasing handle + fseek(fp, 0, SEEK_END); + size_t oldSize = (size_t)ftell(fp); + fclose(fp); + png_destroy_read_struct(&read_ptr, &read_info,NULL); + + // Check to see if we're dealing with a 9-patch + // If we are, process appropriately + if (source.getBasePath().getPathExtension() == ".9") { + if (do_9patch(source.string(), &imageInfo) != NO_ERROR) { + return error; + } + } + + // Call libpng to create a structure to hold the processed image data + // that can be written to disk + write_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!write_ptr) { + png_destroy_write_struct(&write_ptr, &write_info); + return error; + } + + // Call libpng to create a structure to hold processed image info that can + // be written to disk + write_info = png_create_info_struct(write_ptr); + if (!write_info) { + png_destroy_write_struct(&write_ptr, &write_info); + return error; + } + + // Open up our destination file for writing + fp = fopen(dest.string(), "wb"); + if (!fp) { + fprintf(stderr, "%s ERROR: Unable to open PNG file\n", dest.string()); + png_destroy_write_struct(&write_ptr, &write_info); + return error; + } + + // Set up libpng to write to our file + png_init_io(write_ptr, fp); + + // Set up a jump for libpng to long jump back on on errors + if (setjmp(png_jmpbuf(write_ptr))) { + fclose(fp); + png_destroy_write_struct(&write_ptr, &write_info); + return error; + } + + // Actually write out to the new png + write_png(dest.string(), write_ptr, write_info, imageInfo, + bundle->getGrayscaleTolerance()); + + if (bundle->getVerbose()) { + // Find the size of our new file + FILE* reader = fopen(dest.string(), "rb"); + fseek(reader, 0, SEEK_END); + size_t newSize = (size_t)ftell(reader); + fclose(reader); + + float factor = ((float)newSize)/oldSize; + int percent = (int)(factor*100); + printf(" (processed image to cache entry %s: %d%% size of source)\n", + dest.string(), percent); + } + + //Clean up + fclose(fp); + png_destroy_write_struct(&write_ptr, &write_info); + + return NO_ERROR; +} status_t postProcessImage(const sp<AaptAssets>& assets, ResourceTable* table, const sp<AaptFile>& file) diff --git a/tools/aapt/Images.h b/tools/aapt/Images.h index 168e22f..4816905 100644 --- a/tools/aapt/Images.h +++ b/tools/aapt/Images.h @@ -8,11 +8,19 @@ #define IMAGES_H #include "ResourceTable.h" +#include "Bundle.h" + +#include <utils/String8.h> +#include <utils/RefBase.h> + +using android::String8; status_t preProcessImage(Bundle* bundle, const sp<AaptAssets>& assets, const sp<AaptFile>& file, String8* outNewLeafName); +status_t preProcessImageToCache(Bundle* bundle, String8 source, String8 dest); + status_t postProcessImage(const sp<AaptAssets>& assets, - ResourceTable* table, const sp<AaptFile>& file); + ResourceTable* table, const sp<AaptFile>& file); #endif diff --git a/tools/aapt/Main.cpp b/tools/aapt/Main.cpp index 8edb5b5..5135787 100644 --- a/tools/aapt/Main.cpp +++ b/tools/aapt/Main.cpp @@ -83,6 +83,9 @@ void usage(void) " %s a[dd] [-v] file.{zip,jar,apk} file1 [file2 ...]\n" " Add specified files to Zip-compatible archive.\n\n", gProgName); fprintf(stderr, + " %s c[runch] [-v] -S resource-sources ... -C output-folder ...\n" + " Do PNG preprocessing and store the results in output folder.\n\n", gProgName); + fprintf(stderr, " %s v[ersion]\n" " Print program version.\n\n", gProgName); fprintf(stderr, @@ -148,7 +151,7 @@ void usage(void) " --extra-packages\n" " generate R.java for libraries. Separate libraries with ':'.\n" " --generate-dependencies\n" - " generate a dependency file for R.java.\n" + " generate dependency files in the same directories for R.java and resource package\n" " --auto-add-overlay\n" " Automatically add resources that are only in overlays.\n" " --rename-manifest-package\n" @@ -190,6 +193,7 @@ int handleCommand(Bundle* bundle) case kCommandAdd: return doAdd(bundle); case kCommandRemove: return doRemove(bundle); case kCommandPackage: return doPackage(bundle); + case kCommandCrunch: return doCrunch(bundle); default: fprintf(stderr, "%s: requested command not yet supported\n", gProgName); return 1; @@ -227,6 +231,8 @@ int main(int argc, char* const argv[]) bundle.setCommand(kCommandRemove); else if (argv[1][0] == 'p') bundle.setCommand(kCommandPackage); + else if (argv[1][0] == 'c') + bundle.setCommand(kCommandCrunch); else { fprintf(stderr, "ERROR: Unknown command '%s'\n", argv[1]); wantUsage = true; @@ -397,6 +403,17 @@ int main(int argc, char* const argv[]) convertPath(argv[0]); bundle.addResourceSourceDir(argv[0]); break; + case 'C': + argc--; + argv++; + if (!argc) { + fprintf(stderr, "ERROR: No argument supplied for '-C' option\n"); + wantUsage = true; + goto bail; + } + convertPath(argv[0]); + bundle.setCrunchedOutputDir(argv[0]); + break; case '0': argc--; argv++; @@ -523,7 +540,9 @@ int main(int argc, char* const argv[]) bundle.setProduct(argv[0]); } else if (strcmp(cp, "-non-constant-id") == 0) { bundle.setNonConstantId(true); - } else { + } else if (strcmp(cp, "-no-crunch") == 0) { + bundle.setUseCrunchCache(true); + }else { fprintf(stderr, "ERROR: Unknown option '-%s'\n", cp); wantUsage = true; goto bail; diff --git a/tools/aapt/Main.h b/tools/aapt/Main.h index 1df1144..d20c601 100644 --- a/tools/aapt/Main.h +++ b/tools/aapt/Main.h @@ -14,12 +14,21 @@ #include "AaptAssets.h" #include "ZipFile.h" + +/* Benchmarking Flag */ +//#define BENCHMARK 1 + +#if BENCHMARK + #include <time.h> +#endif /* BENCHMARK */ + extern int doVersion(Bundle* bundle); extern int doList(Bundle* bundle); extern int doDump(Bundle* bundle); extern int doAdd(Bundle* bundle); extern int doRemove(Bundle* bundle); extern int doPackage(Bundle* bundle); +extern int doCrunch(Bundle* bundle); extern int calcPercent(long uncompressedLen, long compressedLen); @@ -27,6 +36,8 @@ extern android::status_t writeAPK(Bundle* bundle, const sp<AaptAssets>& assets, const android::String8& outputFile); +extern android::status_t updatePreProcessedCache(Bundle* bundle); + extern android::status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets); @@ -46,5 +57,6 @@ int dumpResources(Bundle* bundle); String8 getAttribute(const ResXMLTree& tree, const char* ns, const char* attr, String8* outError); -status_t writeDependencyPreReqs(Bundle* bundle, const sp<AaptAssets>& assets, FILE* fp); +status_t writeDependencyPreReqs(Bundle* bundle, const sp<AaptAssets>& assets, + FILE* fp, bool includeRaw); #endif // __MAIN_H diff --git a/tools/aapt/Package.cpp b/tools/aapt/Package.cpp index ab71f34..c9f6870 100644 --- a/tools/aapt/Package.cpp +++ b/tools/aapt/Package.cpp @@ -50,6 +50,11 @@ ssize_t processJarFiles(Bundle* bundle, ZipFile* zip); status_t writeAPK(Bundle* bundle, const sp<AaptAssets>& assets, const String8& outputFile) { + #if BENCHMARK + fprintf(stdout, "BENCHMARK: Starting APK Bundling \n"); + long startAPKTime = clock(); + #endif /* BENCHMARK */ + status_t result = NO_ERROR; ZipFile* zip = NULL; int count; @@ -172,6 +177,16 @@ status_t writeAPK(Bundle* bundle, const sp<AaptAssets>& assets, } } + if (bundle->getGenDependencies()) { + // Add this file to the dependency file + String8 dependencyFile = outputFile.getBasePath(); + dependencyFile.append(".d"); + + FILE* fp = fopen(dependencyFile.string(), "a"); + fprintf(fp, "%s \\\n", outputFile.string()); + fclose(fp); + } + assert(result == NO_ERROR); bail: @@ -187,6 +202,10 @@ bail: if (result == NO_ERROR && bundle->getVerbose()) printf("Done!\n"); + + #if BENCHMARK + fprintf(stdout, "BENCHMARK: End APK Bundling. Time Elapsed: %f ms \n",(clock() - startAPKTime)/1000.0); + #endif /* BENCHMARK */ return result; } diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp index 99e781d..cb6484f 100644 --- a/tools/aapt/Resource.cpp +++ b/tools/aapt/Resource.cpp @@ -10,6 +10,10 @@ #include "ResourceTable.h" #include "Images.h" +#include "CrunchCache.h" +#include "FileFinder.h" +#include "CacheUpdater.h" + #define NOISY(x) // x // ========================================================================== @@ -293,18 +297,19 @@ static status_t makeFileResources(Bundle* bundle, const sp<AaptAssets>& assets, static status_t preProcessImages(Bundle* bundle, const sp<AaptAssets>& assets, const sp<ResourceTypeSet>& set, const char* type) { - ResourceDirIterator it(set, String8(type)); - Vector<sp<AaptFile> > newNameFiles; - Vector<String8> newNamePaths; bool hasErrors = false; - ssize_t res; - while ((res=it.next()) == NO_ERROR) { - res = preProcessImage(bundle, assets, it.getFile(), NULL); - if (res < NO_ERROR) { - hasErrors = true; + ssize_t res = NO_ERROR; + if (bundle->getUseCrunchCache() == false) { + ResourceDirIterator it(set, String8(type)); + Vector<sp<AaptFile> > newNameFiles; + Vector<String8> newNamePaths; + while ((res=it.next()) == NO_ERROR) { + res = preProcessImage(bundle, assets, it.getFile(), NULL); + if (res < NO_ERROR) { + hasErrors = true; + } } } - return (hasErrors || (res < NO_ERROR)) ? UNKNOWN_ERROR : NO_ERROR; } @@ -754,6 +759,35 @@ status_t massageManifest(Bundle* bundle, sp<XMLNode> root) } \ } while (0) +status_t updatePreProcessedCache(Bundle* bundle) +{ + #if BENCHMARK + fprintf(stdout, "BENCHMARK: Starting PNG PreProcessing \n"); + long startPNGTime = clock(); + #endif /* BENCHMARK */ + + String8 source(bundle->getResourceSourceDirs()[0]); + String8 dest(bundle->getCrunchedOutputDir()); + + FileFinder* ff = new SystemFileFinder(); + CrunchCache cc(source,dest,ff); + + CacheUpdater* cu = new SystemCacheUpdater(bundle); + size_t numFiles = cc.crunch(cu); + + if (bundle->getVerbose()) + fprintf(stdout, "Crunched %d PNG files to update cache\n", (int)numFiles); + + delete ff; + delete cu; + + #if BENCHMARK + fprintf(stdout, "BENCHMARK: End PNG PreProcessing. Time Elapsed: %f ms \n" + ,(clock() - startPNGTime)/1000.0); + #endif /* BENCHMARK */ + return 0; +} + status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets) { // First, look for a package file to parse. This is required to @@ -2261,11 +2295,11 @@ writeProguardFile(Bundle* bundle, const sp<AaptAssets>& assets) return err; } -status_t -writeDependencyPreReqs(Bundle* bundle, const sp<AaptAssets>& assets, FILE* fp) +// Loops through the string paths and writes them to the file pointer +// Each file path is written on its own line with a terminating backslash. +status_t writePathsToFile(const sp<FilePathStore>& files, FILE* fp) { status_t deps = -1; - sp<FilePathStore> files = assets->getFullResPaths(); for (size_t file_i = 0; file_i < files->size(); ++file_i) { // Add the full file path to the dependency file fprintf(fp, "%s \\\n", files->itemAt(file_i).string()); @@ -2273,3 +2307,14 @@ writeDependencyPreReqs(Bundle* bundle, const sp<AaptAssets>& assets, FILE* fp) } return deps; } + +status_t +writeDependencyPreReqs(Bundle* bundle, const sp<AaptAssets>& assets, FILE* fp, bool includeRaw) +{ + status_t deps = -1; + deps += writePathsToFile(assets->getFullResPaths(), fp); + if (includeRaw) { + deps += writePathsToFile(assets->getFullAssetPaths(), fp); + } + return deps; +} diff --git a/tools/aapt/ZipFile.h b/tools/aapt/ZipFile.h index 7877550..dbbd072 100644 --- a/tools/aapt/ZipFile.h +++ b/tools/aapt/ZipFile.h @@ -57,7 +57,7 @@ public: /* * Open a new or existing archive. */ - enum { + typedef enum { kOpenReadOnly = 0x01, kOpenReadWrite = 0x02, kOpenCreate = 0x04, // create if it doesn't exist diff --git a/tools/aapt/tests/CrunchCache_test.cpp b/tools/aapt/tests/CrunchCache_test.cpp new file mode 100644 index 0000000..20b5022 --- /dev/null +++ b/tools/aapt/tests/CrunchCache_test.cpp @@ -0,0 +1,97 @@ +// +// Copyright 2011 The Android Open Source Project +// +#include <utils/String8.h> +#include <iostream> +#include <errno.h> + +#include "CrunchCache.h" +#include "FileFinder.h" +#include "MockFileFinder.h" +#include "CacheUpdater.h" +#include "MockCacheUpdater.h" + +using namespace android; +using std::cout; +using std::endl; + +void expectEqual(int got, int expected, const char* desc) { + cout << "Checking " << desc << ": "; + cout << "Got " << got << ", expected " << expected << "..."; + cout << ( (got == expected) ? "PASSED" : "FAILED") << endl; + errno += ((got == expected) ? 0 : 1); +} + +int main() { + + errno = 0; + + String8 source("res"); + String8 dest("res2"); + + // Create data for MockFileFinder to feed to the cache + KeyedVector<String8, time_t> sourceData; + // This shouldn't be updated + sourceData.add(String8("res/drawable/hello.png"),3); + // This should be updated + sourceData.add(String8("res/drawable/world.png"),5); + // This should cause make directory to be called + sourceData.add(String8("res/drawable-cool/hello.png"),3); + + KeyedVector<String8, time_t> destData; + destData.add(String8("res2/drawable/hello.png"),3); + destData.add(String8("res2/drawable/world.png"),3); + // this should call delete + destData.add(String8("res2/drawable/dead.png"),3); + + // Package up data and create mock file finder + KeyedVector<String8, KeyedVector<String8,time_t> > data; + data.add(source,sourceData); + data.add(dest,destData); + FileFinder* ff = new MockFileFinder(data); + CrunchCache cc(source,dest,ff); + + MockCacheUpdater* mcu = new MockCacheUpdater(); + CacheUpdater* cu(mcu); + + cout << "Running Crunch..."; + int result = cc.crunch(cu); + cout << ((result > 0) ? "PASSED" : "FAILED") << endl; + errno += ((result > 0) ? 0 : 1); + + const int EXPECTED_RESULT = 2; + expectEqual(result, EXPECTED_RESULT, "number of files touched"); + + cout << "Checking calls to deleteFile and processImage:" << endl; + const int EXPECTED_DELETES = 1; + const int EXPECTED_PROCESSED = 2; + // Deletes + expectEqual(mcu->deleteCount, EXPECTED_DELETES, "deleteFile"); + // processImage + expectEqual(mcu->processCount, EXPECTED_PROCESSED, "processImage"); + + const int EXPECTED_OVERWRITES = 3; + result = cc.crunch(cu, true); + expectEqual(result, EXPECTED_OVERWRITES, "number of files touched with overwrite"); + \ + + if (errno == 0) + cout << "ALL TESTS PASSED!" << endl; + else + cout << errno << " TESTS FAILED" << endl; + + delete ff; + delete cu; + + // TESTS BELOW WILL GO AWAY SOON + + String8 source2("ApiDemos/res"); + String8 dest2("ApiDemos/res2"); + + FileFinder* sff = new SystemFileFinder(); + CacheUpdater* scu = new SystemCacheUpdater(); + + CrunchCache scc(source2,dest2,sff); + + scc.crunch(scu); +}
\ No newline at end of file diff --git a/tools/aapt/tests/FileFinder_test.cpp b/tools/aapt/tests/FileFinder_test.cpp new file mode 100644 index 0000000..07bd665 --- /dev/null +++ b/tools/aapt/tests/FileFinder_test.cpp @@ -0,0 +1,101 @@ +// +// Copyright 2011 The Android Open Source Project +// +#include <utils/Vector.h> +#include <utils/KeyedVector.h> +#include <iostream> +#include <cassert> +#include <utils/String8.h> +#include <utility> + +#include "DirectoryWalker.h" +#include "MockDirectoryWalker.h" +#include "FileFinder.h" + +using namespace android; + +using std::pair; +using std::cout; +using std::endl; + + + +int main() +{ + + cout << "\n\n STARTING FILE FINDER TESTS" << endl; + String8 path("ApiDemos"); + + // Storage to pass to findFiles() + KeyedVector<String8,time_t> testStorage; + + // Mock Directory Walker initialization. First data, then sdw + Vector< pair<String8,time_t> > data; + data.push( pair<String8,time_t>(String8("hello.png"),3) ); + data.push( pair<String8,time_t>(String8("world.PNG"),3) ); + data.push( pair<String8,time_t>(String8("foo.pNg"),3) ); + // Neither of these should be found + data.push( pair<String8,time_t>(String8("hello.jpg"),3) ); + data.push( pair<String8,time_t>(String8(".hidden.png"),3)); + + DirectoryWalker* sdw = new StringDirectoryWalker(path,data); + + // Extensions to look for + Vector<String8> exts; + exts.push(String8(".png")); + + errno = 0; + + // Make sure we get a valid mock directory walker + // Make sure we finish without errors + cout << "Checking DirectoryWalker..."; + assert(sdw != NULL); + cout << "PASSED" << endl; + + // Make sure we finish without errors + cout << "Running findFiles()..."; + bool findStatus = FileFinder::findFiles(path,exts, testStorage, sdw); + assert(findStatus); + cout << "PASSED" << endl; + + const size_t SIZE_EXPECTED = 3; + // Check to make sure we have the right number of things in our storage + cout << "Running size comparison: Size is " << testStorage.size() << ", "; + cout << "Expected " << SIZE_EXPECTED << "..."; + if(testStorage.size() == SIZE_EXPECTED) + cout << "PASSED" << endl; + else { + cout << "FAILED" << endl; + errno++; + } + + // Check to make sure that each of our found items has the right extension + cout << "Checking Returned Extensions..."; + bool extsOkay = true; + String8 wrongExts; + for (size_t i = 0; i < SIZE_EXPECTED; ++i) { + String8 testExt(testStorage.keyAt(i).getPathExtension()); + testExt.toLower(); + if (testExt != ".png") { + wrongExts += testStorage.keyAt(i); + wrongExts += "\n"; + extsOkay = false; + } + } + if (extsOkay) + cout << "PASSED" << endl; + else { + cout << "FAILED" << endl; + cout << "The following extensions didn't check out" << endl << wrongExts; + } + + // Clean up + delete sdw; + + if(errno == 0) { + cout << "ALL TESTS PASSED" << endl; + } else { + cout << errno << " TESTS FAILED" << endl; + } + return errno; +}
\ No newline at end of file diff --git a/tools/aapt/tests/MockCacheUpdater.h b/tools/aapt/tests/MockCacheUpdater.h new file mode 100644 index 0000000..c7f4bd7 --- /dev/null +++ b/tools/aapt/tests/MockCacheUpdater.h @@ -0,0 +1,40 @@ +// +// Copyright 2011 The Android Open Source Project +// +#ifndef MOCKCACHEUPDATER_H +#define MOCKCACHEUPDATER_H + +#include <utils/String8.h> +#include "CacheUpdater.h" + +using namespace android; + +class MockCacheUpdater : public CacheUpdater { +public: + + MockCacheUpdater() + : deleteCount(0), processCount(0) { }; + + // Make sure all the directories along this path exist + virtual void ensureDirectoriesExist(String8 path) + { + // Nothing to do + }; + + // Delete a file + virtual void deleteFile(String8 path) { + deleteCount++; + }; + + // Process an image from source out to dest + virtual void processImage(String8 source, String8 dest) { + processCount++; + }; + + // DATA MEMBERS + int deleteCount; + int processCount; +private: +}; + +#endif // MOCKCACHEUPDATER_H
\ No newline at end of file diff --git a/tools/aapt/tests/MockDirectoryWalker.h b/tools/aapt/tests/MockDirectoryWalker.h new file mode 100644 index 0000000..5900cf3 --- /dev/null +++ b/tools/aapt/tests/MockDirectoryWalker.h @@ -0,0 +1,85 @@ +// +// Copyright 2011 The Android Open Source Project +// +#ifndef MOCKDIRECTORYWALKER_H +#define MOCKDIRECTORYWALKER_H + +#include <utils/Vector.h> +#include <utils/String8.h> +#include <utility> +#include "DirectoryWalker.h" + +using namespace android; +using std::pair; + +// String8 Directory Walker +// This is an implementation of the Directory Walker abstraction that is built +// for testing. +// Instead of system calls it queries a private data structure for the directory +// entries. It takes a path and a map of filenames and their modification times. +// functions are inlined since they are short and simple + +class StringDirectoryWalker : public DirectoryWalker { +public: + StringDirectoryWalker(String8& path, Vector< pair<String8,time_t> >& data) + : mPos(0), mBasePath(path), mData(data) { + //fprintf(stdout,"StringDW built to mimic %s with %d files\n", + // mBasePath.string()); + }; + // Default copy constructor, and destructor are fine + + virtual bool openDir(String8 path) { + // If the user is trying to query the "directory" that this + // walker was initialized with, then return success. Else fail. + return path == mBasePath; + }; + virtual bool openDir(const char* path) { + String8 p(path); + openDir(p); + return true; + }; + // Advance to next entry in the Vector + virtual struct dirent* nextEntry() { + // Advance position and check to see if we're done + if (mPos >= mData.size()) + return NULL; + + // Place data in the entry descriptor. This class only returns files. + mEntry.d_type = DT_REG; + mEntry.d_ino = mPos; + // Copy chars from the string name to the entry name + size_t i = 0; + for (i; i < mData[mPos].first.size(); ++i) + mEntry.d_name[i] = mData[mPos].first[i]; + mEntry.d_name[i] = '\0'; + + // Place data in stats + mStats.st_ino = mPos; + mStats.st_mtime = mData[mPos].second; + + // Get ready to move to the next entry + mPos++; + + return &mEntry; + }; + // Get the stats for the current entry + virtual struct stat* entryStats() { + return &mStats; + }; + // Nothing to do in clean up + virtual void closeDir() { + // Nothing to do + }; + virtual DirectoryWalker* clone() { + return new StringDirectoryWalker(*this); + }; +private: + // Current position in the Vector + size_t mPos; + // Base path + String8 mBasePath; + // Data to simulate a directory full of files. + Vector< pair<String8,time_t> > mData; +}; + +#endif // MOCKDIRECTORYWALKER_H
\ No newline at end of file diff --git a/tools/aapt/tests/MockFileFinder.h b/tools/aapt/tests/MockFileFinder.h new file mode 100644 index 0000000..da5ea4f --- /dev/null +++ b/tools/aapt/tests/MockFileFinder.h @@ -0,0 +1,55 @@ +// +// Copyright 2011 The Android Open Source Project +// + +#ifndef MOCKFILEFINDER_H +#define MOCKFILEFINDER_H + +#include <utils/Vector.h> +#include <utils/KeyedVector.h> +#include <utils/String8.h> + +#include "DirectoryWalker.h" + +using namespace android; + +class MockFileFinder : public FileFinder { +public: + MockFileFinder (KeyedVector<String8, KeyedVector<String8,time_t> >& files) + : mFiles(files) + { + // Nothing left to do + }; + + /** + * findFiles implementation for the abstraction. + * PRECONDITIONS: + * No checking is done, so there MUST be an entry in mFiles with + * path matching basePath. + * + * POSTCONDITIONS: + * fileStore is filled with a copy of the data in mFiles corresponding + * to the basePath. + */ + + virtual bool findFiles(String8 basePath, Vector<String8>& extensions, + KeyedVector<String8,time_t>& fileStore, + DirectoryWalker* dw) + { + const KeyedVector<String8,time_t>* payload(&mFiles.valueFor(basePath)); + // Since KeyedVector doesn't implement swap + // (who doesn't use swap??) we loop and add one at a time. + for (size_t i = 0; i < payload->size(); ++i) { + fileStore.add(payload->keyAt(i),payload->valueAt(i)); + } + return true; + } + +private: + // Virtual mapping between "directories" and the "files" contained + // in them + KeyedVector<String8, KeyedVector<String8,time_t> > mFiles; +}; + + +#endif // MOCKFILEFINDER_H
\ No newline at end of file diff --git a/wifi/java/android/net/wifi/StateChangeResult.java b/wifi/java/android/net/wifi/StateChangeResult.java new file mode 100644 index 0000000..8ab5982 --- /dev/null +++ b/wifi/java/android/net/wifi/StateChangeResult.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + package android.net.wifi; + +/** + * Stores supplicant state change information passed from WifiMonitor to + * a state machine. WifiStateMachine, SupplicantStateTracker and WpsStateMachine + * are example state machines that handle it. + * @hide + */ +public class StateChangeResult { + StateChangeResult(int networkId, String BSSID, SupplicantState state) { + this.state = state; + this.BSSID = BSSID; + this.networkId = networkId; + } + int networkId; + String BSSID; + SupplicantState state; +} diff --git a/wifi/java/android/net/wifi/SupplicantStateTracker.java b/wifi/java/android/net/wifi/SupplicantStateTracker.java index 0c4f9f6..9168e62 100644 --- a/wifi/java/android/net/wifi/SupplicantStateTracker.java +++ b/wifi/java/android/net/wifi/SupplicantStateTracker.java @@ -19,7 +19,7 @@ package android.net.wifi; import com.android.internal.util.State; import com.android.internal.util.StateMachine; -import android.net.wifi.WifiStateMachine.StateChangeResult; +import android.net.wifi.StateChangeResult; import android.content.Context; import android.content.Intent; import android.os.Handler; @@ -159,11 +159,11 @@ class SupplicantStateTracker extends StateMachine { public boolean processMessage(Message message) { if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); switch (message.what) { - case WifiStateMachine.AUTHENTICATION_FAILURE_EVENT: + case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: mAuthenticationFailuresCount++; mAuthFailureInSupplicantBroadcast = true; break; - case WifiStateMachine.SUPPLICANT_STATE_CHANGE_EVENT: + case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: StateChangeResult stateChangeResult = (StateChangeResult) message.obj; SupplicantState state = stateChangeResult.state; sendSupplicantStateChangedBroadcast(state, mAuthFailureInSupplicantBroadcast); @@ -251,7 +251,7 @@ class SupplicantStateTracker extends StateMachine { public boolean processMessage(Message message) { if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); switch (message.what) { - case WifiStateMachine.SUPPLICANT_STATE_CHANGE_EVENT: + case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: StateChangeResult stateChangeResult = (StateChangeResult) message.obj; SupplicantState state = stateChangeResult.state; if (SupplicantState.isHandshakeState(state)) { @@ -293,7 +293,7 @@ class SupplicantStateTracker extends StateMachine { public boolean processMessage(Message message) { if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); switch(message.what) { - case WifiStateMachine.SUPPLICANT_STATE_CHANGE_EVENT: + case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: StateChangeResult stateChangeResult = (StateChangeResult) message.obj; SupplicantState state = stateChangeResult.state; sendSupplicantStateChangedBroadcast(state, mAuthFailureInSupplicantBroadcast); diff --git a/wifi/java/android/net/wifi/WifiMonitor.java b/wifi/java/android/net/wifi/WifiMonitor.java index 4ec4cfc..2ccc8a2 100644 --- a/wifi/java/android/net/wifi/WifiMonitor.java +++ b/wifi/java/android/net/wifi/WifiMonitor.java @@ -16,15 +16,24 @@ package android.net.wifi; -import android.util.Log; import android.net.NetworkInfo; +import android.net.wifi.p2p.WifiP2pConfig; +import android.net.wifi.p2p.WifiP2pDevice; +import android.net.wifi.p2p.WifiP2pGroup; +import android.net.wifi.StateChangeResult; +import android.os.Message; +import android.util.Log; + + +import com.android.internal.util.Protocol; +import com.android.internal.util.StateMachine; import java.util.regex.Pattern; import java.util.regex.Matcher; /** * Listens for events from the wpa_supplicant server, and passes them on - * to the {@link WifiStateMachine} for handling. Runs in its own thread. + * to the {@link StateMachine} for handling. Runs in its own thread. * * @hide */ @@ -45,16 +54,16 @@ public class WifiMonitor { private static final int UNKNOWN = 9; /** All events coming from the supplicant start with this prefix */ - private static final String eventPrefix = "CTRL-EVENT-"; - private static final int eventPrefixLen = eventPrefix.length(); + private static final String EVENT_PREFIX_STR = "CTRL-EVENT-"; + private static final int EVENT_PREFIX_LEN_STR = EVENT_PREFIX_STR.length(); /** All WPA events coming from the supplicant start with this prefix */ - private static final String wpaEventPrefix = "WPA:"; - private static final String passwordKeyMayBeIncorrectEvent = + private static final String WPA_EVENT_PREFIX_STR = "WPA:"; + private static final String PASSWORD_MAY_BE_INCORRECT_STR = "pre-shared key may be incorrect"; /* WPS events */ - private static final String wpsOverlapEvent = "WPS-OVERLAP-DETECTED"; + private static final String WPS_OVERLAP_STR = "WPS-OVERLAP-DETECTED"; /** * Names of events from wpa_supplicant (minus the prefix). In the @@ -68,26 +77,26 @@ public class WifiMonitor { * </pre> * <code>xx:xx:xx:xx:xx:xx</code> is the BSSID of the associated access point */ - private static final String connectedEvent = "CONNECTED"; + private static final String CONNECTED_STR = "CONNECTED"; /** * <pre> * CTRL-EVENT-DISCONNECTED - Disconnect event - remove keys * </pre> */ - private static final String disconnectedEvent = "DISCONNECTED"; + private static final String DISCONNECTED_STR = "DISCONNECTED"; /** * <pre> * CTRL-EVENT-STATE-CHANGE x * </pre> * <code>x</code> is the numerical value of the new state. */ - private static final String stateChangeEvent = "STATE-CHANGE"; + private static final String STATE_CHANGE_STR = "STATE-CHANGE"; /** * <pre> * CTRL-EVENT-SCAN-RESULTS ready * </pre> */ - private static final String scanResultsEvent = "SCAN-RESULTS"; + private static final String SCAN_RESULTS_STR = "SCAN-RESULTS"; /** * <pre> @@ -95,32 +104,32 @@ public class WifiMonitor { * </pre> * {@code x} is the link speed in Mb/sec. */ - private static final String linkSpeedEvent = "LINK-SPEED"; + private static final String LINK_SPEED_STR = "LINK-SPEED"; /** * <pre> * CTRL-EVENT-TERMINATING - signal x * </pre> * <code>x</code> is the signal that caused termination. */ - private static final String terminatingEvent = "TERMINATING"; + private static final String TERMINATING_STR = "TERMINATING"; /** * <pre> * CTRL-EVENT-DRIVER-STATE state * </pre> * <code>state</code> can be HANGED */ - private static final String driverStateEvent = "DRIVER-STATE"; + private static final String DRIVER_STATE_STR = "DRIVER-STATE"; /** * <pre> * CTRL-EVENT-EAP-FAILURE EAP authentication failed * </pre> */ - private static final String eapFailureEvent = "EAP-FAILURE"; + private static final String EAP_FAILURE_STR = "EAP-FAILURE"; /** * This indicates an authentication failure on EAP FAILURE event */ - private static final String eapAuthFailure = "EAP authentication failed"; + private static final String EAP_AUTH_FAILURE_STR = "EAP authentication failed"; /** * Regex pattern for extracting an Ethernet-style MAC address from a string. @@ -130,17 +139,116 @@ public class WifiMonitor { private static Pattern mConnectedEventPattern = Pattern.compile("((?:[0-9a-f]{2}:){5}[0-9a-f]{2}) .* \\[id=([0-9]+) "); - private final WifiStateMachine mWifiStateMachine; + /** P2P events */ + private static final String P2P_EVENT_PREFIX_STR = "P2P"; + + /* P2P-DEVICE-FOUND fa:7b:7a:42:02:13 p2p_dev_addr=fa:7b:7a:42:02:13 pri_dev_type=1-0050F204-1 + name='p2p-TEST1' config_methods=0x188 dev_capab=0x27 group_capab=0x0 */ + private static final String P2P_DEVICE_FOUND_STR = "P2P-DEVICE-FOUND"; + + /* P2P-DEVICE-LOST p2p_dev_addr=42:fc:89:e1:e2:27 */ + private static final String P2P_DEVICE_LOST_STR = "P2P-DEVICE-LOST"; + + /* P2P-GO-NEG-REQUEST 42:fc:89:a8:96:09 dev_passwd_id=4 */ + private static final String P2P_GO_NEG_REQUEST_STR = "P2P-GO-NEG-REQUEST"; + + private static final String P2P_GO_NEG_SUCCESS_STR = "P2P-GO-NEG-SUCCESS"; + + private static final String P2P_GO_NEG_FAILURE_STR = "P2P-GO-NEG-FAILURE"; + + private static final String P2P_GROUP_FORMATION_SUCCESS_STR = + "P2P-GROUP-FORMATION-SUCCESS"; + + private static final String P2P_GROUP_FORMATION_FAILURE_STR = + "P2P-GROUP-FORMATION-FAILURE"; + + /* P2P-GROUP-STARTED p2p-wlan0-0 [client|GO] ssid="DIRECT-W8" freq=2437 + [psk=2182b2e50e53f260d04f3c7b25ef33c965a3291b9b36b455a82d77fd82ca15bc|passphrase="fKG4jMe3"] + go_dev_addr=fa:7b:7a:42:02:13 */ + private static final String P2P_GROUP_STARTED_STR = "P2P-GROUP-STARTED"; + + /* P2P-GROUP-REMOVED p2p-wlan0-0 [client|GO] reason=REQUESTED */ + private static final String P2P_GROUP_REMOVED_STR = "P2P-GROUP-REMOVED"; + + /* P2P-INVITATION-RECEIVED sa=fa:7b:7a:42:02:13 go_dev_addr=f8:7b:7a:42:02:13 + bssid=fa:7b:7a:42:82:13 unknown-network */ + private static final String P2P_INVITATION_RECEIVED_STR = "P2P-INVITATION-RECEIVED"; + + /* P2P-INVITATION-RESULT status=1 */ + private static final String P2P_INVITATION_RESULT_STR = "P2P-INVITATION-RESULT"; + + /* P2P-PROV-DISC-PBC-REQ 42:fc:89:e1:e2:27 p2p_dev_addr=42:fc:89:e1:e2:27 + pri_dev_type=1-0050F204-1 name='p2p-TEST2' config_methods=0x188 dev_capab=0x27 + group_capab=0x0 */ + private static final String P2P_PROV_DISC_PBC_REQ_STR = "P2P-PROV-DISC-PBC-REQ"; + /* P2P-PROV-DISC-ENTER-PIN 42:fc:89:e1:e2:27 p2p_dev_addr=42:fc:89:e1:e2:27 + pri_dev_type=1-0050F204-1 name='p2p-TEST2' config_methods=0x188 dev_capab=0x27 + group_capab=0x0 */ + private static final String P2P_PROV_DISC_ENTER_PIN_STR = "P2P-PROV-DISC-ENTER-PIN"; + /* P2P-PROV-DISC-SHOW-PIN 42:fc:89:e1:e2:27 44490607 p2p_dev_addr=42:fc:89:e1:e2:27 + pri_dev_type=1-0050F204-1 name='p2p-TEST2' config_methods=0x188 dev_capab=0x27 + group_capab=0x0 */ + private static final String P2P_PROV_DISC_SHOW_PIN_STR = "P2P-PROV-DISC-SHOW-PIN"; + + private static final String HOST_AP_EVENT_PREFIX_STR = "AP"; + /* AP-STA-CONNECTED 42:fc:89:a8:96:09 */ + private static final String AP_STA_CONNECTED_STR = "AP-STA-CONNECTED"; + /* AP-STA-DISCONNECTED 42:fc:89:a8:96:09 */ + private static final String AP_STA_DISCONNECTED_STR = "AP-STA-DISCONNECTED"; + + private final StateMachine mStateMachine; + + /* Supplicant events reported to a state machine */ + private static final int BASE = Protocol.BASE_WIFI_MONITOR; + + /* Connection to supplicant established */ + public static final int SUP_CONNECTION_EVENT = BASE + 1; + /* Connection to supplicant lost */ + public static final int SUP_DISCONNECTION_EVENT = BASE + 2; + /* Network connection completed */ + public static final int NETWORK_CONNECTION_EVENT = BASE + 3; + /* Network disconnection completed */ + public static final int NETWORK_DISCONNECTION_EVENT = BASE + 4; + /* Scan results are available */ + public static final int SCAN_RESULTS_EVENT = BASE + 5; + /* Supplicate state changed */ + public static final int SUPPLICANT_STATE_CHANGE_EVENT = BASE + 6; + /* Password failure and EAP authentication failure */ + public static final int AUTHENTICATION_FAILURE_EVENT = BASE + 7; + /* WPS overlap detected */ + public static final int WPS_OVERLAP_EVENT = BASE + 8; + /* Driver was hung */ + public static final int DRIVER_HUNG_EVENT = BASE + 9; + + /* P2P events */ + public static final int P2P_DEVICE_FOUND_EVENT = BASE + 21; + public static final int P2P_DEVICE_LOST_EVENT = BASE + 22; + public static final int P2P_GO_NEGOTIATION_REQUEST_EVENT = BASE + 23; + public static final int P2P_GO_NEGOTIATION_SUCCESS_EVENT = BASE + 25; + public static final int P2P_GO_NEGOTIATION_FAILURE_EVENT = BASE + 26; + public static final int P2P_GROUP_FORMATION_SUCCESS_EVENT = BASE + 27; + public static final int P2P_GROUP_FORMATION_FAILURE_EVENT = BASE + 28; + public static final int P2P_GROUP_STARTED_EVENT = BASE + 29; + public static final int P2P_GROUP_REMOVED_EVENT = BASE + 30; + public static final int P2P_INVITATION_RECEIVED_EVENT = BASE + 31; + public static final int P2P_INVITATION_RESULT_EVENT = BASE + 32; + public static final int P2P_PROV_DISC_PBC_REQ_EVENT = BASE + 33; + public static final int P2P_PROV_DISC_ENTER_PIN_EVENT = BASE + 34; + public static final int P2P_PROV_DISC_SHOW_PIN_EVENT = BASE + 35; + + /* hostap events */ + public static final int AP_STA_DISCONNECTED_EVENT = BASE + 41; + public static final int AP_STA_CONNECTED_EVENT = BASE + 42; /** * This indicates the supplicant connection for the monitor is closed */ - private static final String monitorSocketClosed = "connection closed"; + private static final String MONITOR_SOCKET_CLOSED_STR = "connection closed"; /** * This indicates a read error on the monitor socket conenction */ - private static final String wpaRecvError = "recv error"; + private static final String WPA_RECV_ERROR_STR = "recv error"; /** * Tracks consecutive receive errors @@ -152,8 +260,8 @@ public class WifiMonitor { */ private static final int MAX_RECV_ERRORS = 10; - public WifiMonitor(WifiStateMachine wifiStateMachine) { - mWifiStateMachine = wifiStateMachine; + public WifiMonitor(StateMachine wifiStateMachine) { + mStateMachine = wifiStateMachine; } public void startMonitoring() { @@ -170,9 +278,9 @@ public class WifiMonitor { if (connectToSupplicant()) { // Send a message indicating that it is now possible to send commands // to the supplicant - mWifiStateMachine.notifySupplicantConnection(); + mStateMachine.sendMessage(SUP_CONNECTION_EVENT); } else { - mWifiStateMachine.notifySupplicantLost(); + mStateMachine.sendMessage(SUP_DISCONNECTION_EVENT); return; } @@ -181,20 +289,24 @@ public class WifiMonitor { String eventStr = WifiNative.waitForEvent(); // Skip logging the common but mostly uninteresting scan-results event - if (false && eventStr.indexOf(scanResultsEvent) == -1) { - Log.v(TAG, "Event [" + eventStr + "]"); + if (false && eventStr.indexOf(SCAN_RESULTS_STR) == -1) { + Log.d(TAG, "Event [" + eventStr + "]"); } - if (!eventStr.startsWith(eventPrefix)) { - if (eventStr.startsWith(wpaEventPrefix) && - 0 < eventStr.indexOf(passwordKeyMayBeIncorrectEvent)) { - mWifiStateMachine.notifyAuthenticationFailure(); - } else if (eventStr.startsWith(wpsOverlapEvent)) { - mWifiStateMachine.notifyWpsOverlap(); + if (!eventStr.startsWith(EVENT_PREFIX_STR)) { + if (eventStr.startsWith(WPA_EVENT_PREFIX_STR) && + 0 < eventStr.indexOf(PASSWORD_MAY_BE_INCORRECT_STR)) { + mStateMachine.sendMessage(AUTHENTICATION_FAILURE_EVENT); + } else if (eventStr.startsWith(WPS_OVERLAP_STR)) { + mStateMachine.sendMessage(WPS_OVERLAP_EVENT); + } else if (eventStr.startsWith(P2P_EVENT_PREFIX_STR)) { + handleP2pEvents(eventStr); + } else if (eventStr.startsWith(HOST_AP_EVENT_PREFIX_STR)) { + handleHostApEvents(eventStr); } continue; } - String eventName = eventStr.substring(eventPrefixLen); + String eventName = eventStr.substring(EVENT_PREFIX_LEN_STR); int nameEnd = eventName.indexOf(' '); if (nameEnd != -1) eventName = eventName.substring(0, nameEnd); @@ -206,21 +318,21 @@ public class WifiMonitor { * Map event name into event enum */ int event; - if (eventName.equals(connectedEvent)) + if (eventName.equals(CONNECTED_STR)) event = CONNECTED; - else if (eventName.equals(disconnectedEvent)) + else if (eventName.equals(DISCONNECTED_STR)) event = DISCONNECTED; - else if (eventName.equals(stateChangeEvent)) + else if (eventName.equals(STATE_CHANGE_STR)) event = STATE_CHANGE; - else if (eventName.equals(scanResultsEvent)) + else if (eventName.equals(SCAN_RESULTS_STR)) event = SCAN_RESULTS; - else if (eventName.equals(linkSpeedEvent)) + else if (eventName.equals(LINK_SPEED_STR)) event = LINK_SPEED; - else if (eventName.equals(terminatingEvent)) + else if (eventName.equals(TERMINATING_STR)) event = TERMINATING; - else if (eventName.equals(driverStateEvent)) + else if (eventName.equals(DRIVER_STATE_STR)) event = DRIVER_STATE; - else if (eventName.equals(eapFailureEvent)) + else if (eventName.equals(EAP_FAILURE_STR)) event = EAP_FAILURE; else event = UNKNOWN; @@ -249,7 +361,7 @@ public class WifiMonitor { * If monitor socket is closed, we have already * stopped the supplicant, simply exit the monitor thread */ - if (eventData.startsWith(monitorSocketClosed)) { + if (eventData.startsWith(MONITOR_SOCKET_CLOSED_STR)) { if (false) { Log.d(TAG, "Monitor socket is closed, exiting thread"); } @@ -260,7 +372,7 @@ public class WifiMonitor { * Close the supplicant connection if we see * too many recv errors */ - if (eventData.startsWith(wpaRecvError)) { + if (eventData.startsWith(WPA_RECV_ERROR_STR)) { if (++mRecvErrors > MAX_RECV_ERRORS) { if (false) { Log.d(TAG, "too many recv errors, closing connection"); @@ -271,11 +383,11 @@ public class WifiMonitor { } // notify and exit - mWifiStateMachine.notifySupplicantLost(); + mStateMachine.sendMessage(SUP_DISCONNECTION_EVENT); break; } else if (event == EAP_FAILURE) { - if (eventData.startsWith(eapAuthFailure)) { - mWifiStateMachine.notifyAuthenticationFailure(); + if (eventData.startsWith(EAP_AUTH_FAILURE_STR)) { + mStateMachine.sendMessage(AUTHENTICATION_FAILURE_EVENT); } } else { handleEvent(event, eventData); @@ -305,7 +417,7 @@ public class WifiMonitor { return; } if (state.equals("HANGED")) { - mWifiStateMachine.notifyDriverHung(); + mStateMachine.sendMessage(DRIVER_HUNG_EVENT); } } @@ -326,7 +438,7 @@ public class WifiMonitor { break; case SCAN_RESULTS: - mWifiStateMachine.notifyScanResultsAvailable(); + mStateMachine.sendMessage(SCAN_RESULTS_EVENT); break; case UNKNOWN: @@ -335,6 +447,59 @@ public class WifiMonitor { } /** + * Handle p2p events + */ + private void handleP2pEvents(String dataString) { + if (dataString.startsWith(P2P_DEVICE_FOUND_STR)) { + mStateMachine.sendMessage(P2P_DEVICE_FOUND_EVENT, new WifiP2pDevice(dataString)); + } else if (dataString.startsWith(P2P_DEVICE_LOST_STR)) { + mStateMachine.sendMessage(P2P_DEVICE_LOST_EVENT, new WifiP2pDevice(dataString)); + } else if (dataString.startsWith(P2P_GO_NEG_REQUEST_STR)) { + mStateMachine.sendMessage(P2P_GO_NEGOTIATION_REQUEST_EVENT, + new WifiP2pConfig(dataString)); + } else if (dataString.startsWith(P2P_GO_NEG_SUCCESS_STR)) { + mStateMachine.sendMessage(P2P_GO_NEGOTIATION_SUCCESS_EVENT); + } else if (dataString.startsWith(P2P_GO_NEG_FAILURE_STR)) { + mStateMachine.sendMessage(P2P_GO_NEGOTIATION_FAILURE_EVENT); + } else if (dataString.startsWith(P2P_GROUP_FORMATION_SUCCESS_STR)) { + mStateMachine.sendMessage(P2P_GROUP_FORMATION_SUCCESS_EVENT); + } else if (dataString.startsWith(P2P_GROUP_FORMATION_FAILURE_STR)) { + mStateMachine.sendMessage(P2P_GROUP_FORMATION_FAILURE_EVENT); + } else if (dataString.startsWith(P2P_GROUP_STARTED_STR)) { + mStateMachine.sendMessage(P2P_GROUP_STARTED_EVENT, new WifiP2pGroup(dataString)); + } else if (dataString.startsWith(P2P_GROUP_REMOVED_STR)) { + mStateMachine.sendMessage(P2P_GROUP_REMOVED_EVENT, new WifiP2pGroup(dataString)); + } else if (dataString.startsWith(P2P_INVITATION_RECEIVED_STR)) { + mStateMachine.sendMessage(P2P_INVITATION_RECEIVED_EVENT, + new WifiP2pGroup(dataString)); + } else if (dataString.startsWith(P2P_INVITATION_RESULT_STR)) { + String[] tokens = dataString.split(" "); + if (tokens.length != 2) return; + String[] nameValue = tokens[1].split("="); + if (nameValue.length != 2) return; + mStateMachine.sendMessage(P2P_INVITATION_RESULT_EVENT, nameValue[1]); + } else if (dataString.startsWith(P2P_PROV_DISC_PBC_REQ_STR)) { + mStateMachine.sendMessage(P2P_PROV_DISC_PBC_REQ_EVENT, + new WifiP2pDevice(dataString)); + } else if (dataString.startsWith(P2P_PROV_DISC_ENTER_PIN_STR)) { + mStateMachine.sendMessage(P2P_PROV_DISC_ENTER_PIN_EVENT, + new WifiP2pDevice(dataString)); + } + } + + /** + * Handle hostap events + */ + private void handleHostApEvents(String dataString) { + String[] tokens = dataString.split(" "); + if (tokens[0].equals(AP_STA_CONNECTED_STR)) { + mStateMachine.sendMessage(AP_STA_CONNECTED_EVENT, tokens[1]); + } else if (tokens[0].equals(AP_STA_DISCONNECTED_STR)) { + mStateMachine.sendMessage(AP_STA_DISCONNECTED_EVENT, tokens[1]); + } + } + + /** * Handle the supplicant STATE-CHANGE event * @param dataString New supplicant state string in the format: * id=network-id state=new-state @@ -383,7 +548,7 @@ public class WifiMonitor { if (newSupplicantState == SupplicantState.INVALID) { Log.w(TAG, "Invalid supplicant state: " + newState); } - mWifiStateMachine.notifySupplicantStateChange(networkId, BSSID, newSupplicantState); + notifySupplicantStateChange(networkId, BSSID, newSupplicantState); } } @@ -403,7 +568,40 @@ public class WifiMonitor { } } } - mWifiStateMachine.notifyNetworkStateChange(newState, BSSID, networkId); + notifyNetworkStateChange(newState, BSSID, networkId); + } + + /** + * Send the state machine a notification that the state of Wifi connectivity + * has changed. + * @param networkId the configured network on which the state change occurred + * @param newState the new network state + * @param BSSID when the new state is {@link DetailedState#CONNECTED + * NetworkInfo.DetailedState.CONNECTED}, + * this is the MAC address of the access point. Otherwise, it + * is {@code null}. + */ + void notifyNetworkStateChange(NetworkInfo.DetailedState newState, String BSSID, int netId) { + if (newState == NetworkInfo.DetailedState.CONNECTED) { + Message m = mStateMachine.obtainMessage(NETWORK_CONNECTION_EVENT, + netId, 0, BSSID); + mStateMachine.sendMessage(m); + } else { + Message m = mStateMachine.obtainMessage(NETWORK_DISCONNECTION_EVENT, + netId, 0, BSSID); + mStateMachine.sendMessage(m); + } + } + + /** + * Send the state machine a notification that the state of the supplicant + * has changed. + * @param networkId the configured network on which the state change occurred + * @param newState the new {@code SupplicantState} + */ + void notifySupplicantStateChange(int networkId, String BSSID, SupplicantState newState) { + mStateMachine.sendMessage(mStateMachine.obtainMessage(SUPPLICANT_STATE_CHANGE_EVENT, + new StateChangeResult(networkId, BSSID, newState))); } /** diff --git a/wifi/java/android/net/wifi/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java index 6e13d0f..3b043b3 100644 --- a/wifi/java/android/net/wifi/WifiNative.java +++ b/wifi/java/android/net/wifi/WifiNative.java @@ -16,6 +16,16 @@ package android.net.wifi; +import android.net.wifi.p2p.WifiP2pConfig; +import android.net.wifi.p2p.WifiP2pGroup; +import android.net.wifi.p2p.WifiP2pDevice; +import android.util.Log; + +import java.io.InputStream; +import java.lang.Process; +import java.util.ArrayList; +import java.util.List; + /** * Native calls for sending requests to the supplicant daemon, and for * receiving asynchronous events. All methods of the form "xxxxCommand()" @@ -28,6 +38,10 @@ package android.net.wifi; * WifiStateTracker class except for waitForEvent() call which is * on a separate monitor channel for WifiMonitor * + * TODO: clean up the API and move the functionality from JNI to here. We should + * be able to get everything done with doBooleanCommand, doIntCommand and + * doStringCommand native commands + * * {@hide} */ public class WifiNative { @@ -104,18 +118,30 @@ public class WifiNative { public native static boolean stopDriverCommand(); + + /** + * Start filtering out Multicast V4 packets + * @return {@code true} if the operation succeeded, {@code false} otherwise + */ + public native static boolean startFilteringMulticastV4Packets(); + /** - * Start filtering out multicast packets, to reduce battery consumption - * that would result from processing them, only to discard them. + * Stop filtering out Multicast V4 packets. * @return {@code true} if the operation succeeded, {@code false} otherwise */ - public native static boolean startPacketFiltering(); + public native static boolean stopFilteringMulticastV4Packets(); /** - * Stop filtering out multicast packets. + * Start filtering out Multicast V6 packets * @return {@code true} if the operation succeeded, {@code false} otherwise */ - public native static boolean stopPacketFiltering(); + public native static boolean startFilteringMulticastV6Packets(); + + /** + * Stop filtering out Multicast V6 packets. + * @return {@code true} if the operation succeeded, {@code false} otherwise + */ + public native static boolean stopFilteringMulticastV6Packets(); public native static boolean setPowerModeCommand(int mode); @@ -174,4 +200,141 @@ public class WifiNative { public native static void enableBackgroundScanCommand(boolean enable); public native static void setScanIntervalCommand(int scanInterval); + + private native static boolean doBooleanCommand(String command); + + //STOPSHIP: remove this after native interface works and replace all + //calls to doBooleanTempCommand() with doBooleanCommand() + private static boolean doBooleanTempCommand(String command) { + try { + String str = "/system/bin/wpa_cli " + command; + Log.e("WifiNative", "===> " + str); + Runtime.getRuntime() + .exec(str).waitFor(); + } catch (Exception e) { + Log.e("WifiNative", "exception with doBooleanTempCommand"); + return false; + } + return true; + } + + private static String doStringTempCommand(String command) { + String lines[] = null; + try { + String str = "/system/bin/wpa_cli " + command; + Log.e("WifiNative", "===> " + str); + Process p = Runtime.getRuntime() + .exec(str); + InputStream in = p.getInputStream(); + p.waitFor(); + byte[] bytes=new byte[in.available()]; + in.read(bytes); + String s = new String(bytes); + Log.e("WifiNative", "====> doString: " + s); + lines = s.split("\\r?\\n"); + } catch (Exception e) { + Log.e("WifiNative", "exception with doBooleanTempCommand"); + return null; + } + return lines[1]; + } + + private native static int doIntCommand(String command); + + private native static String doStringCommand(String command); + + public static boolean p2pFind() { + return doBooleanTempCommand("p2p_find"); + } + + public static boolean p2pFind(int timeout) { + if (timeout <= 0) { + return p2pFind(); + } + return doBooleanTempCommand("p2p_find " + timeout); + } + + public static boolean p2pListen() { + return doBooleanTempCommand("p2p_listen"); + } + + public static boolean p2pListen(int timeout) { + if (timeout <= 0) { + return p2pListen(); + } + return doBooleanTempCommand("p2p_listen " + timeout); + } + + public static boolean p2pFlush() { + return doBooleanTempCommand("p2p_flush"); + } + + /* p2p_connect <peer device address> <pbc|pin|PIN#> [label|display|keypad] + [persistent] [join|auth] [go_intent=<0..15>] [freq=<in MHz>] */ + public static String p2pConnect(WifiP2pConfig config) { + if (config == null) return null; + List<String> args = new ArrayList<String>(); + WpsConfiguration wpsConfig = config.wpsConfig; + args.add(config.deviceAddress); + + switch (wpsConfig.setup) { + case PBC: + args.add("pbc"); + break; + case DISPLAY: + //TODO: pass the pin back for display + args.add("pin"); + args.add("display"); + break; + case KEYPAD: + args.add(wpsConfig.pin); + args.add("keypad"); + break; + case LABEL: + args.add(wpsConfig.pin); + args.add("label"); + default: + break; + } + + if (config.isPersistent) args.add("persistent"); + if (config.joinExistingGroup) args.add("join"); + + args.add("go_intent=" + config.groupOwnerIntent); + if (config.channel > 0) args.add("freq=" + config.channel); + + String command = "p2p_connect "; + for (String s : args) command += s + " "; + + return doStringTempCommand(command); + } + + public static boolean p2pGroupAdd() { + return doBooleanTempCommand("p2p_group_add"); + } + + public static boolean p2pGroupRemove(String iface) { + if (iface == null) return false; + return doBooleanTempCommand("p2p_group_remove " + iface); + } + + public static boolean p2pReject(String deviceAddress) { + return doBooleanTempCommand("p2p_reject " + deviceAddress); + } + + /* Invite a peer to a group */ + public static boolean p2pInvite(WifiP2pGroup group, String deviceAddress) { + if (group == null || deviceAddress == null) return false; + return doBooleanTempCommand("p2p_invite group=" + group.getInterface() + + " peer=" + deviceAddress + " go_dev_addr=" + group.getOwner().deviceAddress); + } + + public static boolean p2pWpsPbc() { + return doBooleanTempCommand("wps_pbc"); + } + + public static boolean p2pWpsPin(String pin) { + return doBooleanTempCommand("wps_pin any " + pin); + } + } diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java index 12efeb1..54685a6 100644 --- a/wifi/java/android/net/wifi/WifiStateMachine.java +++ b/wifi/java/android/net/wifi/WifiStateMachine.java @@ -56,6 +56,8 @@ import android.net.NetworkInfo; import android.net.NetworkInfo.DetailedState; import android.net.NetworkUtils; import android.net.wifi.WpsResult.Status; +import android.net.wifi.p2p.WifiP2pManager; +import android.net.wifi.StateChangeResult; import android.os.Binder; import android.os.IBinder; import android.os.INetworkManagementService; @@ -67,6 +69,7 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemProperties; import android.os.WorkSource; +import android.server.WifiP2pService; import android.provider.Settings; import android.util.EventLog; import android.util.Log; @@ -82,12 +85,21 @@ import java.net.InetAddress; import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.regex.Pattern; /** * Track the state of Wifi connectivity. All event handling is done here, * and all changes in connectivity state are initiated here. * + * Wi-Fi now supports three modes of operation: Client, Soft Ap and Direct + * In the current implementation, we do not support any concurrency and thus only + * one of Client, Soft Ap or Direct operation is supported at any time. + * + * The WifiStateMachine supports Soft Ap and Client operations while WifiP2pService + * handles Direct. WifiP2pService and WifiStateMachine co-ordinate to ensure only + * one exists at a certain time. + * * @hide */ public class WifiStateMachine extends StateMachine { @@ -96,7 +108,7 @@ public class WifiStateMachine extends StateMachine { private static final String NETWORKTYPE = "WIFI"; private static final boolean DBG = false; - /* TODO: fetch a configurable interface */ + /* TODO: This is no more used with the hostapd code. Clean up */ private static final String SOFTAP_IFACE = "wl0.1"; private WifiMonitor mWifiMonitor; @@ -160,9 +172,16 @@ public class WifiStateMachine extends StateMachine { /* Tracks current frequency mode */ private AtomicInteger mFrequencyBand = new AtomicInteger(WifiManager.WIFI_FREQUENCY_BAND_AUTO); + /* Tracks if we are filtering Multicast v4 packets. Default is to filter. */ + private AtomicBoolean mFilteringMulticastV4Packets = new AtomicBoolean(true); + // Channel for sending replies. private AsyncChannel mReplyChannel = new AsyncChannel(); + private WifiP2pManager mWifiP2pManager; + //Used to initiate a connection with WifiP2pService + private AsyncChannel mWifiP2pChannel = new AsyncChannel(); + // Event log tags (must be in sync with event-log-tags) private static final int EVENTLOG_WIFI_STATE_CHANGED = 50021; private static final int EVENTLOG_WIFI_EVENT_HANDLED = 50022; @@ -204,27 +223,10 @@ public class WifiStateMachine extends StateMachine { static final int CMD_SET_AP_CONFIG = BASE + 23; /* Get the soft access point configuration */ static final int CMD_GET_AP_CONFIG = BASE + 24; + /* Set configuration on tether interface */ + static final int CMD_TETHER_INTERFACE = BASE + 25; - static final int CMD_BLUETOOTH_ADAPTER_STATE_CHANGE = BASE + 25; - - /* Supplicant events */ - /* Connection to supplicant established */ - static final int SUP_CONNECTION_EVENT = BASE + 31; - /* Connection to supplicant lost */ - static final int SUP_DISCONNECTION_EVENT = BASE + 32; - /* Network connection completed */ - static final int NETWORK_CONNECTION_EVENT = BASE + 33; - /* Network disconnection completed */ - static final int NETWORK_DISCONNECTION_EVENT = BASE + 34; - /* Scan results are available */ - static final int SCAN_RESULTS_EVENT = BASE + 35; - /* Supplicate state changed */ - static final int SUPPLICANT_STATE_CHANGE_EVENT = BASE + 36; - /* Password failure and EAP authentication failure */ - static final int AUTHENTICATION_FAILURE_EVENT = BASE + 37; - /* WPS overlap detected */ - static final int WPS_OVERLAP_EVENT = BASE + 38; - + static final int CMD_BLUETOOTH_ADAPTER_STATE_CHANGE = BASE + 26; /* Supplicant commands */ /* Is supplicant alive ? */ @@ -285,6 +287,11 @@ public class WifiStateMachine extends StateMachine { static final int CMD_START_PACKET_FILTERING = BASE + 84; /* Clear packet filter */ static final int CMD_STOP_PACKET_FILTERING = BASE + 85; + + /* arg1 values to CMD_STOP_PACKET_FILTERING and CMD_START_PACKET_FILTERING */ + static final int MULTICAST_V6 = 1; + static final int MULTICAST_V4 = 0; + /* Connect to a specified network (network id * or WifiConfiguration) This involves increasing * the priority of the network, enabling the network @@ -321,6 +328,10 @@ public class WifiStateMachine extends StateMachine { /* Reset the WPS state machine */ static final int CMD_RESET_WPS_STATE = BASE + 122; + /* Interaction with WifiP2pService */ + public static final int WIFI_ENABLE_PENDING = BASE + 131; + public static final int P2P_ENABLE_PROCEED = BASE + 132; + private static final int CONNECT_MODE = 1; private static final int SCAN_ONLY_MODE = 2; @@ -412,8 +423,13 @@ public class WifiStateMachine extends StateMachine { /* Waiting for WPS to be completed*/ private State mWaitForWpsCompletionState = new WaitForWpsCompletionState(); - /* Soft Ap is running */ + /* Soft ap is running */ private State mSoftApStartedState = new SoftApStartedState(); + /* Soft ap is running and we are tethered through connectivity service */ + private State mTetheredState = new TetheredState(); + + /* Wait till p2p is disabled */ + private State mWaitForP2pDisableState = new WaitForP2pDisableState(); /** @@ -504,13 +520,9 @@ public class WifiStateMachine extends StateMachine { new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - ArrayList<String> available = intent.getStringArrayListExtra( ConnectivityManager.EXTRA_AVAILABLE_TETHER); - ArrayList<String> active = intent.getStringArrayListExtra( - ConnectivityManager.EXTRA_ACTIVE_TETHER); - updateTetherState(available, active); - + sendMessage(CMD_TETHER_INTERFACE, available); } },new IntentFilter(ConnectivityManager.ACTION_TETHER_STATE_CHANGED)); @@ -550,6 +562,8 @@ public class WifiStateMachine extends StateMachine { addState(mDriverStoppedState, mSupplicantStartedState); addState(mSupplicantStoppingState, mDefaultState); addState(mSoftApStartedState, mDefaultState); + addState(mTetheredState, mSoftApStartedState); + addState(mWaitForP2pDisableState, mDefaultState); setInitialState(mInitialState); @@ -868,17 +882,33 @@ public class WifiStateMachine extends StateMachine { } /** - * Start packet filtering + * Start filtering Multicast v4 packets + */ + public void startFilteringMulticastV4Packets() { + mFilteringMulticastV4Packets.set(true); + sendMessage(obtainMessage(CMD_START_PACKET_FILTERING, MULTICAST_V4, 0)); + } + + /** + * Stop filtering Multicast v4 packets */ - public void startPacketFiltering() { - sendMessage(CMD_START_PACKET_FILTERING); + public void stopFilteringMulticastV4Packets() { + mFilteringMulticastV4Packets.set(false); + sendMessage(obtainMessage(CMD_STOP_PACKET_FILTERING, MULTICAST_V4, 0)); } /** - * Stop packet filtering + * Start filtering Multicast v4 packets */ - public void stopPacketFiltering() { - sendMessage(CMD_STOP_PACKET_FILTERING); + public void startFilteringMulticastV6Packets() { + sendMessage(obtainMessage(CMD_START_PACKET_FILTERING, MULTICAST_V6, 0)); + } + + /** + * Stop filtering Multicast v4 packets + */ + public void stopFilteringMulticastV6Packets() { + sendMessage(obtainMessage(CMD_STOP_PACKET_FILTERING, MULTICAST_V6, 0)); } /** @@ -1023,14 +1053,17 @@ public class WifiStateMachine extends StateMachine { * Internal private functions ********************************************************/ - private void updateTetherState(ArrayList<String> available, ArrayList<String> tethered) { - - boolean wifiTethered = false; - boolean wifiAvailable = false; - + private void checkAndSetConnectivityInstance() { if (mCm == null) { mCm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); } + } + + private void startTethering(ArrayList<String> available) { + + boolean wifiAvailable = false; + + checkAndSetConnectivityInstance(); String[] wifiRegexs = mCm.getTetherableWifiRegexs(); @@ -1066,6 +1099,29 @@ public class WifiStateMachine extends StateMachine { } } + private void stopTethering() { + + checkAndSetConnectivityInstance(); + + /* Clear the interface config to allow dhcp correctly configure new + ip settings */ + InterfaceConfiguration ifcg = null; + try { + ifcg = nwService.getInterfaceConfig(mInterfaceName); + if (ifcg != null) { + ifcg.addr = new LinkAddress(NetworkUtils.numericToInetAddress( + "0.0.0.0"), 0); + nwService.setInterfaceConfig(mInterfaceName, ifcg); + } + } catch (Exception e) { + Log.e(TAG, "Error resetting interface " + mInterfaceName + ", :" + e); + } + + if (mCm.untether(mInterfaceName) != ConnectivityManager.TETHER_ERROR_NO_ERROR) { + Log.e(TAG, "Untether initiate failed!"); + } + } + /** * Set the country code from the system setting value, if any. */ @@ -1591,12 +1647,15 @@ public class WifiStateMachine extends StateMachine { if (currentStatus == SOFT_AP_STOPPED) { nwService.startAccessPoint(config, mInterfaceName, SOFTAP_IFACE); } else if (currentStatus == SOFT_AP_RUNNING) { - nwService.setAccessPoint(config, mInterfaceName, SOFTAP_IFACE); + //nwService.setAccessPoint(config, mInterfaceName, SOFTAP_IFACE); + //TODO: when we have a control channel to hostapd, we should not need to do this + nwService.stopAccessPoint(mInterfaceName); + nwService.startAccessPoint(config, mInterfaceName, SOFTAP_IFACE); } } catch (Exception e) { Log.e(TAG, "Exception in softap start " + e); try { - nwService.stopAccessPoint(); + nwService.stopAccessPoint(mInterfaceName); nwService.startAccessPoint(config, mInterfaceName, SOFTAP_IFACE); } catch (Exception ee) { Log.e(TAG, "Exception during softap restart : " + ee); @@ -1606,105 +1665,6 @@ public class WifiStateMachine extends StateMachine { return true; } - - /********************************************************* - * Notifications from WifiMonitor - ********************************************************/ - - /** - * Stores supplicant state change information passed from WifiMonitor - */ - static class StateChangeResult { - StateChangeResult(int networkId, String BSSID, SupplicantState state) { - this.state = state; - this.BSSID = BSSID; - this.networkId = networkId; - } - int networkId; - String BSSID; - SupplicantState state; - } - - /** - * Send the tracker a notification that a user provided - * configuration caused authentication failure - this could - * be a password failure or a EAP authentication failure - */ - void notifyAuthenticationFailure() { - sendMessage(AUTHENTICATION_FAILURE_EVENT); - } - - /** - * Send a notification that the supplicant has detected overlapped - * WPS sessions - */ - void notifyWpsOverlap() { - sendMessage(WPS_OVERLAP_EVENT); - } - - /** - * Send the tracker a notification that a connection to the supplicant - * daemon has been established. - */ - void notifySupplicantConnection() { - sendMessage(SUP_CONNECTION_EVENT); - } - - /** - * Send the tracker a notification that connection to the supplicant - * daemon is lost - */ - void notifySupplicantLost() { - sendMessage(SUP_DISCONNECTION_EVENT); - } - - /** - * Send the tracker a notification that the state of Wifi connectivity - * has changed. - * @param networkId the configured network on which the state change occurred - * @param newState the new network state - * @param BSSID when the new state is {@link DetailedState#CONNECTED - * NetworkInfo.DetailedState.CONNECTED}, - * this is the MAC address of the access point. Otherwise, it - * is {@code null}. - */ - void notifyNetworkStateChange(DetailedState newState, String BSSID, int networkId) { - if (newState == NetworkInfo.DetailedState.CONNECTED) { - sendMessage(obtainMessage(NETWORK_CONNECTION_EVENT, networkId, 0, BSSID)); - } else { - sendMessage(obtainMessage(NETWORK_DISCONNECTION_EVENT, networkId, 0, BSSID)); - } - } - - /** - * Send the tracker a notification that the state of the supplicant - * has changed. - * @param networkId the configured network on which the state change occurred - * @param newState the new {@code SupplicantState} - */ - void notifySupplicantStateChange(int networkId, String BSSID, SupplicantState newState) { - sendMessage(obtainMessage(SUPPLICANT_STATE_CHANGE_EVENT, - new StateChangeResult(networkId, BSSID, newState))); - } - - /** - * Send the tracker a notification that a scan has completed, and results - * are available. - */ - void notifyScanResultsAvailable() { - /** - * Switch scan mode over to passive. - * Turning off scan-only mode happens only in "Connect" mode - */ - setScanType(false); - sendMessage(SCAN_RESULTS_EVENT); - } - - void notifyDriverHung() { - setWifiEnabled(false); - setWifiEnabled(true); - } - /******************************************************** * HSM states *******************************************************/ @@ -1714,6 +1674,18 @@ public class WifiStateMachine extends StateMachine { public boolean processMessage(Message message) { if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); switch (message.what) { + case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: + if (message.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { + mWifiP2pChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION); + } else { + Log.e(TAG, "WifiP2pService connection failure, error=" + message.arg1); + } + break; + case AsyncChannel.CMD_CHANNEL_DISCONNECTED: + Log.e(TAG, "WifiP2pService channel lost, message.arg1 =" + message.arg1); + //TODO: Re-establish connection to state machine after a delay + //mWifiP2pChannel.connect(mContext, getHandler(), mWifiP2pManager.getMessenger()); + break; case CMD_BLUETOOTH_ADAPTER_STATE_CHANGE: mBluetoothConnectionActive = (message.arg1 != BluetoothAdapter.STATE_DISCONNECTED); @@ -1749,18 +1721,19 @@ public class WifiStateMachine extends StateMachine { case CMD_STOP_DRIVER: case CMD_START_AP: case CMD_STOP_AP: + case CMD_TETHER_INTERFACE: case CMD_START_SCAN: case CMD_DISCONNECT: case CMD_RECONNECT: case CMD_REASSOCIATE: - case SUP_CONNECTION_EVENT: - case SUP_DISCONNECTION_EVENT: - case NETWORK_CONNECTION_EVENT: - case NETWORK_DISCONNECTION_EVENT: - case SCAN_RESULTS_EVENT: - case SUPPLICANT_STATE_CHANGE_EVENT: - case AUTHENTICATION_FAILURE_EVENT: - case WPS_OVERLAP_EVENT: + case WifiMonitor.SUP_CONNECTION_EVENT: + case WifiMonitor.SUP_DISCONNECTION_EVENT: + case WifiMonitor.NETWORK_CONNECTION_EVENT: + case WifiMonitor.NETWORK_DISCONNECTION_EVENT: + case WifiMonitor.SCAN_RESULTS_EVENT: + case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: + case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: + case WifiMonitor.WPS_OVERLAP_EVENT: case CMD_BLACKLIST_NETWORK: case CMD_CLEAR_BLACKLIST: case CMD_SET_SCAN_MODE: @@ -1777,11 +1750,20 @@ public class WifiStateMachine extends StateMachine { case DhcpStateMachine.CMD_PRE_DHCP_ACTION: case DhcpStateMachine.CMD_POST_DHCP_ACTION: break; + case WifiMonitor.DRIVER_HUNG_EVENT: + setWifiEnabled(false); + setWifiEnabled(true); + break; case CMD_START_WPS: /* Return failure when the state machine cannot handle WPS initiation*/ mReplyChannel.replyToMessage(message, WifiManager.CMD_WPS_COMPLETED, new WpsResult(Status.FAILURE)); break; + case WifiP2pService.P2P_ENABLE_PENDING: + // turn off wifi and defer to be handled in DriverUnloadedState + setWifiEnabled(false); + deferMessage(message); + break; default: Log.e(TAG, "Error! unhandled message" + message); break; @@ -1808,6 +1790,11 @@ public class WifiStateMachine extends StateMachine { else { transitionTo(mDriverUnloadedState); } + + //Connect to WifiP2pService + mWifiP2pManager = (WifiP2pManager) mContext.getSystemService(Context.WIFI_P2P_SERVICE); + mWifiP2pChannel.connect(mContext, getHandler(), mWifiP2pManager.getMessenger()); + } } @@ -2023,7 +2010,11 @@ public class WifiStateMachine extends StateMachine { if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); switch (message.what) { case CMD_LOAD_DRIVER: - transitionTo(mDriverLoadingState); + mWifiP2pChannel.sendMessage(WIFI_ENABLE_PENDING); + transitionTo(mWaitForP2pDisableState); + break; + case WifiP2pService.P2P_ENABLE_PENDING: + mReplyChannel.replyToMessage(message, P2P_ENABLE_PROCEED); break; default: return NOT_HANDLED; @@ -2057,7 +2048,7 @@ public class WifiStateMachine extends StateMachine { public boolean processMessage(Message message) { if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); switch(message.what) { - case SUP_CONNECTION_EVENT: + case WifiMonitor.SUP_CONNECTION_EVENT: Log.d(TAG, "Supplicant connection established"); setWifiState(WIFI_STATE_ENABLED); mSupplicantRestartCount = 0; @@ -2074,13 +2065,10 @@ public class WifiStateMachine extends StateMachine { WifiConfigStore.initialize(mContext); - //TODO: initialize and fix multicast filtering - //mWM.initializeMulticastFiltering(); - sendSupplicantConnectionChangedBroadcast(true); transitionTo(mDriverStartedState); break; - case SUP_DISCONNECTION_EVENT: + case WifiMonitor.SUP_DISCONNECTION_EVENT: if (++mSupplicantRestartCount <= SUPPLICANT_RESTART_TRIES) { Log.e(TAG, "Failed to setup control channel, restart supplicant"); WifiNative.killSupplicant(); @@ -2143,7 +2131,7 @@ public class WifiStateMachine extends StateMachine { case CMD_STOP_SUPPLICANT: /* Supplicant stopped by user */ transitionTo(mSupplicantStoppingState); break; - case SUP_DISCONNECTION_EVENT: /* Supplicant connection lost */ + case WifiMonitor.SUP_DISCONNECTION_EVENT: /* Supplicant connection lost */ Log.e(TAG, "Connection lost, restart supplicant"); WifiNative.killSupplicant(); WifiNative.closeSupplicantConnection(); @@ -2155,7 +2143,7 @@ public class WifiStateMachine extends StateMachine { transitionTo(mDriverLoadedState); sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS); break; - case SCAN_RESULTS_EVENT: + case WifiMonitor.SCAN_RESULTS_EVENT: eventLoggingEnabled = false; setScanResults(WifiNative.scanResultsCommand()); sendScanResultsAvailableBroadcast(); @@ -2257,10 +2245,10 @@ public class WifiStateMachine extends StateMachine { public boolean processMessage(Message message) { if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); switch(message.what) { - case SUP_CONNECTION_EVENT: + case WifiMonitor.SUP_CONNECTION_EVENT: Log.e(TAG, "Supplicant connection received while stopping"); break; - case SUP_DISCONNECTION_EVENT: + case WifiMonitor.SUP_DISCONNECTION_EVENT: Log.d(TAG, "Supplicant connection lost"); WifiNative.closeSupplicantConnection(); transitionTo(mDriverLoadedState); @@ -2300,7 +2288,7 @@ public class WifiStateMachine extends StateMachine { public boolean processMessage(Message message) { if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); switch(message.what) { - case SUPPLICANT_STATE_CHANGE_EVENT: + case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: SupplicantState state = handleSupplicantStateChange(message); /* If suplicant is exiting out of INTERFACE_DISABLED state into * a state that indicates driver has started, it is ready to @@ -2313,10 +2301,10 @@ public class WifiStateMachine extends StateMachine { /* Queue driver commands & connection events */ case CMD_START_DRIVER: case CMD_STOP_DRIVER: - case NETWORK_CONNECTION_EVENT: - case NETWORK_DISCONNECTION_EVENT: - case AUTHENTICATION_FAILURE_EVENT: - case WPS_OVERLAP_EVENT: + case WifiMonitor.NETWORK_CONNECTION_EVENT: + case WifiMonitor.NETWORK_DISCONNECTION_EVENT: + case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: + case WifiMonitor.WPS_OVERLAP_EVENT: case CMD_SET_SCAN_TYPE: case CMD_SET_HIGH_PERF_MODE: case CMD_SET_COUNTRY_CODE: @@ -2359,6 +2347,16 @@ public class WifiStateMachine extends StateMachine { /* initialize network state */ setNetworkDetailedState(DetailedState.DISCONNECTED); + /* Remove any filtering on Multicast v6 at start */ + WifiNative.stopFilteringMulticastV6Packets(); + + /* Reset Multicast v4 filtering state */ + if (mFilteringMulticastV4Packets.get()) { + WifiNative.startFilteringMulticastV4Packets(); + } else { + WifiNative.stopFilteringMulticastV4Packets(); + } + if (mIsScanMode) { WifiNative.setScanResultHandlingCommand(SCAN_ONLY_MODE); WifiNative.disconnectCommand(); @@ -2419,10 +2417,22 @@ public class WifiStateMachine extends StateMachine { mWakeLock.release(); break; case CMD_START_PACKET_FILTERING: - WifiNative.startPacketFiltering(); + if (message.arg1 == MULTICAST_V6) { + WifiNative.startFilteringMulticastV6Packets(); + } else if (message.arg1 == MULTICAST_V4) { + WifiNative.startFilteringMulticastV4Packets(); + } else { + Log.e(TAG, "Illegal arugments to CMD_START_PACKET_FILTERING"); + } break; case CMD_STOP_PACKET_FILTERING: - WifiNative.stopPacketFiltering(); + if (message.arg1 == MULTICAST_V6) { + WifiNative.stopFilteringMulticastV6Packets(); + } else if (message.arg1 == MULTICAST_V4) { + WifiNative.stopFilteringMulticastV4Packets(); + } else { + Log.e(TAG, "Illegal arugments to CMD_STOP_PACKET_FILTERING"); + } break; default: return NOT_HANDLED; @@ -2451,7 +2461,7 @@ public class WifiStateMachine extends StateMachine { public boolean processMessage(Message message) { if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); switch(message.what) { - case SUPPLICANT_STATE_CHANGE_EVENT: + case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: SupplicantState state = handleSupplicantStateChange(message); if (state == SupplicantState.INTERFACE_DISABLED) { transitionTo(mDriverStoppedState); @@ -2495,7 +2505,7 @@ public class WifiStateMachine extends StateMachine { WifiNative.startDriverCommand(); mWakeLock.release(); break; - case SUPPLICANT_STATE_CHANGE_EVENT: + case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: SupplicantState state = handleSupplicantStateChange(message); /* A driver start causes supplicant to first report an INTERFACE_DISABLED * state before transitioning out of it for connection. Stay in @@ -2541,9 +2551,9 @@ public class WifiStateMachine extends StateMachine { case CMD_DISCONNECT: case CMD_RECONNECT: case CMD_REASSOCIATE: - case SUPPLICANT_STATE_CHANGE_EVENT: - case NETWORK_CONNECTION_EVENT: - case NETWORK_DISCONNECTION_EVENT: + case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: + case WifiMonitor.NETWORK_CONNECTION_EVENT: + case WifiMonitor.NETWORK_DISCONNECTION_EVENT: break; default: return NOT_HANDLED; @@ -2564,14 +2574,14 @@ public class WifiStateMachine extends StateMachine { if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); StateChangeResult stateChangeResult; switch(message.what) { - case AUTHENTICATION_FAILURE_EVENT: - mSupplicantStateTracker.sendMessage(AUTHENTICATION_FAILURE_EVENT); + case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: + mSupplicantStateTracker.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT); break; - case WPS_OVERLAP_EVENT: + case WifiMonitor.WPS_OVERLAP_EVENT: /* We just need to broadcast the error */ sendErrorBroadcast(WifiManager.WPS_OVERLAP_ERROR); break; - case SUPPLICANT_STATE_CHANGE_EVENT: + case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: handleSupplicantStateChange(message); break; /* Do a redundant disconnect without transition */ @@ -2613,12 +2623,12 @@ public class WifiStateMachine extends StateMachine { mWpsStateMachine.sendMessage(Message.obtain(message)); transitionTo(mWaitForWpsCompletionState); break; - case SCAN_RESULTS_EVENT: + case WifiMonitor.SCAN_RESULTS_EVENT: /* Set the scan setting back to "connect" mode */ WifiNative.setScanResultHandlingCommand(CONNECT_MODE); /* Handle scan results */ return NOT_HANDLED; - case NETWORK_CONNECTION_EVENT: + case WifiMonitor.NETWORK_CONNECTION_EVENT: Log.d(TAG,"Network connection established"); mLastNetworkId = message.arg1; mLastBssid = (String) message.obj; @@ -2632,7 +2642,7 @@ public class WifiStateMachine extends StateMachine { sendNetworkStateChangeBroadcast(mLastBssid); transitionTo(mConnectingState); break; - case NETWORK_DISCONNECTION_EVENT: + case WifiMonitor.NETWORK_DISCONNECTION_EVENT: Log.d(TAG,"Network connection lost"); handleNetworkDisconnect(); transitionTo(mDisconnectedState); @@ -2719,7 +2729,7 @@ public class WifiStateMachine extends StateMachine { deferMessage(message); break; /* Ignore */ - case NETWORK_CONNECTION_EVENT: + case WifiMonitor.NETWORK_CONNECTION_EVENT: break; case CMD_STOP_DRIVER: sendMessage(CMD_DISCONNECT); @@ -2784,10 +2794,7 @@ public class WifiStateMachine extends StateMachine { deferMessage(message); break; case CMD_REQUEST_CM_WAKELOCK: - if (mCm == null) { - mCm = (ConnectivityManager)mContext.getSystemService( - Context.CONNECTIVITY_SERVICE); - } + checkAndSetConnectivityInstance(); mCm.requestNetworkTransitionWakelock(TAG); break; case CMD_SET_SCAN_MODE: @@ -2829,7 +2836,7 @@ public class WifiStateMachine extends StateMachine { } break; /* Ignore */ - case NETWORK_CONNECTION_EVENT: + case WifiMonitor.NETWORK_CONNECTION_EVENT: break; case CMD_RSSI_POLL: eventLoggingEnabled = false; @@ -2890,7 +2897,7 @@ public class WifiStateMachine extends StateMachine { } break; /* Handle in DisconnectedState */ - case SUPPLICANT_STATE_CHANGE_EVENT: + case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: deferMessage(message); break; default: @@ -2975,9 +2982,9 @@ public class WifiStateMachine extends StateMachine { } break; /* Ignore network disconnect */ - case NETWORK_DISCONNECTION_EVENT: + case WifiMonitor.NETWORK_DISCONNECTION_EVENT: break; - case SUPPLICANT_STATE_CHANGE_EVENT: + case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: StateChangeResult stateChangeResult = (StateChangeResult) message.obj; setNetworkDetailedState(WifiInfo.getDetailedStateOf(stateChangeResult.state)); /* ConnectModeState does the rest of the handling */ @@ -2989,7 +2996,7 @@ public class WifiStateMachine extends StateMachine { } /* Handled in parent state */ return NOT_HANDLED; - case SCAN_RESULTS_EVENT: + case WifiMonitor.SCAN_RESULTS_EVENT: /* Re-enable background scan when a pending scan result is received */ if (mEnableBackgroundScan && mScanResultIsPending) { WifiNative.enableBackgroundScanCommand(true); @@ -3032,10 +3039,10 @@ public class WifiStateMachine extends StateMachine { case CMD_ENABLE_NETWORK: case CMD_RECONNECT: case CMD_REASSOCIATE: - case NETWORK_CONNECTION_EVENT: /* Handled after IP & proxy update */ + case WifiMonitor.NETWORK_CONNECTION_EVENT: /* Handled after IP & proxy update */ deferMessage(message); break; - case NETWORK_DISCONNECTION_EVENT: + case WifiMonitor.NETWORK_DISCONNECTION_EVENT: Log.d(TAG,"Network connection lost"); handleNetworkDisconnect(); break; @@ -3065,16 +3072,9 @@ public class WifiStateMachine extends StateMachine { case CMD_STOP_AP: Log.d(TAG,"Stopping Soft AP"); setWifiApState(WIFI_AP_STATE_DISABLING); - - if (mCm == null) { - mCm = (ConnectivityManager) mContext.getSystemService( - Context.CONNECTIVITY_SERVICE); - } - if (mCm.untether(SOFTAP_IFACE) != ConnectivityManager.TETHER_ERROR_NO_ERROR) { - Log.e(TAG, "Untether initiate failed!"); - } + stopTethering(); try { - nwService.stopAccessPoint(); + nwService.stopAccessPoint(mInterfaceName); } catch(Exception e) { Log.e(TAG, "Exception in stopAccessPoint()"); } @@ -3096,6 +3096,60 @@ public class WifiStateMachine extends StateMachine { Log.e(TAG,"Cannot start supplicant with a running soft AP"); setWifiState(WIFI_STATE_UNKNOWN); break; + case CMD_TETHER_INTERFACE: + ArrayList<String> available = (ArrayList<String>) message.obj; + startTethering(available); + transitionTo(mTetheredState); + break; + case WifiP2pService.P2P_ENABLE_PENDING: + // turn of soft Ap and defer to be handled in DriverUnloadedState + setWifiApEnabled(null, false); + deferMessage(message); + break; + default: + return NOT_HANDLED; + } + EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what); + return HANDLED; + } + } + + class WaitForP2pDisableState extends State { + private int mSavedArg; + @Override + public void enter() { + if (DBG) Log.d(TAG, getName() + "\n"); + EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName()); + + //Preserve the argument arg1 that has information used in DriverLoadingState + mSavedArg = getCurrentMessage().arg1; + } + @Override + public boolean processMessage(Message message) { + if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); + switch(message.what) { + case WifiP2pService.WIFI_ENABLE_PROCEED: + //restore argument from original message (CMD_LOAD_DRIVER) + message.arg1 = mSavedArg; + transitionTo(mDriverLoadingState); + break; + case CMD_LOAD_DRIVER: + case CMD_UNLOAD_DRIVER: + case CMD_START_SUPPLICANT: + case CMD_STOP_SUPPLICANT: + case CMD_START_AP: + case CMD_STOP_AP: + case CMD_START_DRIVER: + case CMD_STOP_DRIVER: + case CMD_SET_SCAN_MODE: + case CMD_SET_SCAN_TYPE: + case CMD_SET_HIGH_PERF_MODE: + case CMD_SET_COUNTRY_CODE: + case CMD_SET_FREQUENCY_BAND: + case CMD_START_PACKET_FILTERING: + case CMD_STOP_PACKET_FILTERING: + deferMessage(message); + break; default: return NOT_HANDLED; } @@ -3103,4 +3157,24 @@ public class WifiStateMachine extends StateMachine { return HANDLED; } } + + class TetheredState extends State { + @Override + public void enter() { + if (DBG) Log.d(TAG, getName() + "\n"); + EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName()); + } + @Override + public boolean processMessage(Message message) { + if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); + switch(message.what) { + case CMD_TETHER_INTERFACE: + // Ignore any duplicate interface available notifications + // when in tethered state + return HANDLED; + default: + return NOT_HANDLED; + } + } + } } diff --git a/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java b/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java index 0eb73b7..fa7cf21 100644 --- a/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java +++ b/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java @@ -16,11 +16,15 @@ package android.net.wifi; +import android.app.Notification; +import android.app.NotificationManager; +import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.res.Resources; import android.database.ContentObserver; import android.net.ConnectivityManager; import android.net.DnsPinger; @@ -29,7 +33,7 @@ import android.net.Uri; import android.os.Message; import android.os.SystemClock; import android.provider.Settings; -import android.text.TextUtils; +import android.provider.Settings.Secure; import android.util.Slog; import com.android.internal.util.Protocol; @@ -45,6 +49,7 @@ import java.net.URL; import java.util.HashSet; import java.util.List; import java.util.Scanner; +import java.util.regex.Pattern; /** * {@link WifiWatchdogStateMachine} monitors the initial connection to a Wi-Fi @@ -62,6 +67,7 @@ import java.util.Scanner; */ public class WifiWatchdogStateMachine extends StateMachine { + private static final boolean VDBG = false; private static final boolean DBG = true; private static final String WWSM_TAG = "WifiWatchdogStateMachine"; @@ -72,18 +78,22 @@ public class WifiWatchdogStateMachine extends StateMachine { */ private static final int LOW_SIGNAL_CUTOFF = 1; - private static final long MIN_LOW_SIGNAL_CHECK_INTERVAL_MS = 2 * 60 * 1000; - private static final long MIN_SINGLE_DNS_CHECK_INTERVAL_MS = 10 * 60 * 1000; - private static final long MIN_WALLED_GARDEN_INTERVAL_MS = 30 * 60 * 1000; - - private static final int MAX_CHECKS_PER_SSID = 7; - private static final int NUM_DNS_PINGS = 5; - private static final double MIN_DNS_RESPONSE_RATE = 0.50; + private static final long DEFAULT_DNS_CHECK_SHORT_INTERVAL_MS = 2 * 60 * 1000; + private static final long DEFAULT_DNS_CHECK_LONG_INTERVAL_MS = 10 * 60 * 1000; + private static final long DEFAULT_WALLED_GARDEN_INTERVAL_MS = 30 * 60 * 1000; - private static final int DNS_PING_TIMEOUT_MS = 800; + private static final int DEFAULT_MAX_SSID_BLACKLISTS = 7; + private static final int DEFAULT_NUM_DNS_PINGS = 5; + private static final int DEFAULT_MIN_DNS_RESPONSES = 3; private static final long DNS_PING_INTERVAL_MS = 100; - private static final long BLACKLIST_FOLLOWUP_INTERVAL_MS = 15 * 1000; + private static final int DEFAULT_DNS_PING_TIMEOUT_MS = 1500; + + private static final long DEFAULT_BLACKLIST_FOLLOWUP_INTERVAL_MS = 15 * 1000; + + private static final String DEFAULT_WALLED_GARDEN_URL = "http://www.google.com/"; + private static final String DEFAULT_WALLED_GARDEN_PATTERN = "<title>.*Google.*</title>"; + private static final int BASE = Protocol.BASE_WIFI_WATCHDOG; @@ -104,6 +114,7 @@ public class WifiWatchdogStateMachine extends StateMachine { private static final int EVENT_RSSI_CHANGE = BASE + 3; private static final int EVENT_SCAN_RESULTS_AVAILABLE = BASE + 4; private static final int EVENT_WIFI_RADIO_STATE_CHANGE = BASE + 5; + private static final int EVENT_WATCHDOG_SETTINGS_CHANGE = BASE + 6; private static final int MESSAGE_CHECK_STEP = BASE + 100; private static final int MESSAGE_HANDLE_WALLED_GARDEN = BASE + 101; @@ -132,6 +143,19 @@ public class WifiWatchdogStateMachine extends StateMachine { private WalledGardenState mWalledGardenState = new WalledGardenState(); private BlacklistedApState mBlacklistedApState = new BlacklistedApState(); + private long mDnsCheckShortIntervalMs; + private long mDnsCheckLongIntervalMs; + private long mWalledGardenIntervalMs; + private int mMaxSsidBlacklists; + private int mNumDnsPings; + private int mMinDnsResponses; + private int mDnsPingTimeoutMs; + private long mBlacklistFollowupIntervalMs; + private boolean mWalledGardenTestEnabled; + private String mWalledGardenUrl; + private Pattern mWalledGardenPattern; + + private boolean mShowDisabledNotification; /** * The {@link WifiInfo} object passed to WWSM on network broadcasts */ @@ -142,7 +166,7 @@ public class WifiWatchdogStateMachine extends StateMachine { * Currently maintained but not used, TODO */ private HashSet<String> mBssids = new HashSet<String>(); - private int mNumFullDNSchecks = 0; + private int mNumCheckFailures = 0; private Long mLastWalledGardenCheckTime = null; @@ -158,7 +182,7 @@ public class WifiWatchdogStateMachine extends StateMachine { * / \ * Disabled Enabled * / \ - * Disconnected Connected + * NotConnected Connected * /---------\ * (all other states) */ @@ -174,6 +198,7 @@ public class WifiWatchdogStateMachine extends StateMachine { // The content observer to listen needs a handler registerForSettingsChanges(); + registerForWatchdogToggle(); addState(mDefaultState); addState(mWatchdogDisabledState, mDefaultState); addState(mWatchdogEnabledState, mDefaultState); @@ -186,6 +211,9 @@ public class WifiWatchdogStateMachine extends StateMachine { addState(mOnlineWatchState, mConnectedState); setInitialState(mWatchdogDisabledState); + updateSettings(); + mShowDisabledNotification = getSettingsBoolean(mContentResolver, + Settings.Secure.WIFI_WATCHDOG_SHOW_DISABLED_NETWORK_POPUP, true); } public static WifiWatchdogStateMachine makeWifiWatchdogStateMachine(Context context) { @@ -228,7 +256,7 @@ public class WifiWatchdogStateMachine extends StateMachine { /** * Observes the watchdog on/off setting, and takes action when changed. */ - private void registerForSettingsChanges() { + private void registerForWatchdogToggle() { ContentObserver contentObserver = new ContentObserver(this.getHandler()) { @Override public void onChange(boolean selfChange) { @@ -242,6 +270,54 @@ public class WifiWatchdogStateMachine extends StateMachine { } /** + * Observes watchdogs secure setting changes. + */ + private void registerForSettingsChanges() { + ContentObserver contentObserver = new ContentObserver(this.getHandler()) { + @Override + public void onChange(boolean selfChange) { + sendMessage(EVENT_WATCHDOG_SETTINGS_CHANGE); + } + }; + + mContext.getContentResolver().registerContentObserver( + Settings.Secure.getUriFor( + Settings.Secure.WIFI_WATCHDOG_DNS_CHECK_SHORT_INTERVAL_MS), + false, contentObserver); + mContext.getContentResolver().registerContentObserver( + Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_DNS_CHECK_LONG_INTERVAL_MS), + false, contentObserver); + mContext.getContentResolver().registerContentObserver( + Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_INTERVAL_MS), + false, contentObserver); + mContext.getContentResolver().registerContentObserver( + Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_MAX_SSID_BLACKLISTS), + false, contentObserver); + mContext.getContentResolver().registerContentObserver( + Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_NUM_DNS_PINGS), + false, contentObserver); + mContext.getContentResolver().registerContentObserver( + Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_MIN_DNS_RESPONSES), + false, contentObserver); + mContext.getContentResolver().registerContentObserver( + Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_DNS_PING_TIMEOUT_MS), + false, contentObserver); + mContext.getContentResolver().registerContentObserver( + Settings.Secure.getUriFor( + Settings.Secure.WIFI_WATCHDOG_BLACKLIST_FOLLOWUP_INTERVAL_MS), + false, contentObserver); + mContext.getContentResolver().registerContentObserver( + Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_TEST_ENABLED), + false, contentObserver); + mContext.getContentResolver().registerContentObserver( + Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_URL), + false, contentObserver); + mContext.getContentResolver().registerContentObserver( + Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_PATTERN), + false, contentObserver); + } + + /** * DNS based detection techniques do not work at all hotspots. The one sure * way to check a walled garden is to see if a URL fetch on a known address * fetches the data we expect @@ -250,11 +326,11 @@ public class WifiWatchdogStateMachine extends StateMachine { InputStream in = null; HttpURLConnection urlConnection = null; try { - URL url = new URL(getWalledGardenUrl()); + URL url = new URL(mWalledGardenUrl); urlConnection = (HttpURLConnection) url.openConnection(); in = new BufferedInputStream(urlConnection.getInputStream()); Scanner scanner = new Scanner(in); - if (scanner.findInLine(getWalledGardenPattern()) != null) { + if (scanner.findInLine(mWalledGardenPattern) != null) { return false; } else { return true; @@ -281,49 +357,49 @@ public class WifiWatchdogStateMachine extends StateMachine { pw.print("WatchdogStatus: "); pw.print("State " + getCurrentState()); pw.println(", network [" + mInitialConnInfo + "]"); - pw.print("checkCount " + mNumFullDNSchecks); + pw.print("checkFailures " + mNumCheckFailures); pw.println(", bssids: " + mBssids); pw.println("lastSingleCheck: " + mOnlineWatchState.lastCheckTime); } - /** - * @see android.provider.Settings.Secure#WIFI_WATCHDOG_WALLED_GARDEN_TEST_ENABLED - */ - private Boolean isWalledGardenTestEnabled() { - return Settings.Secure.getInt(mContentResolver, - Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_TEST_ENABLED, 1) == 1; - } - - /** - * @see android.provider.Settings.Secure#WIFI_WATCHDOG_WALLED_GARDEN_URL - */ - private String getWalledGardenUrl() { - String url = Settings.Secure.getString(mContentResolver, - Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_URL); - if (TextUtils.isEmpty(url)) - return "http://www.google.com/"; - return url; - } - - /** - * @see android.provider.Settings.Secure#WIFI_WATCHDOG_WALLED_GARDEN_PATTERN - */ - private String getWalledGardenPattern() { - String pattern = Settings.Secure.getString(mContentResolver, - Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_PATTERN); - if (TextUtils.isEmpty(pattern)) - return "<title>.*Google.*</title>"; - return pattern; - } - - /** - * @see android.provider.Settings.Secure#WIFI_WATCHDOG_ON - */ private boolean isWatchdogEnabled() { - return Settings.Secure.getInt(mContentResolver, - Settings.Secure.WIFI_WATCHDOG_ON, 1) == 1; + return getSettingsBoolean(mContentResolver, Settings.Secure.WIFI_WATCHDOG_ON, true); } + private void updateSettings() { + mDnsCheckShortIntervalMs = Secure.getLong(mContentResolver, + Secure.WIFI_WATCHDOG_DNS_CHECK_SHORT_INTERVAL_MS, + DEFAULT_DNS_CHECK_SHORT_INTERVAL_MS); + mDnsCheckLongIntervalMs = Secure.getLong(mContentResolver, + Secure.WIFI_WATCHDOG_DNS_CHECK_LONG_INTERVAL_MS, + DEFAULT_DNS_CHECK_LONG_INTERVAL_MS); + mMaxSsidBlacklists = Secure.getInt(mContentResolver, + Secure.WIFI_WATCHDOG_MAX_SSID_BLACKLISTS, + DEFAULT_MAX_SSID_BLACKLISTS); + mNumDnsPings = Secure.getInt(mContentResolver, + Secure.WIFI_WATCHDOG_NUM_DNS_PINGS, + DEFAULT_NUM_DNS_PINGS); + mMinDnsResponses = Secure.getInt(mContentResolver, + Secure.WIFI_WATCHDOG_MIN_DNS_RESPONSES, + DEFAULT_MIN_DNS_RESPONSES); + mDnsPingTimeoutMs = Secure.getInt(mContentResolver, + Secure.WIFI_WATCHDOG_DNS_PING_TIMEOUT_MS, + DEFAULT_DNS_PING_TIMEOUT_MS); + mBlacklistFollowupIntervalMs = Secure.getLong(mContentResolver, + Settings.Secure.WIFI_WATCHDOG_BLACKLIST_FOLLOWUP_INTERVAL_MS, + DEFAULT_BLACKLIST_FOLLOWUP_INTERVAL_MS); + mWalledGardenTestEnabled = getSettingsBoolean(mContentResolver, + Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_TEST_ENABLED, true); + mWalledGardenUrl = getSettingsStr(mContentResolver, + Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_URL, + DEFAULT_WALLED_GARDEN_URL); + mWalledGardenPattern = Pattern.compile(getSettingsStr(mContentResolver, + Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_PATTERN, + DEFAULT_WALLED_GARDEN_PATTERN)); + mWalledGardenIntervalMs = Secure.getLong(mContentResolver, + Secure.WIFI_WATCHDOG_WALLED_GARDEN_INTERVAL_MS, + DEFAULT_WALLED_GARDEN_INTERVAL_MS); + } /** * Helper to return wait time left given a min interval and last run @@ -353,7 +429,7 @@ public class WifiWatchdogStateMachine extends StateMachine { mInitialConnInfo = null; mDisableAPNextFailure = false; mLastWalledGardenCheckTime = null; - mNumFullDNSchecks = 0; + mNumCheckFailures = 0; mBssids.clear(); } @@ -365,13 +441,43 @@ public class WifiWatchdogStateMachine extends StateMachine { mContext.startActivity(intent); } - private void sendCheckStepMessage(long delay) { - sendMessageDelayed(obtainMessage(MESSAGE_CHECK_STEP, mNetEventCounter, 0), delay); + private void displayDisabledNetworkNotification() { + Resources r = Resources.getSystem(); + CharSequence title = + r.getText(com.android.internal.R.string.wifi_watchdog_network_disabled); + CharSequence msg = + r.getText(com.android.internal.R.string.wifi_watchdog_network_disabled_detailed); + + Notification wifiDisabledWarning = new Notification.Builder(mContext) + .setSmallIcon(com.android.internal.R.drawable.stat_sys_warning) + .setDefaults(Notification.DEFAULT_ALL) + .setTicker(title) + .setContentTitle(title) + .setContentText(msg) + .setContentIntent(PendingIntent.getActivity(mContext, 0, + new Intent(Settings.ACTION_WIFI_IP_SETTINGS) + .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK), 0)) + .setWhen(System.currentTimeMillis()) + .setAutoCancel(true) + .getNotification(); + + NotificationManager notificationManager = (NotificationManager) mContext + .getSystemService(Context.NOTIFICATION_SERVICE); + + notificationManager.notify("WifiWatchdog", wifiDisabledWarning.icon, wifiDisabledWarning); } class DefaultState extends State { @Override public boolean processMessage(Message msg) { + switch (msg.what) { + case EVENT_WATCHDOG_SETTINGS_CHANGE: + updateSettings(); + if (VDBG) { + Slog.d(WWSM_TAG, "Updating wifi-watchdog secure settings"); + } + return HANDLED; + } if (VDBG) { Slog.v(WWSM_TAG, "Caught message " + msg.what + " in state " + getCurrentState().getName()); @@ -509,6 +615,10 @@ public class WifiWatchdogStateMachine extends StateMachine { mBssids.add(result.BSSID); } return HANDLED; + case EVENT_WATCHDOG_SETTINGS_CHANGE: + // Stop current checks, but let state update + transitionTo(mOnlineWatchState); + return NOT_HANDLED; } return NOT_HANDLED; } @@ -522,13 +632,12 @@ public class WifiWatchdogStateMachine extends StateMachine { @Override public void enter() { - mNumFullDNSchecks++; dnsCheckSuccesses = 0; dnsCheckTries = 0; if (DBG) { Slog.d(WWSM_TAG, "Starting DNS pings at " + SystemClock.elapsedRealtime()); - dnsCheckLogStr = String.format("Dns Check %d. Pinging %s on ssid [%s]: ", - mNumFullDNSchecks, mDnsPinger.getDns(), mInitialConnInfo.getSSID()); + dnsCheckLogStr = String.format("Pinging %s on ssid [%s]: ", + mDnsPinger.getDns(), mInitialConnInfo.getSSID()); } sendCheckStepMessage(0); @@ -545,7 +654,7 @@ public class WifiWatchdogStateMachine extends StateMachine { } long pingResponseTime = mDnsPinger.pingDns(mDnsPinger.getDns(), - DNS_PING_TIMEOUT_MS); + mDnsPingTimeoutMs); dnsCheckTries++; if (pingResponseTime >= 0) @@ -567,14 +676,12 @@ public class WifiWatchdogStateMachine extends StateMachine { * After a full ping count, if we have more responses than this * cutoff, the outcome is success; else it is 'failure'. */ - double pingResponseCutoff = MIN_DNS_RESPONSE_RATE * NUM_DNS_PINGS; - int remainingChecks = NUM_DNS_PINGS - dnsCheckTries; /** * Our final success count will be at least this big, so we're * guaranteed to succeed. */ - if (dnsCheckSuccesses >= pingResponseCutoff) { + if (dnsCheckSuccesses >= mMinDnsResponses) { // DNS CHECKS OK, NOW WALLED GARDEN if (DBG) { Slog.d(WWSM_TAG, dnsCheckLogStr + "| SUCCESS"); @@ -603,7 +710,8 @@ public class WifiWatchdogStateMachine extends StateMachine { * Our final count will be at most the current count plus the * remaining pings - we're guaranteed to fail. */ - if (remainingChecks + dnsCheckSuccesses < pingResponseCutoff) { + int remainingChecks = mNumDnsPings - dnsCheckTries; + if (remainingChecks + dnsCheckSuccesses < mMinDnsResponses) { if (DBG) { Slog.d(WWSM_TAG, dnsCheckLogStr + "| FAILURE"); } @@ -617,12 +725,12 @@ public class WifiWatchdogStateMachine extends StateMachine { } private boolean shouldCheckWalledGarden() { - if (!isWalledGardenTestEnabled()) { + if (!mWalledGardenTestEnabled) { if (VDBG) Slog.v(WWSM_TAG, "Skipping walled garden check - disabled"); return false; } - long waitTime = waitTime(MIN_WALLED_GARDEN_INTERVAL_MS, + long waitTime = waitTime(mWalledGardenIntervalMs, mLastWalledGardenCheckTime); if (waitTime > 0) { if (DBG) { @@ -634,6 +742,10 @@ public class WifiWatchdogStateMachine extends StateMachine { return true; } + private void sendCheckStepMessage(long delay) { + sendMessageDelayed(obtainMessage(MESSAGE_CHECK_STEP, mNetEventCounter, 0), delay); + } + } class OnlineWatchState extends State { @@ -698,7 +810,7 @@ public class WifiWatchdogStateMachine extends StateMachine { } lastCheckTime = SystemClock.elapsedRealtime(); long responseTime = mDnsPinger.pingDns(mDnsPinger.getDns(), - DNS_PING_TIMEOUT_MS); + mDnsPingTimeoutMs); if (responseTime >= 0) { if (VDBG) { Slog.v(WWSM_TAG, "Ran a single DNS ping. Response time: " @@ -720,15 +832,15 @@ public class WifiWatchdogStateMachine extends StateMachine { } /** - * Times a dns check with an interval based on {@link #curSignalStable} + * Times a dns check with an interval based on {@link #signalUnstable} */ private void triggerSingleDnsCheck() { long waitInterval; if (signalUnstable) { - waitInterval = MIN_LOW_SIGNAL_CHECK_INTERVAL_MS; + waitInterval = mDnsCheckShortIntervalMs; unstableSignalChecks = true; } else { - waitInterval = MIN_SINGLE_DNS_CHECK_INTERVAL_MS; + waitInterval = mDnsCheckLongIntervalMs; } sendMessageDelayed(obtainMessage(MESSAGE_SINGLE_DNS_CHECK, checkGuard, 0), waitTime(waitInterval, lastCheckTime)); @@ -738,6 +850,7 @@ public class WifiWatchdogStateMachine extends StateMachine { class DnsCheckFailureState extends State { @Override public void enter() { + mNumCheckFailures++; obtainMessage(MESSAGE_HANDLE_BAD_AP, mNetEventCounter, 0).sendToTarget(); } @@ -754,16 +867,22 @@ public class WifiWatchdogStateMachine extends StateMachine { return HANDLED; } - if (mDisableAPNextFailure || mNumFullDNSchecks >= MAX_CHECKS_PER_SSID) { + if (mDisableAPNextFailure || mNumCheckFailures >= mMaxSsidBlacklists) { // TODO : Unban networks if they had low signal ? Slog.i(WWSM_TAG, "Disabling current SSID " + wifiInfoToStr(mInitialConnInfo) - + ". " + - "numChecks " + mNumFullDNSchecks + ", numAPs " + mBssids.size()); + + ". " + "numCheckFailures " + mNumCheckFailures + + ", numAPs " + mBssids.size()); mWifiManager.disableNetwork(mInitialConnInfo.getNetworkId()); + if (mShowDisabledNotification) { + displayDisabledNetworkNotification(); + mShowDisabledNotification = false; + putSettingsBoolean(mContentResolver, + Settings.Secure.WIFI_WATCHDOG_SHOW_DISABLED_NETWORK_POPUP, false); + } transitionTo(mNotConnectedState); } else { - Slog.i(WWSM_TAG, "Blacklisting current BSSID. " + wifiInfoToStr(mInitialConnInfo) + - "numChecks " + mNumFullDNSchecks + ", numAPs " + mBssids.size()); + Slog.i(WWSM_TAG, "Blacklisting current BSSID. " + wifiInfoToStr(mInitialConnInfo) + + "numCheckFailures " + mNumCheckFailures + ", numAPs " + mBssids.size()); mWifiManager.addToBlacklist(mInitialConnInfo.getBSSID()); mWifiManager.reassociate(); @@ -802,7 +921,7 @@ public class WifiWatchdogStateMachine extends StateMachine { public void enter() { mDisableAPNextFailure = true; sendMessageDelayed(obtainMessage(MESSAGE_NETWORK_FOLLOWUP, mNetEventCounter, 0), - BLACKLIST_FOLLOWUP_INTERVAL_MS); + mBlacklistFollowupIntervalMs); } @Override @@ -822,4 +941,57 @@ public class WifiWatchdogStateMachine extends StateMachine { return HANDLED; } } + + + /** + * Convenience function for retrieving a single secure settings value + * as a string with a default value. + * + * @param cr The ContentResolver to access. + * @param name The name of the setting to retrieve. + * @param def Value to return if the setting is not defined. + * + * @return The setting's current value, or 'def' if it is not defined + */ + private static String getSettingsStr(ContentResolver cr, String name, String def) { + String v = Settings.Secure.getString(cr, name); + return v != null ? v : def; + } + + /** + * Convenience function for retrieving a single secure settings value + * as a boolean. Note that internally setting values are always + * stored as strings; this function converts the string to a boolean + * for you. The default value will be returned if the setting is + * not defined or not a valid boolean. + * + * @param cr The ContentResolver to access. + * @param name The name of the setting to retrieve. + * @param def Value to return if the setting is not defined. + * + * @return The setting's current value, or 'def' if it is not defined + * or not a valid boolean. + */ + private static boolean getSettingsBoolean(ContentResolver cr, String name, boolean def) { + return Settings.Secure.getInt(cr, name, def ? 1 : 0) == 1; + } + + /** + * Convenience function for updating a single settings value as an + * integer. This will either create a new entry in the table if the + * given name does not exist, or modify the value of the existing row + * with that name. Note that internally setting values are always + * stored as strings, so this function converts the given value to a + * string before storing it. + * + * @param cr The ContentResolver to access. + * @param name The name of the setting to modify. + * @param value The new value for the setting. + * @return true if the value was set, false on database errors + */ + private static boolean putSettingsBoolean(ContentResolver cr, String name, boolean value) { + return Settings.Secure.putInt(cr, name, value ? 1 : 0); + } + + } diff --git a/wifi/java/android/net/wifi/WpsConfiguration.java b/wifi/java/android/net/wifi/WpsConfiguration.java index 12d951f..2e7689a 100644 --- a/wifi/java/android/net/wifi/WpsConfiguration.java +++ b/wifi/java/android/net/wifi/WpsConfiguration.java @@ -30,13 +30,16 @@ import java.util.BitSet; */ public class WpsConfiguration implements Parcelable { + /* Wi-Fi Protected Setup. www.wi-fi.org/wifi-protected-setup has details */ public enum Setup { - /* Wi-Fi protected setup push button configuration */ + /* Push button configuration */ PBC, - /* Wi-Fi protected setup pin method configuration with pin obtained from access point */ - PIN_FROM_ACCESS_POINT, - /* Wi-Fi protected setup pin method configuration with pin obtained from device */ - PIN_FROM_DEVICE, + /* Display pin method configuration - pin is generated and displayed on device */ + DISPLAY, + /* Keypad pin method configuration - pin is entered on device */ + KEYPAD, + /* Label pin method configuration - pin is obtained from a printed label */ + LABEL, /* Invalid config */ INVALID } diff --git a/wifi/java/android/net/wifi/WpsStateMachine.java b/wifi/java/android/net/wifi/WpsStateMachine.java index 120b228..af089ab 100644 --- a/wifi/java/android/net/wifi/WpsStateMachine.java +++ b/wifi/java/android/net/wifi/WpsStateMachine.java @@ -22,7 +22,7 @@ import com.android.internal.util.StateMachine; import android.content.Context; import android.content.Intent; -import android.net.wifi.WifiStateMachine.StateChangeResult; +import android.net.wifi.StateChangeResult; import android.net.wifi.WpsResult.Status; import android.os.Handler; import android.os.Message; @@ -99,10 +99,10 @@ class WpsStateMachine extends StateMachine { case PBC: result = WifiConfigStore.startWpsPbc(mWpsConfig); break; - case PIN_FROM_ACCESS_POINT: + case KEYPAD: result = WifiConfigStore.startWpsWithPinFromAccessPoint(mWpsConfig); break; - case PIN_FROM_DEVICE: + case DISPLAY: result = WifiConfigStore.startWpsWithPinFromDevice(mWpsConfig); break; default: @@ -139,7 +139,7 @@ class WpsStateMachine extends StateMachine { boolean retValue = HANDLED; if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); switch (message.what) { - case WifiStateMachine.SUPPLICANT_STATE_CHANGE_EVENT: + case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: StateChangeResult stateChangeResult = (StateChangeResult) message.obj; SupplicantState supState = (SupplicantState) stateChangeResult.state; switch (supState) { @@ -194,7 +194,7 @@ class WpsStateMachine extends StateMachine { if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); switch (message.what) { //Ignore supplicant state changes - case WifiStateMachine.SUPPLICANT_STATE_CHANGE_EVENT: + case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: break; default: retValue = NOT_HANDLED; diff --git a/wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl b/wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl new file mode 100644 index 0000000..a0c7dd1 --- /dev/null +++ b/wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2008, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.wifi.p2p; + +import android.os.Messenger; + +/** + * Interface that WifiP2pService implements + * + * {@hide} + */ +interface IWifiP2pManager +{ + Messenger getMessenger(); + boolean isP2pSupported(); +} + diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pConfig.aidl b/wifi/java/android/net/wifi/p2p/WifiP2pConfig.aidl new file mode 100644 index 0000000..ea3b280 --- /dev/null +++ b/wifi/java/android/net/wifi/p2p/WifiP2pConfig.aidl @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2011, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.wifi.p2p; + +parcelable WifiP2pConfig; diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java b/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java new file mode 100644 index 0000000..fff5ee3 --- /dev/null +++ b/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.wifi.p2p; + +import android.net.wifi.WpsConfiguration; +import android.net.wifi.WpsConfiguration.Setup; +import android.os.Parcelable; +import android.os.Parcel; + +/** + * A class representing a Wi-Fi P2p configuration + * @hide + */ +public class WifiP2pConfig implements Parcelable { + + /** + * Device name + */ + public String deviceName; + + /** + * Device address + */ + public String deviceAddress; + + /** + * WPS configuration + */ + public WpsConfiguration wpsConfig; + + /** + * This is an integer value between 0 and 15 where 0 indicates the least + * inclination to be a group owner and 15 indicates the highest inclination + * to be a group owner. + */ + public int groupOwnerIntent; + + public boolean isPersistent; + + public boolean joinExistingGroup; + + /** + * Channel frequency in MHz + */ + public int channel; + + public WifiP2pConfig() { + //set defaults + wpsConfig = new WpsConfiguration(); + wpsConfig.setup = Setup.PBC; + } + + /* P2P-GO-NEG-REQUEST 42:fc:89:a8:96:09 dev_passwd_id=4 */ + public WifiP2pConfig(String supplicantEvent) throws IllegalArgumentException { + String[] tokens = supplicantEvent.split(" "); + + if (tokens.length < 2 || !tokens[0].equals("P2P-GO-NEG-REQUEST")) { + throw new IllegalArgumentException("Malformed supplicant event"); + } + + deviceAddress = tokens[1]; + wpsConfig = new WpsConfiguration(); + + if (tokens.length > 2) { + String[] nameVal = tokens[2].split("="); + int devPasswdId; + try { + devPasswdId = Integer.parseInt(nameVal[1]); + } catch (NumberFormatException e) { + devPasswdId = 0; + } + //As defined in wps/wps_defs.h + switch (devPasswdId) { + case 0x00: + wpsConfig.setup = Setup.LABEL; + break; + case 0x01: + wpsConfig.setup = Setup.KEYPAD; + break; + case 0x04: + wpsConfig.setup = Setup.PBC; + break; + case 0x05: + wpsConfig.setup = Setup.DISPLAY; + break; + default: + wpsConfig.setup = Setup.PBC; + break; + } + } + } + + public String toString() { + StringBuffer sbuf = new StringBuffer(); + sbuf.append("Device: ").append(deviceName); + sbuf.append("\n address: ").append(deviceAddress); + sbuf.append("\n wps: ").append(wpsConfig); + sbuf.append("\n groupOwnerIntent: ").append(groupOwnerIntent); + sbuf.append("\n isPersistent: ").append(isPersistent); + sbuf.append("\n joinExistingGroup: ").append(joinExistingGroup); + sbuf.append("\n channel: ").append(channel); + return sbuf.toString(); + } + + /** Implement the Parcelable interface {@hide} */ + public int describeContents() { + return 0; + } + + /** copy constructor {@hide} */ + public WifiP2pConfig(WifiP2pConfig source) { + if (source != null) { + //TODO: implement + } + } + + /** Implement the Parcelable interface {@hide} */ + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(deviceName); + dest.writeString(deviceAddress); + dest.writeParcelable(wpsConfig, flags); + dest.writeInt(groupOwnerIntent); + dest.writeInt(isPersistent ? 1 : 0); + dest.writeInt(joinExistingGroup ? 1 : 0); + dest.writeInt(channel); + } + + /** Implement the Parcelable interface {@hide} */ + public static final Creator<WifiP2pConfig> CREATOR = + new Creator<WifiP2pConfig>() { + public WifiP2pConfig createFromParcel(Parcel in) { + WifiP2pConfig config = new WifiP2pConfig(); + config.deviceName = in.readString(); + config.deviceAddress = in.readString(); + config.wpsConfig = (WpsConfiguration) in.readParcelable(null); + config.groupOwnerIntent = in.readInt(); + config.isPersistent = (in.readInt() == 1); + config.joinExistingGroup = (in.readInt() == 1); + config.channel = in.readInt(); + return config; + } + + public WifiP2pConfig[] newArray(int size) { + return new WifiP2pConfig[size]; + } + }; +} diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pDevice.aidl b/wifi/java/android/net/wifi/p2p/WifiP2pDevice.aidl new file mode 100644 index 0000000..8790c6f --- /dev/null +++ b/wifi/java/android/net/wifi/p2p/WifiP2pDevice.aidl @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2011, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.wifi.p2p; + +parcelable WifiP2pDevice; diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java b/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java new file mode 100644 index 0000000..83dc285 --- /dev/null +++ b/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java @@ -0,0 +1,312 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.wifi.p2p; + +import android.os.Parcelable; +import android.os.Parcel; +import android.util.Log; + +import java.util.regex.Pattern; + +/** + * A class representing a Wi-Fi p2p device + * @hide + */ +public class WifiP2pDevice implements Parcelable { + + private static final String TAG = "WifiP2pDevice"; + /** + * Device name + */ + public String deviceName; + + /** + * Device MAC address + */ + public String deviceAddress; + + /** + * interfaceAddress + * + * This address is used during group owner negotiation as the Intended + * P2P Interface Address and the group interface will be created with + * address as the local address in case of successfully completed + * negotiation. + */ + public String interfaceAddress; + + /** + * Primary device type + */ + public String primaryDeviceType; + + /** + * Secondary device type + */ + public String secondaryDeviceType; + + + // These definitions match the ones in wpa_supplicant + /* WPS config methods supported */ + private static final int WPS_CONFIG_USBA = 0x0001; + private static final int WPS_CONFIG_ETHERNET = 0x0002; + private static final int WPS_CONFIG_LABEL = 0x0004; + private static final int WPS_CONFIG_DISPLAY = 0x0008; + private static final int WPS_CONFIG_EXT_NFC_TOKEN = 0x0010; + private static final int WPS_CONFIG_INT_NFC_TOKEN = 0x0020; + private static final int WPS_CONFIG_NFC_INTERFACE = 0x0040; + private static final int WPS_CONFIG_PUSHBUTTON = 0x0080; + private static final int WPS_CONFIG_KEYPAD = 0x0100; + private static final int WPS_CONFIG_VIRT_PUSHBUTTON = 0x0280; + private static final int WPS_CONFIG_PHY_PUSHBUTTON = 0x0480; + private static final int WPS_CONFIG_VIRT_DISPLAY = 0x2008; + private static final int WPS_CONFIG_PHY_DISPLAY = 0x4008; + + /* Device Capability bitmap */ + private static final int DEVICE_CAPAB_SERVICE_DISCOVERY = 1; + private static final int DEVICE_CAPAB_CLIENT_DISCOVERABILITY = 1<<1; + private static final int DEVICE_CAPAB_CONCURRENT_OPER = 1<<2; + private static final int DEVICE_CAPAB_INFRA_MANAGED = 1<<3; + private static final int DEVICE_CAPAB_DEVICE_LIMIT = 1<<4; + private static final int DEVICE_CAPAB_INVITATION_PROCEDURE = 1<<5; + + /* Group Capability bitmap */ + private static final int GROUP_CAPAB_GROUP_OWNER = 1; + private static final int GROUP_CAPAB_PERSISTENT_GROUP = 1<<1; + private static final int GROUP_CAPAB_GROUP_LIMIT = 1<<2; + private static final int GROUP_CAPAB_INTRA_BSS_DIST = 1<<3; + private static final int GROUP_CAPAB_CROSS_CONN = 1<<4; + private static final int GROUP_CAPAB_PERSISTENT_RECONN = 1<<5; + private static final int GROUP_CAPAB_GROUP_FORMATION = 1<<6; + + /** + * WPS config methods supported + */ + public int wpsConfigMethodsSupported; + + /** + * Device capability + */ + public int deviceCapability; + + /** + * Group capability + */ + public int groupCapability; + + public enum Status { + CONNECTED, + INVITED, + FAILED, + AVAILABLE, + UNAVAILABLE, + } + + public Status status = Status.UNAVAILABLE; + + public WifiP2pDevice() { + } + + /** + * @param string formats supported include + * P2P-DEVICE-FOUND fa:7b:7a:42:02:13 p2p_dev_addr=fa:7b:7a:42:02:13 + * pri_dev_type=1-0050F204-1 name='p2p-TEST1' config_methods=0x188 dev_capab=0x27 + * group_capab=0x0 + * + * P2P-DEVICE-LOST p2p_dev_addr=fa:7b:7a:42:02:13 + * + * fa:7b:7a:42:02:13 + * + * P2P-PROV-DISC-PBC-REQ 42:fc:89:e1:e2:27 p2p_dev_addr=42:fc:89:e1:e2:27 + * pri_dev_type=1-0050F204-1 name='p2p-TEST2' config_methods=0x188 dev_capab=0x27 + * group_capab=0x0 + * + * P2P-PROV-DISC-ENTER-PIN 42:fc:89:e1:e2:27 p2p_dev_addr=42:fc:89:e1:e2:27 + * pri_dev_type=1-0050F204-1 name='p2p-TEST2' config_methods=0x188 dev_capab=0x27 + * group_capab=0x0 + * + * P2P-PROV-DISC-SHOW-PIN 42:fc:89:e1:e2:27 44490607 p2p_dev_addr=42:fc:89:e1:e2:27 + * pri_dev_type=1-0050F204-1 name='p2p-TEST2' config_methods=0x188 dev_capab=0x27 + * group_capab=0x0 + * + * Note: The events formats can be looked up in the wpa_supplicant code + */ + public WifiP2pDevice(String string) throws IllegalArgumentException { + String[] tokens = string.split(" "); + + if (tokens.length < 1) { + throw new IllegalArgumentException("Malformed supplicant event"); + } + + /* Just a device address */ + if (tokens.length == 1) { + deviceAddress = string; + return; + } + + Pattern p = Pattern.compile("(?:[0-9a-f]{2}:){5}[0-9a-f]{2}", Pattern.CASE_INSENSITIVE); + if (p.matcher(tokens[1]).matches()) interfaceAddress = tokens[1]; + + for (String token : tokens) { + String[] nameValue = token.split("="); + if (nameValue.length != 2) continue; + + if (nameValue[0].equals("p2p_dev_addr")) { + deviceAddress = nameValue[1]; + continue; + } + + if (nameValue[0].equals("pri_dev_type")) { + primaryDeviceType = nameValue[1]; + continue; + } + + if (nameValue[0].equals("name")) { + deviceName = trimQuotes(nameValue[1]); + } + + if (nameValue[0].equals("config_methods")) { + wpsConfigMethodsSupported = parseHex(nameValue[1]); + continue; + } + + if (nameValue[0].equals("dev_capab")) { + deviceCapability = parseHex(nameValue[1]); + continue; + } + + if (nameValue[0].equals("group_capab")) { + groupCapability = parseHex(nameValue[1]); + continue; + } + } + + if (tokens[0].startsWith("P2P-DEVICE-FOUND")) { + status = Status.AVAILABLE; + } + } + + public boolean isGroupOwner() { + return (groupCapability & GROUP_CAPAB_GROUP_OWNER) != 0; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (!(obj instanceof WifiP2pDevice)) return false; + + WifiP2pDevice other = (WifiP2pDevice) obj; + if (other == null || other.deviceAddress == null) { + return (deviceAddress == null); + } + //STOPSHIP: fix later + //return other.deviceAddress.equals(deviceAddress); + return other.deviceAddress.startsWith(deviceAddress.substring(0,8)); + } + + public String toString() { + StringBuffer sbuf = new StringBuffer(); + sbuf.append("Device: ").append(deviceName); + sbuf.append("\n deviceAddress: ").append(deviceAddress); + sbuf.append("\n interfaceAddress: ").append(interfaceAddress); + sbuf.append("\n primary type: ").append(primaryDeviceType); + sbuf.append("\n secondary type: ").append(secondaryDeviceType); + sbuf.append("\n wps: ").append(wpsConfigMethodsSupported); + sbuf.append("\n grpcapab: ").append(groupCapability); + sbuf.append("\n devcapab: ").append(deviceCapability); + sbuf.append("\n status: ").append(status); + return sbuf.toString(); + } + + /** Implement the Parcelable interface {@hide} */ + public int describeContents() { + return 0; + } + + /** copy constructor {@hide} */ + public WifiP2pDevice(WifiP2pDevice source) { + if (source != null) { + deviceName = source.deviceName; + deviceAddress = source.deviceAddress; + interfaceAddress = source.interfaceAddress; + primaryDeviceType = source.primaryDeviceType; + secondaryDeviceType = source.secondaryDeviceType; + wpsConfigMethodsSupported = source.wpsConfigMethodsSupported; + deviceCapability = source.deviceCapability; + groupCapability = source.groupCapability; + status = source.status; + } + } + + /** Implement the Parcelable interface {@hide} */ + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(deviceName); + dest.writeString(deviceAddress); + dest.writeString(interfaceAddress); + dest.writeString(primaryDeviceType); + dest.writeString(secondaryDeviceType); + dest.writeInt(wpsConfigMethodsSupported); + dest.writeInt(deviceCapability); + dest.writeInt(groupCapability); + dest.writeString(status.name()); + } + + /** Implement the Parcelable interface {@hide} */ + public static final Creator<WifiP2pDevice> CREATOR = + new Creator<WifiP2pDevice>() { + public WifiP2pDevice createFromParcel(Parcel in) { + WifiP2pDevice device = new WifiP2pDevice(); + device.deviceName = in.readString(); + device.deviceAddress = in.readString(); + device.interfaceAddress = in.readString(); + device.primaryDeviceType = in.readString(); + device.secondaryDeviceType = in.readString(); + device.wpsConfigMethodsSupported = in.readInt(); + device.deviceCapability = in.readInt(); + device.groupCapability = in.readInt(); + device.status = Status.valueOf(in.readString()); + return device; + } + + public WifiP2pDevice[] newArray(int size) { + return new WifiP2pDevice[size]; + } + }; + + private String trimQuotes(String str) { + str = str.trim(); + if (str.startsWith("'") && str.endsWith("'")) { + return str.substring(1, str.length()-1); + } + return str; + } + + //supported formats: 0x1abc, 0X1abc, 1abc + private int parseHex(String hexString) { + int num = 0; + if (hexString.startsWith("0x") || hexString.startsWith("0X")) { + hexString = hexString.substring(2); + } + + try { + num = Integer.parseInt(hexString, 16); + } catch(NumberFormatException e) { + Log.e(TAG, "Failed to parse hex string " + hexString); + } + return num; + } +} diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.aidl b/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.aidl new file mode 100644 index 0000000..6c79009 --- /dev/null +++ b/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.aidl @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2011, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.wifi.p2p; + +parcelable WifiP2pDeviceList; diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java b/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java new file mode 100644 index 0000000..4ec23b8 --- /dev/null +++ b/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.wifi.p2p; + +import android.os.Parcelable; +import android.os.Parcel; +import android.net.wifi.p2p.WifiP2pDevice; +import android.util.Log; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; + +/** + * A class representing a Wi-Fi P2p device list + * @hide + */ +public class WifiP2pDeviceList implements Parcelable { + + private Collection<WifiP2pDevice> mDevices; + + public WifiP2pDeviceList() { + mDevices = new ArrayList<WifiP2pDevice>(); + } + + //copy constructor + public WifiP2pDeviceList(WifiP2pDeviceList source) { + if (source != null) { + mDevices = source.getDeviceList(); + } + } + + public WifiP2pDeviceList(ArrayList<WifiP2pDevice> devices) { + mDevices = new ArrayList<WifiP2pDevice>(); + for (WifiP2pDevice device : devices) { + mDevices.add(device); + } + } + + public void clear() { + mDevices.clear(); + } + + public void add(WifiP2pDevice device) { + if (device == null) return; + if (mDevices.contains(device)) return; + mDevices.add(device); + } + + public boolean remove(WifiP2pDevice device) { + if (device == null) return false; + return mDevices.remove(device); + } + + public Collection<WifiP2pDevice> getDeviceList() { + return Collections.unmodifiableCollection(mDevices); + } + + public String toString() { + StringBuffer sbuf = new StringBuffer(); + for (WifiP2pDevice device : mDevices) { + sbuf.append("\n").append(device); + } + return sbuf.toString(); + } + + /** Implement the Parcelable interface {@hide} */ + public int describeContents() { + return 0; + } + + /** Implement the Parcelable interface {@hide} */ + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mDevices.size()); + for(WifiP2pDevice device : mDevices) { + dest.writeParcelable(device, flags); + } + } + + /** Implement the Parcelable interface {@hide} */ + public static final Creator<WifiP2pDeviceList> CREATOR = + new Creator<WifiP2pDeviceList>() { + public WifiP2pDeviceList createFromParcel(Parcel in) { + WifiP2pDeviceList deviceList = new WifiP2pDeviceList(); + + int deviceCount = in.readInt(); + for (int i = 0; i < deviceCount; i++) { + deviceList.add((WifiP2pDevice)in.readParcelable(null)); + } + return deviceList; + } + + public WifiP2pDeviceList[] newArray(int size) { + return new WifiP2pDeviceList[size]; + } + }; +} diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pGroup.aidl b/wifi/java/android/net/wifi/p2p/WifiP2pGroup.aidl new file mode 100644 index 0000000..403f2b1 --- /dev/null +++ b/wifi/java/android/net/wifi/p2p/WifiP2pGroup.aidl @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2011, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.wifi.p2p; + +parcelable WifiP2pGroup; diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java b/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java new file mode 100644 index 0000000..ca6e4d5 --- /dev/null +++ b/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java @@ -0,0 +1,224 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.wifi.p2p; + +import android.os.Parcelable; +import android.os.Parcel; + +import java.util.ArrayList; +import java.util.List; +import java.util.Collection; +import java.util.Collections; + +/** + * A class representing a Wi-Fi P2p group + * @hide + */ +public class WifiP2pGroup implements Parcelable { + + /** The network name */ + private String mNetworkName; + + /** The network bssid */ + private String mNetworkBssid; + + /** Group owner */ + private WifiP2pDevice mOwner; + + /** Device is group owner */ + private boolean mIsGroupOwner; + + /** Group clients */ + private List<WifiP2pDevice> mClients = new ArrayList<WifiP2pDevice>(); + + private int mChannel; + + /** + * The network passphrase + * <p/> + * The passphrase used for WPA2-PSK + */ + private String mPassphrase; + + /** + * TODO: fix + * Sometimes supplicant sends a psk + */ + private String mPsk; + + /** Indicates that the group is persistent */ + private boolean mIsPersistent; + + private String mInterface; + + public WifiP2pGroup() { + } + + /** + * @param string formats supported include + * + * P2P-GROUP-STARTED p2p-wlan0-0 [client|GO] ssid="DIRECT-W8" freq=2437 + * [psk=2182b2e50e53f260d04f3c7b25ef33c965a3291b9b36b455a82d77fd82ca15bc| + * passphrase="fKG4jMe3"] go_dev_addr=fa:7b:7a:42:02:13 + * + * P2P-GROUP-REMOVED p2p-wlan0-0 [client|GO] reason=REQUESTED + * + * P2P-INVITATION-RECEIVED sa=fa:7b:7a:42:02:13 go_dev_addr=f8:7b:7a:42:02:13 + * bssid=fa:7b:7a:42:82:13 unknown-network + * + * Note: The events formats can be looked up in the wpa_supplicant code + */ + public WifiP2pGroup(String supplicantEvent) throws IllegalArgumentException { + + String[] tokens = supplicantEvent.split(" "); + + if (tokens.length < 3) { + throw new IllegalArgumentException("Malformed supplicant event"); + } + + if (tokens[0].startsWith("P2P-GROUP")) { + mInterface = tokens[1]; + mIsGroupOwner = tokens[2].equals("GO"); + + for (String token : tokens) { + String[] nameValue = token.split("="); + if (nameValue.length != 2) continue; + + if (nameValue[0].equals("ssid")) { + mNetworkName = nameValue[1]; + continue; + } + + if (nameValue[0].equals("freq")) { + try { + mChannel = Integer.parseInt(nameValue[1]); + } catch (NumberFormatException e) { + mChannel = 0; //invalid + } + continue; + } + + if (nameValue[0].equals("psk")) { + mPsk = nameValue[1]; + continue; + } + + if (nameValue[0].equals("passphrase")) { + mPassphrase = nameValue[1]; + continue; + } + + if (nameValue[0].equals("go_dev_addr")) { + mOwner = new WifiP2pDevice(nameValue[1]); + } + } + } else if (tokens[0].equals("P2P-INVITATION-RECEIVED")) { + for (String token : tokens) { + String[] nameValue = token.split("="); + if (nameValue.length != 2) continue; + + if (nameValue[0].equals("go_dev_addr")) { + mOwner = new WifiP2pDevice(nameValue[1]); + continue; + } + + if (nameValue[0].equals("bssid")) { + mNetworkBssid = nameValue[1]; + } + } + } else { + throw new IllegalArgumentException("Malformed supplicant event"); + } + } + + public boolean isGroupOwner() { + return mIsGroupOwner; + } + + public WifiP2pDevice getOwner() { + return mOwner; + } + + public void addClient(String address) { + addClient(new WifiP2pDevice(address)); + } + + public void addClient(WifiP2pDevice device) { + for (WifiP2pDevice client : mClients) { + if (client.equals(device)) return; + } + mClients.add(device); + } + + public boolean removeClient(String address) { + return mClients.remove(new WifiP2pDevice(address)); + } + + public boolean removeClient(WifiP2pDevice device) { + return mClients.remove(device); + } + + public boolean isClientListEmpty() { + return mClients.size() == 0; + } + + public Collection<WifiP2pDevice> getClientList() { + return Collections.unmodifiableCollection(mClients); + } + + public String getInterface() { + return mInterface; + } + + // TODO: implement + public String toString() { + StringBuffer sbuf = new StringBuffer(); + //sbuf.append("SSID: ").append(SSID); + //sbuf.append("\n passphrase: ").append(passphrase); + return sbuf.toString(); + } + + /** Implement the Parcelable interface {@hide} */ + public int describeContents() { + return 0; + } + + /** copy constructor {@hide} */ + // TODO: implement + public WifiP2pGroup(WifiP2pGroup source) { + if (source != null) { + } + } + + /** Implement the Parcelable interface {@hide} */ + // STOPSHIP: implement + public void writeToParcel(Parcel dest, int flags) { + } + + /** Implement the Parcelable interface {@hide} */ + public static final Creator<WifiP2pGroup> CREATOR = + new Creator<WifiP2pGroup>() { + public WifiP2pGroup createFromParcel(Parcel in) { + WifiP2pGroup group = new WifiP2pGroup(); + return group; + } + + public WifiP2pGroup[] newArray(int size) { + return new WifiP2pGroup[size]; + } + }; +} diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java new file mode 100644 index 0000000..ea212ac --- /dev/null +++ b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java @@ -0,0 +1,344 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.wifi.p2p; + +import android.annotation.SdkConstant; +import android.annotation.SdkConstant.SdkConstantType; +import android.content.Context; +import android.os.Binder; +import android.os.IBinder; +import android.os.Handler; +import android.os.Message; +import android.os.RemoteException; +import android.os.WorkSource; +import android.os.Messenger; + +import com.android.internal.util.AsyncChannel; +import com.android.internal.util.Protocol; + +/** + * This class provides the API for managing Wi-Fi p2p + * connectivity. Get an instance of this class by calling + * {@link android.content.Context#getSystemService(String) + * Context.getSystemService(Context.WIFI_P2P_SERVICE)}. + * + * It deals with the following: + * <ul> + * <li>Wi-Fi peer discovery and connection setup. Allows applications to initiate a discovery to + * find available peers and then setup a connection </li> + * <li>Configuration and status query. Allows applications to fetch the current list + * of available and connected peers and query connection status </li> + * <li>Intent actions that are broadcast to track operations + * on a p2p connection</li> + * </ul> + * @hide + */ +public class WifiP2pManager { + /** + * Broadcast intent action to indicate whether Wi-Fi p2p is enabled or disabled. + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String WIFI_P2P_STATE_CHANGED_ACTION = + "android.net.wifi.P2P_STATE_CHANGED"; + + /** + * The lookup key for an int that indicates whether Wi-Fi p2p is enabled or disabled. + * Retrieve it with {@link android.content.Intent#getIntExtra(String,int)}. + * + * @see #WIFI_P2P_STATE_DISABLED + * @see #WIFI_P2P_STATE_ENABLED + */ + public static final String EXTRA_WIFI_STATE = "wifi_p2p_state"; + + /** + * Wi-Fi p2p is disabled. + * + * @see #WIFI_P2P_STATE_CHANGED_ACTION + * @see #getWifiP2pState() + */ + public static final int WIFI_P2P_STATE_DISABLED = 1; + + /** + * Wi-Fi p2p is enabled. + * + * @see #WIFI_P2P_STATE_CHANGED_ACTION + * @see #getWifiP2pState() + */ + public static final int WIFI_P2P_STATE_ENABLED = 2; + + /** + * Broadcast intent action indicating that the state of Wi-Fi p2p connectivity + * has changed. One extra provides the new state + * in the form of a {@link android.net.NetworkInfo} object. + * @see #EXTRA_NETWORK_INFO + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String WIFI_P2P_CONNECTION_CHANGED_ACTION = + "android.net.wifi.CONNECTION_STATE_CHANGE"; + + /** + * The lookup key for a {@link android.net.NetworkInfo} object associated with the + * Wi-Fi network. Retrieve with + * {@link android.content.Intent#getParcelableExtra(String)}. + */ + public static final String EXTRA_NETWORK_INFO = "networkInfo"; + + /** + * Broadcast intent action indicating that the available peer list has changed + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String WIFI_P2P_PEERS_CHANGED_ACTION = + "android.net.wifi.PEERS_CHANGED"; + + /** + * Activity Action: Pick a Wi-Fi p2p network to connect to. + * <p>Input: Nothing. + * <p>Output: Nothing. + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_PICK_WIFI_P2P_NETWORK = + "android.net.wifi.PICK_WIFI_P2P_NETWORK"; + + IWifiP2pManager mService; + + /* For communication with WifiP2pService */ + private AsyncChannel mAsyncChannel = new AsyncChannel(); + + /* AsyncChannel notifications to apps */ + public static final int HANDLER_CONNECTION = AsyncChannel.CMD_CHANNEL_HALF_CONNECTED; + public static final int HANDLER_DISCONNECTION = AsyncChannel.CMD_CHANNEL_DISCONNECTED; + + private static final int BASE = Protocol.BASE_WIFI_P2P_MANAGER; + + public static final int ENABLE_P2P = BASE + 1; + public static final int ENABLE_P2P_FAILED = BASE + 2; + public static final int ENABLE_P2P_SUCCEEDED = BASE + 3; + + /* arg1 on ENABLE_P2P_FAILED indicates a reason for failure */ + public static final int P2P_UNSUPPORTED = 1; + + public static final int DISABLE_P2P = BASE + 5; + public static final int DISABLE_P2P_FAILED = BASE + 6; + public static final int DISABLE_P2P_SUCCEEDED = BASE + 7; + + public static final int START_LISTEN_MODE = BASE + 9; + public static final int START_LISTEN_FAILED = BASE + 10; + public static final int START_LISTEN_SUCCEEDED = BASE + 11; + + public static final int DISCOVER_PEERS = BASE + 13; + public static final int DISCOVER_PEERS_FAILED = BASE + 14; + public static final int DISCOVER_PEERS_SUCCEDED = BASE + 15; + + public static final int CANCEL_DISCOVER_PEERS = BASE + 17; + public static final int CANCEL_DISCOVER_PEERS_FAILED = BASE + 18; + public static final int CANCEL_DISCOVER_PEERS_SUCCEDED = BASE + 19; + + public static final int CONNECT = BASE + 21; + public static final int CONNECT_FAILED = BASE + 22; + public static final int CONNECT_SUCCEEDED = BASE + 23; + + public static final int CANCEL_CONNECT = BASE + 25; + public static final int CANCEL_CONNECT_FAILED = BASE + 26; + public static final int CANCEL_CONNECT_SUCCEDED = BASE + 27; + + public static final int REJECT = BASE + 28; + public static final int REJECT_FAILED = BASE + 29; + public static final int REJECT_SUCCEEDED = BASE + 30; + + public static final int CREATE_GROUP = BASE + 31; + public static final int CREATE_GROUP_FAILED = BASE + 32; + public static final int CREATE_GROUP_SUCCEEDED = BASE + 33; + + public static final int REMOVE_GROUP = BASE + 34; + public static final int REMOVE_GROUP_FAILED = BASE + 35; + public static final int REMOVE_GROUP_SUCCEEDED = BASE + 36; + + public static final int REQUEST_SETTINGS = BASE + 37; + public static final int RESPONSE_SETTINGS = BASE + 38; + + public static final int REQUEST_PEERS = BASE + 39; + public static final int RESPONSE_PEERS = BASE + 40; + + public static final int REQUEST_CONNECTION_STATUS = BASE + 41; + public static final int RESPONSE_CONNECTION_STATUS = BASE + 42; + + public static final int WPS_PBC = BASE + 43; + public static final int WPS_PIN = BASE + 44; + public static final int WPS_PIN_AVAILABLE = BASE + 45; + + /** + * Create a new WifiP2pManager instance. Applications use + * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve + * the standard {@link android.content.Context#WIFI_P2P_SERVICE Context.WIFI_P2P_SERVICE}. + * @param service the Binder interface + * @param handler target for messages + * @hide - hide this because it takes in a parameter of type IWifiP2pManager, which + * is a system private class. + */ + public WifiP2pManager(IWifiP2pManager service) { + mService = service; + } + + /** + * Registers the application handler with the Wi-Fi framework. + * This function must be the first to be called before any p2p control + * or query operations can be performed. + * @param srcContext is the context of the source + * @param srcHandler is the handler on which the source receives messages + * @return {@code true} if the operation succeeded + */ + public boolean connectHandler(Context srcContext, Handler srcHandler) { + Messenger messenger = getMessenger(); + if (messenger == null) return false; + return mAsyncChannel.connectSync(srcContext, srcHandler, messenger) + == AsyncChannel.STATUS_SUCCESSFUL; + } + + public boolean isP2pSupported() { + try { + return mService.isP2pSupported(); + } catch (RemoteException e) { + return false; + } + } + + /** + * Sends in a request to the system to enable p2p. This will pop up a dialog + * to the user and upon authorization will enable p2p. + */ + public void enableP2p() { + mAsyncChannel.sendMessage(ENABLE_P2P); + } + + /** + * Sends in a request to the system to disable p2p. This will pop up a dialog + * to the user and upon authorization will enable p2p. + */ + public void disableP2p() { + mAsyncChannel.sendMessage(DISABLE_P2P); + } + + /** + * Set device in listen mode. This will make the device discoverable by + * another peer. + * A dialog to the user is thrown to request his permission since it can + * have a significant impact on power consumption + */ + public void setListenState(int timeout) { + mAsyncChannel.sendMessage(START_LISTEN_MODE, timeout); + } + + /** + * Initiates peer discovery + */ + public void discoverPeers() { + mAsyncChannel.sendMessage(DISCOVER_PEERS); + } + + /** + * Initiates peer discovery with a timeout + */ + public void discoverPeers(int timeout) { + mAsyncChannel.sendMessage(DISCOVER_PEERS, timeout); + } + + /** + * Cancel any existing peer discovery operation + */ + public void cancelPeerDiscovery() { + mAsyncChannel.sendMessage(CANCEL_DISCOVER_PEERS); + } + + /** + * Start a p2p connection + * + * @param peer Configuration described in a {@link WifiP2pConfig} object. + */ + public void connect(WifiP2pConfig config) { + mAsyncChannel.sendMessage(CONNECT, config); + } + + /** + * Cancel any ongoing negotiation or disconnect from an existing group + */ + public void disconnect() { + mAsyncChannel.sendMessage(CANCEL_CONNECT); + } + + /** + * Create a p2p group. This is essentially an access point that can accept + * client connections. + */ + public void createGroup() { + mAsyncChannel.sendMessage(CREATE_GROUP); + } + + /** + * Remove the current group. This also removes the p2p interface created + * during group formation. + */ + public void removeGroup() { + mAsyncChannel.sendMessage(REMOVE_GROUP); + } + + /** + * Request current p2p settings. This returns a RESPONSE_SETTINGS on the source + * handler. + */ + public void requestP2pSettings() { + mAsyncChannel.sendMessage(REQUEST_SETTINGS); + } + + /** + * Request the list of peers. This returns a RESPONSE_PEERS on the source + * handler. + */ + public void requestPeers() { + mAsyncChannel.sendMessage(REQUEST_PEERS); + } + + /** + * Fetch device list from a RESPONSE_PEERS message + */ + public WifiP2pDeviceList peersInResponse(Message msg) { + return (WifiP2pDeviceList) msg.obj; + } + + /** + * Request device connection status. This returns a RESPONSE_CONNECTION_STATUS on + * the source handler. + */ + public void requestConnectionStatus() { + mAsyncChannel.sendMessage(REQUEST_CONNECTION_STATUS); + } + + + /** + * Get a reference to WifiP2pService handler. This is used to establish + * an AsyncChannel communication with WifiService + * + * @return Messenger pointing to the WifiP2pService handler + * @hide + */ + public Messenger getMessenger() { + try { + return mService.getMessenger(); + } catch (RemoteException e) { + return null; + } + } +} diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java new file mode 100644 index 0000000..4988f0b --- /dev/null +++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java @@ -0,0 +1,880 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.server; + +import android.app.AlertDialog; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.DialogInterface; +import android.content.DialogInterface.OnClickListener; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.PackageManager; +import android.content.res.Resources; +import android.net.wifi.WifiManager; +import android.net.wifi.WifiMonitor; +import android.net.wifi.WifiNative; +import android.net.wifi.WifiStateMachine; +import android.net.wifi.WpsConfiguration; +import android.net.wifi.WpsConfiguration.Setup; +import android.net.wifi.p2p.IWifiP2pManager; +import android.net.wifi.p2p.WifiP2pConfig; +import android.net.wifi.p2p.WifiP2pDevice; +import android.net.wifi.p2p.WifiP2pDevice.Status; +import android.net.wifi.p2p.WifiP2pDeviceList; +import android.net.wifi.p2p.WifiP2pGroup; +import android.net.wifi.p2p.WifiP2pManager; +import android.os.Binder; +import android.os.IBinder; +import android.os.Handler; +import android.os.Messenger; +import android.os.HandlerThread; +import android.os.IBinder; +import android.os.Message; +import android.util.Slog; +import android.view.LayoutInflater; +import android.view.View; +import android.view.WindowManager; +import android.widget.EditText; + +import java.io.FileDescriptor; +import java.io.PrintWriter; +import java.util.Collection; + +import com.android.internal.util.AsyncChannel; +import com.android.internal.util.Protocol; +import com.android.internal.R; +import com.android.internal.util.State; +import com.android.internal.util.StateMachine; + +/** + * WifiP2pService inclues a state machine to perform Wi-Fi p2p operations. Applications + * communicate with this service to issue device discovery and connectivity requests + * through the WifiP2pManager interface. The state machine communicates with the wifi + * driver through wpa_supplicant and handles the event responses through WifiMonitor. + * + * Note that the term Wifi when used without a p2p suffix refers to the client mode + * of Wifi operation + * @hide + */ +public class WifiP2pService extends IWifiP2pManager.Stub { + private static final String TAG = "WifiP2pService"; + private static final boolean DBG = true; + + private Context mContext; + + // Tracked to notify the user about wifi client/hotspot being shut down + // during p2p bring up + private int mWifiState = WifiManager.WIFI_STATE_DISABLED; + private int mWifiApState = WifiManager.WIFI_AP_STATE_DISABLED; + + private P2pStateMachine mP2pStateMachine; + private AsyncChannel mReplyChannel = new AsyncChannel();; + private AsyncChannel mWifiChannel; + + private static final int BASE = Protocol.BASE_WIFI_P2P_SERVICE; + + /* Message sent to WifiStateMachine to indicate p2p enable is pending */ + public static final int P2P_ENABLE_PENDING = BASE + 1; + /* Message sent to WifiStateMachine to indicate Wi-Fi client/hotspot operation can proceed */ + public static final int WIFI_ENABLE_PROCEED = BASE + 2; + + /* User accepted to disable Wi-Fi in order to enable p2p */ + private static final int WIFI_DISABLE_USER_ACCEPT = BASE + 11; + + private final boolean mP2pSupported; + + public WifiP2pService(Context context) { + mContext = context; + + mP2pSupported = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_wifi_p2p_support); + + mP2pStateMachine = new P2pStateMachine(TAG, mP2pSupported); + mP2pStateMachine.start(); + + // broadcasts + IntentFilter filter = new IntentFilter(); + filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); + filter.addAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION); + mContext.registerReceiver(new WifiStateReceiver(), filter); + + } + + private class WifiStateReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + if (intent.getAction().equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) { + mWifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, + WifiManager.WIFI_STATE_DISABLED); + } else if (intent.getAction().equals(WifiManager.WIFI_AP_STATE_CHANGED_ACTION)) { + mWifiApState = intent.getIntExtra(WifiManager.EXTRA_WIFI_AP_STATE, + WifiManager.WIFI_AP_STATE_DISABLED); + } + } + } + + private void enforceAccessPermission() { + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_WIFI_STATE, + "WifiP2pService"); + } + + private void enforceChangePermission() { + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CHANGE_WIFI_STATE, + "WifiP2pService"); + } + + /** + * Get a reference to handler. This is used by a client to establish + * an AsyncChannel communication with WifiP2pService + */ + public Messenger getMessenger() { + enforceAccessPermission(); + enforceChangePermission(); + return new Messenger(mP2pStateMachine.getHandler()); + } + + /** + * Return if p2p is supported + */ + public boolean isP2pSupported() { + enforceAccessPermission(); + return mP2pSupported; + } + + @Override + protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) + != PackageManager.PERMISSION_GRANTED) { + pw.println("Permission Denial: can't dump WifiP2pService from from pid=" + + Binder.getCallingPid() + + ", uid=" + Binder.getCallingUid()); + return; + } + } + + + /** + * Handles interaction with WifiStateMachine + */ + private class P2pStateMachine extends StateMachine { + + private DefaultState mDefaultState = new DefaultState(); + private P2pNotSupportedState mP2pNotSupportedState = new P2pNotSupportedState(); + private P2pDisablingState mP2pDisablingState = new P2pDisablingState(); + private P2pDisabledState mP2pDisabledState = new P2pDisabledState(); + private WaitForWifiDisableState mWaitForWifiDisableState = new WaitForWifiDisableState(); + private P2pEnablingState mP2pEnablingState = new P2pEnablingState(); + private P2pEnabledState mP2pEnabledState = new P2pEnabledState(); + // Inactive is when p2p is enabled with no connectivity + private InactiveState mInactiveState = new InactiveState(); + private GroupNegotiationState mGroupNegotiationState = new GroupNegotiationState(); + private GroupCreatedState mGroupCreatedState = new GroupCreatedState(); + + private WifiMonitor mWifiMonitor = new WifiMonitor(this); + + private WifiP2pDeviceList mPeers = new WifiP2pDeviceList(); + private WifiP2pGroup mGroup; + + // Saved enable request message so the state machine can send an appropriate response + private Message mSavedEnableRequestMessage; + + // Saved WifiP2pConfig from GO negotiation request + private WifiP2pConfig mSavedGoNegotiationConfig; + + // Saved WifiP2pConfig from connect request + private WifiP2pConfig mSavedConnectConfig; + + // Saved WifiP2pGroup from invitation request + private WifiP2pGroup mSavedP2pGroup; + + P2pStateMachine(String name, boolean p2pSupported) { + super(name); + + addState(mDefaultState); + addState(mP2pNotSupportedState, mDefaultState); + addState(mP2pDisablingState, mDefaultState); + addState(mP2pDisabledState, mDefaultState); + addState(mWaitForWifiDisableState, mDefaultState); + addState(mP2pEnablingState, mDefaultState); + addState(mP2pEnabledState, mDefaultState); + addState(mInactiveState, mP2pEnabledState); + addState(mGroupNegotiationState, mP2pEnabledState); + addState(mGroupCreatedState, mP2pEnabledState); + + if (p2pSupported) { + setInitialState(mP2pDisabledState); + } else { + setInitialState(mP2pNotSupportedState); + } + } + + // TODO: Respond to every p2p request with success/failure + class DefaultState extends State { + @Override + public boolean processMessage(Message message) { + if (DBG) Slog.d(TAG, getName() + message.toString()); + switch (message.what) { + case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: + if (message.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { + if (DBG) Slog.d(TAG, "Full connection with WifiStateMachine established"); + mWifiChannel = (AsyncChannel) message.obj; + } else { + Slog.e(TAG, "Full connection failure, error = " + message.arg1); + mWifiChannel = null; + } + break; + + case AsyncChannel.CMD_CHANNEL_DISCONNECTED: + if (message.arg1 == AsyncChannel.STATUS_SEND_UNSUCCESSFUL) { + Slog.e(TAG, "Send failed, client connection lost"); + } else { + Slog.e(TAG, "Client connection lost with reason: " + message.arg1); + } + mWifiChannel = null; + break; + + case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: + AsyncChannel ac = new AsyncChannel(); + ac.connect(mContext, getHandler(), message.replyTo); + break; + case WifiStateMachine.WIFI_ENABLE_PENDING: + // Disable p2p operation before we can respond + sendMessage(WifiP2pManager.DISABLE_P2P); + deferMessage(message); + break; + case WifiP2pManager.ENABLE_P2P: + mReplyChannel.replyToMessage(message, WifiP2pManager.ENABLE_P2P_FAILED); + break; + case WifiP2pManager.DISABLE_P2P: + mReplyChannel.replyToMessage(message, WifiP2pManager.DISABLE_P2P_FAILED); + break; + case WifiP2pManager.START_LISTEN_MODE: + mReplyChannel.replyToMessage(message, WifiP2pManager.START_LISTEN_FAILED); + break; + case WifiP2pManager.DISCOVER_PEERS: + mReplyChannel.replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED); + break; + case WifiP2pManager.CANCEL_DISCOVER_PEERS: + mReplyChannel.replyToMessage(message, + WifiP2pManager.CANCEL_DISCOVER_PEERS_FAILED); + break; + case WifiP2pManager.CONNECT: + mReplyChannel.replyToMessage(message, WifiP2pManager.CONNECT_FAILED); + break; + case WifiP2pManager.CANCEL_CONNECT: + mReplyChannel.replyToMessage(message, WifiP2pManager.CANCEL_CONNECT_FAILED); + break; + case WifiP2pManager.REJECT: + mReplyChannel.replyToMessage(message, WifiP2pManager.REJECT_FAILED); + break; + case WifiP2pManager.CREATE_GROUP: + mReplyChannel.replyToMessage(message, WifiP2pManager.CREATE_GROUP_FAILED); + break; + case WifiP2pManager.REMOVE_GROUP: + mReplyChannel.replyToMessage(message, WifiP2pManager.REMOVE_GROUP_FAILED); + break; + // TODO: fix + case WifiP2pManager.REQUEST_SETTINGS: + case WifiP2pManager.REQUEST_PEERS: + case WifiP2pManager.REQUEST_CONNECTION_STATUS: + break; + // Ignore + case WIFI_DISABLE_USER_ACCEPT: + break; + default: + Slog.e(TAG, "Unhandled message " + message); + return NOT_HANDLED; + } + return HANDLED; + } + } + + class P2pNotSupportedState extends State { + @Override + public boolean processMessage(Message message) { + switch (message.what) { + // Allow Wi-Fi to proceed + case WifiStateMachine.WIFI_ENABLE_PENDING: + mReplyChannel.replyToMessage(message, WIFI_ENABLE_PROCEED); + break; + case WifiP2pManager.ENABLE_P2P: + mReplyChannel.replyToMessage(message, WifiP2pManager.ENABLE_P2P_FAILED, + WifiP2pManager.P2P_UNSUPPORTED); + break; + case WifiP2pManager.DISABLE_P2P: + mReplyChannel.replyToMessage(message, WifiP2pManager.DISABLE_P2P_FAILED, + WifiP2pManager.P2P_UNSUPPORTED); + break; + default: + return NOT_HANDLED; + } + return HANDLED; + } + } + + class P2pDisablingState extends State { + @Override + public void enter() { + if (DBG) Slog.d(TAG, getName()); + // TODO: fix later + WifiNative.unloadDriver(); + transitionTo(mP2pDisabledState); + } + + @Override + public boolean processMessage(Message message) { + if (DBG) Slog.d(TAG, getName() + message.toString()); + switch (message.what) { + case WifiMonitor.SUP_DISCONNECTION_EVENT: + WifiNative.unloadDriver(); + transitionTo(mP2pDisabledState); + break; + default: + return NOT_HANDLED; + } + return HANDLED; + } + } + + + class P2pDisabledState extends State { + @Override + public void enter() { + if (DBG) Slog.d(TAG, getName()); + } + + @Override + public boolean processMessage(Message message) { + if (DBG) Slog.d(TAG, getName() + message.toString()); + switch (message.what) { + case WifiP2pManager.ENABLE_P2P: + mSavedEnableRequestMessage = Message.obtain(message); + OnClickListener listener = new OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + if (which == DialogInterface.BUTTON_POSITIVE) { + sendMessage(WIFI_DISABLE_USER_ACCEPT); + } else { + mReplyChannel.replyToMessage(mSavedEnableRequestMessage, + WifiP2pManager.ENABLE_P2P_FAILED); + } + } + }; + + // Show a user request dialog if we know Wi-Fi client/hotspot is in operation + if (mWifiState != WifiManager.WIFI_STATE_DISABLED || + mWifiApState != WifiManager.WIFI_AP_STATE_DISABLED) { + Resources r = Resources.getSystem(); + AlertDialog dialog = new AlertDialog.Builder(mContext) + .setTitle(r.getString(R.string.wifi_p2p_dialog_title)) + .setMessage(r.getString(R.string.wifi_p2p_turnon_message)) + .setPositiveButton(r.getString(R.string.ok), listener) + .setNegativeButton(r.getString(R.string.cancel), listener) + .create(); + dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); + dialog.show(); + } else { + mWifiChannel.sendMessage(P2P_ENABLE_PENDING); + transitionTo(mWaitForWifiDisableState); + } + break; + case WIFI_DISABLE_USER_ACCEPT: + mWifiChannel.sendMessage(P2P_ENABLE_PENDING); + transitionTo(mWaitForWifiDisableState); + break; + case WifiStateMachine.WIFI_ENABLE_PENDING: + mReplyChannel.replyToMessage(message, WIFI_ENABLE_PROCEED); + break; + default: + return NOT_HANDLED; + } + return HANDLED; + } + } + + class WaitForWifiDisableState extends State { + @Override + public void enter() { + if (DBG) Slog.d(TAG, getName()); + } + + @Override + public boolean processMessage(Message message) { + if (DBG) Slog.d(TAG, getName() + message.toString()); + switch (message.what) { + case WifiStateMachine.P2P_ENABLE_PROCEED: + // TODO: fix this for p2p + if (WifiNative.loadDriver() && + WifiNative.startSupplicant()) { + Slog.d(TAG, "Wi-fi Direct start successful"); + mWifiMonitor.startMonitoring(); + transitionTo(mP2pEnablingState); + } else { + notifyP2pEnableFailure(); + mReplyChannel.replyToMessage(mSavedEnableRequestMessage, + WifiP2pManager.ENABLE_P2P_FAILED); + transitionTo(mP2pDisabledState); + } + break; + default: + return NOT_HANDLED; + } + return HANDLED; + } + } + + class P2pEnablingState extends State { + @Override + public void enter() { + if (DBG) Slog.d(TAG, getName()); + } + + @Override + public boolean processMessage(Message message) { + if (DBG) Slog.d(TAG, getName() + message.toString()); + switch (message.what) { + case WifiMonitor.SUP_CONNECTION_EVENT: + mReplyChannel.replyToMessage(mSavedEnableRequestMessage, + WifiP2pManager.ENABLE_P2P_SUCCEEDED); + transitionTo(mInactiveState); + break; + default: + return NOT_HANDLED; + } + return HANDLED; + } + } + + class P2pEnabledState extends State { + @Override + public void enter() { + if (DBG) Slog.d(TAG, getName()); + sendP2pStateChangedBroadcast(true); + } + + @Override + public boolean processMessage(Message message) { + if (DBG) Slog.d(TAG, getName() + message.toString()); + switch (message.what) { + case WifiP2pManager.DISABLE_P2P: + // TODO: use stopSupplicant after control channel fixed + WifiNative.killSupplicant(); + transitionTo(mP2pDisablingState); + break; + case WifiP2pManager.DISCOVER_PEERS: + int timeout = message.arg1; + WifiNative.p2pFlush(); + WifiNative.p2pFind(timeout); + break; + case WifiP2pManager.REQUEST_PEERS: + mReplyChannel.replyToMessage(message, WifiP2pManager.RESPONSE_PEERS, mPeers); + break; + case WifiMonitor.P2P_DEVICE_FOUND_EVENT: + WifiP2pDevice device = (WifiP2pDevice) message.obj; + mPeers.add(device); + sendP2pPeersChangedBroadcast(); + break; + case WifiMonitor.P2P_DEVICE_LOST_EVENT: + device = (WifiP2pDevice) message.obj; + if (mPeers.remove(device)) sendP2pPeersChangedBroadcast(); + break; + case WifiP2pManager.CONNECT: + if (DBG) Slog.d(TAG, getName() + " sending connect"); + mSavedConnectConfig = (WifiP2pConfig) message.obj; + String pin = WifiNative.p2pConnect(mSavedConnectConfig); + try { + Integer.parseInt(pin); + notifyWpsPin(pin, mSavedConnectConfig.deviceAddress); + } catch (NumberFormatException ignore) { + // do nothing if p2pConnect did not return a pin + } + updateDeviceStatus(mSavedConnectConfig.deviceAddress, Status.INVITED); + sendP2pPeersChangedBroadcast(); + transitionTo(mGroupNegotiationState); + break; + case WifiP2pManager.REJECT: + if (DBG) Slog.d(TAG, getName() + " sending reject"); + WifiNative.p2pReject((String) message.obj); + break; + default: + return NOT_HANDLED; + } + return HANDLED; + } + + @Override + public void exit() { + sendP2pStateChangedBroadcast(false); + } + } + + class InactiveState extends State { + @Override public void enter() { + if (DBG) Slog.d(TAG, getName()); + } + + @Override + public boolean processMessage(Message message) { + if (DBG) Slog.d(TAG, getName() + message.toString()); + switch (message.what) { + case WifiMonitor.P2P_GO_NEGOTIATION_REQUEST_EVENT: + mSavedGoNegotiationConfig = (WifiP2pConfig) message.obj; + notifyP2pGoNegotationRequest(mSavedGoNegotiationConfig); + break; + case WifiP2pManager.CREATE_GROUP: + WifiNative.p2pGroupAdd(); + transitionTo(mGroupNegotiationState); + break; + case WifiMonitor.P2P_INVITATION_RECEIVED_EVENT: + WifiP2pGroup group = (WifiP2pGroup) message.obj; + notifyP2pInvitationReceived(group); + break; + default: + return NOT_HANDLED; + } + return HANDLED; + } + } + + class GroupNegotiationState extends State { + @Override public void enter() { + if (DBG) Slog.d(TAG, getName()); + } + + @Override + public boolean processMessage(Message message) { + if (DBG) Slog.d(TAG, getName() + message.toString()); + switch (message.what) { + // We ignore these right now, since we get a GROUP_STARTED notification + // afterwards + case WifiMonitor.P2P_GO_NEGOTIATION_SUCCESS_EVENT: + case WifiMonitor.P2P_GROUP_FORMATION_SUCCESS_EVENT: + if (DBG) Slog.d(TAG, getName() + " go success"); + break; + case WifiMonitor.P2P_GO_NEGOTIATION_FAILURE_EVENT: + case WifiMonitor.P2P_GROUP_FORMATION_FAILURE_EVENT: + if (DBG) Slog.d(TAG, getName() + " go failure"); + updateDeviceStatus(mSavedConnectConfig.deviceAddress, Status.FAILED); + mSavedConnectConfig = null; + transitionTo(mInactiveState); + break; + case WifiMonitor.P2P_GROUP_STARTED_EVENT: + mGroup = (WifiP2pGroup) message.obj; + if (DBG) Slog.d(TAG, getName() + " group started"); + // If this device is GO, do nothing since there is a follow up + // AP_STA_CONNECTED event + if (!mGroup.isGroupOwner()) { + WifiP2pDevice groupOwner = mGroup.getOwner(); + updateDeviceStatus(groupOwner.deviceAddress, Status.CONNECTED); + sendP2pPeersChangedBroadcast(); + } + transitionTo(mGroupCreatedState); + break; + case WifiP2pManager.CANCEL_CONNECT: + // TODO: fix + break; + default: + return NOT_HANDLED; + } + return HANDLED; + } + } + + class GroupCreatedState extends State { + @Override + public void enter() { + if (DBG) Slog.d(TAG, getName()); + } + + @Override + public boolean processMessage(Message message) { + if (DBG) Slog.d(TAG, getName() + message.toString()); + switch (message.what) { + case WifiMonitor.AP_STA_CONNECTED_EVENT: + String address = (String) message.obj; + mGroup.addClient(address); + updateDeviceStatus(address, Status.CONNECTED); + if (DBG) Slog.d(TAG, getName() + " ap sta connected"); + sendP2pPeersChangedBroadcast(); + break; + case WifiMonitor.AP_STA_DISCONNECTED_EVENT: + address = (String) message.obj; + updateDeviceStatus(address, Status.AVAILABLE); + if (mGroup.removeClient(address)) { + if (DBG) Slog.d(TAG, "Removed client " + address); + if (mGroup.isClientListEmpty()) { + Slog.d(TAG, "Client list empty, killing p2p connection"); + sendMessage(WifiP2pManager.REMOVE_GROUP); + } else { + // Just send a notification + sendP2pPeersChangedBroadcast(); + } + } else { + if (DBG) Slog.d(TAG, "Failed to remove client " + address); + for (WifiP2pDevice c : mGroup.getClientList()) { + if (DBG) Slog.d(TAG,"client " + c.deviceAddress); + } + } + if (DBG) Slog.e(TAG, getName() + " ap sta disconnected"); + break; + // Disconnect & remove group have same effect when connected + case WifiP2pManager.CANCEL_CONNECT: + case WifiP2pManager.REMOVE_GROUP: + if (DBG) Slog.e(TAG, getName() + " remove group"); + WifiNative.p2pFlush(); + WifiNative.p2pGroupRemove(mGroup.getInterface()); + break; + case WifiMonitor.P2P_GROUP_REMOVED_EVENT: + if (DBG) Slog.e(TAG, getName() + " group removed"); + Collection <WifiP2pDevice> devices = mGroup.getClientList(); + boolean changed = false; + for (WifiP2pDevice d : mPeers.getDeviceList()) { + if (devices.contains(d) || mGroup.getOwner().equals(d)) { + d.status = Status.AVAILABLE; + changed = true; + } + } + mGroup = null; + if (changed) sendP2pPeersChangedBroadcast(); + transitionTo(mInactiveState); + break; + case WifiMonitor.P2P_DEVICE_LOST_EVENT: + WifiP2pDevice device = (WifiP2pDevice) message.obj; + if (device.equals(mGroup.getOwner())) { + Slog.d(TAG, "Lost the group owner, killing p2p connection"); + sendMessage(WifiP2pManager.REMOVE_GROUP); + } else if (mGroup.removeClient(device) && mGroup.isClientListEmpty()) { + Slog.d(TAG, "Client list empty, killing p2p connection"); + sendMessage(WifiP2pManager.REMOVE_GROUP); + } + return NOT_HANDLED; // Do the regular device lost handling + case WifiP2pManager.DISABLE_P2P: + sendMessage(WifiP2pManager.REMOVE_GROUP); + deferMessage(message); + break; + case WifiP2pManager.DISCOVER_PEERS: + int timeout = message.arg1; + WifiNative.p2pFind(timeout); + break; + case WifiP2pManager.CONNECT: + WifiP2pConfig config = (WifiP2pConfig) message.obj; + Slog.d(TAG, "Inviting device : " + config.deviceAddress); + WifiNative.p2pInvite(mGroup, config.deviceAddress); + updateDeviceStatus(config.deviceAddress, Status.INVITED); + sendP2pPeersChangedBroadcast(); + // TODO: figure out updating the status to declined when invitation is rejected + break; + case WifiMonitor.P2P_INVITATION_RESULT_EVENT: + Slog.d(TAG,"===> INVITATION RESULT EVENT : " + message.obj); + break; + case WifiMonitor.P2P_PROV_DISC_PBC_REQ_EVENT: + notifyP2pProvDiscPbcRequest((WifiP2pDevice) message.obj); + break; + case WifiMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT: + notifyP2pProvDiscPinRequest((WifiP2pDevice) message.obj); + break; + case WifiP2pManager.WPS_PBC: + WifiNative.p2pWpsPbc(); + break; + case WifiP2pManager.WPS_PIN: + WifiNative.p2pWpsPin((String) message.obj); + break; + default: + return NOT_HANDLED; + } + return HANDLED; + } + } + + private void sendP2pStateChangedBroadcast(boolean enabled) { + final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION); + intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); + if (enabled) { + intent.putExtra(WifiP2pManager.EXTRA_WIFI_STATE, + WifiP2pManager.WIFI_P2P_STATE_ENABLED); + } else { + intent.putExtra(WifiP2pManager.EXTRA_WIFI_STATE, + WifiP2pManager.WIFI_P2P_STATE_DISABLED); + } + mContext.sendStickyBroadcast(intent); + } + + private void sendP2pPeersChangedBroadcast() { + final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION); + intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); + mContext.sendBroadcast(intent); + } + + private void notifyP2pEnableFailure() { + Resources r = Resources.getSystem(); + AlertDialog dialog = new AlertDialog.Builder(mContext) + .setTitle(r.getString(R.string.wifi_p2p_dialog_title)) + .setMessage(r.getString(R.string.wifi_p2p_failed_message)) + .setPositiveButton(r.getString(R.string.ok), null) + .create(); + dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); + dialog.show(); + } + + private void notifyWpsPin(String pin, String peerAddress) { + Resources r = Resources.getSystem(); + AlertDialog dialog = new AlertDialog.Builder(mContext) + .setTitle(r.getString(R.string.wifi_p2p_dialog_title)) + .setMessage(r.getString(R.string.wifi_p2p_pin_display_message, pin, peerAddress)) + .setPositiveButton(r.getString(R.string.ok), null) + .create(); + dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); + dialog.show(); + } + + private void notifyP2pGoNegotationRequest(WifiP2pConfig config) { + Resources r = Resources.getSystem(); + WpsConfiguration wpsConfig = config.wpsConfig; + final View textEntryView = LayoutInflater.from(mContext) + .inflate(R.layout.wifi_p2p_go_negotiation_request_alert, null); + final EditText pin = (EditText) textEntryView .findViewById(R.id.wifi_p2p_wps_pin); + + AlertDialog dialog = new AlertDialog.Builder(mContext) + .setTitle(r.getString(R.string.wifi_p2p_dialog_title)) + .setView(textEntryView) + .setPositiveButton(r.getString(R.string.ok), new OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + if (DBG) Slog.d(TAG, getName() + " connect " + pin.getText()); + mSavedGoNegotiationConfig.wpsConfig.setup = Setup.KEYPAD; + mSavedGoNegotiationConfig.wpsConfig.pin = pin.getText().toString(); + sendMessage(WifiP2pManager.CONNECT, mSavedGoNegotiationConfig); + mSavedGoNegotiationConfig = null; + } + }) + .setNegativeButton(r.getString(R.string.cancel), new OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + if (DBG) Slog.d(TAG, getName() + " reject"); + sendMessage(WifiP2pManager.REJECT, + mSavedGoNegotiationConfig.deviceAddress); + mSavedGoNegotiationConfig = null; + } + }) + .create(); + + if (wpsConfig.setup == Setup.PBC) { + pin.setVisibility(View.GONE); + dialog.setMessage(r.getString(R.string.wifi_p2p_pbc_go_negotiation_request_message, + config.deviceAddress)); + } else { + dialog.setMessage(r.getString(R.string.wifi_p2p_pin_go_negotiation_request_message, + config.deviceAddress)); + } + + dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); + dialog.show(); + } + + private void notifyP2pProvDiscPbcRequest(WifiP2pDevice peer) { + Resources r = Resources.getSystem(); + final View textEntryView = LayoutInflater.from(mContext) + .inflate(R.layout.wifi_p2p_go_negotiation_request_alert, null); + final EditText pin = (EditText) textEntryView .findViewById(R.id.wifi_p2p_wps_pin); + + AlertDialog dialog = new AlertDialog.Builder(mContext) + .setTitle(r.getString(R.string.wifi_p2p_dialog_title)) + .setView(textEntryView) + .setPositiveButton(r.getString(R.string.ok), new OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + if (DBG) Slog.d(TAG, getName() + " wps_pbc"); + sendMessage(WifiP2pManager.WPS_PBC); + } + }) + .setNegativeButton(r.getString(R.string.cancel), null) + .create(); + + pin.setVisibility(View.GONE); + dialog.setMessage(r.getString(R.string.wifi_p2p_pbc_go_negotiation_request_message, + peer.deviceAddress)); + + dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); + dialog.show(); + } + + private void notifyP2pProvDiscPinRequest(WifiP2pDevice peer) { + Resources r = Resources.getSystem(); + final View textEntryView = LayoutInflater.from(mContext) + .inflate(R.layout.wifi_p2p_go_negotiation_request_alert, null); + final EditText pin = (EditText) textEntryView .findViewById(R.id.wifi_p2p_wps_pin); + + AlertDialog dialog = new AlertDialog.Builder(mContext) + .setTitle(r.getString(R.string.wifi_p2p_dialog_title)) + .setView(textEntryView) + .setPositiveButton(r.getString(R.string.ok), new OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + if (DBG) Slog.d(TAG, getName() + " wps_pin"); + sendMessage(WifiP2pManager.WPS_PIN, pin.getText().toString()); + } + }) + .setNegativeButton(r.getString(R.string.cancel), null) + .create(); + + dialog.setMessage(r.getString(R.string.wifi_p2p_pin_go_negotiation_request_message, + peer.deviceAddress)); + + dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); + dialog.show(); + } + + private void notifyP2pInvitationReceived(WifiP2pGroup group) { + mSavedP2pGroup = group; + Resources r = Resources.getSystem(); + final View textEntryView = LayoutInflater.from(mContext) + .inflate(R.layout.wifi_p2p_go_negotiation_request_alert, null); + final EditText pin = (EditText) textEntryView .findViewById(R.id.wifi_p2p_wps_pin); + + AlertDialog dialog = new AlertDialog.Builder(mContext) + .setTitle(r.getString(R.string.wifi_p2p_dialog_title)) + .setView(textEntryView) + .setPositiveButton(r.getString(R.string.ok), new OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + WifiP2pConfig config = new WifiP2pConfig(); + config.deviceAddress = mSavedP2pGroup.getOwner().deviceAddress; + config.joinExistingGroup = true; + if (DBG) Slog.d(TAG, getName() + " connect to invited group"); + sendMessage(WifiP2pManager.CONNECT, config); + mSavedP2pGroup = null; + } + }) + .setNegativeButton(r.getString(R.string.cancel), null) + .create(); + + pin.setVisibility(View.GONE); + dialog.setMessage(r.getString(R.string.wifi_p2p_pbc_go_negotiation_request_message, + group.getOwner().deviceAddress)); + + dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); + dialog.show(); + } + + private void updateDeviceStatus(String deviceAddress, Status status) { + for (WifiP2pDevice d : mPeers.getDeviceList()) { + // TODO: fix later + // if (d.deviceAddress.equals(deviceAddress)) { + if (d.deviceAddress.startsWith(deviceAddress.substring(0, 8))) { + d.status = status; + } + } + } + } +} diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pStatus.aidl b/wifi/java/android/net/wifi/p2p/WifiP2pStatus.aidl new file mode 100644 index 0000000..7bab5d3 --- /dev/null +++ b/wifi/java/android/net/wifi/p2p/WifiP2pStatus.aidl @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2011, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.wifi.p2p; + +parcelable WifiP2pStatus; diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pStatus.java b/wifi/java/android/net/wifi/p2p/WifiP2pStatus.java new file mode 100644 index 0000000..1c9b76c --- /dev/null +++ b/wifi/java/android/net/wifi/p2p/WifiP2pStatus.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.wifi.p2p; + +import android.os.Parcelable; +import android.os.Parcel; + +/** + * A class representing Wi-fi P2p status + * @hide + */ +public class WifiP2pStatus implements Parcelable { + + //Comes from the wpa_supplicant + enum p2p_status_code { + SUCCESS, + FAIL_INFO_CURRENTLY_UNAVAILABLE, + FAIL_INCOMPATIBLE_PARAMS, + FAIL_LIMIT_REACHED, + FAIL_INVALID_PARAMS, + FAIL_UNABLE_TO_ACCOMMODATE, + FAIL_PREV_PROTOCOL_ERROR, + FAIL_NO_COMMON_CHANNELS, + FAIL_UNKNOWN_GROUP, + FAIL_BOTH_GO_INTENT_15, + FAIL_INCOMPATIBLE_PROV_METHOD, + FAIL_REJECTED_BY_USER + }; + + public WifiP2pStatus() { + } + + //TODO: add support + public String toString() { + StringBuffer sbuf = new StringBuffer(); + return sbuf.toString(); + } + + /** Implement the Parcelable interface {@hide} */ + public int describeContents() { + return 0; + } + + /** copy constructor {@hide} */ + //TODO: implement + public WifiP2pStatus(WifiP2pStatus source) { + if (source != null) { + } + } + + /** Implement the Parcelable interface {@hide} */ + // STOPSHIP: implement + public void writeToParcel(Parcel dest, int flags) { + } + + /** Implement the Parcelable interface {@hide} */ + public static final Creator<WifiP2pStatus> CREATOR = + new Creator<WifiP2pStatus>() { + public WifiP2pStatus createFromParcel(Parcel in) { + WifiP2pStatus status = new WifiP2pStatus(); + return status; + } + + public WifiP2pStatus[] newArray(int size) { + return new WifiP2pStatus[size]; + } + }; +} |