summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/current.txt44
-rw-r--r--core/java/android/content/pm/IPackageManager.aidl8
-rw-r--r--core/java/android/content/pm/PackageManager.java12
-rw-r--r--core/java/android/net/CaptivePortalTracker.java133
-rw-r--r--core/java/android/net/ConnectivityManager.java89
-rw-r--r--core/java/android/net/IConnectivityManager.aidl5
-rw-r--r--core/java/android/net/MobileDataStateTracker.java94
-rw-r--r--core/java/android/net/NetworkInfo.java7
-rw-r--r--core/java/android/nfc/cardemulation/ApduServiceInfo.java20
-rw-r--r--core/java/android/nfc/cardemulation/CardEmulationManager.java101
-rw-r--r--core/java/android/nfc/cardemulation/HostApduService.java2
-rw-r--r--core/java/android/print/IPrintManager.aidl4
-rw-r--r--core/java/android/print/PrintDocumentAdapter.java18
-rw-r--r--core/java/android/print/PrintDocumentInfo.java30
-rw-r--r--core/java/android/print/PrintFileDocumentAdapter.java10
-rw-r--r--core/java/android/print/PrintJobInfo.java62
-rw-r--r--core/java/android/print/PrintManager.java13
-rw-r--r--core/java/android/print/PrinterDiscoverySession.java35
-rw-r--r--core/java/android/print/pdf/PrintedPdfDocument.java5
-rw-r--r--core/java/android/printservice/IPrintService.aidl4
-rw-r--r--core/java/android/printservice/PrintDocument.java11
-rw-r--r--core/java/android/printservice/PrintJob.java71
-rw-r--r--core/java/android/printservice/PrintService.java44
-rw-r--r--core/java/android/printservice/PrinterDiscoverySession.java100
-rw-r--r--core/java/android/provider/AlarmClock.java9
-rw-r--r--core/java/android/provider/Settings.java6
-rw-r--r--core/java/android/util/LayoutDirection.java8
-rw-r--r--core/java/android/webkit/WebView.java28
-rw-r--r--core/java/android/webkit/WebViewClassic.java7
-rw-r--r--core/java/android/webkit/WebViewProvider.java8
-rw-r--r--core/java/android/widget/GridLayout.java124
-rw-r--r--core/java/com/android/internal/app/ResolverActivity.java228
-rw-r--r--core/jni/android/graphics/Bitmap.cpp1
-rw-r--r--core/jni/android/graphics/BitmapFactory.cpp55
-rw-r--r--core/jni/android/graphics/BitmapRegionDecoder.cpp43
-rw-r--r--core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp276
-rw-r--r--core/jni/android/graphics/CreateJavaOutputStreamAdaptor.h66
-rw-r--r--core/jni/android/graphics/Movie.cpp13
-rw-r--r--core/jni/android/graphics/Picture.cpp8
-rw-r--r--core/jni/android/graphics/Utils.cpp48
-rw-r--r--core/jni/android/graphics/Utils.h13
-rw-r--r--core/res/AndroidManifest.xml15
-rw-r--r--core/res/res/layout/resolve_list_item.xml48
-rw-r--r--core/res/res/layout/resolver_list.xml (renamed from core/res/res/layout/resolver_grid.xml)16
-rw-r--r--core/res/res/values-mcc208-mnc26/config.xml26
-rw-r--r--core/res/res/values-mcc214-mnc04/config.xml25
-rw-r--r--core/res/res/values-mcc234-mnc30/config.xml30
-rw-r--r--core/res/res/values-mcc234-mnc31/config.xml30
-rw-r--r--core/res/res/values-mcc234-mnc32/config.xml30
-rw-r--r--core/res/res/values-mcc234-mnc33/config.xml10
-rw-r--r--core/res/res/values-mcc234-mnc34/config.xml30
-rw-r--r--core/res/res/values-mcc234-mnc86/config.xml30
-rw-r--r--core/res/res/values-mcc302-mnc610/config.xml25
-rw-r--r--core/res/res/values-mcc302-mnc640/config.xml25
-rw-r--r--core/res/res/values-mcc302-mnc780/config.xml4
-rw-r--r--core/res/res/values-mcc425-mnc07/config.xml4
-rw-r--r--core/res/res/values-mcc425-mnc08/config.xml25
-rw-r--r--core/res/res/values/attrs.xml6
-rw-r--r--core/res/res/values/config.xml15
-rw-r--r--core/res/res/values/public.xml1
-rw-r--r--core/res/res/values/strings.xml16
-rw-r--r--[-rwxr-xr-x]core/res/res/values/symbols.xml8
-rw-r--r--docs/downloads/training/AndroidTestingFun.zipbin0 -> 475029 bytes
-rw-r--r--docs/html/images/training/lesson2_MyFirstTestActivityTest_result.pngbin0 -> 12854 bytes
-rw-r--r--docs/html/training/activity-testing/activity-basic-testing.jd227
-rw-r--r--docs/html/training/activity-testing/activity-functional-testing.jd166
-rw-r--r--docs/html/training/activity-testing/activity-ui-testing.jd216
-rw-r--r--docs/html/training/activity-testing/activity-unit-testing.jd134
-rw-r--r--docs/html/training/activity-testing/index.jd68
-rw-r--r--docs/html/training/activity-testing/preparing-activity-testing.jd95
-rw-r--r--docs/html/training/testing.jd7
-rw-r--r--docs/html/training/training_toc.cs39
-rw-r--r--graphics/java/android/graphics/BitmapFactory.java74
-rw-r--r--graphics/java/android/graphics/BitmapRegionDecoder.java7
-rw-r--r--graphics/java/android/renderscript/Allocation.java14
-rw-r--r--graphics/java/android/renderscript/ScriptIntrinsicColorMatrix.java4
-rw-r--r--graphics/java/android/renderscript/ScriptIntrinsicHistogram.java4
-rw-r--r--media/jni/android_media_ImageReader.cpp9
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardSelectorView.java16
-rw-r--r--packages/PrintSpooler/Android.mk2
-rw-r--r--packages/PrintSpooler/AndroidManifest.xml18
-rw-r--r--packages/PrintSpooler/res/values/strings.xml22
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/FusedPrintersProvider.java14
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/NotificationController.java39
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java13
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java28
-rw-r--r--packages/SystemUI/res/drawable-hdpi/arrow_dashed.pngbin12185 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/btn_cling_normal.9.pngbin333 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/btn_cling_pressed.9.pngbin467 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/btn_default_small_normal.9.pngbin862 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/btn_default_small_normal_disable.9.pngbin550 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/btn_default_small_normal_disable_focused.9.pngbin799 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/btn_default_small_pressed.9.pngbin1228 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/btn_default_small_selected.9.pngbin1249 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/recents_blue_glow.9.pngbin3000 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/recents_thumbnail_bg_dragging.9.pngbin262 -> 264 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/recents_thumbnail_bg_normal.9.pngbin462 -> 454 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/recents_thumbnail_bg_press.9.pngbin324 -> 326 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/screenshot_panel.9.pngbin596 -> 582 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_alarm.pngbin1120 -> 1130 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_device_access_location_found.pngbin1906 -> 1052 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_ringer_silent.pngbin981 -> 1014 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_ringer_vibrate.pngbin939 -> 1041 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0.pngbin1095 -> 646 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully.pngbin1091 -> 646 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1.pngbin1108 -> 654 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully.pngbin1065 -> 681 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2.pngbin1103 -> 673 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully.pngbin982 -> 700 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3.pngbin1087 -> 695 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully.pngbin886 -> 733 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4.pngbin1039 -> 690 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully.pngbin791 -> 736 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_signal_null.pngbin922 -> 717 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_sync.pngbin947 -> 1009 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_sync_error.pngbin1014 -> 1062 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/status_bar_bg_tile.pngbin115 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/status_bar_close_off.9.pngbin453 -> 399 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/status_bar_close_on.9.pngbin466 -> 397 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/title_bar_shadow.9.pngbin217 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/arrow_dashed.pngbin7244 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/btn_cling_normal.9.pngbin245 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/btn_cling_pressed.9.pngbin370 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/btn_default_small_normal.9.pngbin671 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/btn_default_small_normal_disable.9.pngbin429 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/btn_default_small_normal_disable_focused.9.pngbin633 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/btn_default_small_pressed.9.pngbin891 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/btn_default_small_selected.9.pngbin899 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/recents_blue_glow.9.pngbin1576 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/recents_thumbnail_bg_dragging.9.pngbin243 -> 243 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/recents_thumbnail_bg_normal.9.pngbin354 -> 359 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/recents_thumbnail_bg_press.9.pngbin280 -> 284 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/screenshot_panel.9.pngbin404 -> 404 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_alarm.pngbin804 -> 787 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_device_access_location_found.pngbin1184 -> 766 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_ringer_silent.pngbin724 -> 749 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_ringer_vibrate.pngbin735 -> 771 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0.pngbin791 -> 547 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully.pngbin770 -> 547 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1.pngbin817 -> 562 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully.pngbin779 -> 566 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2.pngbin819 -> 566 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully.pngbin739 -> 573 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3.pngbin807 -> 584 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully.pngbin691 -> 584 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4.pngbin784 -> 580 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully.pngbin604 -> 610 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_signal_null.pngbin744 -> 570 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_sync.pngbin703 -> 728 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_sync_error.pngbin735 -> 735 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/status_bar_bg_tile.pngbin98 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/status_bar_close_off.9.pngbin332 -> 292 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/status_bar_close_on.9.pngbin337 -> 299 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/title_bar_shadow.9.pngbin193 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw600dp-xxhdpi/heads_up_window_bg.9.pngbin0 -> 2028 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw600dp-xxhdpi/notification_panel_bg.9.pngbin0 -> 2927 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw720dp-hdpi/notify_panel_clock_bg_normal.9.pngbin3693 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw720dp-hdpi/notify_panel_clock_bg_pressed.9.pngbin3699 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw720dp-hdpi/recents_blue_glow.9.pngbin21122 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw720dp-hdpi/sysbar_notification_panel_bg.9.pngbin2498 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw720dp-mdpi/notify_panel_clock_bg_normal.9.pngbin2193 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw720dp-mdpi/notify_panel_clock_bg_pressed.9.pngbin2199 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw720dp-mdpi/recents_blue_glow.9.pngbin9741 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw720dp-mdpi/sysbar_notification_panel_bg.9.pngbin1551 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw720dp-tvdpi/sysbar_notification_panel_bg.9.pngbin2212 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw720dp-xhdpi/notify_panel_clock_bg_normal.9.pngbin5948 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw720dp-xhdpi/notify_panel_clock_bg_pressed.9.pngbin5956 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw720dp-xhdpi/recents_blue_glow.9.pngbin30164 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw720dp-xhdpi/sysbar_notification_panel_bg.9.pngbin3910 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/arrow_dashed.pngbin17897 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/btn_cling_normal.9.pngbin400 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/btn_cling_pressed.9.pngbin601 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/btn_default_small_normal.9.pngbin1592 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/btn_default_small_normal_disable.9.pngbin1128 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/btn_default_small_normal_disable_focused.9.pngbin1920 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/btn_default_small_pressed.9.pngbin2210 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/btn_default_small_selected.9.pngbin2206 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/recents_blue_glow.9.pngbin5152 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/recents_thumbnail_bg_dragging.9.pngbin322 -> 322 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/recents_thumbnail_bg_normal.9.pngbin636 -> 620 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/recents_thumbnail_bg_press.9.pngbin411 -> 413 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/screenshot_panel.9.pngbin797 -> 804 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/stat_sys_alarm.pngbin1593 -> 1553 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/stat_sys_device_access_location_found.pngbin2643 -> 1455 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/stat_sys_ringer_silent.pngbin1280 -> 1340 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/stat_sys_ringer_vibrate.pngbin1218 -> 1362 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0.pngbin1356 -> 800 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_fully.pngbin1419 -> 800 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1.pngbin1346 -> 838 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_fully.pngbin1335 -> 846 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2.pngbin1310 -> 853 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_fully.pngbin1237 -> 899 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3.pngbin1294 -> 878 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_fully.pngbin1129 -> 942 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4.pngbin1260 -> 879 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_fully.pngbin993 -> 953 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_null.pngbin1177 -> 916 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/stat_sys_sync.pngbin1237 -> 1327 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/stat_sys_sync_error.pngbin1327 -> 1414 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/status_bar_bg_tile.pngbin142 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/status_bar_close_off.9.pngbin514 -> 460 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/status_bar_close_on.9.pngbin522 -> 461 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/title_bar_shadow.9.pngbin227 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/heads_up_window_bg.9.pngbin0 -> 2028 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/ic_menu_share.pngbin0 -> 1279 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_15.pngbin0 -> 1248 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_bang_orange.pngbin0 -> 1577 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_bang_red.pngbin0 -> 1553 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_bang_white.pngbin0 -> 1224 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_charge_0.pngbin0 -> 1954 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_charge_15.pngbin0 -> 1986 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_highlight.pngbin0 -> 6225 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_highlight_land.pngbin0 -> 5571 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/notification_panel_bg.9.pngbin0 -> 1045 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/recents_thumbnail_bg_dragging.9.pngbin0 -> 1229 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/recents_thumbnail_bg_normal.9.pngbin0 -> 1715 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/recents_thumbnail_bg_press.9.pngbin0 -> 1350 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/screenshot_panel.9.pngbin0 -> 2060 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/stat_sys_alarm.pngbin2406 -> 2432 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/stat_sys_device_access_location_found.pngbin3074 -> 2279 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/stat_sys_ringer_silent.pngbin2179 -> 2293 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/stat_sys_ringer_vibrate.pngbin2115 -> 2309 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_0.pngbin1860 -> 1301 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_0_fully.pngbin1842 -> 1301 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_1.pngbin1870 -> 1322 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_1_fully.pngbin1775 -> 1333 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_2.pngbin1845 -> 1326 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_2_fully.pngbin1707 -> 1345 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_3.pngbin1837 -> 1340 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_3_fully.pngbin1639 -> 1362 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_4.pngbin1818 -> 1341 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_4_fully.pngbin1569 -> 1431 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_null.pngbin1788 -> 1414 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/stat_sys_sync.pngbin1875 -> 1973 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/stat_sys_sync_error.pngbin1982 -> 2127 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/status_bar_close_off.9.pngbin0 -> 1433 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/status_bar_close_on.9.pngbin0 -> 1444 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/title_bar_shadow.9.pngbin0 -> 1128 bytes
-rw-r--r--packages/SystemUI/res/drawable/btn_default_small.xml33
-rw-r--r--packages/SystemUI/res/drawable/cling_button_bg.xml20
-rw-r--r--packages/SystemUI/res/drawable/notify_panel_clock_bg.xml22
-rw-r--r--packages/SystemUI/res/drawable/status_bar_bg.xml21
-rw-r--r--packages/SystemUI/res/layout-land/status_bar_help.xml71
-rw-r--r--packages/SystemUI/res/layout/status_bar_help.xml63
-rw-r--r--packages/SystemUI/res/values/ids.xml20
-rw-r--r--packages/SystemUI/res/values/strings.xml4
-rw-r--r--packages/SystemUI/res/values/styles.xml29
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java89
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/Prefs.java2
-rw-r--r--services/java/com/android/server/ConnectivityService.java476
-rw-r--r--services/java/com/android/server/PreferredComponent.java36
-rw-r--r--services/java/com/android/server/am/ActivityStackSupervisor.java5
-rw-r--r--services/java/com/android/server/content/SyncStorageEngine.java2
-rwxr-xr-xservices/java/com/android/server/pm/PackageManagerService.java106
-rw-r--r--services/java/com/android/server/pm/PreferredActivity.java6
-rw-r--r--services/java/com/android/server/pm/PreferredIntentResolver.java2
-rw-r--r--services/java/com/android/server/pm/Settings.java2
-rw-r--r--services/java/com/android/server/pm/UserManagerService.java42
-rw-r--r--services/java/com/android/server/print/PrintManagerService.java40
-rw-r--r--services/java/com/android/server/print/RemotePrintService.java129
-rw-r--r--services/java/com/android/server/print/UserState.java226
-rw-r--r--telephony/java/com/android/internal/telephony/DctConstants.java3
-rw-r--r--telephony/java/com/android/internal/telephony/TelephonyIntents.java23
263 files changed, 3618 insertions, 1352 deletions
diff --git a/api/current.txt b/api/current.txt
index 0418cd9..8d71796 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -25,6 +25,7 @@ package android {
field public static final java.lang.String BIND_NFC_SERVICE = "android.permission.BIND_NFC_SERVICE";
field public static final java.lang.String BIND_NOTIFICATION_LISTENER_SERVICE = "android.permission.BIND_NOTIFICATION_LISTENER_SERVICE";
field public static final java.lang.String BIND_PRINT_SERVICE = "android.permission.BIND_PRINT_SERVICE";
+ field public static final java.lang.String BIND_PRINT_SPOOLER_SERVICE = "android.permission.BIND_PRINT_SPOOLER_SERVICE";
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_VPN_SERVICE = "android.permission.BIND_VPN_SERVICE";
@@ -867,6 +868,7 @@ package android {
field public static final int reqKeyboardType = 16843304; // 0x1010228
field public static final int reqNavigation = 16843306; // 0x101022a
field public static final int reqTouchScreen = 16843303; // 0x1010227
+ field public static final int requireDeviceUnlock = 16843754; // 0x10103ea
field public static final int required = 16843406; // 0x101028e
field public static final int requiredAccountType = 16843734; // 0x10103d6
field public static final int requiredForAllUsers = 16843728; // 0x10103d0
@@ -7328,7 +7330,7 @@ package android.content.pm {
field public static final java.lang.String FEATURE_LOCATION_NETWORK = "android.hardware.location.network";
field public static final java.lang.String FEATURE_MICROPHONE = "android.hardware.microphone";
field public static final java.lang.String FEATURE_NFC = "android.hardware.nfc";
- field public static final java.lang.String FEATURE_NFC_HCE = "android.hardware.nfc.hce";
+ field public static final java.lang.String FEATURE_NFC_HOST_CARD_EMULATION = "android.hardware.nfc.hce";
field public static final java.lang.String FEATURE_SCREEN_LANDSCAPE = "android.hardware.screen.landscape";
field public static final java.lang.String FEATURE_SCREEN_PORTRAIT = "android.hardware.screen.portrait";
field public static final java.lang.String FEATURE_SENSOR_ACCELEROMETER = "android.hardware.sensor.accelerometer";
@@ -15260,6 +15262,7 @@ package android.nfc.cardemulation {
public final class CardEmulationManager {
method public static synchronized android.nfc.cardemulation.CardEmulationManager getInstance(android.nfc.NfcAdapter);
+ method public int getSelectionModeForCategory(java.lang.String);
method public boolean isDefaultServiceForAid(android.content.ComponentName, java.lang.String);
method public boolean isDefaultServiceForCategory(android.content.ComponentName, java.lang.String);
field public static final java.lang.String ACTION_CHANGE_DEFAULT = "android.nfc.cardemulation.ACTION_CHANGE_DEFAULT";
@@ -15267,6 +15270,9 @@ package android.nfc.cardemulation {
field public static final java.lang.String CATEGORY_PAYMENT = "payment";
field public static final java.lang.String EXTRA_CATEGORY = "category";
field public static final java.lang.String EXTRA_SERVICE_COMPONENT = "component";
+ field public static final int SELECTION_MODE_ALWAYS_ASK = 1; // 0x1
+ field public static final int SELECTION_MODE_ASK_IF_CONFLICT = 2; // 0x2
+ field public static final int SELECTION_MODE_PREFER_DEFAULT = 0; // 0x0
}
public abstract class HostApduService extends android.app.Service {
@@ -19142,7 +19148,7 @@ package android.print {
method public void onFinish();
method public abstract void onLayout(android.print.PrintAttributes, android.print.PrintAttributes, android.os.CancellationSignal, android.print.PrintDocumentAdapter.LayoutResultCallback, android.os.Bundle);
method public void onStart();
- method public abstract void onWrite(android.print.PageRange[], java.io.FileDescriptor, android.os.CancellationSignal, android.print.PrintDocumentAdapter.WriteResultCallback);
+ method public abstract void onWrite(android.print.PageRange[], android.os.ParcelFileDescriptor, android.os.CancellationSignal, android.print.PrintDocumentAdapter.WriteResultCallback);
field public static final java.lang.String METADATA_KEY_PRINT_PREVIEW = "KEY_METADATA_PRINT_PREVIEW";
}
@@ -19162,6 +19168,7 @@ package android.print {
method public int describeContents();
method public int getColorMode();
method public int getContentType();
+ method public long getDataSize();
method public int getFittingMode();
method public android.print.PrintAttributes.Margins getMargins();
method public android.print.PrintAttributes.MediaSize getMediaSize();
@@ -19193,7 +19200,7 @@ package android.print {
public class PrintFileDocumentAdapter extends android.print.PrintDocumentAdapter {
ctor public PrintFileDocumentAdapter(android.content.Context, java.io.File, android.print.PrintDocumentInfo);
method public void onLayout(android.print.PrintAttributes, android.print.PrintAttributes, android.os.CancellationSignal, android.print.PrintDocumentAdapter.LayoutResultCallback, android.os.Bundle);
- method public void onWrite(android.print.PageRange[], java.io.FileDescriptor, android.os.CancellationSignal, android.print.PrintDocumentAdapter.WriteResultCallback);
+ method public void onWrite(android.print.PageRange[], android.os.ParcelFileDescriptor, android.os.CancellationSignal, android.print.PrintDocumentAdapter.WriteResultCallback);
}
public final class PrintJob {
@@ -19215,9 +19222,10 @@ package android.print {
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator CREATOR;
field public static final int PRINT_JOB_ID_UNDEFINED = -1; // 0xffffffff
- field public static final int STATE_CANCELED = 6; // 0x6
- field public static final int STATE_COMPLETED = 4; // 0x4
- field public static final int STATE_FAILED = 5; // 0x5
+ field public static final int STATE_BLOCKED = 4; // 0x4
+ field public static final int STATE_CANCELED = 7; // 0x7
+ field public static final int STATE_COMPLETED = 5; // 0x5
+ field public static final int STATE_FAILED = 6; // 0x6
field public static final int STATE_QUEUED = 2; // 0x2
field public static final int STATE_STARTED = 3; // 0x3
}
@@ -19335,17 +19343,19 @@ package android.print.pdf {
package android.printservice {
public final class PrintDocument {
- method public java.io.FileDescriptor getData();
+ method public android.os.ParcelFileDescriptor getData();
method public android.print.PrintDocumentInfo getInfo();
}
public final class PrintJob {
+ method public boolean block(java.lang.String);
method public boolean cancel();
method public boolean complete();
method public boolean fail(java.lang.String);
method public android.printservice.PrintDocument getDocument();
method public int getId();
method public android.print.PrintJobInfo getInfo();
+ method public boolean isBlocked();
method public boolean isCancelled();
method public boolean isCompleted();
method public boolean isFailed();
@@ -19377,9 +19387,11 @@ package android.printservice {
method public final boolean isDestroyed();
method public final boolean isPrinterDiscoveryStarted();
method public abstract void onDestroy();
- method public abstract void onRequestPrinterUpdate(android.print.PrinterId);
method public abstract void onStartPrinterDiscovery(java.util.List<android.print.PrinterId>);
+ method public abstract void onStartPrinterStateTracking(android.print.PrinterId);
method public abstract void onStopPrinterDiscovery();
+ method public abstract void onStopPrinterStateTracking(android.print.PrinterId);
+ method public abstract void onValidatePrinters(java.util.List<android.print.PrinterId>);
method public final void removePrinters(java.util.List<android.print.PrinterId>);
method public final void updatePrinters(java.util.List<android.print.PrinterInfo>);
}
@@ -19392,6 +19404,7 @@ package android.provider {
ctor public AlarmClock();
field public static final java.lang.String ACTION_SET_ALARM = "android.intent.action.SET_ALARM";
field public static final java.lang.String ACTION_SET_TIMER = "android.intent.action.SET_TIMER";
+ field public static final java.lang.String ACTION_SHOW_ALARMS = "android.intent.action.SHOW_ALARMS";
field public static final java.lang.String EXTRA_DAYS = "android.intent.extra.alarm.DAYS";
field public static final java.lang.String EXTRA_HOUR = "android.intent.extra.alarm.HOUR";
field public static final java.lang.String EXTRA_LENGTH = "android.intent.extra.alarm.LENGTH";
@@ -21708,6 +21721,7 @@ package android.renderscript {
method public deprecated synchronized void resize(int);
method public void setFromFieldPacker(int, android.renderscript.FieldPacker);
method public void setFromFieldPacker(int, int, android.renderscript.FieldPacker);
+ method public void setOnBufferAvailableListener(android.renderscript.Allocation.OnBufferAvailableListener);
method public void setSurface(android.view.Surface);
method public void syncAll(int);
field public static final int USAGE_GRAPHICS_CONSTANTS = 8; // 0x8
@@ -21728,6 +21742,10 @@ package android.renderscript {
enum_constant public static final android.renderscript.Allocation.MipmapControl MIPMAP_ON_SYNC_TO_TEXTURE;
}
+ public static abstract interface Allocation.OnBufferAvailableListener {
+ method public abstract void onBufferAvailable(android.renderscript.Allocation);
+ }
+
public class AllocationAdapter extends android.renderscript.Allocation {
method public static android.renderscript.AllocationAdapter create1D(android.renderscript.RenderScript, android.renderscript.Allocation);
method public static android.renderscript.AllocationAdapter create2D(android.renderscript.RenderScript, android.renderscript.Allocation);
@@ -22377,7 +22395,7 @@ package android.renderscript {
}
public final class ScriptIntrinsicColorMatrix extends android.renderscript.ScriptIntrinsic {
- method public static android.renderscript.ScriptIntrinsicColorMatrix create(android.renderscript.RenderScript, android.renderscript.Element);
+ method public static deprecated android.renderscript.ScriptIntrinsicColorMatrix create(android.renderscript.RenderScript, android.renderscript.Element);
method public static android.renderscript.ScriptIntrinsicColorMatrix create(android.renderscript.RenderScript);
method public void forEach(android.renderscript.Allocation, android.renderscript.Allocation);
method public android.renderscript.Script.KernelID getKernelID();
@@ -22411,9 +22429,9 @@ package android.renderscript {
public final class ScriptIntrinsicHistogram extends android.renderscript.ScriptIntrinsic {
method public static android.renderscript.ScriptIntrinsicHistogram create(android.renderscript.RenderScript, android.renderscript.Element);
method public void forEach(android.renderscript.Allocation);
- method public void forEach_dot(android.renderscript.Allocation);
+ method public void forEach_Dot(android.renderscript.Allocation);
method public android.renderscript.Script.FieldID getFieldID_Input();
- method public android.renderscript.Script.KernelID getKernelID_seperate();
+ method public android.renderscript.Script.KernelID getKernelID_Separate();
method public void setDotCoefficients(float, float, float, float);
method public void setOutput(android.renderscript.Allocation);
}
@@ -25730,7 +25748,7 @@ package android.util {
method public android.util.JsonWriter value(java.lang.Number) throws java.io.IOException;
}
- public abstract interface LayoutDirection {
+ public final class LayoutDirection {
field public static final int INHERIT = 2; // 0x2
field public static final int LOCALE = 3; // 0x3
field public static final int LTR = 0; // 0x0
@@ -31147,7 +31165,6 @@ package android.widget {
method public int getAlignmentMode();
method public int getColumnCount();
method public int getOrientation();
- method public android.util.Printer getPrinter();
method public int getRowCount();
method public boolean getUseDefaultMargins();
method public boolean isColumnOrderPreserved();
@@ -31157,7 +31174,6 @@ package android.widget {
method public void setColumnCount(int);
method public void setColumnOrderPreserved(boolean);
method public void setOrientation(int);
- method public void setPrinter(android.util.Printer);
method public void setRowCount(int);
method public void setRowOrderPreserved(boolean);
method public void setUseDefaultMargins(boolean);
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index eba69b6..2b0c896 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -216,6 +216,12 @@ interface IPackageManager {
void resetPreferredActivities(int userId);
+ ResolveInfo getLastChosenActivity(in Intent intent,
+ String resolvedType, int flags);
+
+ void setLastChosenActivity(in Intent intent, String resolvedType, int flags,
+ in IntentFilter filter, int match, in ComponentName activity);
+
void addPreferredActivity(in IntentFilter filter, int match,
in ComponentName[] set, in ComponentName activity, int userId);
@@ -226,7 +232,7 @@ interface IPackageManager {
int getPreferredActivities(out List<IntentFilter> outFilters,
out List<ComponentName> outActivities, String packageName);
-
+
/**
* As per {@link android.content.pm.PackageManager#setComponentEnabledSetting}.
*/
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 81f860e..d58b14c 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -957,12 +957,24 @@ public abstract class PackageManager {
* Feature for {@link #getSystemAvailableFeatures} and
* {@link #hasSystemFeature}: The device supports host-
* based NFC card emulation.
+ *
+ * TODO remove when depending apps have moved to new constant.
+ * @hide
+ * @deprecated
*/
@SdkConstant(SdkConstantType.FEATURE)
public static final String FEATURE_NFC_HCE = "android.hardware.nfc.hce";
/**
* Feature for {@link #getSystemAvailableFeatures} and
+ * {@link #hasSystemFeature}: The device supports host-
+ * based NFC card emulation.
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_NFC_HOST_CARD_EMULATION = "android.hardware.nfc.hce";
+
+ /**
+ * Feature for {@link #getSystemAvailableFeatures} and
* {@link #hasSystemFeature}: The device includes an accelerometer.
*/
@SdkConstant(SdkConstantType.FEATURE)
diff --git a/core/java/android/net/CaptivePortalTracker.java b/core/java/android/net/CaptivePortalTracker.java
index 74c2c59..01977cd 100644
--- a/core/java/android/net/CaptivePortalTracker.java
+++ b/core/java/android/net/CaptivePortalTracker.java
@@ -16,22 +16,16 @@
package android.net;
-import android.app.Activity;
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.res.Resources;
import android.database.ContentObserver;
import android.net.ConnectivityManager;
import android.net.IConnectivityManager;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Handler;
-import android.os.UserHandle;
import android.os.Message;
import android.os.RemoteException;
import android.os.SystemClock;
@@ -46,7 +40,6 @@ import android.telephony.CellInfoGsm;
import android.telephony.CellInfoLte;
import android.telephony.CellInfoWcdma;
import android.telephony.TelephonyManager;
-import android.text.TextUtils;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
@@ -60,8 +53,6 @@ import java.net.URL;
import java.net.UnknownHostException;
import java.util.List;
-import com.android.internal.R;
-
/**
* This class allows captive portal detection on a network.
* @hide
@@ -71,7 +62,6 @@ public class CaptivePortalTracker extends StateMachine {
private static final String TAG = "CaptivePortalTracker";
private static final String DEFAULT_SERVER = "clients3.google.com";
- private static final String NOTIFICATION_ID = "CaptivePortal.Notification";
private static final int SOCKET_TIMEOUT_MS = 10000;
@@ -93,7 +83,6 @@ public class CaptivePortalTracker extends StateMachine {
private String mServer;
private String mUrl;
- private boolean mNotificationShown = false;
private boolean mIsCaptivePortalCheckEnabled = false;
private IConnectivityManager mConnService;
private TelephonyManager mTelephonyManager;
@@ -192,12 +181,12 @@ public class CaptivePortalTracker extends StateMachine {
private class DefaultState extends State {
@Override
public void enter() {
- if (DBG) log(getName() + "\n");
+ setNotificationOff();
}
@Override
public boolean processMessage(Message message) {
- if (DBG) log(getName() + message.toString() + "\n");
+ if (DBG) log(getName() + message.toString());
switch (message.what) {
case CMD_DETECT_PORTAL:
NetworkInfo info = (NetworkInfo) message.obj;
@@ -219,23 +208,24 @@ public class CaptivePortalTracker extends StateMachine {
private class NoActiveNetworkState extends State {
@Override
public void enter() {
- if (DBG) log(getName() + "\n");
mNetworkInfo = null;
- /* Clear any previous notification */
- setNotificationVisible(false);
}
@Override
public boolean processMessage(Message message) {
- if (DBG) log(getName() + message.toString() + "\n");
+ if (DBG) log(getName() + message.toString());
InetAddress server;
NetworkInfo info;
switch (message.what) {
case CMD_CONNECTIVITY_CHANGE:
info = (NetworkInfo) message.obj;
- if (info.isConnected() && isActiveNetwork(info)) {
- mNetworkInfo = info;
- transitionTo(mDelayedCaptiveCheckState);
+ if (info.getType() == ConnectivityManager.TYPE_WIFI) {
+ if (info.isConnected() && isActiveNetwork(info)) {
+ mNetworkInfo = info;
+ transitionTo(mDelayedCaptiveCheckState);
+ }
+ } else {
+ log(getName() + " not a wifi connectivity change, ignore");
}
break;
default:
@@ -248,7 +238,7 @@ public class CaptivePortalTracker extends StateMachine {
private class ActiveNetworkState extends State {
@Override
public void enter() {
- if (DBG) log(getName() + "\n");
+ setNotificationOff();
}
@Override
@@ -281,7 +271,6 @@ public class CaptivePortalTracker extends StateMachine {
private class DelayedCaptiveCheckState extends State {
@Override
public void enter() {
- if (DBG) log(getName() + "\n");
Message message = obtainMessage(CMD_DELAYED_CAPTIVE_CHECK, ++mDelayedCheckToken, 0);
if (mDeviceProvisioned) {
sendMessageDelayed(message, DELAYED_CHECK_INTERVAL_MS);
@@ -292,7 +281,7 @@ public class CaptivePortalTracker extends StateMachine {
@Override
public boolean processMessage(Message message) {
- if (DBG) log(getName() + message.toString() + "\n");
+ if (DBG) log(getName() + message.toString());
switch (message.what) {
case CMD_DELAYED_CAPTIVE_CHECK:
if (message.arg1 == mDelayedCheckToken) {
@@ -308,7 +297,12 @@ public class CaptivePortalTracker extends StateMachine {
if (captive) {
// Setup Wizard will assist the user in connecting to a captive
// portal, so make the notification visible unless during setup
- setNotificationVisible(true);
+ try {
+ mConnService.setProvisioningNotificationVisible(true,
+ mNetworkInfo.getType(), mNetworkInfo.getExtraInfo(), mUrl);
+ } catch(RemoteException e) {
+ e.printStackTrace();
+ }
}
} else {
Intent intent = new Intent(
@@ -366,6 +360,15 @@ public class CaptivePortalTracker extends StateMachine {
return false;
}
+ private void setNotificationOff() {
+ try {
+ mConnService.setProvisioningNotificationVisible(false, ConnectivityManager.TYPE_NONE,
+ null, null);
+ } catch (RemoteException e) {
+ log("setNotificationOff: " + e);
+ }
+ }
+
/**
* Do a URL fetch on a known server to see if we get the data we expect.
* Measure the response time and broadcast that.
@@ -394,17 +397,14 @@ public class CaptivePortalTracker extends StateMachine {
long responseTimestamp = SystemClock.elapsedRealtime();
// we got a valid response, but not from the real google
- boolean isCaptivePortal = urlConnection.getResponseCode() != 204;
+ int rspCode = urlConnection.getResponseCode();
+ boolean isCaptivePortal = rspCode != 204;
sendNetworkConditionsBroadcast(true /* response received */, isCaptivePortal,
requestTimestamp, responseTimestamp);
+
+ if (DBG) log("isCaptivePortal: ret=" + isCaptivePortal + " rspCode=" + rspCode);
return isCaptivePortal;
- } catch (SocketTimeoutException e) {
- if (DBG) log("Probably a portal: exception " + e);
- if (requestTimestamp != -1) {
- sendFailedCaptivePortalCheckBroadcast(requestTimestamp);
- } // else something went wrong with setting up the urlConnection
- return true;
} catch (IOException e) {
if (DBG) log("Probably not a portal: exception " + e);
if (requestTimestamp != -1) {
@@ -435,77 +435,6 @@ public class CaptivePortalTracker extends StateMachine {
return null;
}
- private void setNotificationVisible(boolean visible) {
- // if it should be hidden and it is already hidden, then noop
- if (!visible && !mNotificationShown) {
- if (DBG) log("setNotivicationVisible: false and not shown, so noop");
- return;
- }
-
- Resources r = Resources.getSystem();
- NotificationManager notificationManager = (NotificationManager) mContext
- .getSystemService(Context.NOTIFICATION_SERVICE);
-
- if (visible) {
- CharSequence title;
- CharSequence details;
- int icon;
- String url = null;
- switch (mNetworkInfo.getType()) {
- case ConnectivityManager.TYPE_WIFI:
- title = r.getString(R.string.wifi_available_sign_in, 0);
- details = r.getString(R.string.network_available_sign_in_detailed,
- mNetworkInfo.getExtraInfo());
- icon = R.drawable.stat_notify_wifi_in_range;
- url = mUrl;
- break;
- case ConnectivityManager.TYPE_MOBILE:
- title = r.getString(R.string.network_available_sign_in, 0);
- // TODO: Change this to pull from NetworkInfo once a printable
- // name has been added to it
- details = mTelephonyManager.getNetworkOperatorName();
- icon = R.drawable.stat_notify_rssi_in_range;
- try {
- url = mConnService.getMobileProvisioningUrl();
- if (TextUtils.isEmpty(url)) {
- url = mConnService.getMobileRedirectedProvisioningUrl();
- }
- } catch(RemoteException e) {
- e.printStackTrace();
- }
- if (TextUtils.isEmpty(url)) {
- url = mUrl;
- }
- break;
- default:
- title = r.getString(R.string.network_available_sign_in, 0);
- details = r.getString(R.string.network_available_sign_in_detailed,
- mNetworkInfo.getExtraInfo());
- icon = R.drawable.stat_notify_rssi_in_range;
- url = mUrl;
- break;
- }
-
- Notification notification = new Notification();
- notification.when = 0;
- notification.icon = icon;
- notification.flags = Notification.FLAG_AUTO_CANCEL;
- Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
- intent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT |
- Intent.FLAG_ACTIVITY_NEW_TASK);
- notification.contentIntent = PendingIntent.getActivity(mContext, 0, intent, 0);
- notification.tickerText = title;
- notification.setLatestEventInfo(mContext, title, details, notification.contentIntent);
-
- if (DBG) log("setNotivicationVisible: make visible");
- notificationManager.notify(NOTIFICATION_ID, 1, notification);
- } else {
- if (DBG) log("setNotivicationVisible: cancel notification");
- notificationManager.cancel(NOTIFICATION_ID, 1);
- }
- mNotificationShown = visible;
- }
-
private void sendFailedCaptivePortalCheckBroadcast(long requestTimestampMs) {
sendNetworkConditionsBroadcast(false /* response received */, false /* ignored */,
requestTimestampMs, 0 /* ignored */);
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index f6a3a4a..3874369 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -624,6 +624,29 @@ public class ConnectivityManager {
}
/**
+ * Returns details about the Provisioning or currently active default data network. When
+ * connected, this network is the default route for outgoing connections.
+ * You should always check {@link NetworkInfo#isConnected()} before initiating
+ * network traffic. This may return {@code null} when there is no default
+ * network.
+ *
+ * @return a {@link NetworkInfo} object for the current default network
+ * or {@code null} if no network default network is currently active
+ *
+ * <p>This method requires the call to hold the permission
+ * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}.
+ *
+ * {@hide}
+ */
+ public NetworkInfo getProvisioningOrActiveNetworkInfo() {
+ try {
+ return mService.getProvisioningOrActiveNetworkInfo();
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
+ /**
* Returns the IP information for the current default network.
*
* @return a {@link LinkProperties} object describing the IP info
@@ -1357,63 +1380,19 @@ public class ConnectivityManager {
}
/**
- * The ResultReceiver resultCode for checkMobileProvisioning (CMP_RESULT_CODE)
- */
-
- /**
- * No connection was possible to the network.
- * {@hide}
- */
- public static final int CMP_RESULT_CODE_NO_CONNECTION = 0;
-
- /**
- * A connection was made to the internet, all is well.
- * {@hide}
- */
- public static final int CMP_RESULT_CODE_CONNECTABLE = 1;
-
- /**
- * A connection was made but there was a redirection, we appear to be in walled garden.
- * This is an indication of a warm sim on a mobile network.
- * {@hide}
- */
- public static final int CMP_RESULT_CODE_REDIRECTED = 2;
-
- /**
- * A connection was made but no dns server was available to resolve a name to address.
- * This is an indication of a warm sim on a mobile network.
+ * Check mobile provisioning.
*
- * {@hide}
- */
- public static final int CMP_RESULT_CODE_NO_DNS = 3;
-
- /**
- * A connection was made but could not open a TCP connection.
- * This is an indication of a warm sim on a mobile network.
- * {@hide}
- */
- public static final int CMP_RESULT_CODE_NO_TCP_CONNECTION = 4;
-
- /**
- * Check mobile provisioning. The resultCode passed to
- * onReceiveResult will be one of the CMP_RESULT_CODE_xxxx values above.
- * This may take a minute or more to complete.
- *
- * @param sendNotificaiton, when true a notification will be sent to user.
* @param suggestedTimeOutMs, timeout in milliseconds
- * @param resultReceiver needs to be supplied to receive the result
*
* @return time out that will be used, maybe less that suggestedTimeOutMs
* -1 if an error.
*
* {@hide}
*/
- public int checkMobileProvisioning(boolean sendNotification, int suggestedTimeOutMs,
- ResultReceiver resultReceiver) {
+ public int checkMobileProvisioning(int suggestedTimeOutMs) {
int timeOutMs = -1;
try {
- timeOutMs = mService.checkMobileProvisioning(sendNotification, suggestedTimeOutMs,
- resultReceiver);
+ timeOutMs = mService.checkMobileProvisioning(suggestedTimeOutMs);
} catch (RemoteException e) {
}
return timeOutMs;
@@ -1481,4 +1460,20 @@ public class ConnectivityManager {
return null;
}
}
+
+ /**
+ * Set sign in error notification to visible or in visible
+ *
+ * @param visible
+ * @param networkType
+ *
+ * {@hide}
+ */
+ public void setProvisioningNotificationVisible(boolean visible, int networkType,
+ String extraInfo, String url) {
+ try {
+ mService.setProvisioningNotificationVisible(visible, networkType, extraInfo, url);
+ } catch (RemoteException e) {
+ }
+ }
}
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index bf2dade..c07e900 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -50,6 +50,8 @@ interface IConnectivityManager
NetworkInfo getNetworkInfo(int networkType);
NetworkInfo[] getAllNetworkInfo();
+ NetworkInfo getProvisioningOrActiveNetworkInfo();
+
boolean isNetworkSupported(int networkType);
LinkProperties getActiveLinkProperties();
@@ -141,7 +143,7 @@ interface IConnectivityManager
int findConnectionTypeForIface(in String iface);
- int checkMobileProvisioning(boolean sendNotification, int suggestedTimeOutMs, in ResultReceiver resultReceiver);
+ int checkMobileProvisioning(int suggestedTimeOutMs);
String getMobileProvisioningUrl();
@@ -153,4 +155,5 @@ interface IConnectivityManager
LinkInfo[] getAllLinkInfo();
+ void setProvisioningNotificationVisible(boolean visible, int networkType, in String extraInfo, in String url);
}
diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java
index faa13b0..125d5c1 100644
--- a/core/java/android/net/MobileDataStateTracker.java
+++ b/core/java/android/net/MobileDataStateTracker.java
@@ -61,8 +61,12 @@ public class MobileDataStateTracker extends BaseNetworkStateTracker {
private ITelephony mPhoneService;
private String mApnType;
+ private NetworkInfo mNetworkInfo;
private boolean mTeardownRequested = false;
private Handler mTarget;
+ private Context mContext;
+ private LinkProperties mLinkProperties;
+ private LinkCapabilities mLinkCapabilities;
private boolean mPrivateDnsRouteSet = false;
private boolean mDefaultRouteSet = false;
@@ -106,6 +110,7 @@ public class MobileDataStateTracker extends BaseNetworkStateTracker {
IntentFilter filter = new IntentFilter();
filter.addAction(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
+ filter.addAction(TelephonyIntents.ACTION_DATA_CONNECTION_CONNECTED_TO_PROVISIONING_APN);
filter.addAction(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED);
mContext.registerReceiver(new MobileDataStateReceiver(), filter);
@@ -184,10 +189,41 @@ public class MobileDataStateTracker extends BaseNetworkStateTracker {
public void releaseWakeLock() {
}
+ private void updateLinkProperitesAndCapatilities(Intent intent) {
+ mLinkProperties = intent.getParcelableExtra(
+ PhoneConstants.DATA_LINK_PROPERTIES_KEY);
+ if (mLinkProperties == null) {
+ loge("CONNECTED event did not supply link properties.");
+ mLinkProperties = new LinkProperties();
+ }
+ mLinkCapabilities = intent.getParcelableExtra(
+ PhoneConstants.DATA_LINK_CAPABILITIES_KEY);
+ if (mLinkCapabilities == null) {
+ loge("CONNECTED event did not supply link capabilities.");
+ mLinkCapabilities = new LinkCapabilities();
+ }
+ }
+
private class MobileDataStateReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(TelephonyIntents.
+ ACTION_DATA_CONNECTION_CONNECTED_TO_PROVISIONING_APN)) {
+ String apnName = intent.getStringExtra(PhoneConstants.DATA_APN_KEY);
+ String apnType = intent.getStringExtra(PhoneConstants.DATA_APN_TYPE_KEY);
+ if (!TextUtils.equals(mApnType, apnType)) {
+ return;
+ }
+ if (DBG) {
+ log("Broadcast received: " + intent.getAction() + " apnType=" + apnType
+ + " apnName=" + apnName);
+ }
+
+ // Make us in the connecting state until we make a new TYPE_MOBILE_PROVISIONING
+ mMobileDataState = PhoneConstants.DataState.CONNECTING;
+ updateLinkProperitesAndCapatilities(intent);
+ setDetailedState(DetailedState.CONNECTED_TO_PROVISIONING_NETWORK, "", apnName);
+ } else if (intent.getAction().equals(TelephonyIntents.
ACTION_ANY_DATA_CONNECTION_STATE_CHANGED)) {
String apnType = intent.getStringExtra(PhoneConstants.DATA_APN_TYPE_KEY);
if (VDBG) {
@@ -249,18 +285,7 @@ public class MobileDataStateTracker extends BaseNetworkStateTracker {
setDetailedState(DetailedState.SUSPENDED, reason, apnName);
break;
case CONNECTED:
- mLinkProperties = intent.getParcelableExtra(
- PhoneConstants.DATA_LINK_PROPERTIES_KEY);
- if (mLinkProperties == null) {
- loge("CONNECTED event did not supply link properties.");
- mLinkProperties = new LinkProperties();
- }
- mLinkCapabilities = intent.getParcelableExtra(
- PhoneConstants.DATA_LINK_CAPABILITIES_KEY);
- if (mLinkCapabilities == null) {
- loge("CONNECTED event did not supply link capabilities.");
- mLinkCapabilities = new LinkCapabilities();
- }
+ updateLinkProperitesAndCapatilities(intent);
setDetailedState(DetailedState.CONNECTED, reason, apnName);
break;
}
@@ -319,8 +344,8 @@ public class MobileDataStateTracker extends BaseNetworkStateTracker {
String reason = intent.getStringExtra(PhoneConstants.FAILURE_REASON_KEY);
String apnName = intent.getStringExtra(PhoneConstants.DATA_APN_KEY);
if (DBG) {
- log("Received " + intent.getAction() +
- " broadcast" + (reason == null ? "" : "(" + reason + ")"));
+ log("Broadcast received: " + intent.getAction() +
+ " reason=" + reason == null ? "null" : reason);
}
setDetailedState(DetailedState.FAILED, reason, apnName);
} else {
@@ -412,6 +437,13 @@ public class MobileDataStateTracker extends BaseNetworkStateTracker {
return (setEnableApn(mApnType, false) != PhoneConstants.APN_REQUEST_FAILED);
}
+ /**
+ * @return true if this is ready to operate
+ */
+ public boolean isReady() {
+ return mDataConnectionTrackerAc != null;
+ }
+
@Override
public void captivePortalCheckComplete() {
// not implemented
@@ -574,6 +606,40 @@ public class MobileDataStateTracker extends BaseNetworkStateTracker {
}
}
+ /**
+ * Inform DCT mobile provisioning has started, it ends when provisioning completes.
+ */
+ public void enableMobileProvisioning(String url) {
+ if (DBG) log("enableMobileProvisioning(url=" + url + ")");
+ final AsyncChannel channel = mDataConnectionTrackerAc;
+ if (channel != null) {
+ Message msg = Message.obtain();
+ msg.what = DctConstants.CMD_ENABLE_MOBILE_PROVISIONING;
+ msg.setData(Bundle.forPair(DctConstants.PROVISIONING_URL_KEY, url));
+ channel.sendMessage(msg);
+ }
+ }
+
+ /**
+ * Return if this network is the provisioning network. Valid only if connected.
+ * @param met
+ */
+ public boolean isProvisioningNetwork() {
+ boolean retVal;
+ try {
+ Message msg = Message.obtain();
+ msg.what = DctConstants.CMD_IS_PROVISIONING_APN;
+ msg.setData(Bundle.forPair(DctConstants.APN_TYPE_KEY, mApnType));
+ Message result = mDataConnectionTrackerAc.sendMessageSynchronously(msg);
+ retVal = result.arg1 == DctConstants.ENABLED;
+ } catch (NullPointerException e) {
+ loge("isProvisioningNetwork: X " + e);
+ retVal = false;
+ }
+ if (DBG) log("isProvisioningNetwork: retVal=" + retVal);
+ return retVal;
+ }
+
@Override
public void addStackedLink(LinkProperties link) {
mLinkProperties.addStackedLink(link);
diff --git a/core/java/android/net/NetworkInfo.java b/core/java/android/net/NetworkInfo.java
index 689dae5..dabc73a 100644
--- a/core/java/android/net/NetworkInfo.java
+++ b/core/java/android/net/NetworkInfo.java
@@ -84,6 +84,12 @@ public class NetworkInfo implements Parcelable {
VERIFYING_POOR_LINK,
/** Checking if network is a captive portal */
CAPTIVE_PORTAL_CHECK,
+ /**
+ * Network is connected to provisioning network
+ * TODO: Probably not needed when we add TYPE_PROVISIONING_NETWORK
+ * @hide
+ */
+ CONNECTED_TO_PROVISIONING_NETWORK
}
/**
@@ -108,6 +114,7 @@ public class NetworkInfo implements Parcelable {
stateMap.put(DetailedState.DISCONNECTED, State.DISCONNECTED);
stateMap.put(DetailedState.FAILED, State.DISCONNECTED);
stateMap.put(DetailedState.BLOCKED, State.DISCONNECTED);
+ stateMap.put(DetailedState.CONNECTED_TO_PROVISIONING_NETWORK, State.CONNECTED);
}
private int mNetworkType;
diff --git a/core/java/android/nfc/cardemulation/ApduServiceInfo.java b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
index 3f7e3ef..b83911a 100644
--- a/core/java/android/nfc/cardemulation/ApduServiceInfo.java
+++ b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
@@ -75,16 +75,22 @@ public final class ApduServiceInfo implements Parcelable {
final HashMap<String, AidGroup> mCategoryToGroup;
/**
+ * Whether this service should only be started when the device is unlocked.
+ */
+ final boolean mRequiresDeviceUnlock;
+
+ /**
* @hide
*/
public ApduServiceInfo(ResolveInfo info, boolean onHost, String description,
- ArrayList<AidGroup> aidGroups) {
+ ArrayList<AidGroup> aidGroups, boolean requiresUnlock) {
this.mService = info;
this.mDescription = description;
this.mAidGroups = aidGroups;
this.mAids = new ArrayList<String>();
this.mCategoryToGroup = new HashMap<String, AidGroup>();
this.mOnHost = onHost;
+ this.mRequiresDeviceUnlock = requiresUnlock;
for (AidGroup aidGroup : aidGroups) {
this.mCategoryToGroup.put(aidGroup.category, aidGroup);
this.mAids.addAll(aidGroup.aids);
@@ -132,12 +138,16 @@ public final class ApduServiceInfo implements Parcelable {
mService = info;
mDescription = sa.getString(
com.android.internal.R.styleable.HostApduService_description);
+ mRequiresDeviceUnlock = sa.getBoolean(
+ com.android.internal.R.styleable.HostApduService_requireDeviceUnlock,
+ false);
} else {
TypedArray sa = res.obtainAttributes(attrs,
com.android.internal.R.styleable.OffHostApduService);
mService = info;
mDescription = sa.getString(
com.android.internal.R.styleable.OffHostApduService_description);
+ mRequiresDeviceUnlock = false;
}
mAidGroups = new ArrayList<AidGroup>();
@@ -226,6 +236,10 @@ public final class ApduServiceInfo implements Parcelable {
return mOnHost;
}
+ public boolean requiresUnlock() {
+ return mRequiresDeviceUnlock;
+ }
+
public CharSequence loadLabel(PackageManager pm) {
return mService.loadLabel(pm);
}
@@ -287,6 +301,7 @@ public final class ApduServiceInfo implements Parcelable {
if (mAidGroups.size() > 0) {
dest.writeTypedList(mAidGroups);
}
+ dest.writeInt(mRequiresDeviceUnlock ? 1 : 0);
};
public static final Parcelable.Creator<ApduServiceInfo> CREATOR =
@@ -301,7 +316,8 @@ public final class ApduServiceInfo implements Parcelable {
if (numGroups > 0) {
source.readTypedList(aidGroups, AidGroup.CREATOR);
}
- return new ApduServiceInfo(info, onHost, description, aidGroups);
+ boolean requiresUnlock = (source.readInt() != 0) ? true : false;
+ return new ApduServiceInfo(info, onHost, description, aidGroups, requiresUnlock);
}
@Override
diff --git a/core/java/android/nfc/cardemulation/CardEmulationManager.java b/core/java/android/nfc/cardemulation/CardEmulationManager.java
index 537fded..9d60c73 100644
--- a/core/java/android/nfc/cardemulation/CardEmulationManager.java
+++ b/core/java/android/nfc/cardemulation/CardEmulationManager.java
@@ -27,6 +27,7 @@ import android.nfc.INfcCardEmulation;
import android.nfc.NfcAdapter;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.provider.Settings;
import android.util.Log;
import java.util.HashMap;
@@ -78,19 +79,68 @@ public final class CardEmulationManager {
*/
public static final String CATEGORY_OTHER = "other";
- static boolean sIsInitialized = false;
- static HashMap<Context, CardEmulationManager> sCardEmuManagers = new HashMap();
- static INfcCardEmulation sService;
+ /**
+ * Return value for {@link #getSelectionModeForCategory(String)}.
+ *
+ * <p>In this mode, the user has set a default service for this
+ * AID category. If a remote reader selects any of the AIDs
+ * that the default service has registered in this category,
+ * that service will automatically be bound to to handle
+ * the transaction.
+ *
+ * <p>There are still cases where a service that is
+ * not the default for a category can selected:
+ * <p>
+ * If a remote reader selects an AID in this category
+ * that is not handled by the default service, and there is a set
+ * of other services {S} that do handle this AID, the
+ * user is asked if he wants to use any of the services in
+ * {S} instead.
+ * <p>
+ * As a special case, if the size of {S} is one, containing a single service X,
+ * and all AIDs X has registered in this category are not
+ * registered by any other service, then X will be
+ * selected automatically without asking the user.
+ * <p>Example:
+ * <ul>
+ * <li>Service A registers AIDs "1", "2" and "3" in the category
+ * <li>Service B registers AIDs "3" and "4" in the category
+ * <li>Service C registers AIDs "5" and "6" in the category
+ * </ul>
+ * In this case, the following will happen when service A
+ * is the default:
+ * <ul>
+ * <li>Reader selects AID "1", "2" or "3": service A is invoked automatically
+ * <li>Reader selects AID "4": the user is asked to confirm he
+ * wants to use service B, because its AIDs overlap with service A.
+ * <li>Reader selects AID "5" or "6": service C is invoked automatically,
+ * because all AIDs it has asked for are only registered by C,
+ * and there is no overlap.
+ * </ul>
+ *
+ */
+ public static final int SELECTION_MODE_PREFER_DEFAULT = 0;
/**
- * @hide
+ * Return value for {@link #getSelectionModeForCategory(String)}.
+ *
+ * <p>In this mode, whenever an AID of this category is selected,
+ * the user is asked which service he wants to use to handle
+ * the transaction, even if there is only one matching service.
*/
- public static final String PAYMENT_MODE_AUTO = "auto";
+ public static final int SELECTION_MODE_ALWAYS_ASK = 1;
/**
- * @hide
+ * Return value for {@link #getSelectionModeForCategory(String)}.
+ *
+ * <p>In this mode, the user will only be asked to select a service
+ * if the selected AID has been registered by multiple applications.
*/
- public static final String PAYMENT_MODE_MANUAL = "manual";
+ public static final int SELECTION_MODE_ASK_IF_CONFLICT = 2;
+
+ static boolean sIsInitialized = false;
+ static HashMap<Context, CardEmulationManager> sCardEmuManagers = new HashMap();
+ static INfcCardEmulation sService;
final Context mContext;
@@ -113,7 +163,7 @@ public final class CardEmulationManager {
throw new UnsupportedOperationException();
}
try {
- if (!pm.hasSystemFeature(PackageManager.FEATURE_NFC_HCE)) {
+ if (!pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION)) {
Log.e(TAG, "This device does not support card emulation");
throw new UnsupportedOperationException();
}
@@ -137,6 +187,10 @@ public final class CardEmulationManager {
* Allows an application to query whether a service is currently
* the default service to handle a card emulation category.
*
+ * <p>Note that if {@link #getSelectionModeForCategory(String)}
+ * returns {@link #SELECTION_MODE_ALWAYS_ASK}, this method will always
+ * return false.
+ *
* @param service The ComponentName of the service
* @param category The category
* @return whether service is currently the default service for the category.
@@ -147,6 +201,10 @@ public final class CardEmulationManager {
} catch (RemoteException e) {
// Try one more time
recoverService();
+ if (sService == null) {
+ Log.e(TAG, "Failed to recover CardEmulationService.");
+ return false;
+ }
try {
return sService.isDefaultServiceForCategory(UserHandle.myUserId(), service,
category);
@@ -186,6 +244,33 @@ public final class CardEmulationManager {
}
/**
+ * Returns the application selection mode for the passed in category.
+ * Valid return values are:
+ * <p>{@link #SELECTION_MODE_PREFER_DEFAULT} the user has requested a default
+ * application for this category, which will be preferred.
+ * <p>{@link #SELECTION_MODE_ALWAYS_ASK} the user has requested to be asked
+ * every time what app he would like to use in this category.
+ * <p>{@link #SELECTION_MODE_ASK_IF_CONFLICT} the user will only be asked
+ * to pick a service if there is a conflict.
+ * @param category The category, for example {@link #CATEGORY_PAYMENT}
+ * @return
+ */
+ public int getSelectionModeForCategory(String category) {
+ if (CATEGORY_PAYMENT.equals(category)) {
+ String defaultComponent = Settings.Secure.getString(mContext.getContentResolver(),
+ Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT);
+ if (defaultComponent != null) {
+ return SELECTION_MODE_PREFER_DEFAULT;
+ } else {
+ return SELECTION_MODE_ALWAYS_ASK;
+ }
+ } else {
+ // All other categories are in "only ask if conflict" mode
+ return SELECTION_MODE_ASK_IF_CONFLICT;
+ }
+ }
+
+ /**
* @hide
*/
public boolean setDefaultServiceForCategory(ComponentName service, String category) {
diff --git a/core/java/android/nfc/cardemulation/HostApduService.java b/core/java/android/nfc/cardemulation/HostApduService.java
index cdc4adb..ae94b2f 100644
--- a/core/java/android/nfc/cardemulation/HostApduService.java
+++ b/core/java/android/nfc/cardemulation/HostApduService.java
@@ -4,13 +4,11 @@ import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.app.Service;
import android.content.Intent;
-import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
-import android.os.Parcel;
import android.os.RemoteException;
import android.util.Log;
diff --git a/core/java/android/print/IPrintManager.aidl b/core/java/android/print/IPrintManager.aidl
index 3bfd9a1..fb6bb2e 100644
--- a/core/java/android/print/IPrintManager.aidl
+++ b/core/java/android/print/IPrintManager.aidl
@@ -41,7 +41,9 @@ interface IPrintManager {
void startPrinterDiscovery(in IPrinterDiscoveryObserver observer,
in List<PrinterId> priorityList, int userId);
void stopPrinterDiscovery(in IPrinterDiscoveryObserver observer, int userId);
- void requestPrinterUpdate(in PrinterId printerId, int userId);
+ void validatePrinters(in List<PrinterId> printerIds, int userId);
+ void startPrinterStateTracking(in PrinterId printerId, int userId);
+ void stopPrinterStateTracking(in PrinterId printerId, int userId);
void destroyPrinterDiscoverySession(in IPrinterDiscoveryObserver observer,
int userId);
}
diff --git a/core/java/android/print/PrintDocumentAdapter.java b/core/java/android/print/PrintDocumentAdapter.java
index 8a64e85..33b4aad 100644
--- a/core/java/android/print/PrintDocumentAdapter.java
+++ b/core/java/android/print/PrintDocumentAdapter.java
@@ -18,8 +18,8 @@ package android.print;
import android.os.Bundle;
import android.os.CancellationSignal;
+import android.os.ParcelFileDescriptor;
-import java.io.FileDescriptor;
import java.util.List;
/**
@@ -41,7 +41,7 @@ import java.util.List;
* <li>
* After every call to {@link #onLayout(PrintAttributes, PrintAttributes,
* CancellationSignal, LayoutResultCallback, Bundle)}, you may get a call to
- * {@link #onWrite(PageRange[], FileDescriptor, CancellationSignal, WriteResultCallback)}
+ * {@link #onWrite(PageRange[], ParcelFileDescriptor, CancellationSignal, WriteResultCallback)}
* asking you to write a PDF file with the content for specific pages.
* </li>
* <li>
@@ -64,7 +64,7 @@ import java.util.List;
* PrintAttributes, CancellationSignal, LayoutResultCallback, Bundle)} on
* the UI thread (assuming onStart initializes resources needed for layout).
* This will ensure that the UI does not change while you are laying out the
- * printed content. Then you can handle {@link #onWrite(PageRange[], FileDescriptor,
+ * printed content. Then you can handle {@link #onWrite(PageRange[], ParcelFileDescriptor,
* CancellationSignal, WriteResultCallback)} and {@link #onFinish()} on another
* thread. This will ensure that the UI is frozen for the minimal amount of
* time. Also this assumes that you will generate the printed content in
@@ -150,10 +150,10 @@ public abstract class PrintDocumentAdapter {
* from of a PDF file to the given file descriptor. This method is invoked
* on the main thread.
*<p>
- * After you are done writing, you should <strong>not</strong> close the
- * file descriptor, rather you must invoke: {@link WriteResultCallback
- * #onWriteFinished(List)}, if writing completed successfully; or {@link
- * WriteResultCallback#onWriteFailed(CharSequence)}, if an error occurred.
+ * After you are done writing, you should close the file descriptor and
+ * invoke {@link WriteResultCallback #onWriteFinished(List)}, if writing
+ * completed successfully; or {@link WriteResultCallback#onWriteFailed(
+ * CharSequence)}, if an error occurred.
* </p>
* <p>
* <strong>Note:</strong> If the printed content is large, it is a good
@@ -171,7 +171,7 @@ public abstract class PrintDocumentAdapter {
* @see WriteResultCallback
* @see CancellationSignal
*/
- public abstract void onWrite(PageRange[] pages, FileDescriptor destination,
+ public abstract void onWrite(PageRange[] pages, ParcelFileDescriptor destination,
CancellationSignal cancellationSignal, WriteResultCallback callback);
/**
@@ -185,7 +185,7 @@ public abstract class PrintDocumentAdapter {
/**
* Base class for implementing a callback for the result of {@link
- * PrintDocumentAdapter#onWrite(PageRange[], FileDescriptor, CancellationSignal,
+ * PrintDocumentAdapter#onWrite(PageRange[], ParcelFileDescriptor, CancellationSignal,
* WriteResultCallback)}.
*/
public static abstract class WriteResultCallback {
diff --git a/core/java/android/print/PrintDocumentInfo.java b/core/java/android/print/PrintDocumentInfo.java
index b32961b..f2b91ae 100644
--- a/core/java/android/print/PrintDocumentInfo.java
+++ b/core/java/android/print/PrintDocumentInfo.java
@@ -60,6 +60,7 @@ public final class PrintDocumentInfo implements Parcelable {
private int mColorMode;
private Margins mMargins;
private MediaSize mMediaSize;
+ private long mDataSize;
/**
* Creates a new instance.
@@ -82,6 +83,7 @@ public final class PrintDocumentInfo implements Parcelable {
mColorMode = prototype.mColorMode;
mMargins = prototype.mMargins;
mMediaSize = prototype.mMediaSize;
+ mDataSize = prototype.mDataSize;
}
/**
@@ -98,6 +100,7 @@ public final class PrintDocumentInfo implements Parcelable {
mColorMode = parcel.readInt();
mMargins = Margins.createFromParcel(parcel);
mMediaSize = MediaSize.createFromParcel(parcel);
+ mDataSize = parcel.readLong();
}
/**
@@ -188,6 +191,26 @@ public final class PrintDocumentInfo implements Parcelable {
return mMediaSize;
}
+ /**
+ * Gets the document data size in bytes.
+ *
+ * @return The data size.
+ */
+ public long getDataSize() {
+ return mDataSize;
+ }
+
+ /**
+ * Sets the document data size in bytes.
+ *
+ * @param dataSize The data size.
+ *
+ * @hide
+ */
+ public void setDataSize(long dataSize) {
+ mDataSize = dataSize;
+ }
+
@Override
public int describeContents() {
return 0;
@@ -203,6 +226,7 @@ public final class PrintDocumentInfo implements Parcelable {
parcel.writeInt(mColorMode);
mMargins.writeToParcel(parcel);
mMediaSize.writeToParcel(parcel);
+ parcel.writeLong(mDataSize);
}
@Override
@@ -217,6 +241,8 @@ public final class PrintDocumentInfo implements Parcelable {
result = prime * result + mColorMode;
result = prime * result + (mMargins != null ? mMargins.hashCode() : 0);
result = prime * result + (mMediaSize != null ? mMediaSize.hashCode() : 0);
+ result = prime * result + (int) mDataSize;
+ result = prime * result + (int) mDataSize >> 32;
return result;
}
@@ -264,6 +290,9 @@ public final class PrintDocumentInfo implements Parcelable {
} else if (!mMediaSize.equals(other.mMediaSize)) {
return false;
}
+ if (mDataSize != other.mDataSize) {
+ return false;
+ }
return true;
}
@@ -279,6 +308,7 @@ public final class PrintDocumentInfo implements Parcelable {
builder.append(", colorMode=").append(PrintAttributes.colorModeToString(mColorMode));
builder.append(", margins=").append(mMargins);
builder.append(", mediaSize=").append(mMediaSize);
+ builder.append(", size=").append(mDataSize);
builder.append("}");
return builder.toString();
}
diff --git a/core/java/android/print/PrintFileDocumentAdapter.java b/core/java/android/print/PrintFileDocumentAdapter.java
index dbc8b6f..b905396 100644
--- a/core/java/android/print/PrintFileDocumentAdapter.java
+++ b/core/java/android/print/PrintFileDocumentAdapter.java
@@ -21,6 +21,7 @@ import android.os.AsyncTask;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.CancellationSignal.OnCancelListener;
+import android.os.ParcelFileDescriptor;
import android.util.Log;
import com.android.internal.R;
@@ -28,7 +29,6 @@ import com.android.internal.R;
import libcore.io.IoUtils;
import java.io.File;
-import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
@@ -81,7 +81,7 @@ public class PrintFileDocumentAdapter extends PrintDocumentAdapter {
}
@Override
- public void onWrite(PageRange[] pages, FileDescriptor destination,
+ public void onWrite(PageRange[] pages, ParcelFileDescriptor destination,
CancellationSignal cancellationSignal, WriteResultCallback callback) {
mWriteFileAsyncTask = new WriteFileAsyncTask(destination, cancellationSignal, callback);
mWriteFileAsyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,
@@ -90,13 +90,13 @@ public class PrintFileDocumentAdapter extends PrintDocumentAdapter {
private final class WriteFileAsyncTask extends AsyncTask<Void, Void, Void> {
- private final FileDescriptor mDestination;
+ private final ParcelFileDescriptor mDestination;
private final WriteResultCallback mResultCallback;
private final CancellationSignal mCancellationSignal;
- public WriteFileAsyncTask(FileDescriptor destination,
+ public WriteFileAsyncTask(ParcelFileDescriptor destination,
CancellationSignal cancellationSignal, WriteResultCallback callback) {
mDestination = destination;
mResultCallback = callback;
@@ -112,7 +112,7 @@ public class PrintFileDocumentAdapter extends PrintDocumentAdapter {
@Override
protected Void doInBackground(Void... params) {
InputStream in = null;
- OutputStream out = new FileOutputStream(mDestination);
+ OutputStream out = new FileOutputStream(mDestination.getFileDescriptor());
final byte[] buffer = new byte[8192];
try {
in = new FileInputStream(mFile);
diff --git a/core/java/android/print/PrintJobInfo.java b/core/java/android/print/PrintJobInfo.java
index 602f3c1..b919ad6 100644
--- a/core/java/android/print/PrintJobInfo.java
+++ b/core/java/android/print/PrintJobInfo.java
@@ -44,6 +44,13 @@ public final class PrintJobInfo implements Parcelable {
public static final int STATE_ANY_VISIBLE_TO_CLIENTS = -2;
/**
+ * Constant for matching any active print job state.
+ *
+ * @hide
+ */
+ public static final int STATE_ANY_ACTIVE = -3;
+
+ /**
* Print job state: The print job is being created but not yet
* ready to be printed.
* <p>
@@ -55,7 +62,7 @@ public final class PrintJobInfo implements Parcelable {
public static final int STATE_CREATED = 1;
/**
- * Print job status: The print jobs is created, it is ready
+ * Print job state: The print jobs is created, it is ready
* to be printed and should be processed.
* <p>
* Next valid states: {@link #STATE_STARTED}, {@link #STATE_FAILED},
@@ -65,40 +72,49 @@ public final class PrintJobInfo implements Parcelable {
public static final int STATE_QUEUED = 2;
/**
- * Print job status: The print job is being printed.
+ * Print job state: The print job is being printed.
* <p>
* Next valid states: {@link #STATE_COMPLETED}, {@link #STATE_FAILED},
- * {@link #STATE_CANCELED}
+ * {@link #STATE_CANCELED}, {@link #STATE_BLOCKED}
* </p>
*/
public static final int STATE_STARTED = 3;
/**
- * Print job status: The print job was successfully printed.
+ * Print job state: The print job is blocked.
+ * <p>
+ * Next valid states: {@link #STATE_FAILED}, {@link #STATE_CANCELED},
+ * {@link #STATE_STARTED}
+ * </p>
+ */
+ public static final int STATE_BLOCKED = 4;
+
+ /**
+ * Print job state: The print job was successfully printed.
* This is a terminal state.
* <p>
* Next valid states: None
* </p>
*/
- public static final int STATE_COMPLETED = 4;
+ public static final int STATE_COMPLETED = 5;
/**
- * Print job status: The print job was printing but printing failed.
+ * Print job state: The print job was printing but printing failed.
* This is a terminal state.
* <p>
* Next valid states: None
* </p>
*/
- public static final int STATE_FAILED = 5;
+ public static final int STATE_FAILED = 6;
/**
- * Print job status: The print job was canceled.
+ * Print job state: The print job was canceled.
* This is a terminal state.
* <p>
* Next valid states: None
* </p>
*/
- public static final int STATE_CANCELED = 6;
+ public static final int STATE_CANCELED = 7;
/** The unique print job id. */
private int mId;
@@ -127,8 +143,8 @@ public final class PrintJobInfo implements Parcelable {
/** How many copies to print. */
private int mCopies;
- /** Failure reason if this job failed. */
- private String mFailureReason;
+ /** Reason for the print job being in its current state. */
+ private String mStateReason;
/** The pages to print */
private PageRange[] mPageRanges;
@@ -155,7 +171,7 @@ public final class PrintJobInfo implements Parcelable {
mUserId = other.mUserId;
mTag = other.mTag;
mCopies = other.mCopies;
- mFailureReason = other.mFailureReason;
+ mStateReason = other.mStateReason;
mPageRanges = other.mPageRanges;
mAttributes = other.mAttributes;
mDocumentInfo = other.mDocumentInfo;
@@ -171,7 +187,7 @@ public final class PrintJobInfo implements Parcelable {
mUserId = parcel.readInt();
mTag = parcel.readString();
mCopies = parcel.readInt();
- mFailureReason = parcel.readString();
+ mStateReason = parcel.readString();
if (parcel.readInt() == 1) {
Parcelable[] parcelables = parcel.readParcelableArray(null);
mPageRanges = new PageRange[parcelables.length];
@@ -377,25 +393,27 @@ public final class PrintJobInfo implements Parcelable {
}
/**
- * The failure reason if this print job failed.
+ * Gets the reason for the print job being in the current state.
*
- * @return The failure reason.
+ * @return The reason, or null if there is no reason or the
+ * reason is unknown.
*
* @hide
*/
- public String getFailureReason() {
- return mFailureReason;
+ public String getStateReason() {
+ return mStateReason;
}
/**
- * The failure reason if this print job failed.
+ * Sets the reason for the print job being in the current state.
*
- * @param failureReason The failure reason.
+ * @param stateReason The reason, or null if there is no reason
+ * or the reason is unknown.
*
* @hide
*/
- public void setFailureReason(String failureReason) {
- mFailureReason = failureReason;
+ public void setStateReason(String stateReason) {
+ mStateReason = stateReason;
}
/**
@@ -476,7 +494,7 @@ public final class PrintJobInfo implements Parcelable {
parcel.writeInt(mUserId);
parcel.writeString(mTag);
parcel.writeInt(mCopies);
- parcel.writeString(mFailureReason);
+ parcel.writeString(mStateReason);
if (mPageRanges != null) {
parcel.writeInt(1);
parcel.writeParcelableArray(mPageRanges, flags);
diff --git a/core/java/android/print/PrintManager.java b/core/java/android/print/PrintManager.java
index d3e35c3..6e32c05 100644
--- a/core/java/android/print/PrintManager.java
+++ b/core/java/android/print/PrintManager.java
@@ -36,7 +36,6 @@ import com.android.internal.os.SomeArgs;
import libcore.io.IoUtils;
import java.io.File;
-import java.io.FileDescriptor;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
@@ -163,7 +162,7 @@ public final class PrintManager {
* @param pdfFile The PDF file to print.
* @param documentInfo Information about the printed document.
* @param attributes The default print job attributes.
- * @return The created print job.
+ * @return The created print job on success or null on failure.
*
* @see PrintJob
*/
@@ -181,7 +180,7 @@ public final class PrintManager {
* @param printJobName A name for the new print job.
* @param documentAdapter An adapter that emits the document to print.
* @param attributes The default print job attributes.
- * @return The created print job.
+ * @return The created print job on success or null on failure.
*
* @see PrintJob
*/
@@ -279,7 +278,7 @@ public final class PrintManager {
}
SomeArgs args = SomeArgs.obtain();
args.arg1 = pages;
- args.arg2 = fd.getFileDescriptor();
+ args.arg2 = fd;
args.arg3 = callback;
args.argi1 = sequence;
mHandler.removeMessages(MyHandler.MSG_WRITE);
@@ -342,7 +341,7 @@ public final class PrintManager {
case MSG_WRITE: {
SomeArgs args = (SomeArgs) message.obj;
PageRange[] pages = (PageRange[]) args.arg1;
- FileDescriptor fd = (FileDescriptor) args.arg2;
+ ParcelFileDescriptor fd = (ParcelFileDescriptor) args.arg2;
IWriteResultCallback callback = (IWriteResultCallback) args.arg3;
final int sequence = args.argi1;
args.recycle();
@@ -428,12 +427,12 @@ public final class PrintManager {
}
private final class MyWriteResultCallback extends WriteResultCallback {
- private FileDescriptor mFd;
+ private ParcelFileDescriptor mFd;
private int mSequence;
private IWriteResultCallback mCallback;
public MyWriteResultCallback(IWriteResultCallback callback,
- FileDescriptor fd, int sequence) {
+ ParcelFileDescriptor fd, int sequence) {
mFd = fd;
mSequence = sequence;
mCallback = callback;
diff --git a/core/java/android/print/PrinterDiscoverySession.java b/core/java/android/print/PrinterDiscoverySession.java
index 8fbdd9c..46f0bef 100644
--- a/core/java/android/print/PrinterDiscoverySession.java
+++ b/core/java/android/print/PrinterDiscoverySession.java
@@ -74,6 +74,7 @@ public final class PrinterDiscoverySession {
public final void startPrinterDisovery(List<PrinterId> priorityList) {
if (isDestroyed()) {
Log.w(LOG_TAG, "Ignoring start printers dsicovery - session destroyed");
+ return;
}
if (!mIsPrinterDiscoveryStarted) {
mIsPrinterDiscoveryStarted = true;
@@ -88,6 +89,7 @@ public final class PrinterDiscoverySession {
public final void stopPrinterDiscovery() {
if (isDestroyed()) {
Log.w(LOG_TAG, "Ignoring stop printers discovery - session destroyed");
+ return;
}
if (mIsPrinterDiscoveryStarted) {
mIsPrinterDiscoveryStarted = false;
@@ -99,14 +101,39 @@ public final class PrinterDiscoverySession {
}
}
- public final void requestPrinterUpdate(PrinterId printerId) {
+ public final void startPrinterStateTracking(PrinterId printerId) {
+ if (isDestroyed()) {
+ Log.w(LOG_TAG, "Ignoring start printer state tracking - session destroyed");
+ return;
+ }
+ try {
+ mPrintManager.startPrinterStateTracking(printerId, mUserId);
+ } catch (RemoteException re) {
+ Log.e(LOG_TAG, "Error starting printer state tracking", re);
+ }
+ }
+
+ public final void stopPrinterStateTracking(PrinterId printerId) {
if (isDestroyed()) {
- Log.w(LOG_TAG, "Ignoring reqeust printer update - session destroyed");
+ Log.w(LOG_TAG, "Ignoring stop printer state tracking - session destroyed");
+ return;
+ }
+ try {
+ mPrintManager.stopPrinterStateTracking(printerId, mUserId);
+ } catch (RemoteException re) {
+ Log.e(LOG_TAG, "Error stoping printer state tracking", re);
+ }
+ }
+
+ public final void validatePrinters(List<PrinterId> printerIds) {
+ if (isDestroyed()) {
+ Log.w(LOG_TAG, "Ignoring validate printers - session destroyed");
+ return;
}
try {
- mPrintManager.requestPrinterUpdate(printerId, mUserId);
+ mPrintManager.validatePrinters(printerIds, mUserId);
} catch (RemoteException re) {
- Log.e(LOG_TAG, "Error requesting printer update", re);
+ Log.e(LOG_TAG, "Error validating printers", re);
}
}
diff --git a/core/java/android/print/pdf/PrintedPdfDocument.java b/core/java/android/print/pdf/PrintedPdfDocument.java
index a3be38b..bee17ef 100644
--- a/core/java/android/print/pdf/PrintedPdfDocument.java
+++ b/core/java/android/print/pdf/PrintedPdfDocument.java
@@ -111,7 +111,10 @@ public final class PrintedPdfDocument {
* @see #finishPage(Page)
*/
public Page startPage(int pageNumber) {
- PageInfo pageInfo = new PageInfo.Builder(mPageSize, 0).create();
+ PageInfo pageInfo = new PageInfo
+ .Builder(mPageSize, 0)
+ .setContentSize(mContentSize)
+ .create();
Page page = mDocument.startPage(pageInfo);
return page;
}
diff --git a/core/java/android/printservice/IPrintService.aidl b/core/java/android/printservice/IPrintService.aidl
index 2cee1d8..ee36619 100644
--- a/core/java/android/printservice/IPrintService.aidl
+++ b/core/java/android/printservice/IPrintService.aidl
@@ -33,6 +33,8 @@ oneway interface IPrintService {
void createPrinterDiscoverySession();
void startPrinterDiscovery(in List<PrinterId> priorityList);
void stopPrinterDiscovery();
- void requestPrinterUpdate(in PrinterId printerId);
+ void validatePrinters(in List<PrinterId> printerIds);
+ void startPrinterStateTracking(in PrinterId printerId);
+ void stopPrinterStateTracking(in PrinterId printerId);
void destroyPrinterDiscoverySession();
}
diff --git a/core/java/android/printservice/PrintDocument.java b/core/java/android/printservice/PrintDocument.java
index 7437dc5..8292cfb 100644
--- a/core/java/android/printservice/PrintDocument.java
+++ b/core/java/android/printservice/PrintDocument.java
@@ -21,12 +21,15 @@ import android.os.RemoteException;
import android.print.PrintDocumentInfo;
import android.util.Log;
-import java.io.FileDescriptor;
import java.io.IOException;
/**
* This class represents a printed document from the perspective of a print
* service. It exposes APIs to query the document and obtain its data.
+ * <p>
+ * <strong>Note: </strong> All methods of this class must be executed on the
+ * main application thread.
+ * </p>
*/
public final class PrintDocument {
@@ -51,6 +54,7 @@ public final class PrintDocument {
* @return The document info.
*/
public PrintDocumentInfo getInfo() {
+ PrintService.throwIfNotCalledOnMainThread();
return mInfo;
}
@@ -64,7 +68,8 @@ public final class PrintDocument {
*
* @return A file descriptor for reading the data.
*/
- public FileDescriptor getData() {
+ public ParcelFileDescriptor getData() {
+ PrintService.throwIfNotCalledOnMainThread();
ParcelFileDescriptor source = null;
ParcelFileDescriptor sink = null;
try {
@@ -72,7 +77,7 @@ public final class PrintDocument {
source = fds[0];
sink = fds[1];
mPrintServiceClient.writePrintJobData(sink, mPrintJobId);
- return source.getFileDescriptor();
+ return source;
} catch (IOException ioe) {
Log.e(LOG_TAG, "Error calling getting print job data!", ioe);
} catch (RemoteException re) {
diff --git a/core/java/android/printservice/PrintJob.java b/core/java/android/printservice/PrintJob.java
index d2fbef2..8bae9d6 100644
--- a/core/java/android/printservice/PrintJob.java
+++ b/core/java/android/printservice/PrintJob.java
@@ -18,6 +18,7 @@ package android.printservice;
import android.os.RemoteException;
import android.print.PrintJobInfo;
+import android.text.TextUtils;
import android.util.Log;
/**
@@ -123,6 +124,21 @@ public final class PrintJob {
}
/**
+ * Gets whether this print job is blocked. Such a print job is halted
+ * due to an abnormal condition and can be started or canceled or failed.
+ *
+ * @return Whether the print job is blocked.
+ *
+ * @see #start()
+ * @see #cancel()
+ * @see #fail(CharSequence)
+ */
+ public boolean isBlocked() {
+ PrintService.throwIfNotCalledOnMainThread();
+ return getInfo().getState() == PrintJobInfo.STATE_BLOCKED;
+ }
+
+ /**
* Gets whether this print job is completed. Such a print job
* is successfully printed. This is a final state.
*
@@ -163,21 +179,49 @@ public final class PrintJob {
/**
* Starts the print job. You should call this method if {@link
- * #isQueued()} returns true and you started printing.
+ * #isQueued()} or {@link #isBlocked()} returns true and you started
+ * resumed printing.
*
- * @return Whether the job as started.
+ * @return Whether the job was started.
*
* @see #isQueued()
+ * @see #isBlocked()
*/
public boolean start() {
PrintService.throwIfNotCalledOnMainThread();
- if (isQueued()) {
+ final int state = getInfo().getState();
+ if (state == PrintJobInfo.STATE_QUEUED
+ || state == PrintJobInfo.STATE_BLOCKED) {
return setState(PrintJobInfo.STATE_STARTED, null);
}
return false;
}
/**
+ * Blocks the print job. You should call this method if {@link
+ * #isStarted()} or {@link #isBlocked()} returns true and you need
+ * to block the print job. For example, the user has to add some
+ * paper to continue printing. To resume the print job call {@link
+ * #start()}.
+ *
+ * @return Whether the job was blocked.
+ *
+ * @see #isStarted()
+ * @see #isBlocked()
+ */
+ public boolean block(String reason) {
+ PrintService.throwIfNotCalledOnMainThread();
+ PrintJobInfo info = getInfo();
+ final int state = info.getState();
+ if (state == PrintJobInfo.STATE_STARTED
+ || (state == PrintJobInfo.STATE_BLOCKED
+ && !TextUtils.equals(info.getStateReason(), reason))) {
+ return setState(PrintJobInfo.STATE_BLOCKED, reason);
+ }
+ return false;
+ }
+
+ /**
* Completes the print job. You should call this method if {@link
* #isStarted()} returns true and you are done printing.
*
@@ -195,8 +239,8 @@ public final class PrintJob {
/**
* Fails the print job. You should call this method if {@link
- * #isQueued()} or {@link #isStarted()} returns true you failed
- * while printing.
+ * #isQueued()} or {@link #isStarted()} or {@link #isBlocked()}
+ * returns true you failed while printing.
*
* @param error The human readable, short, and translated reason
* for the failure.
@@ -204,10 +248,11 @@ public final class PrintJob {
*
* @see #isQueued()
* @see #isStarted()
+ * @see #isBlocked()
*/
public boolean fail(String error) {
PrintService.throwIfNotCalledOnMainThread();
- if (isQueued() || isStarted()) {
+ if (!isInImmutableState()) {
return setState(PrintJobInfo.STATE_FAILED, error);
}
return false;
@@ -215,18 +260,19 @@ public final class PrintJob {
/**
* Cancels the print job. You should call this method if {@link
- * #isQueued()} or {@link #isStarted()} returns true and you canceled
- * the print job as a response to a call to {@link
- * PrintService#onRequestCancelPrintJob(PrintJob)}.
+ * #isQueued()} or {@link #isStarted() or #isBlocked()} returns
+ * true and you canceled the print job as a response to a call to
+ * {@link PrintService#onRequestCancelPrintJob(PrintJob)}.
*
* @return Whether the job is canceled.
*
* @see #isStarted()
* @see #isQueued()
+ * @see #isBlocked()
*/
public boolean cancel() {
PrintService.throwIfNotCalledOnMainThread();
- if (isQueued() || isStarted()) {
+ if (!isInImmutableState()) {
return setState(PrintJobInfo.STATE_CANCELED, null);
}
return false;
@@ -277,7 +323,8 @@ public final class PrintJob {
private boolean isInImmutableState() {
final int state = mCachedInfo.getState();
return state == PrintJobInfo.STATE_COMPLETED
- || state == PrintJobInfo.STATE_CANCELED;
+ || state == PrintJobInfo.STATE_CANCELED
+ || state == PrintJobInfo.STATE_FAILED;
}
private boolean setState(int state, String error) {
@@ -287,7 +334,7 @@ public final class PrintJob {
// we may not be able to re-fetch it later if the job gets
// removed from the spooler as a result of the state change.
mCachedInfo.setState(state);
- mCachedInfo.setFailureReason(error);
+ mCachedInfo.setStateReason(error);
return true;
}
} catch (RemoteException re) {
diff --git a/core/java/android/printservice/PrintService.java b/core/java/android/printservice/PrintService.java
index f6c0a9a..96552af 100644
--- a/core/java/android/printservice/PrintService.java
+++ b/core/java/android/printservice/PrintService.java
@@ -314,8 +314,20 @@ public abstract class PrintService extends Service {
}
@Override
- public void requestPrinterUpdate(PrinterId printerId) {
- mHandler.obtainMessage(ServiceHandler.MSG_REQUEST_PRINTER_UPDATE,
+ public void validatePrinters(List<PrinterId> printerIds) {
+ mHandler.obtainMessage(ServiceHandler.MSG_VALIDATE_PRINTERS,
+ printerIds).sendToTarget();
+ }
+
+ @Override
+ public void startPrinterStateTracking(PrinterId printerId) {
+ mHandler.obtainMessage(ServiceHandler.MSG_START_PRINTER_STATE_TRACKING,
+ printerId).sendToTarget();
+ }
+
+ @Override
+ public void stopPrinterStateTracking(PrinterId printerId) {
+ mHandler.obtainMessage(ServiceHandler.MSG_STOP_PRINTER_STATE_TRACKING,
printerId).sendToTarget();
}
@@ -344,10 +356,12 @@ public abstract class PrintService extends Service {
public static final int MSG_DESTROY_PRINTER_DISCOVERY_SESSION = 2;
public static final int MSG_START_PRINTER_DISCOVERY = 3;
public static final int MSG_STOP_PRINTER_DISCOVERY = 4;
- public static final int MSG_REQUEST_PRINTER_UPDATE = 5;
- public static final int MSG_ON_PRINTJOB_QUEUED = 6;
- public static final int MSG_ON_REQUEST_CANCEL_PRINTJOB = 7;
- public static final int MSG_SET_CLEINT = 8;
+ public static final int MSG_VALIDATE_PRINTERS = 5;
+ public static final int MSG_START_PRINTER_STATE_TRACKING = 6;
+ public static final int MSG_STOP_PRINTER_STATE_TRACKING = 7;
+ public static final int MSG_ON_PRINTJOB_QUEUED = 8;
+ public static final int MSG_ON_REQUEST_CANCEL_PRINTJOB = 9;
+ public static final int MSG_SET_CLEINT = 10;
public ServiceHandler(Looper looper) {
super(looper, null, true);
@@ -391,10 +405,24 @@ public abstract class PrintService extends Service {
}
} break;
- case MSG_REQUEST_PRINTER_UPDATE: {
+ case MSG_VALIDATE_PRINTERS: {
+ if (mDiscoverySession != null) {
+ List<PrinterId> printerIds = (List<PrinterId>) message.obj;
+ mDiscoverySession.validatePrinters(printerIds);
+ }
+ } break;
+
+ case MSG_START_PRINTER_STATE_TRACKING: {
+ if (mDiscoverySession != null) {
+ PrinterId printerId = (PrinterId) message.obj;
+ mDiscoverySession.startPrinterStateTracking(printerId);
+ }
+ } break;
+
+ case MSG_STOP_PRINTER_STATE_TRACKING: {
if (mDiscoverySession != null) {
PrinterId printerId = (PrinterId) message.obj;
- mDiscoverySession.requestPrinterUpdate(printerId);
+ mDiscoverySession.stopPrinterStateTracking(printerId);
}
} break;
diff --git a/core/java/android/printservice/PrinterDiscoverySession.java b/core/java/android/printservice/PrinterDiscoverySession.java
index 8b959a6..1f86ecc 100644
--- a/core/java/android/printservice/PrinterDiscoverySession.java
+++ b/core/java/android/printservice/PrinterDiscoverySession.java
@@ -53,15 +53,23 @@ import java.util.List;
* session. Printers are <strong>not</strong> persisted across sessions.
* </p>
* <p>
- * The system will make a call to
- * {@link PrinterDiscoverySession#onRequestPrinterUpdate(PrinterId)} if you
- * need to update a given printer. It is possible that you add a printer without
+ * The system will make a call to {@link #onValidatePrinters(List)} if you
+ * need to update some printers. It is possible that you add a printer without
* specifying its capabilities. This enables you to avoid querying all discovered
* printers for their capabilities, rather querying the capabilities of a printer
* only if necessary. For example, the system will request that you update a printer
- * if it gets selected by the user. If you did not report the printer capabilities
- * when adding it, you must do so after the system requests a printer update.
- * Otherwise, the printer will be ignored.
+ * if it gets selected by the user. When validating printers you do not need to
+ * provide the printers' capabilities but may do so.
+ * </p>
+ * <p>
+ * If the system is interested in being constantly updated for the state of a
+ * printer you will receive a call to {@link #onStartPrinterStateTracking(PrinterId)}
+ * after which you will have to do a best effort to keep the system updated for
+ * changes in the printer state and capabilities. You also <strong>must</strong>
+ * update the printer capabilities if you did not provide them when adding it, or
+ * the printer will be ignored. When the system is no longer interested in getting
+ * updates for a printer you will receive a call to {@link #onStopPrinterStateTracking(
+ * PrinterId)}.
* </p>
* <p>
* <strong>Note: </strong> All callbacks in this class are executed on the main
@@ -115,7 +123,7 @@ public abstract class PrinterDiscoverySession {
* the printer that was added but not removed.
* <p>
* <strong>Note: </strong> Calls to this method after the session is
- * destroyed, i.e. after the {@link #onDestroy()} callback, will be ignored.
+ * destroyed, that is after the {@link #onDestroy()} callback, will be ignored.
* </p>
*
* @return The printers.
@@ -139,7 +147,7 @@ public abstract class PrinterDiscoverySession {
* times during the life of this session. Duplicates will be ignored.
* <p>
* <strong>Note: </strong> Calls to this method after the session is
- * destroyed, i.e. after the {@link #onDestroy()} callback, will be ignored.
+ * destroyed, that is after the {@link #onDestroy()} callback, will be ignored.
* </p>
*
* @param printers The printers to add.
@@ -218,7 +226,7 @@ public abstract class PrinterDiscoverySession {
* call this method multiple times during the lifetime of this session.
* <p>
* <strong>Note: </strong> Calls to this method after the session is
- * destroyed, i.e. after the {@link #onDestroy()} callback, will be ignored.
+ * destroyed, that is after the {@link #onDestroy()} callback, will be ignored.
* </p>
*
* @param printerIds The ids of the removed printers.
@@ -293,7 +301,7 @@ public abstract class PrinterDiscoverySession {
* during the lifetime of this session.
* <p>
* <strong>Note: </strong> Calls to this method after the session is
- * destroyed, i.e. after the {@link #onDestroy()} callback, will be ignored.
+ * destroyed, that is after the {@link #onDestroy()} callback, will be ignored.
* </p>
*
* @param printers The printers to update.
@@ -441,7 +449,9 @@ public abstract class PrinterDiscoverySession {
* <p>
* <strong>Note: </strong>You are also given a list of printers whose availability
* has to be checked first. For example, these printers could be the user's favorite
- * ones, therefore they have to be verified first.
+ * ones, therefore they have to be verified first. You do <strong>not need</strong>
+ * to provide the capabilities of the printers, rather verify whether they exist
+ * similarly to {@link #onValidatePrinters(List)}.
* </p>
*
* @param priorityList The list of printers to validate first. Never null.
@@ -463,9 +473,28 @@ public abstract class PrinterDiscoverySession {
public abstract void onStopPrinterDiscovery();
/**
- * Requests that you update a printer. You are responsible for updating
- * the printer by also reporting its capabilities via calling {@link
- * #updatePrinters(List)}.
+ * Callback asking you to validate that the given printers are valid, that
+ * is they exist. You are responsible for checking whether these printers
+ * exist and for the ones that do exist notify the system via calling
+ * {@link #updatePrinters(List)}.
+ * <p>
+ * <strong>Note: </strong> You are <strong>not required</strong> to provide
+ * the printer capabilities when updating the printers that do exist.
+ * <p>
+ *
+ * @param printerIds The printers to validate.
+ *
+ * @see #updatePrinters(List)
+ * @see PrinterInfo.Builder#setCapabilities(PrinterCapabilitiesInfo)
+ * PrinterInfo.Builder.setCapabilities(PrinterCapabilitiesInfo)
+ */
+ public abstract void onValidatePrinters(List<PrinterId> printerIds);
+
+ /**
+ * Callback asking you to start tracking the state of a printer. Tracking
+ * the state means that you should do a best effort to observe the state
+ * of this printer and notify the system if that state changes via calling
+ * {@link #updatePrinters(List)}.
* <p>
* <strong>Note: </strong> A printer can be initially added without its
* capabilities to avoid polling printers that the user will not select.
@@ -473,18 +502,33 @@ public abstract class PrinterDiscoverySession {
* printer <strong>including</strong> its capabilities. Otherwise, the
* printer will be ignored.
* <p>
- * A scenario when you may be requested to update a printer is if the user
- * selects it and the system has to present print options UI based on the
- * printer's capabilities.
+ * <p>
+ * A scenario when you may be requested to track a printer's state is if
+ * the user selects that printer and the system has to present print
+ * options UI based on the printer's capabilities. In this case the user
+ * should be promptly informed if, for example, the printer becomes
+ * unavailable.
* </p>
*
- * @param printerId The printer id.
+ * @param printerId The printer to start tracking.
*
+ * @see #onStopPrinterStateTracking(PrinterId)
* @see #updatePrinters(List)
* @see PrinterInfo.Builder#setCapabilities(PrinterCapabilitiesInfo)
* PrinterInfo.Builder.setCapabilities(PrinterCapabilitiesInfo)
*/
- public abstract void onRequestPrinterUpdate(PrinterId printerId);
+ public abstract void onStartPrinterStateTracking(PrinterId printerId);
+
+ /**
+ * Callback asking you to stop tracking the state of a printer. The passed
+ * in printer id is the one for which you received a call to {@link
+ * #onStartPrinterStateTracking(PrinterId)}.
+ *
+ * @param printerId The printer to stop tracking.
+ *
+ * @see #onStartPrinterStateTracking(PrinterId)
+ */
+ public abstract void onStopPrinterStateTracking(PrinterId printerId);
/**
* Notifies you that the session is destroyed. After this callback is invoked
@@ -538,9 +582,21 @@ public abstract class PrinterDiscoverySession {
}
}
- void requestPrinterUpdate(PrinterId printerId) {
- if (!mIsDestroyed) {
- onRequestPrinterUpdate(printerId);
+ void validatePrinters(List<PrinterId> printerIds) {
+ if (!mIsDestroyed && mObserver != null) {
+ onValidatePrinters(printerIds);
+ }
+ }
+
+ void startPrinterStateTracking(PrinterId printerId) {
+ if (!mIsDestroyed && mObserver != null) {
+ onStartPrinterStateTracking(printerId);
+ }
+ }
+
+ void stopPrinterStateTracking(PrinterId printerId) {
+ if (!mIsDestroyed && mObserver != null) {
+ onStopPrinterStateTracking(printerId);
}
}
diff --git a/core/java/android/provider/AlarmClock.java b/core/java/android/provider/AlarmClock.java
index 5e56e934..724d76d 100644
--- a/core/java/android/provider/AlarmClock.java
+++ b/core/java/android/provider/AlarmClock.java
@@ -90,6 +90,15 @@ public final class AlarmClock {
public static final String ACTION_SET_TIMER = "android.intent.action.SET_TIMER";
/**
+ * Activity Action: Show the alarms.
+ * <p>
+ * This action opens the alarms page.
+ * </p>
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_SHOW_ALARMS = "android.intent.action.SHOW_ALARMS";
+
+ /**
* Bundle extra: Weekdays for repeating alarm.
* <p>
* Used by {@link #ACTION_SET_ALARM}.
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 24dbf0e..802bedf 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -4285,12 +4285,6 @@ public final class Settings {
public static final String NFC_PAYMENT_DEFAULT_COMPONENT = "nfc_payment_default_component";
/**
- * Whether to automatically invoke NFC payment app or manually select on tap.
- * @hide
- */
- public static final String NFC_PAYMENT_MODE = "nfc_payment_mode";
-
- /**
* Name of a package that the current user has explicitly allowed to see all of that
* user's notifications.
*
diff --git a/core/java/android/util/LayoutDirection.java b/core/java/android/util/LayoutDirection.java
index e37d2f2..20af20b 100644
--- a/core/java/android/util/LayoutDirection.java
+++ b/core/java/android/util/LayoutDirection.java
@@ -17,11 +17,15 @@
package android.util;
/**
- * An interface for defining layout directions. A layout direction can be left-to-right (LTR)
+ * A class for defining layout directions. A layout direction can be left-to-right (LTR)
* or right-to-left (RTL). It can also be inherited (from a parent) or deduced from the default
* language script of a locale.
*/
-public interface LayoutDirection {
+public final class LayoutDirection {
+
+ // No instantiation
+ private LayoutDirection() {}
+
/**
* Horizontal layout direction is from Left to Right.
*/
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 1b57d50..eded438 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -31,7 +31,9 @@ import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.Looper;
import android.os.Message;
+import android.os.ParcelFileDescriptor;
import android.os.StrictMode;
+import android.print.PrintAttributes;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
@@ -49,7 +51,6 @@ import android.widget.AbsoluteLayout;
import java.io.BufferedWriter;
import java.io.File;
-import java.io.OutputStream;
import java.util.Map;
/**
@@ -498,6 +499,8 @@ public class WebView extends AbsoluteLayout
ensureProviderCreated();
mProvider.init(javaScriptInterfaces, privateBrowsing);
+ // Post condition of creating a webview is the CookieSyncManager instance exists.
+ CookieSyncManager.createInstance(getContext());
}
/**
@@ -1040,7 +1043,9 @@ public class WebView extends AbsoluteLayout
* Exports the contents of this Webview as PDF. Only supported for API levels
* {@link android.os.Build.VERSION_CODES#KEY_LIME_PIE} and above.
*
- * @param out The stream to export the PDF contents to. Cannot be null.
+ * TODO(sgurun) the parameter list is stale. Fix it before unhiding.
+ *
+ * @param fd The FileDescriptor to export the PDF contents to. Cannot be null.
* @param width The page width. Should be larger than 0.
* @param height The page height. Should be larger than 0.
* @param resultCallback A callback to be invoked when the PDF content is exported.
@@ -1049,21 +1054,26 @@ public class WebView extends AbsoluteLayout
* be null.
*
* The PDF conversion is done asynchronously and the PDF output is written to the provided
- * outputstream. The caller should not close the outputstream until the resultCallback is
- * called, indicating PDF conversion is complete. Webview cannot be drawn during the pdf
- * export so the application is recommended to take it offscreen, or putting in a layer
- * with an overlaid progress UI / spinner.
+ * file descriptor. The caller should not close the file descriptor until the resultCallback
+ * is called, indicating PDF conversion is complete. Webview will never close the file
+ * descriptor.
+ * Limitations: Webview cannot be drawn during the PDF export so the application is
+ * recommended to take it offscreen, or putting in a layer with an overlaid progress
+ * UI / spinner.
*
* If the caller cancels the task using the cancellationSignal, the cancellation will be
* acked using the resultCallback signal.
*
+ * Throws an exception if an IO error occurs accessing the file descriptor.
+ *
* TODO(sgurun) margins, explain the units, make it public.
* @hide
*/
- public void exportToPdf(OutputStream out, int width, int height,
- ValueCallback<Boolean> resultCallback, CancellationSignal cancellationSignal) {
+ public void exportToPdf(ParcelFileDescriptor fd, PrintAttributes attributes,
+ ValueCallback<Boolean> resultCallback, CancellationSignal cancellationSignal)
+ throws java.io.IOException {
checkThread();
- mProvider.exportToPdf(out, width, height, resultCallback, cancellationSignal);
+ mProvider.exportToPdf(fd, attributes, resultCallback, cancellationSignal);
}
/**
diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java
index db98d30..b1a7878 100644
--- a/core/java/android/webkit/WebViewClassic.java
+++ b/core/java/android/webkit/WebViewClassic.java
@@ -62,6 +62,7 @@ import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;
+import android.print.PrintAttributes;
import android.security.KeyChain;
import android.text.Editable;
import android.text.InputType;
@@ -2896,11 +2897,11 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
* See {@link WebView#exportToPdf()}
*/
@Override
- public void exportToPdf(java.io.OutputStream out, int width, int height,
- ValueCallback<Boolean> resultCallback, CancellationSignal cancellationSignal) {
+ public void exportToPdf(android.os.ParcelFileDescriptor fd, PrintAttributes attributes,
+ ValueCallback<Boolean> resultCallback, CancellationSignal cancellationSignal)
+ throws java.io.IOException {
// K-only API not implemented in WebViewClassic.
throw new IllegalStateException("This API not supported on Android 4.3 and earlier");
-
}
/**
diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java
index 8fe6edf..d625d8a 100644
--- a/core/java/android/webkit/WebViewProvider.java
+++ b/core/java/android/webkit/WebViewProvider.java
@@ -27,6 +27,8 @@ import android.net.http.SslCertificate;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.Message;
+import android.os.ParcelFileDescriptor;
+import android.print.PrintAttributes;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
@@ -41,7 +43,6 @@ import android.webkit.WebView.PictureListener;
import java.io.BufferedWriter;
import java.io.File;
-import java.io.OutputStream;
import java.util.Map;
/**
@@ -148,8 +149,9 @@ public interface WebViewProvider {
public Picture capturePicture();
- public void exportToPdf(OutputStream out, int width, int height,
- ValueCallback<Boolean> resultCallback, CancellationSignal cancellationSignal);
+ public void exportToPdf(ParcelFileDescriptor fd, PrintAttributes attributes,
+ ValueCallback<Boolean> resultCallback, CancellationSignal cancellationSignal)
+ throws java.io.IOException;
public float getScale();
diff --git a/core/java/android/widget/GridLayout.java b/core/java/android/widget/GridLayout.java
index 109fcfe..54cc3f4 100644
--- a/core/java/android/widget/GridLayout.java
+++ b/core/java/android/widget/GridLayout.java
@@ -251,14 +251,14 @@ public class GridLayout extends ViewGroup {
// Instance variables
- final Axis horizontalAxis = new Axis(true);
- final Axis verticalAxis = new Axis(false);
- int orientation = DEFAULT_ORIENTATION;
- boolean useDefaultMargins = DEFAULT_USE_DEFAULT_MARGINS;
- int alignmentMode = DEFAULT_ALIGNMENT_MODE;
- int defaultGap;
- int lastLayoutParamsHashCode = UNINITIALIZED_HASH;
- Printer printer = LOG_PRINTER;
+ final Axis mHorizontalAxis = new Axis(true);
+ final Axis mVerticalAxis = new Axis(false);
+ int mOrientation = DEFAULT_ORIENTATION;
+ boolean mUseDefaultMargins = DEFAULT_USE_DEFAULT_MARGINS;
+ int mAlignmentMode = DEFAULT_ALIGNMENT_MODE;
+ int mDefaultGap;
+ int mLastLayoutParamsHashCode = UNINITIALIZED_HASH;
+ Printer mPrinter = LOG_PRINTER;
// Constructors
@@ -267,7 +267,7 @@ public class GridLayout extends ViewGroup {
*/
public GridLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
- defaultGap = context.getResources().getDimensionPixelOffset(R.dimen.default_gap);
+ mDefaultGap = context.getResources().getDimensionPixelOffset(R.dimen.default_gap);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.GridLayout);
try {
setRowCount(a.getInt(ROW_COUNT, DEFAULT_COUNT));
@@ -309,7 +309,7 @@ public class GridLayout extends ViewGroup {
* @attr ref android.R.styleable#GridLayout_orientation
*/
public int getOrientation() {
- return orientation;
+ return mOrientation;
}
/**
@@ -349,8 +349,8 @@ public class GridLayout extends ViewGroup {
* @attr ref android.R.styleable#GridLayout_orientation
*/
public void setOrientation(int orientation) {
- if (this.orientation != orientation) {
- this.orientation = orientation;
+ if (this.mOrientation != orientation) {
+ this.mOrientation = orientation;
invalidateStructure();
requestLayout();
}
@@ -369,7 +369,7 @@ public class GridLayout extends ViewGroup {
* @attr ref android.R.styleable#GridLayout_rowCount
*/
public int getRowCount() {
- return verticalAxis.getCount();
+ return mVerticalAxis.getCount();
}
/**
@@ -384,7 +384,7 @@ public class GridLayout extends ViewGroup {
* @attr ref android.R.styleable#GridLayout_rowCount
*/
public void setRowCount(int rowCount) {
- verticalAxis.setCount(rowCount);
+ mVerticalAxis.setCount(rowCount);
invalidateStructure();
requestLayout();
}
@@ -402,7 +402,7 @@ public class GridLayout extends ViewGroup {
* @attr ref android.R.styleable#GridLayout_columnCount
*/
public int getColumnCount() {
- return horizontalAxis.getCount();
+ return mHorizontalAxis.getCount();
}
/**
@@ -417,7 +417,7 @@ public class GridLayout extends ViewGroup {
* @attr ref android.R.styleable#GridLayout_columnCount
*/
public void setColumnCount(int columnCount) {
- horizontalAxis.setCount(columnCount);
+ mHorizontalAxis.setCount(columnCount);
invalidateStructure();
requestLayout();
}
@@ -433,7 +433,7 @@ public class GridLayout extends ViewGroup {
* @attr ref android.R.styleable#GridLayout_useDefaultMargins
*/
public boolean getUseDefaultMargins() {
- return useDefaultMargins;
+ return mUseDefaultMargins;
}
/**
@@ -463,7 +463,7 @@ public class GridLayout extends ViewGroup {
* @attr ref android.R.styleable#GridLayout_useDefaultMargins
*/
public void setUseDefaultMargins(boolean useDefaultMargins) {
- this.useDefaultMargins = useDefaultMargins;
+ this.mUseDefaultMargins = useDefaultMargins;
requestLayout();
}
@@ -480,7 +480,7 @@ public class GridLayout extends ViewGroup {
* @attr ref android.R.styleable#GridLayout_alignmentMode
*/
public int getAlignmentMode() {
- return alignmentMode;
+ return mAlignmentMode;
}
/**
@@ -499,7 +499,7 @@ public class GridLayout extends ViewGroup {
* @attr ref android.R.styleable#GridLayout_alignmentMode
*/
public void setAlignmentMode(int alignmentMode) {
- this.alignmentMode = alignmentMode;
+ this.mAlignmentMode = alignmentMode;
requestLayout();
}
@@ -514,7 +514,7 @@ public class GridLayout extends ViewGroup {
* @attr ref android.R.styleable#GridLayout_rowOrderPreserved
*/
public boolean isRowOrderPreserved() {
- return verticalAxis.isOrderPreserved();
+ return mVerticalAxis.isOrderPreserved();
}
/**
@@ -534,7 +534,7 @@ public class GridLayout extends ViewGroup {
* @attr ref android.R.styleable#GridLayout_rowOrderPreserved
*/
public void setRowOrderPreserved(boolean rowOrderPreserved) {
- verticalAxis.setOrderPreserved(rowOrderPreserved);
+ mVerticalAxis.setOrderPreserved(rowOrderPreserved);
invalidateStructure();
requestLayout();
}
@@ -550,7 +550,7 @@ public class GridLayout extends ViewGroup {
* @attr ref android.R.styleable#GridLayout_columnOrderPreserved
*/
public boolean isColumnOrderPreserved() {
- return horizontalAxis.isOrderPreserved();
+ return mHorizontalAxis.isOrderPreserved();
}
/**
@@ -570,7 +570,7 @@ public class GridLayout extends ViewGroup {
* @attr ref android.R.styleable#GridLayout_columnOrderPreserved
*/
public void setColumnOrderPreserved(boolean columnOrderPreserved) {
- horizontalAxis.setOrderPreserved(columnOrderPreserved);
+ mHorizontalAxis.setOrderPreserved(columnOrderPreserved);
invalidateStructure();
requestLayout();
}
@@ -581,9 +581,11 @@ public class GridLayout extends ViewGroup {
* @see #setPrinter(android.util.Printer)
*
* @return the printer associated with this view
+ *
+ * @hide
*/
public Printer getPrinter() {
- return printer;
+ return mPrinter;
}
/**
@@ -593,9 +595,11 @@ public class GridLayout extends ViewGroup {
* @param printer the printer associated with this layout
*
* @see #getPrinter()
+ *
+ * @hide
*/
public void setPrinter(Printer printer) {
- this.printer = (printer == null) ? NO_PRINTER : printer;
+ this.mPrinter = (printer == null) ? NO_PRINTER : printer;
}
// Static utility methods
@@ -643,7 +647,7 @@ public class GridLayout extends ViewGroup {
if (c.getClass() == Space.class) {
return 0;
}
- return defaultGap / 2;
+ return mDefaultGap / 2;
}
private int getDefaultMargin(View c, boolean isAtEdge, boolean horizontal, boolean leading) {
@@ -651,11 +655,11 @@ public class GridLayout extends ViewGroup {
}
private int getDefaultMargin(View c, LayoutParams p, boolean horizontal, boolean leading) {
- if (!useDefaultMargins) {
+ if (!mUseDefaultMargins) {
return 0;
}
Spec spec = horizontal ? p.columnSpec : p.rowSpec;
- Axis axis = horizontal ? horizontalAxis : verticalAxis;
+ Axis axis = horizontal ? mHorizontalAxis : mVerticalAxis;
Interval span = spec.span;
boolean leading1 = (horizontal && isLayoutRtl()) ? !leading : leading;
boolean isAtEdge = leading1 ? (span.min == 0) : (span.max == axis.getCount());
@@ -672,10 +676,10 @@ public class GridLayout extends ViewGroup {
}
private int getMargin(View view, boolean horizontal, boolean leading) {
- if (alignmentMode == ALIGN_MARGINS) {
+ if (mAlignmentMode == ALIGN_MARGINS) {
return getMargin1(view, horizontal, leading);
} else {
- Axis axis = horizontal ? horizontalAxis : verticalAxis;
+ Axis axis = horizontal ? mHorizontalAxis : mVerticalAxis;
int[] margins = leading ? axis.getLeadingMargins() : axis.getTrailingMargins();
LayoutParams lp = getLayoutParams(view);
Spec spec = horizontal ? lp.columnSpec : lp.rowSpec;
@@ -722,8 +726,8 @@ public class GridLayout extends ViewGroup {
// install default indices for cells that don't define them
private void validateLayoutParams() {
- final boolean horizontal = (orientation == HORIZONTAL);
- final Axis axis = horizontal ? horizontalAxis : verticalAxis;
+ final boolean horizontal = (mOrientation == HORIZONTAL);
+ final Axis axis = horizontal ? mHorizontalAxis : mVerticalAxis;
final int count = (axis.definedCount != UNDEFINED) ? axis.definedCount : 0;
int major = 0;
@@ -779,9 +783,9 @@ public class GridLayout extends ViewGroup {
}
private void invalidateStructure() {
- lastLayoutParamsHashCode = UNINITIALIZED_HASH;
- horizontalAxis.invalidateStructure();
- verticalAxis.invalidateStructure();
+ mLastLayoutParamsHashCode = UNINITIALIZED_HASH;
+ mHorizontalAxis.invalidateStructure();
+ mVerticalAxis.invalidateStructure();
// This can end up being done twice. Better twice than not at all.
invalidateValues();
}
@@ -789,9 +793,9 @@ public class GridLayout extends ViewGroup {
private void invalidateValues() {
// Need null check because requestLayout() is called in View's initializer,
// before we are set up.
- if (horizontalAxis != null && verticalAxis != null) {
- horizontalAxis.invalidateValues();
- verticalAxis.invalidateValues();
+ if (mHorizontalAxis != null && mVerticalAxis != null) {
+ mHorizontalAxis.invalidateValues();
+ mVerticalAxis.invalidateValues();
}
}
@@ -822,7 +826,7 @@ public class GridLayout extends ViewGroup {
if (span.min != UNDEFINED && span.min < 0) {
handleInvalidParams(groupName + " indices must be positive");
}
- Axis axis = horizontal ? horizontalAxis : verticalAxis;
+ Axis axis = horizontal ? mHorizontalAxis : mVerticalAxis;
int count = axis.definedCount;
if (count != UNDEFINED) {
if (span.max > count) {
@@ -908,7 +912,7 @@ public class GridLayout extends ViewGroup {
int right = getWidth() - getPaddingRight() - insets.right;
int bottom = getHeight() - getPaddingBottom() - insets.bottom;
- int[] xs = horizontalAxis.locations;
+ int[] xs = mHorizontalAxis.locations;
if (xs != null) {
for (int i = 0, length = xs.length; i < length; i++) {
int x = left + xs[i];
@@ -916,7 +920,7 @@ public class GridLayout extends ViewGroup {
}
}
- int[] ys = verticalAxis.locations;
+ int[] ys = mVerticalAxis.locations;
if (ys != null) {
for (int i = 0, length = ys.length; i < length; i++) {
int y = top + ys[i];
@@ -973,11 +977,11 @@ public class GridLayout extends ViewGroup {
}
private void consistencyCheck() {
- if (lastLayoutParamsHashCode == UNINITIALIZED_HASH) {
+ if (mLastLayoutParamsHashCode == UNINITIALIZED_HASH) {
validateLayoutParams();
- lastLayoutParamsHashCode = computeLayoutParamsHashCode();
- } else if (lastLayoutParamsHashCode != computeLayoutParamsHashCode()) {
- printer.println("The fields of some layout parameters were modified in between "
+ mLastLayoutParamsHashCode = computeLayoutParamsHashCode();
+ } else if (mLastLayoutParamsHashCode != computeLayoutParamsHashCode()) {
+ mPrinter.println("The fields of some layout parameters were modified in between "
+ "layout operations. Check the javadoc for GridLayout.LayoutParams#rowSpec.");
invalidateStructure();
consistencyCheck();
@@ -1005,11 +1009,11 @@ public class GridLayout extends ViewGroup {
if (firstPass) {
measureChildWithMargins2(c, widthSpec, heightSpec, lp.width, lp.height);
} else {
- boolean horizontal = (orientation == HORIZONTAL);
+ boolean horizontal = (mOrientation == HORIZONTAL);
Spec spec = horizontal ? lp.columnSpec : lp.rowSpec;
if (spec.alignment == FILL) {
Interval span = spec.span;
- Axis axis = horizontal ? horizontalAxis : verticalAxis;
+ Axis axis = horizontal ? mHorizontalAxis : mVerticalAxis;
int[] locations = axis.getLocations();
int cellSize = locations[span.max] - locations[span.min];
int viewSize = cellSize - getTotalMargin(c, horizontal);
@@ -1048,14 +1052,14 @@ public class GridLayout extends ViewGroup {
int heightSansPadding;
// Use the orientation property to decide which axis should be laid out first.
- if (orientation == HORIZONTAL) {
- widthSansPadding = horizontalAxis.getMeasure(widthSpecSansPadding);
+ if (mOrientation == HORIZONTAL) {
+ widthSansPadding = mHorizontalAxis.getMeasure(widthSpecSansPadding);
measureChildrenWithMargins(widthSpecSansPadding, heightSpecSansPadding, false);
- heightSansPadding = verticalAxis.getMeasure(heightSpecSansPadding);
+ heightSansPadding = mVerticalAxis.getMeasure(heightSpecSansPadding);
} else {
- heightSansPadding = verticalAxis.getMeasure(heightSpecSansPadding);
+ heightSansPadding = mVerticalAxis.getMeasure(heightSpecSansPadding);
measureChildrenWithMargins(widthSpecSansPadding, heightSpecSansPadding, false);
- widthSansPadding = horizontalAxis.getMeasure(widthSpecSansPadding);
+ widthSansPadding = mHorizontalAxis.getMeasure(widthSpecSansPadding);
}
int measuredWidth = Math.max(widthSansPadding + hPadding, getSuggestedMinimumWidth());
@@ -1114,11 +1118,11 @@ public class GridLayout extends ViewGroup {
int paddingRight = getPaddingRight();
int paddingBottom = getPaddingBottom();
- horizontalAxis.layout(targetWidth - paddingLeft - paddingRight);
- verticalAxis.layout(targetHeight - paddingTop - paddingBottom);
+ mHorizontalAxis.layout(targetWidth - paddingLeft - paddingRight);
+ mVerticalAxis.layout(targetHeight - paddingTop - paddingBottom);
- int[] hLocations = horizontalAxis.getLocations();
- int[] vLocations = verticalAxis.getLocations();
+ int[] hLocations = mHorizontalAxis.getLocations();
+ int[] vLocations = mVerticalAxis.getLocations();
for (int i = 0, N = getChildCount(); i < N; i++) {
View c = getChildAt(i);
@@ -1145,8 +1149,8 @@ public class GridLayout extends ViewGroup {
Alignment hAlign = getAlignment(columnSpec.alignment, true);
Alignment vAlign = getAlignment(rowSpec.alignment, false);
- Bounds boundsX = horizontalAxis.getGroupBounds().getValue(i);
- Bounds boundsY = verticalAxis.getGroupBounds().getValue(i);
+ Bounds boundsX = mHorizontalAxis.getGroupBounds().getValue(i);
+ Bounds boundsY = mVerticalAxis.getGroupBounds().getValue(i);
// Gravity offsets: the location of the alignment group relative to its cell group.
int gravityOffsetX = hAlign.getGravityOffset(c, cellWidth - boundsX.size(true));
@@ -1571,7 +1575,7 @@ public class GridLayout extends ViewGroup {
removed.add(arc);
}
}
- printer.println(axisName + " constraints: " + arcsToString(culprits) +
+ mPrinter.println(axisName + " constraints: " + arcsToString(culprits) +
" are inconsistent; permanently removing: " + arcsToString(removed) + ". ");
}
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index aa94728..ab81a37 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -22,11 +22,13 @@ import com.android.internal.content.PackageMonitor;
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
+import android.app.AppGlobals;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
+import android.content.pm.IPackageManager;
import android.content.pm.LabeledIntent;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
@@ -45,7 +47,6 @@ import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.Button;
-import android.widget.GridView;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
@@ -71,13 +72,13 @@ public class ResolverActivity extends AlertActivity implements AdapterView.OnIte
private PackageManager mPm;
private boolean mAlwaysUseOption;
private boolean mShowExtended;
- private GridView mGrid;
+ private ListView mListView;
private Button mAlwaysButton;
private Button mOnceButton;
private int mIconDpi;
private int mIconSize;
private int mMaxColumns;
- private int mLastSelected = GridView.INVALID_POSITION;
+ private int mLastSelected = ListView.INVALID_POSITION;
private boolean mRegistered;
private final PackageMonitor mPackageMonitor = new PackageMonitor() {
@@ -139,17 +140,15 @@ public class ResolverActivity extends AlertActivity implements AdapterView.OnIte
finish();
return;
} else if (count > 1) {
- ap.mView = getLayoutInflater().inflate(R.layout.resolver_grid, null);
- mGrid = (GridView) ap.mView.findViewById(R.id.resolver_grid);
- mGrid.setAdapter(mAdapter);
- mGrid.setOnItemClickListener(this);
- mGrid.setOnItemLongClickListener(new ItemLongClickListener());
+ ap.mView = getLayoutInflater().inflate(R.layout.resolver_list, null);
+ mListView = (ListView) ap.mView.findViewById(R.id.resolver_list);
+ mListView.setAdapter(mAdapter);
+ mListView.setOnItemClickListener(this);
+ mListView.setOnItemLongClickListener(new ItemLongClickListener());
if (alwaysUseOption) {
- mGrid.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
+ mListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
}
-
- resizeGrid();
} else if (count == 1) {
startActivity(mAdapter.intentForPosition(0));
mPackageMonitor.unregister();
@@ -172,11 +171,11 @@ public class ResolverActivity extends AlertActivity implements AdapterView.OnIte
mAlwaysUseOption = false;
}
}
- }
-
- void resizeGrid() {
- final int itemCount = mAdapter.getCount();
- mGrid.setNumColumns(Math.min(itemCount, mMaxColumns));
+ final int initialHighlight = mAdapter.getInitialHighlight();
+ if (initialHighlight >= 0) {
+ mListView.setItemChecked(initialHighlight, true);
+ onItemClick(null, null, initialHighlight, 0); // Other entries are not used
+ }
}
Drawable getIcon(Resources res, int resId) {
@@ -247,26 +246,26 @@ public class ResolverActivity extends AlertActivity implements AdapterView.OnIte
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
if (mAlwaysUseOption) {
- final int checkedPos = mGrid.getCheckedItemPosition();
- final boolean enabled = checkedPos != GridView.INVALID_POSITION;
+ final int checkedPos = mListView.getCheckedItemPosition();
+ final boolean enabled = checkedPos != ListView.INVALID_POSITION;
mLastSelected = checkedPos;
mAlwaysButton.setEnabled(enabled);
mOnceButton.setEnabled(enabled);
if (enabled) {
- mGrid.setSelection(checkedPos);
+ mListView.setSelection(checkedPos);
}
}
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- final int checkedPos = mGrid.getCheckedItemPosition();
- final boolean hasValidSelection = checkedPos != GridView.INVALID_POSITION;
+ final int checkedPos = mListView.getCheckedItemPosition();
+ final boolean hasValidSelection = checkedPos != ListView.INVALID_POSITION;
if (mAlwaysUseOption && (!hasValidSelection || mLastSelected != checkedPos)) {
mAlwaysButton.setEnabled(hasValidSelection);
mOnceButton.setEnabled(hasValidSelection);
if (hasValidSelection) {
- mGrid.smoothScrollToPosition(checkedPos);
+ mListView.smoothScrollToPosition(checkedPos);
}
mLastSelected = checkedPos;
} else {
@@ -276,7 +275,7 @@ public class ResolverActivity extends AlertActivity implements AdapterView.OnIte
public void onButtonClick(View v) {
final int id = v.getId();
- startSelected(mGrid.getCheckedItemPosition(), id == R.id.button_always);
+ startSelected(mListView.getCheckedItemPosition(), id == R.id.button_always);
dismiss();
}
@@ -288,94 +287,103 @@ public class ResolverActivity extends AlertActivity implements AdapterView.OnIte
}
protected void onIntentSelected(ResolveInfo ri, Intent intent, boolean alwaysCheck) {
- if (alwaysCheck) {
- // Build a reasonable intent filter, based on what matched.
- IntentFilter filter = new IntentFilter();
+ // Build a reasonable intent filter, based on what matched.
+ IntentFilter filter = new IntentFilter();
- if (intent.getAction() != null) {
- filter.addAction(intent.getAction());
- }
- Set<String> categories = intent.getCategories();
- if (categories != null) {
- for (String cat : categories) {
- filter.addCategory(cat);
- }
+ if (intent.getAction() != null) {
+ filter.addAction(intent.getAction());
+ }
+ Set<String> categories = intent.getCategories();
+ if (categories != null) {
+ for (String cat : categories) {
+ filter.addCategory(cat);
}
- filter.addCategory(Intent.CATEGORY_DEFAULT);
-
- int cat = ri.match&IntentFilter.MATCH_CATEGORY_MASK;
- Uri data = intent.getData();
- if (cat == IntentFilter.MATCH_CATEGORY_TYPE) {
- String mimeType = intent.resolveType(this);
- if (mimeType != null) {
- try {
- filter.addDataType(mimeType);
- } catch (IntentFilter.MalformedMimeTypeException e) {
- Log.w("ResolverActivity", e);
- filter = null;
- }
+ }
+ filter.addCategory(Intent.CATEGORY_DEFAULT);
+
+ int cat = ri.match&IntentFilter.MATCH_CATEGORY_MASK;
+ Uri data = intent.getData();
+ if (cat == IntentFilter.MATCH_CATEGORY_TYPE) {
+ String mimeType = intent.resolveType(this);
+ if (mimeType != null) {
+ try {
+ filter.addDataType(mimeType);
+ } catch (IntentFilter.MalformedMimeTypeException e) {
+ Log.w("ResolverActivity", e);
+ filter = null;
}
}
- if (data != null && data.getScheme() != null) {
- // We need the data specification if there was no type,
- // OR if the scheme is not one of our magical "file:"
- // or "content:" schemes (see IntentFilter for the reason).
- if (cat != IntentFilter.MATCH_CATEGORY_TYPE
- || (!"file".equals(data.getScheme())
- && !"content".equals(data.getScheme()))) {
- filter.addDataScheme(data.getScheme());
-
- // Look through the resolved filter to determine which part
- // of it matched the original Intent.
- Iterator<PatternMatcher> pIt = ri.filter.schemeSpecificPartsIterator();
- if (pIt != null) {
- String ssp = data.getSchemeSpecificPart();
- while (ssp != null && pIt.hasNext()) {
- PatternMatcher p = pIt.next();
- if (p.match(ssp)) {
- filter.addDataSchemeSpecificPart(p.getPath(), p.getType());
- break;
- }
+ }
+ if (data != null && data.getScheme() != null) {
+ // We need the data specification if there was no type,
+ // OR if the scheme is not one of our magical "file:"
+ // or "content:" schemes (see IntentFilter for the reason).
+ if (cat != IntentFilter.MATCH_CATEGORY_TYPE
+ || (!"file".equals(data.getScheme())
+ && !"content".equals(data.getScheme()))) {
+ filter.addDataScheme(data.getScheme());
+
+ // Look through the resolved filter to determine which part
+ // of it matched the original Intent.
+ Iterator<PatternMatcher> pIt = ri.filter.schemeSpecificPartsIterator();
+ if (pIt != null) {
+ String ssp = data.getSchemeSpecificPart();
+ while (ssp != null && pIt.hasNext()) {
+ PatternMatcher p = pIt.next();
+ if (p.match(ssp)) {
+ filter.addDataSchemeSpecificPart(p.getPath(), p.getType());
+ break;
}
}
- Iterator<IntentFilter.AuthorityEntry> aIt = ri.filter.authoritiesIterator();
- if (aIt != null) {
- while (aIt.hasNext()) {
- IntentFilter.AuthorityEntry a = aIt.next();
- if (a.match(data) >= 0) {
- int port = a.getPort();
- filter.addDataAuthority(a.getHost(),
- port >= 0 ? Integer.toString(port) : null);
- break;
- }
+ }
+ Iterator<IntentFilter.AuthorityEntry> aIt = ri.filter.authoritiesIterator();
+ if (aIt != null) {
+ while (aIt.hasNext()) {
+ IntentFilter.AuthorityEntry a = aIt.next();
+ if (a.match(data) >= 0) {
+ int port = a.getPort();
+ filter.addDataAuthority(a.getHost(),
+ port >= 0 ? Integer.toString(port) : null);
+ break;
}
}
- pIt = ri.filter.pathsIterator();
- if (pIt != null) {
- String path = data.getPath();
- while (path != null && pIt.hasNext()) {
- PatternMatcher p = pIt.next();
- if (p.match(path)) {
- filter.addDataPath(p.getPath(), p.getType());
- break;
- }
+ }
+ pIt = ri.filter.pathsIterator();
+ if (pIt != null) {
+ String path = data.getPath();
+ while (path != null && pIt.hasNext()) {
+ PatternMatcher p = pIt.next();
+ if (p.match(path)) {
+ filter.addDataPath(p.getPath(), p.getType());
+ break;
}
}
}
}
+ }
- if (filter != null) {
- final int N = mAdapter.mList.size();
- ComponentName[] set = new ComponentName[N];
- int bestMatch = 0;
- for (int i=0; i<N; i++) {
- ResolveInfo r = mAdapter.mList.get(i).ri;
- set[i] = new ComponentName(r.activityInfo.packageName,
- r.activityInfo.name);
- if (r.match > bestMatch) bestMatch = r.match;
- }
+ if (filter != null) {
+ final int N = mAdapter.mList.size();
+ ComponentName[] set = new ComponentName[N];
+ int bestMatch = 0;
+ for (int i=0; i<N; i++) {
+ ResolveInfo r = mAdapter.mList.get(i).ri;
+ set[i] = new ComponentName(r.activityInfo.packageName,
+ r.activityInfo.name);
+ if (r.match > bestMatch) bestMatch = r.match;
+ }
+ if (alwaysCheck) {
getPackageManager().addPreferredActivity(filter, bestMatch, set,
intent.getComponent());
+ } else {
+ try {
+ AppGlobals.getPackageManager().setLastChosenActivity(intent,
+ intent.resolveTypeIfNeeded(getContentResolver()),
+ PackageManager.MATCH_DEFAULT_ONLY,
+ filter, bestMatch, intent.getComponent());
+ } catch (RemoteException re) {
+ Log.d(TAG, "Error calling setLastChosenActivity\n" + re);
+ }
}
}
@@ -410,11 +418,13 @@ public class ResolverActivity extends AlertActivity implements AdapterView.OnIte
private final class ResolveListAdapter extends BaseAdapter {
private final Intent[] mInitialIntents;
private final List<ResolveInfo> mBaseResolveList;
+ private ResolveInfo mLastChosen;
private final Intent mIntent;
private final int mLaunchedFromUid;
private final LayoutInflater mInflater;
private List<DisplayResolveInfo> mList;
+ private int mInitialHighlight = -1;
public ResolveListAdapter(Context context, Intent intent,
Intent[] initialIntents, List<ResolveInfo> rList, int launchedFromUid) {
@@ -436,14 +446,24 @@ public class ResolverActivity extends AlertActivity implements AdapterView.OnIte
if (newItemCount == 0) {
// We no longer have any items... just finish the activity.
finish();
- } else if (newItemCount != oldItemCount) {
- resizeGrid();
}
}
+ public int getInitialHighlight() {
+ return mInitialHighlight;
+ }
+
private void rebuildList() {
List<ResolveInfo> currentResolveList;
+ try {
+ mLastChosen = AppGlobals.getPackageManager().getLastChosenActivity(
+ mIntent, mIntent.resolveTypeIfNeeded(getContentResolver()),
+ PackageManager.MATCH_DEFAULT_ONLY);
+ } catch (RemoteException re) {
+ Log.d(TAG, "Error calling setLastChosenActivity\n" + re);
+ }
+
mList.clear();
if (mBaseResolveList != null) {
currentResolveList = mBaseResolveList;
@@ -556,6 +576,12 @@ public class ResolverActivity extends AlertActivity implements AdapterView.OnIte
// Process labels from start to i
int num = end - start+1;
if (num == 1) {
+ if (mLastChosen != null
+ && mLastChosen.activityInfo.packageName.equals(
+ ro.activityInfo.packageName)
+ && mLastChosen.activityInfo.name.equals(ro.activityInfo.name)) {
+ mInitialHighlight = mList.size();
+ }
// No duplicate labels. Use label for entry at start
mList.add(new DisplayResolveInfo(ro, roLabel, null, null));
} else {
@@ -585,6 +611,12 @@ public class ResolverActivity extends AlertActivity implements AdapterView.OnIte
}
for (int k = start; k <= end; k++) {
ResolveInfo add = rList.get(k);
+ if (mLastChosen != null
+ && mLastChosen.activityInfo.packageName.equals(
+ add.activityInfo.packageName)
+ && mLastChosen.activityInfo.name.equals(add.activityInfo.name)) {
+ mInitialHighlight = mList.size();
+ }
if (usePkg) {
// Use application name for all entries from start to end-1
mList.add(new DisplayResolveInfo(add, roLabel,
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index fd9fbae..eea9ee1 100644
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -5,6 +5,7 @@
#include "GraphicsJNI.h"
#include "SkDither.h"
#include "SkUnPreMultiply.h"
+#include "SkStream.h"
#include <binder/Parcel.h>
#include "android_os_Parcel.h"
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index c433874..16beb02 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -202,7 +202,7 @@ private:
// since we "may" create a purgeable imageref, we require the stream be ref'able
// i.e. dynamically allocated, since its lifetime may exceed the current stack
// frame.
-static jobject doDecode(JNIEnv* env, SkStream* stream, jobject padding,
+static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding,
jobject options, bool allowPurgeable, bool forcePurgeable = false) {
int sampleSize = 1;
@@ -459,26 +459,17 @@ static jobject nativeDecodeStream(JNIEnv* env, jobject clazz, jobject is, jbyteA
jobject padding, jobject options) {
jobject bitmap = NULL;
- SkStream* stream = CreateJavaInputStreamAdaptor(env, is, storage, 0);
+ SkAutoTUnref<SkStreamRewindable> stream(GetRewindableStream(env, is, storage));
- if (stream) {
+ if (stream.get()) {
// for now we don't allow purgeable with java inputstreams
+ // FIXME: GetRewindableStream may have made a copy, in which case
+ // purgeable should be allowed.
bitmap = doDecode(env, stream, padding, options, false, false);
- stream->unref();
}
return bitmap;
}
-static ssize_t getFDSize(int fd) {
- off64_t curr = ::lseek64(fd, 0, SEEK_CUR);
- if (curr < 0) {
- return 0;
- }
- size_t size = ::lseek(fd, 0, SEEK_END);
- ::lseek64(fd, curr, SEEK_SET);
- return size;
-}
-
static jobject nativeDecodeFileDescriptor(JNIEnv* env, jobject clazz, jobject fileDescriptor,
jobject padding, jobject bitmapFactoryOptions) {
@@ -512,44 +503,16 @@ static jobject nativeDecodeFileDescriptor(JNIEnv* env, jobject clazz, jobject fi
return doDecode(env, stream, padding, bitmapFactoryOptions, weOwnTheFD);
}
-/* make a deep copy of the asset, and return it as a stream, or NULL if there
- was an error.
- */
-static SkStream* copyAssetToStream(Asset* asset) {
- // if we could "ref/reopen" the asset, we may not need to copy it here
- off64_t size = asset->seek(0, SEEK_SET);
- if ((off64_t)-1 == size) {
- SkDebugf("---- copyAsset: asset rewind failed\n");
- return NULL;
- }
-
- size = asset->getLength();
- if (size <= 0) {
- SkDebugf("---- copyAsset: asset->getLength() returned %d\n", size);
- return NULL;
- }
-
- SkStream* stream = new SkMemoryStream(size);
- void* data = const_cast<void*>(stream->getMemoryBase());
- off64_t len = asset->read(data, size);
- if (len != size) {
- SkDebugf("---- copyAsset: asset->read(%d) returned %d\n", size, len);
- delete stream;
- stream = NULL;
- }
- return stream;
-}
-
static jobject nativeDecodeAsset(JNIEnv* env, jobject clazz, jint native_asset,
jobject padding, jobject options) {
- SkStream* stream;
+ SkStreamRewindable* stream;
Asset* asset = reinterpret_cast<Asset*>(native_asset);
bool forcePurgeable = optionsPurgeable(env, options);
if (forcePurgeable) {
// if we could "ref/reopen" the asset, we may not need to copy it here
// and we could assume optionsShareable, since assets are always RO
- stream = copyAssetToStream(asset);
+ stream = CopyAssetToStream(asset);
if (stream == NULL) {
return NULL;
}
@@ -559,7 +522,7 @@ static jobject nativeDecodeAsset(JNIEnv* env, jobject clazz, jint native_asset,
stream = new AssetStreamAdaptor(asset);
}
SkAutoUnref aur(stream);
- return doDecode(env, stream, padding, options, true, forcePurgeable);
+ return doDecode(env, stream, padding, options, forcePurgeable, forcePurgeable);
}
static jobject nativeDecodeByteArray(JNIEnv* env, jobject, jbyteArray byteArray,
@@ -572,7 +535,7 @@ static jobject nativeDecodeByteArray(JNIEnv* env, jobject, jbyteArray byteArray,
*/
bool purgeable = optionsPurgeable(env, options) && !optionsJustBounds(env, options);
AutoJavaByteArray ar(env, byteArray);
- SkStream* stream = new SkMemoryStream(ar.ptr() + offset, length, purgeable);
+ SkMemoryStream* stream = new SkMemoryStream(ar.ptr() + offset, length, purgeable);
SkAutoUnref aur(stream);
return doDecode(env, stream, NULL, options, purgeable);
}
diff --git a/core/jni/android/graphics/BitmapRegionDecoder.cpp b/core/jni/android/graphics/BitmapRegionDecoder.cpp
index 8867a11..6646579 100644
--- a/core/jni/android/graphics/BitmapRegionDecoder.cpp
+++ b/core/jni/android/graphics/BitmapRegionDecoder.cpp
@@ -76,27 +76,6 @@ private:
int fHeight;
};
-static SkMemoryStream* buildSkMemoryStream(SkStream *stream) {
- size_t bufferSize = 4096;
- size_t streamLen = 0;
- size_t len;
- char* data = (char*)sk_malloc_throw(bufferSize);
-
- while ((len = stream->read(data + streamLen,
- bufferSize - streamLen)) != 0) {
- streamLen += len;
- if (streamLen == bufferSize) {
- bufferSize *= 2;
- data = (char*)sk_realloc_throw(data, bufferSize);
- }
- }
- data = (char*)sk_realloc_throw(data, streamLen);
-
- SkMemoryStream* streamMem = new SkMemoryStream();
- streamMem->setMemoryOwned(data, streamLen);
- return streamMem;
-}
-
static jobject createBitmapRegionDecoder(JNIEnv* env, SkStream* stream) {
SkImageDecoder* decoder = SkImageDecoder::Factory(stream);
int width, height;
@@ -161,14 +140,12 @@ static jobject nativeNewInstanceFromStream(JNIEnv* env, jobject clazz,
jbyteArray storage, // byte[]
jboolean isShareable) {
jobject brd = NULL;
- SkStream* stream = CreateJavaInputStreamAdaptor(env, is, storage, 1024);
+ // for now we don't allow shareable with java inputstreams
+ SkStream* stream = CopyJavaInputStream(env, is, storage);
if (stream) {
- // for now we don't allow shareable with java inputstreams
- SkMemoryStream* mStream = buildSkMemoryStream(stream);
- brd = createBitmapRegionDecoder(env, mStream);
- SkSafeUnref(mStream); // the decoder now holds a reference
- stream->unref();
+ brd = createBitmapRegionDecoder(env, stream);
+ stream->unref(); // the decoder now holds a reference
}
return brd;
}
@@ -176,14 +153,14 @@ static jobject nativeNewInstanceFromStream(JNIEnv* env, jobject clazz,
static jobject nativeNewInstanceFromAsset(JNIEnv* env, jobject clazz,
jint native_asset, // Asset
jboolean isShareable) {
- SkStream* stream, *assStream;
Asset* asset = reinterpret_cast<Asset*>(native_asset);
- assStream = new AssetStreamAdaptor(asset);
- stream = buildSkMemoryStream(assStream);
- assStream->unref();
+ SkAutoTUnref<SkMemoryStream> stream(CopyAssetToStream(asset));
+ if (NULL == stream.get()) {
+ return NULL;
+ }
- jobject brd = createBitmapRegionDecoder(env, stream);
- SkSafeUnref(stream); // the decoder now holds a reference
+ jobject brd = createBitmapRegionDecoder(env, stream.get());
+ // The decoder now holds a reference to stream.
return brd;
}
diff --git a/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp b/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp
index aa4cbde..797d155 100644
--- a/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp
+++ b/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp
@@ -1,28 +1,83 @@
#include "CreateJavaOutputStreamAdaptor.h"
+#include "JNIHelp.h"
+#include "SkData.h"
+#include "SkRefCnt.h"
+#include "SkStream.h"
+#include "SkTypes.h"
+#include "Utils.h"
+#include <androidfw/Asset.h>
#define RETURN_NULL_IF_NULL(value) \
do { if (!(value)) { SkASSERT(0); return NULL; } } while (false)
+#define RETURN_ZERO_IF_NULL(value) \
+ do { if (!(value)) { SkASSERT(0); return 0; } } while (false)
+
static jmethodID gInputStream_resetMethodID;
static jmethodID gInputStream_markMethodID;
-static jmethodID gInputStream_availableMethodID;
+static jmethodID gInputStream_markSupportedMethodID;
static jmethodID gInputStream_readMethodID;
static jmethodID gInputStream_skipMethodID;
+class RewindableJavaStream;
+
+/**
+ * Non-rewindable wrapper for a Java InputStream.
+ */
class JavaInputStreamAdaptor : public SkStream {
public:
JavaInputStreamAdaptor(JNIEnv* env, jobject js, jbyteArray ar)
: fEnv(env), fJavaInputStream(js), fJavaByteArray(ar) {
SkASSERT(ar);
- fCapacity = env->GetArrayLength(ar);
+ fCapacity = env->GetArrayLength(ar);
SkASSERT(fCapacity > 0);
- fBytesRead = 0;
+ fBytesRead = 0;
+ fIsAtEnd = false;
+ }
+
+ virtual size_t read(void* buffer, size_t size) {
+ JNIEnv* env = fEnv;
+ if (NULL == buffer) {
+ if (0 == size) {
+ return 0;
+ } else {
+ /* InputStream.skip(n) can return <=0 but still not be at EOF
+ If we see that value, we need to call read(), which will
+ block if waiting for more data, or return -1 at EOF
+ */
+ size_t amountSkipped = 0;
+ do {
+ size_t amount = this->doSkip(size - amountSkipped);
+ if (0 == amount) {
+ char tmp;
+ amount = this->doRead(&tmp, 1);
+ if (0 == amount) {
+ // if read returned 0, we're at EOF
+ fIsAtEnd = true;
+ break;
+ }
+ }
+ amountSkipped += amount;
+ } while (amountSkipped < size);
+ return amountSkipped;
+ }
+ }
+ return this->doRead(buffer, size);
+ }
+
+ virtual bool isAtEnd() const {
+ return fIsAtEnd;
}
- virtual bool rewind() {
+private:
+ // Does not override rewind, since a JavaInputStreamAdaptor's interface
+ // does not support rewinding. RewindableJavaStream, which is a friend,
+ // will be able to call this method to rewind.
+ bool doRewind() {
JNIEnv* env = fEnv;
fBytesRead = 0;
+ fIsAtEnd = false;
env->CallVoidMethod(fJavaInputStream, gInputStream_resetMethodID);
if (env->ExceptionCheck()) {
@@ -53,6 +108,7 @@ public:
}
if (n < 0) { // n == 0 should not be possible, see InputStream read() specifications.
+ fIsAtEnd = true;
break; // eof
}
@@ -92,58 +148,19 @@ public:
return (size_t)skipped;
}
- size_t doSize() {
- JNIEnv* env = fEnv;
- jint avail = env->CallIntMethod(fJavaInputStream,
- gInputStream_availableMethodID);
- if (env->ExceptionCheck()) {
- env->ExceptionDescribe();
- env->ExceptionClear();
- SkDebugf("------- available threw an exception\n");
- avail = 0;
- }
- return avail;
- }
-
- virtual size_t read(void* buffer, size_t size) {
- JNIEnv* env = fEnv;
- if (NULL == buffer) {
- if (0 == size) {
- return this->doSize();
- } else {
- /* InputStream.skip(n) can return <=0 but still not be at EOF
- If we see that value, we need to call read(), which will
- block if waiting for more data, or return -1 at EOF
- */
- size_t amountSkipped = 0;
- do {
- size_t amount = this->doSkip(size - amountSkipped);
- if (0 == amount) {
- char tmp;
- amount = this->doRead(&tmp, 1);
- if (0 == amount) {
- // if read returned 0, we're at EOF
- break;
- }
- }
- amountSkipped += amount;
- } while (amountSkipped < size);
- return amountSkipped;
- }
- }
- return this->doRead(buffer, size);
- }
-
-private:
JNIEnv* fEnv;
jobject fJavaInputStream; // the caller owns this object
jbyteArray fJavaByteArray; // the caller owns this object
size_t fCapacity;
size_t fBytesRead;
+ bool fIsAtEnd;
+
+ // Allows access to doRewind and fBytesRead.
+ friend class RewindableJavaStream;
};
-SkStream* CreateJavaInputStreamAdaptor(JNIEnv* env, jobject stream,
- jbyteArray storage, int markSize) {
+SkStream* WrapJavaInputStream(JNIEnv* env, jobject stream,
+ jbyteArray storage) {
static bool gInited;
if (!gInited) {
@@ -154,8 +171,8 @@ SkStream* CreateJavaInputStreamAdaptor(JNIEnv* env, jobject stream,
"reset", "()V");
gInputStream_markMethodID = env->GetMethodID(inputStream_Clazz,
"mark", "(I)V");
- gInputStream_availableMethodID = env->GetMethodID(inputStream_Clazz,
- "available", "()I");
+ gInputStream_markSupportedMethodID = env->GetMethodID(inputStream_Clazz,
+ "markSupported", "()Z");
gInputStream_readMethodID = env->GetMethodID(inputStream_Clazz,
"read", "([BII)I");
gInputStream_skipMethodID = env->GetMethodID(inputStream_Clazz,
@@ -163,18 +180,167 @@ SkStream* CreateJavaInputStreamAdaptor(JNIEnv* env, jobject stream,
RETURN_NULL_IF_NULL(gInputStream_resetMethodID);
RETURN_NULL_IF_NULL(gInputStream_markMethodID);
- RETURN_NULL_IF_NULL(gInputStream_availableMethodID);
+ RETURN_NULL_IF_NULL(gInputStream_markSupportedMethodID);
RETURN_NULL_IF_NULL(gInputStream_readMethodID);
RETURN_NULL_IF_NULL(gInputStream_skipMethodID);
gInited = true;
}
- if (markSize) {
- env->CallVoidMethod(stream, gInputStream_markMethodID, markSize);
+ return new JavaInputStreamAdaptor(env, stream, storage);
+}
+
+static SkMemoryStream* adaptor_to_mem_stream(SkStream* adaptor) {
+ SkASSERT(adaptor != NULL);
+ SkDynamicMemoryWStream wStream;
+ const int bufferSize = 256 * 1024; // 256 KB, same as ViewStateSerializer.
+ uint8_t buffer[bufferSize];
+ do {
+ size_t bytesRead = adaptor->read(buffer, bufferSize);
+ wStream.write(buffer, bytesRead);
+ } while (!adaptor->isAtEnd());
+ SkAutoTUnref<SkData> data(wStream.copyToData());
+ return new SkMemoryStream(data.get());
+}
+
+SkMemoryStream* CopyJavaInputStream(JNIEnv* env, jobject stream,
+ jbyteArray storage) {
+ SkAutoTUnref<SkStream> adaptor(WrapJavaInputStream(env, stream, storage));
+ if (NULL == adaptor.get()) {
+ return NULL;
}
+ return adaptor_to_mem_stream(adaptor.get());
+}
- return new JavaInputStreamAdaptor(env, stream, storage);
+/**
+ * Wrapper for a Java InputStream which is rewindable and
+ * has a length.
+ */
+class RewindableJavaStream : public SkStreamRewindable {
+public:
+ // RewindableJavaStream takes ownership of adaptor.
+ RewindableJavaStream(JavaInputStreamAdaptor* adaptor, size_t length)
+ : fAdaptor(adaptor)
+ , fLength(length) {
+ SkASSERT(fAdaptor != NULL);
+ }
+
+ virtual ~RewindableJavaStream() {
+ fAdaptor->unref();
+ }
+
+ virtual bool rewind() {
+ return fAdaptor->doRewind();
+ }
+
+ virtual size_t read(void* buffer, size_t size) {
+ return fAdaptor->read(buffer, size);
+ }
+
+ virtual bool isAtEnd() const {
+ return fAdaptor->isAtEnd();
+ }
+
+ virtual size_t getLength() const {
+ return fLength;
+ }
+
+ virtual bool hasLength() const {
+ return true;
+ }
+
+ virtual SkStreamRewindable* duplicate() const {
+ // Duplicating this stream requires rewinding and
+ // reading, which modify this Stream (and could
+ // fail, leaving this one invalid).
+ SkASSERT(false);
+ return NULL;
+ }
+
+private:
+ JavaInputStreamAdaptor* fAdaptor;
+ const size_t fLength;
+};
+
+/**
+ * If jstream is a ByteArrayInputStream, return its remaining length. Otherwise
+ * return 0.
+ */
+static size_t get_length_from_byte_array_stream(JNIEnv* env, jobject jstream) {
+ static jclass byteArrayInputStream_Clazz;
+ static jfieldID countField;
+ static jfieldID posField;
+
+ byteArrayInputStream_Clazz = env->FindClass("java/io/ByteArrayInputStream");
+ RETURN_ZERO_IF_NULL(byteArrayInputStream_Clazz);
+
+ countField = env->GetFieldID(byteArrayInputStream_Clazz, "count", "I");
+ RETURN_ZERO_IF_NULL(byteArrayInputStream_Clazz);
+ posField = env->GetFieldID(byteArrayInputStream_Clazz, "pos", "I");
+ RETURN_ZERO_IF_NULL(byteArrayInputStream_Clazz);
+
+ if (env->IsInstanceOf(jstream, byteArrayInputStream_Clazz)) {
+ // Return the remaining length, to keep the same behavior of using the rest of the
+ // stream.
+ return env->GetIntField(jstream, countField) - env->GetIntField(jstream, posField);
+ }
+ return 0;
+}
+
+/**
+ * If jstream is a class that has a length, return it. Otherwise
+ * return 0.
+ * Only checks for a set of subclasses.
+ */
+static size_t get_length_if_supported(JNIEnv* env, jobject jstream) {
+ size_t len = get_length_from_byte_array_stream(env, jstream);
+ if (len > 0) {
+ return len;
+ }
+ return 0;
+}
+
+SkStreamRewindable* GetRewindableStream(JNIEnv* env, jobject stream,
+ jbyteArray storage) {
+ SkAutoTUnref<SkStream> adaptor(WrapJavaInputStream(env, stream, storage));
+ if (NULL == adaptor.get()) {
+ return NULL;
+ }
+
+ const size_t length = get_length_if_supported(env, stream);
+ if (length > 0 && env->CallBooleanMethod(stream, gInputStream_markSupportedMethodID)) {
+ // Set the readLimit for mark to the end of the stream, so it can
+ // be rewound regardless of how much has been read.
+ env->CallVoidMethod(stream, gInputStream_markMethodID, length);
+ // RewindableJavaStream will unref adaptor when it is destroyed.
+ return new RewindableJavaStream(static_cast<JavaInputStreamAdaptor*>(adaptor.detach()),
+ length);
+ }
+
+ return adaptor_to_mem_stream(adaptor.get());
+}
+
+android::AssetStreamAdaptor* CheckForAssetStream(JNIEnv* env, jobject jstream) {
+ static jclass assetInputStream_Clazz;
+ static jmethodID getAssetIntMethodID;
+
+ assetInputStream_Clazz = env->FindClass("android/content/res/AssetManager$AssetInputStream");
+ RETURN_NULL_IF_NULL(assetInputStream_Clazz);
+
+ getAssetIntMethodID = env->GetMethodID(assetInputStream_Clazz, "getAssetInt", "()I");
+ RETURN_NULL_IF_NULL(getAssetIntMethodID);
+
+ if (!env->IsInstanceOf(jstream, assetInputStream_Clazz)) {
+ return NULL;
+ }
+
+ jint jasset = env->CallIntMethod(jstream, getAssetIntMethodID);
+ android::Asset* a = reinterpret_cast<android::Asset*>(jasset);
+ if (NULL == a) {
+ jniThrowNullPointerException(env, "NULL native asset");
+ return NULL;
+ }
+ return new android::AssetStreamAdaptor(a);
}
///////////////////////////////////////////////////////////////////////////////
diff --git a/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.h b/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.h
index c34c96a..5218dc5 100644
--- a/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.h
+++ b/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.h
@@ -3,10 +3,70 @@
//#include <android_runtime/AndroidRuntime.h>
#include "jni.h"
-#include "SkStream.h"
-SkStream* CreateJavaInputStreamAdaptor(JNIEnv* env, jobject stream,
- jbyteArray storage, int markSize = 0);
+namespace android {
+ class AssetStreamAdaptor;
+}
+
+class SkMemoryStream;
+class SkStream;
+class SkStreamRewindable;
+class SkWStream;
+
+/**
+ * Return an adaptor from a Java InputStream to an SkStream.
+ * @param env JNIEnv object.
+ * @param stream Pointer to Java InputStream.
+ * @param storage Java byte array for retrieving data from the
+ * Java InputStream.
+ * @return SkStream Simple subclass of SkStream which supports its
+ * basic methods like reading. Only valid until the calling
+ * function returns, since the Java InputStream is not managed
+ * by the SkStream.
+ */
+SkStream* WrapJavaInputStream(JNIEnv* env, jobject stream,
+ jbyteArray storage);
+
+/**
+ * Copy a Java InputStream.
+ * @param env JNIEnv object.
+ * @param stream Pointer to Java InputStream.
+ * @param storage Java byte array for retrieving data from the
+ * Java InputStream.
+ * @return SkMemoryStream The data in stream will be copied to a new
+ * SkMemoryStream.
+ * FIXME: Could return a more generic return type if ViewStateSerializer
+ * did not require an SkMemoryStream.
+ */
+SkMemoryStream* CopyJavaInputStream(JNIEnv* env, jobject stream,
+ jbyteArray storage);
+
+/**
+ * Get a rewindable stream from a Java InputStream.
+ * @param env JNIEnv object.
+ * @param stream Pointer to Java InputStream.
+ * @param storage Java byte array for retrieving data from the
+ * Java InputStream.
+ * @return SkStreamRewindable Either a wrapper around the Java
+ * InputStream, if possible, or a copy which is rewindable.
+ * Since it may be a wrapper, must not be used after the
+ * caller returns, like the result of WrapJavaInputStream.
+ */
+SkStreamRewindable* GetRewindableStream(JNIEnv* env, jobject stream,
+ jbyteArray storage);
+
+/**
+ * If the Java InputStream is an AssetInputStream, return an adaptor.
+ * This should not be used after the calling function returns, since
+ * the caller may close the asset. Returns NULL if the stream is
+ * not an AssetInputStream.
+ * @param env JNIEnv object.
+ * @param stream Pointer to Java InputStream.
+ * @return AssetStreamAdaptor representing the InputStream, or NULL.
+ * Must not be held onto.
+ */
+android::AssetStreamAdaptor* CheckForAssetStream(JNIEnv* env, jobject stream);
+
SkWStream* CreateJavaOutputStreamAdaptor(JNIEnv* env, jobject stream,
jbyteArray storage);
diff --git a/core/jni/android/graphics/Movie.cpp b/core/jni/android/graphics/Movie.cpp
index 4f64ff8..2eae841 100644
--- a/core/jni/android/graphics/Movie.cpp
+++ b/core/jni/android/graphics/Movie.cpp
@@ -1,8 +1,10 @@
+#include "ScopedLocalRef.h"
#include "SkMovie.h"
#include "SkStream.h"
#include "GraphicsJNI.h"
#include "SkTemplates.h"
#include "SkUtils.h"
+#include "Utils.h"
#include "CreateJavaOutputStreamAdaptor.h"
#include <androidfw/Asset.h>
@@ -83,9 +85,14 @@ static jobject movie_decodeStream(JNIEnv* env, jobject clazz, jobject istream) {
NPE_CHECK_RETURN_ZERO(env, istream);
- // what is the lifetime of the array? Can the skstream hold onto it?
- jbyteArray byteArray = env->NewByteArray(16*1024);
- SkStream* strm = CreateJavaInputStreamAdaptor(env, istream, byteArray);
+ SkStreamRewindable* strm = CheckForAssetStream(env, istream);
+ jbyteArray byteArray = NULL;
+ ScopedLocalRef<jbyteArray> scoper(env, NULL);
+ if (NULL == strm) {
+ byteArray = env->NewByteArray(16*1024);
+ scoper.reset(byteArray);
+ strm = GetRewindableStream(env, istream, byteArray);
+ }
if (NULL == strm) {
return 0;
}
diff --git a/core/jni/android/graphics/Picture.cpp b/core/jni/android/graphics/Picture.cpp
index 9c02219..dff2b18 100644
--- a/core/jni/android/graphics/Picture.cpp
+++ b/core/jni/android/graphics/Picture.cpp
@@ -20,6 +20,7 @@
#include "SkCanvas.h"
#include "SkPicture.h"
+#include "SkStream.h"
#include "SkTemplates.h"
#include "CreateJavaOutputStreamAdaptor.h"
@@ -38,10 +39,9 @@ public:
static SkPicture* deserialize(JNIEnv* env, jobject, jobject jstream,
jbyteArray jstorage) {
SkPicture* picture = NULL;
- SkStream* strm = CreateJavaInputStreamAdaptor(env, jstream, jstorage);
- if (strm) {
- picture = SkPicture::CreateFromStream(strm);
- delete strm;
+ SkAutoTUnref<SkStream> strm(WrapJavaInputStream(env, jstream, jstorage));
+ if (strm.get()) {
+ picture = SkPicture::CreateFromStream(strm.get());
}
return picture;
}
diff --git a/core/jni/android/graphics/Utils.cpp b/core/jni/android/graphics/Utils.cpp
index cf6977e..b7d1f3a 100644
--- a/core/jni/android/graphics/Utils.cpp
+++ b/core/jni/android/graphics/Utils.cpp
@@ -28,12 +28,28 @@ bool AssetStreamAdaptor::rewind() {
return true;
}
+size_t AssetStreamAdaptor::getLength() const {
+ return fAsset->getLength();
+}
+
+bool AssetStreamAdaptor::isAtEnd() const {
+ return fAsset->getRemainingLength() == 0;
+}
+
+SkStreamRewindable* AssetStreamAdaptor::duplicate() const {
+ SkASSERT(false);
+ // Cannot create a duplicate, since each AssetStreamAdaptor
+ // would be modifying the Asset.
+ //return new AssetStreamAdaptor(fAsset);
+ return NULL;
+}
+
size_t AssetStreamAdaptor::read(void* buffer, size_t size) {
ssize_t amount;
if (NULL == buffer) {
- if (0 == size) { // caller is asking us for our total length
- return fAsset->getLength();
+ if (0 == size) {
+ return 0;
}
// asset->seek returns new total offset
// we want to return amount that was skipped
@@ -62,6 +78,34 @@ size_t AssetStreamAdaptor::read(void* buffer, size_t size) {
return amount;
}
+SkMemoryStream* android::CopyAssetToStream(Asset* asset) {
+ if (NULL == asset) {
+ return NULL;
+ }
+
+ off64_t size = asset->seek(0, SEEK_SET);
+ if ((off64_t)-1 == size) {
+ SkDebugf("---- copyAsset: asset rewind failed\n");
+ return NULL;
+ }
+
+ size = asset->getLength();
+ if (size <= 0) {
+ SkDebugf("---- copyAsset: asset->getLength() returned %d\n", size);
+ return NULL;
+ }
+
+ SkMemoryStream* stream = new SkMemoryStream(size);
+ void* data = const_cast<void*>(stream->getMemoryBase());
+ off64_t len = asset->read(data, size);
+ if (len != size) {
+ SkDebugf("---- copyAsset: asset->read(%d) returned %d\n", size, len);
+ delete stream;
+ stream = NULL;
+ }
+ return stream;
+}
+
jobject android::nullObjectReturn(const char msg[]) {
if (msg) {
SkDebugf("--- %s\n", msg);
diff --git a/core/jni/android/graphics/Utils.h b/core/jni/android/graphics/Utils.h
index 75ceaa2..a1ac72a 100644
--- a/core/jni/android/graphics/Utils.h
+++ b/core/jni/android/graphics/Utils.h
@@ -26,16 +26,27 @@
namespace android {
-class AssetStreamAdaptor : public SkStream {
+class AssetStreamAdaptor : public SkStreamRewindable {
public:
AssetStreamAdaptor(Asset* a) : fAsset(a) {}
virtual bool rewind();
virtual size_t read(void* buffer, size_t size);
+ virtual bool hasLength() const { return true; }
+ virtual size_t getLength() const;
+ virtual bool isAtEnd() const;
+ virtual SkStreamRewindable* duplicate() const;
private:
Asset* fAsset;
};
+/**
+ * Make a deep copy of the asset, and return it as a stream, or NULL if there
+ * was an error.
+ * FIXME: If we could "ref/reopen" the asset, we may not need to copy it here.
+ */
+
+SkMemoryStream* CopyAssetToStream(Asset*);
/** Restore the file descriptor's offset in our destructor
*/
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index faf6e63..9613df3 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -207,6 +207,7 @@
<protected-broadcast android:name="android.intent.action.DREAMING_STARTED" />
<protected-broadcast android:name="android.intent.action.DREAMING_STOPPED" />
<protected-broadcast android:name="android.intent.action.ANY_DATA_STATE" />
+ <protected-broadcast android:name="android.intent.action.DATA_CONNECTION_CONNECTED_TO_PROVISIONING_APN" />
<protected-broadcast android:name="com.android.server.WifiManager.action.START_SCAN" />
<protected-broadcast android:name="com.android.server.WifiManager.action.DELAYED_DRIVER_STOP" />
@@ -249,6 +250,9 @@
<protected-broadcast android:name="android.location.GPS_FIX_CHANGE" />
<protected-broadcast android:name="android.net.proxy.PAC_REFRESH" />
+ <protected-broadcast
+ android:name="com.android.server.connectivityservice.CONNECTED_TO_PROVISIONING_NETWORK_ACTION" />
+
<!-- ====================================== -->
<!-- Permissions for things that cost money -->
<!-- ====================================== -->
@@ -1915,13 +1919,10 @@
android:description="@string/permdesc_bindNfcService"
android:protectionLevel="signature" />
- <!-- Allows an application to call APIs that give it access to all print jobs
- on the device. Usually an app can access only the print jobts it created.
- This permission is not available to third party applications.
- @hide -->
- <permission android:name="android.permission.ACCESS_ALL_PRINT_JOBS"
- android:label="@string/permlab_accessAllPrintJobs"
- android:description="@string/permdesc_accessAllPrintJobs"
+ <!-- Must be required by the PrintSpooler to ensure that only the system can bind to it. -->
+ <permission android:name="android.permission.BIND_PRINT_SPOOLER_SERVICE"
+ android:label="@string/permlab_bindPrintSpoolerService"
+ android:description="@string/permdesc_bindPrintSpoolerService"
android:protectionLevel="signature" />
<!-- Must be required by a TextService (e.g. SpellCheckerService)
diff --git a/core/res/res/layout/resolve_list_item.xml b/core/res/res/layout/resolve_list_item.xml
index 61cecae..28c5b74 100644
--- a/core/res/res/layout/resolve_list_item.xml
+++ b/core/res/res/layout/resolve_list_item.xml
@@ -18,40 +18,40 @@
*/
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:gravity="center"
- android:orientation="vertical"
+ android:orientation="horizontal"
android:layout_height="wrap_content"
android:layout_width="match_parent"
- android:background="@android:drawable/activity_picker_bg"
- android:padding="16dp">
-
- <!-- Extended activity info to distinguish between duplicate activity names -->
- <TextView android:id="@android:id/text2"
- android:textAppearance="?android:attr/textAppearance"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:gravity="center"
- android:minLines="2"
- android:maxLines="2"
- android:paddingStart="4dip"
- android:paddingEnd="4dip" />
+ android:background="@android:drawable/activity_picker_bg">
<!-- Activity icon when presenting dialog
Size will be filled in by ResolverActivity -->
<ImageView android:id="@+id/icon"
android:layout_width="0dp"
android:layout_height="0dp"
+ android:layout_marginStart="12dp"
+ android:padding="4dp"
android:scaleType="fitCenter" />
- <!-- Activity name -->
- <TextView android:id="@android:id/text1"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:layout_width="wrap_content"
+ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:gravity="start|center_vertical"
+ android:orientation="vertical"
android:layout_height="wrap_content"
- android:gravity="center"
- android:minLines="2"
- android:maxLines="2"
- android:paddingStart="4dip"
- android:paddingEnd="4dip" />
+ android:layout_width="wrap_content"
+ android:layout_gravity="start|center_vertical"
+ android:layout_marginStart="12dp">
+ <!-- Activity name -->
+ <TextView android:id="@android:id/text1"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:maxLines="2" />
+ <!-- Extended activity info to distinguish between duplicate activity names -->
+ <TextView android:id="@android:id/text2"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:maxLines="2"
+ android:paddingTop="4dip" />
+ </LinearLayout>
</LinearLayout>
diff --git a/core/res/res/layout/resolver_grid.xml b/core/res/res/layout/resolver_list.xml
index d271c1a..f88ced1 100644
--- a/core/res/res/layout/resolver_grid.xml
+++ b/core/res/res/layout/resolver_list.xml
@@ -23,20 +23,18 @@
android:divider="?android:attr/dividerHorizontal"
android:showDividers="middle"
android:dividerPadding="0dip">
+
<FrameLayout android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1">
- <GridView
- android:layout_gravity="center"
- android:layout_width="wrap_content"
+
+ <ListView
+ android:layout_width="match_parent"
android:layout_height="match_parent"
- android:id="@+id/resolver_grid"
- android:numColumns="4"
- android:columnWidth="128dp"
- android:padding="16dp"
- android:clipToPadding="false"
- android:scrollbarStyle="outsideOverlay" />
+ android:id="@+id/resolver_list" />
+
</FrameLayout>
+
<LinearLayout
android:id="@+id/button_bar"
android:visibility="gone"
diff --git a/core/res/res/values-mcc208-mnc26/config.xml b/core/res/res/values-mcc208-mnc26/config.xml
new file mode 100644
index 0000000..31d2d0f
--- /dev/null
+++ b/core/res/res/values-mcc208-mnc26/config.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Don't use roaming icon for considered operators -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>20801</item>
+ <item>20810</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc214-mnc04/config.xml b/core/res/res/values-mcc214-mnc04/config.xml
new file mode 100644
index 0000000..71301d5
--- /dev/null
+++ b/core/res/res/values-mcc214-mnc04/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Don't use roaming icon for considered operators -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>21407</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc234-mnc30/config.xml b/core/res/res/values-mcc234-mnc30/config.xml
new file mode 100644
index 0000000..eabdf9a
--- /dev/null
+++ b/core/res/res/values-mcc234-mnc30/config.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Don't use roaming icon for considered operators -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>23430</item>
+ <item>23431</item>
+ <item>23432</item>
+ <item>23433</item>
+ <item>23434</item>
+ <item>23486</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc234-mnc31/config.xml b/core/res/res/values-mcc234-mnc31/config.xml
new file mode 100644
index 0000000..eabdf9a
--- /dev/null
+++ b/core/res/res/values-mcc234-mnc31/config.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Don't use roaming icon for considered operators -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>23430</item>
+ <item>23431</item>
+ <item>23432</item>
+ <item>23433</item>
+ <item>23434</item>
+ <item>23486</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc234-mnc32/config.xml b/core/res/res/values-mcc234-mnc32/config.xml
new file mode 100644
index 0000000..eabdf9a
--- /dev/null
+++ b/core/res/res/values-mcc234-mnc32/config.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Don't use roaming icon for considered operators -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>23430</item>
+ <item>23431</item>
+ <item>23432</item>
+ <item>23433</item>
+ <item>23434</item>
+ <item>23486</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc234-mnc33/config.xml b/core/res/res/values-mcc234-mnc33/config.xml
index d79d212..175f76e 100644
--- a/core/res/res/values-mcc234-mnc33/config.xml
+++ b/core/res/res/values-mcc234-mnc33/config.xml
@@ -35,4 +35,14 @@
"name,apn,proxy,port,username,password,server,mmsc,mmsproxy,mmsport,mcc,mnc,auth,type"
note that empty fields can be ommitted: "name,apn,,,,,,,,,310,260,,DUN" -->
<string translatable="false" name="config_tether_apndata">Consumer Broadband,consumerbroadband,,,,,,,,,234,33,,DUN</string>
+
+ <!-- Don't use roaming icon for considered operators -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>23430</item>
+ <item>23431</item>
+ <item>23432</item>
+ <item>23433</item>
+ <item>23434</item>
+ <item>23486</item>
+ </string-array>
</resources>
diff --git a/core/res/res/values-mcc234-mnc34/config.xml b/core/res/res/values-mcc234-mnc34/config.xml
new file mode 100644
index 0000000..eabdf9a
--- /dev/null
+++ b/core/res/res/values-mcc234-mnc34/config.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Don't use roaming icon for considered operators -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>23430</item>
+ <item>23431</item>
+ <item>23432</item>
+ <item>23433</item>
+ <item>23434</item>
+ <item>23486</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc234-mnc86/config.xml b/core/res/res/values-mcc234-mnc86/config.xml
new file mode 100644
index 0000000..eabdf9a
--- /dev/null
+++ b/core/res/res/values-mcc234-mnc86/config.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Don't use roaming icon for considered operators -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>23430</item>
+ <item>23431</item>
+ <item>23432</item>
+ <item>23433</item>
+ <item>23434</item>
+ <item>23486</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc610/config.xml b/core/res/res/values-mcc302-mnc610/config.xml
new file mode 100644
index 0000000..706570c
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc610/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Don't use roaming icon for considered operators -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>302</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc640/config.xml b/core/res/res/values-mcc302-mnc640/config.xml
new file mode 100644
index 0000000..706570c
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc640/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Don't use roaming icon for considered operators -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>302</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc780/config.xml b/core/res/res/values-mcc302-mnc780/config.xml
index 42d4956..b03d14e 100644
--- a/core/res/res/values-mcc302-mnc780/config.xml
+++ b/core/res/res/values-mcc302-mnc780/config.xml
@@ -37,4 +37,8 @@
note that empty fields can be ommitted: "name,apn,,,,,,,,,310,260,,DUN" -->
<string translatable="false" name="config_tether_apndata">SaskTel Tethering,inet.stm.sk.ca,,,,,,,,,302,780,,DUN</string>
+ <!-- Don't use roaming icon for considered operators -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>302</item>
+ </string-array>
</resources>
diff --git a/core/res/res/values-mcc425-mnc07/config.xml b/core/res/res/values-mcc425-mnc07/config.xml
index 890420e..51a9934 100644
--- a/core/res/res/values-mcc425-mnc07/config.xml
+++ b/core/res/res/values-mcc425-mnc07/config.xml
@@ -37,4 +37,8 @@
note that empty fields can be ommitted: "name,apn,,,,,,,,,310,260,,DUN" -->
<string translatable="false" name="config_tether_apndata">PC HOT mobile,pc.hotm,,,,,,,,,425,07,,DUN</string>
+ <!-- Don't use roaming icon for considered operators -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>42503</item>
+ </string-array>
</resources>
diff --git a/core/res/res/values-mcc425-mnc08/config.xml b/core/res/res/values-mcc425-mnc08/config.xml
new file mode 100644
index 0000000..8470b86
--- /dev/null
+++ b/core/res/res/values-mcc425-mnc08/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Don't use roaming icon for considered operators -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>42502</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 50ea08b..5444cb1 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2602,6 +2602,9 @@
<!-- Short description of the functionality the service implements. This attribute
is mandatory.-->
<attr name="description" />
+ <!-- Whether the device must be unlocked before routing data to this service.
+ The default is false.-->
+ <attr name="requireDeviceUnlock" format="boolean"/>
</declare-styleable>
<!-- Use <code>offhost-apdu-service</code> as the root tag of the XML resource that
@@ -2622,7 +2625,8 @@
<!-- Short description of what the AID group implements. This attribute is mandatory.-->
<attr name="description" />
<!-- The category attribute will be used by the Android platform to present
- multiple applications that register AIDs in the same category uniformly.
+ multiple applications that register ISO 7816 Application IDs (AIDs) in the
+ same category uniformly.
Additionally, when a category is specified, Android will ensure that either
all AIDs in this group are routed to this application, or none at all.
This attribute is optional.-->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 5d4383f..d4a408d 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -820,6 +820,10 @@
<!-- IP address of the dns server to use if nobody else suggests one -->
<string name="config_default_dns_server" translatable="false">8.8.8.8</string>
+ <!-- The default mobile provisioning apn. Empty by default, maybe overridden by
+ an mcc/mnc specific config.xml -->
+ <string name="mobile_provisioning_apn" translatable="false"></string>
+
<!-- The default mobile provisioning url. Empty by default, maybe overridden by
an mcc/mnc specific config.xml -->
<string name="mobile_provisioning_url" translatable="false"></string>
@@ -1207,4 +1211,15 @@
<!-- Default Gravity setting for the system Toast view. Equivalent to: Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM -->
<integer name="config_toastDefaultGravity">0x00000051</integer>
+ <!-- set to false if we need to show user confirmation
+ when alpha identifier is not provided by the UICC -->
+ <bool name="config_stkNoAlphaUsrCnf">true</bool>
+
+ <!-- Don't use roaming icon for considered operators.
+ Can use mcc or mcc+mnc as item. For example, 302 or 21407.
+ If operators, 21404 and 21407, make roaming agreements, user of 21404 should not see
+ the roaming icon as using 21407 network.
+ To do this, add 21407 item to values-mcc214-mnc04/config.xml -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ </string-array>
</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index f2ec04f..696e782 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2073,5 +2073,6 @@
<public type="attr" name="customRoots" />
<public type="attr" name="autoMirrored" />
<public type="attr" name="supportsSwitchingToNextInputMethod" />
+ <public type="attr" name="requireDeviceUnlock" />
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index ead46c2..4b32e2b 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -984,12 +984,13 @@
<string name="permdesc_bindPrintService">Allows the holder to bind to the top-level
interface of a print service. Should never be needed for normal apps.</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_accessAllPrintJobs">access all print jobs</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_accessAllPrintJobs">Allows the holder to access print jobs
- created by another app. Should never be needed for normal apps.</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_bindPrintSpoolerService">bind to a print spooler 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_bindPrintSpoolerService">Allows the holder to bind to the top-level
+ interface of a print spooler service. Should never be needed for normal apps.</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_bindNfcService">bind to NFC service</string>
@@ -4292,6 +4293,9 @@
<!-- Write fail reason: couldn't write the printed content. [CHAR LIMIT=none] -->
<string name="write_fail_reason_cannot_write">Error writing content</string>
+ <!-- Print fail reason: unknown. [CHAR LIMIT=25] -->
+ <string name="reason_unknown">unknown</string>
+
<!-- PIN entry dialog label/hint for PIN [CHAR LIMIT=none] -->
<string name="restr_pin_enter_pin">Enter PIN</string>
<!-- PIN entry dialog label/hint for old PIN [CHAR LIMIT=none] -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index a9c812e..f008b10 100755..100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -668,6 +668,7 @@
<java-symbol type="string" name="preposition_for_time" />
<java-symbol type="string" name="progress_erasing" />
<java-symbol type="string" name="progress_unmounting" />
+ <java-symbol type="string" name="mobile_provisioning_apn" />
<java-symbol type="string" name="mobile_provisioning_url" />
<java-symbol type="string" name="mobile_redirected_provisioning_url" />
<java-symbol type="string" name="reboot_safemode_confirm" />
@@ -868,6 +869,7 @@
<java-symbol type="string" name="mediaSize_na_junior_legal" />
<java-symbol type="string" name="mediaSize_na_ledger" />
<java-symbol type="string" name="mediaSize_na_tabloid" />
+ <java-symbol type="string" name="reason_unknown" />
<java-symbol type="string" name="restr_pin_enter_pin" />
<java-symbol type="string" name="write_fail_reason_cancelled" />
<java-symbol type="string" name="write_fail_reason_cannot_write" />
@@ -910,6 +912,7 @@
<java-symbol type="array" name="config_masterVolumeRamp" />
<java-symbol type="array" name="config_cdma_dun_supported_types" />
<java-symbol type="array" name="config_disabledUntilUsedPreinstalledImes" />
+ <java-symbol type="array" name="config_operatorConsideredNonRoaming" />
<java-symbol type="drawable" name="default_wallpaper" />
<java-symbol type="drawable" name="indicator_input_error" />
@@ -1526,8 +1529,8 @@
<java-symbol type="string" name="enable_explore_by_touch_warning_title" />
<java-symbol type="string" name="enable_explore_by_touch_warning_message" />
- <java-symbol type="layout" name="resolver_grid" />
- <java-symbol type="id" name="resolver_grid" />
+ <java-symbol type="layout" name="resolver_list" />
+ <java-symbol type="id" name="resolver_list" />
<java-symbol type="id" name="button_once" />
<java-symbol type="id" name="button_always" />
<java-symbol type="integer" name="config_maxResolverActivityColumns" />
@@ -1639,6 +1642,7 @@
<java-symbol type="bool" name="config_sf_slowBlur" />
<java-symbol type="drawable" name="ic_volume" />
<java-symbol type="drawable" name="stat_notify_sim_toolkit" />
+ <java-symbol type="bool" name="config_stkNoAlphaUsrCnf" />
<!-- From maps library -->
<java-symbol type="array" name="maps_starting_lat_lng" />
diff --git a/docs/downloads/training/AndroidTestingFun.zip b/docs/downloads/training/AndroidTestingFun.zip
new file mode 100644
index 0000000..dca5812
--- /dev/null
+++ b/docs/downloads/training/AndroidTestingFun.zip
Binary files differ
diff --git a/docs/html/images/training/lesson2_MyFirstTestActivityTest_result.png b/docs/html/images/training/lesson2_MyFirstTestActivityTest_result.png
new file mode 100644
index 0000000..e0e869b
--- /dev/null
+++ b/docs/html/images/training/lesson2_MyFirstTestActivityTest_result.png
Binary files differ
diff --git a/docs/html/training/activity-testing/activity-basic-testing.jd b/docs/html/training/activity-testing/activity-basic-testing.jd
new file mode 100644
index 0000000..016289d
--- /dev/null
+++ b/docs/html/training/activity-testing/activity-basic-testing.jd
@@ -0,0 +1,227 @@
+page.title=Creating and Running a Test Case
+trainingnavtop=true
+
+@jd:body
+
+<!-- This is the training bar -->
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>This lesson teaches you to</h2>
+<ol>
+ <li><a href="#testcase">Create a Test Case for Activity Testing</a>
+ <ol>
+ <li><a href="#fixture">Set Up Your Test Fixture</a></li>
+ <li><a href="#preconditions">Add Test Preconditions</a></li>
+ <li><a href="#test_method">Add Test Methods to Verify Your Activity</a></li>
+ </ol>
+ </li>
+ <li><a href="#build_run">Build and Run Your Test</a></li>
+</ol>
+
+<h2>You should also read</h2>
+<ul>
+<li><a href="{@docRoot}tools/testing/testing_android.html">Testing
+Fundamentals</a></li>
+</ul>
+
+</div>
+</div>
+<p>In order to verify that there are no regressions in the layout design and
+functional behavior in your application, it's important to
+create a test for each {@link android.app.Activity} in your application. For
+each test, you need to create the individual parts of a test case, including
+the test fixture, preconditions test method, and {@link android.app.Activity}
+test methods. You can then run your test to get a test report. If any test
+method fails, this might indicate a potential defect in your code.</p>
+<p class="note"><strong>Note:</strong> In the Test-Driven Development (TDD)
+approach, instead of writing most or all of your app code up-front and then
+running tests later in the development cycle, you would progressively write
+just enough production code to satisfy your test dependencies, update your
+test cases to reflect new functional requirements, and iterate repeatedly this
+way.</p>
+
+<h2 id="testcase">Create a Test Case</h2>
+<p>{@link android.app.Activity} tests are written in a structured way.
+Make sure to put your tests in a separate package, distinct from the code under
+test.</p>
+<p>By convention, your test package name should follow the same name as the
+application package, suffixed with <strong>".tests"</strong>. In the test package
+you created, add the Java class for your test case. By convention, your test case
+name should also follow the same name as the Java or Android class that you
+want to test, but suffixed with <strong>“Test”</strong>.</p>
+<p>To create a new test case in Eclipse:</p>
+<ol type="a">
+ <li>In the Package Explorer, right-click on the {@code /src} directory for
+your test project and select <strong>New &gt; Package</strong>.</li>
+ <li>Set the <strong>Name</strong> field to
+{@code &lt;your_app_package_name&gt;.tests} (for example,
+{@code com.example.android.testingfun.tests}) and click
+<strong>Finish</strong>.</li>
+ <li>Right-click on the test package you created, and select
+<strong>New &gt; Class</strong>.</li>
+ <li>Set the <strong>Name</strong> field to
+{@code &lt;your_app_activity_name&gt;Test} (for example,
+{@code MyFirstTestActivityTest}) and click <strong>Finish</strong>.</li>
+</ol>
+
+<h3 id="fixture">Set Up Your Test Fixture</h3>
+<p>A <em>test fixture</em> consists of objects that must be initialized for
+running one or more tests. To set up the test fixture, you can override the
+{@link junit.framework.TestCase#setUp()} and
+{@link junit.framework.TestCase#tearDown()} methods in your test. The
+test runner automatically runs {@link junit.framework.TestCase#setUp()} before
+running any other test methods, and {@link junit.framework.TestCase#tearDown()}
+at the end of each test method execution. You can use these methods to keep
+the code for test initialization and clean up separate from the tests methods.
+</p>
+<p>To set up your test fixture in Eclipse:</p>
+<ol>
+<li>In the Package Explorer, double-click on the test case that you created
+earlier to bring up the Eclipse Java editor, then modify your test case class
+to extend one of the sub-classes of {@link android.test.ActivityTestCase}.
+<p>For example:</p>
+<pre>
+public class MyFirstTestActivityTest
+ extends ActivityInstrumentationTestCase2&lt;MyFirstTestActivity&gt; {
+</pre>
+</li>
+<li>Next, add the constructor and {@link junit.framework.TestCase#setUp()}
+methods to your test case, and add variable declarations for the
+{@link android.app.Activity} that you want to test.</p>
+<p>For example:</p>
+<pre>
+public class MyFirstTestActivityTest
+ extends ActivityInstrumentationTestCase2&lt;MyFirstTestActivity&gt; {
+
+ private MyFirstTestActivity mFirstTestActivity;
+ private TextView mFirstTestText;
+
+ public MyFirstTestActivityTest() {
+ super(MyFirstTestActivity.class);
+ }
+
+ &#64;Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mFirstTestActivity = getActivity();
+ mFirstTestText =
+ (TextView) mFirstTestActivity
+ .findViewById(R.id.my_first_test_text_view);
+ }
+}
+</pre>
+<p>The constructor is invoked by the test runner to instantiate the test
+class, while the {@link junit.framework.TestCase#setUp()} method is invoked by
+the test runner before it runs any tests in the test class.</p>
+</li>
+</ol>
+
+<p>Typically, in the {@link junit.framework.TestCase#setUp()} method, you
+should:</p>
+<ul>
+<li>Invoke the superclass constructor for
+{@link junit.framework.TestCase#setUp()}, which is required by JUnit.</li>
+<li>Initialize your test fixture state by:
+ <ul>
+ <li>Defining the instance variables that store the state of the fixture.</li>
+ <li>Creating and storing a reference to an instance of the
+{@link android.app.Activity} under test.</li>
+ <li>Obtaining a reference to any UI components in the
+{@link android.app.Activity} that you want to test.</li>
+ </ul>
+</ul>
+
+<p>You can use the
+{@link android.test.ActivityInstrumentationTestCase2#getActivity()} method to
+get a reference to the {@link android.app.Activity} under test.</p>
+
+<h3 id="preconditions">Add Test Preconditions</h3>
+<p>As a sanity check, it is good practice to verify that the test fixture has
+been set up correctly, and the objects that you want to test have been correctly
+instantiated or initialized. That way, you won’t have to see
+tests failing because something was wrong with the setup of your test fixture.
+By convention, the method for verifying your test fixture is called
+{@code testPreconditions()}.</p>
+
+<p>For example, you might want to add a {@code testPreconditons()} method like
+this to your test case:</p>
+
+<pre>
+public void testPreconditions() {
+ assertNotNull(“mFirstTestActivity is null”, mFirstTestActivity);
+ assertNotNull(“mFirstTestText is null”, mFirstTestText);
+}
+</pre>
+
+<p>The assertion methods are from the JUnit {@link junit.framework.Assert}
+class. Generally, you can use assertions to
+verify if a specific condition that you want to test is true.
+<ul>
+<li>If the condition is false, the assertion method throws an
+{@link android.test.AssertionFailedError} exception, which is then typically
+reported by the test runner. You can provide a string in the first argument of
+your assertion method to give some contextual details if the assertion fails.</li>
+<li>If the condition is true, the test passes.</li>
+</ul>
+<p>In both cases, the test runner proceeds to run the other test methods in the
+test case.</p>
+
+<h3 id="test_method">Add Test Methods to Verify Your Activity</h3>
+<p>Next, add one or more test methods to verify the layout and functional
+behavior of your {@link android.app.Activity}.</p>
+<p>For example, if your {@link android.app.Activity} includes a
+{@link android.widget.TextView}, you can add a test method like this to check
+that it has the correct label text:</p>
+<pre>
+public void testMyFirstTestTextView_labelText() {
+ final String expected =
+ mFirstTestActivity.getString(R.string.my_first_test);
+ final String actual = mFirstTestText.getText().toString();
+ assertEquals(expected, actual);
+}
+</pre>
+
+<p>The {@code testMyFirstTestTextView_labelText()} method simply checks that the
+default text of the {@link android.widget.TextView} that is set by the layout
+is the same as the expected text defined in the {@code strings.xml} resource.</p>
+<p class="note"><strong>Note:</strong> When naming test methods, you can use
+an underscore to separate what is being tested from the specific case being
+tested. This style makes it easier to see exactly what cases are being tested.</p>
+<p>When doing this type of string value comparison, it’s good practice to read
+the expected string from your resources, instead of hardcoding the string in
+your comparison code. This prevents your test from easily breaking whenever the
+string definitions are modified in the resource file.</p>
+<p>To perform the comparison, pass both the expected and actual strings as
+arguments to the
+{@link junit.framework.Assert#assertEquals(java.lang.String, java.lang.String) assertEquals()}
+method. If the values are not the same, the assertion will throw an
+{@link junit.framework.AssertionFailedError} exception.</p>
+<p>If you added a {@code testPreconditions()} method, put your test methods
+after the {@code testPreconditions()} definition in your Java class.</p>
+<p>For a complete test case example, take a look at
+{@code MyFirstTestActivityTest.java} in the sample app.</p>
+
+<h2 id="build_run">Build and Run Your Test</h2>
+<p>You can build and run your test easily from the Package Explorer in
+Eclipse.</p>
+<p>To build and run your test:</p>
+<ol>
+<li>Connect an Android device to your machine. On the device or emulator, open
+the <strong>Settings</strong> menu, select <strong>Developer options</strong>
+and make sure that USB debugging is enabled.</li>
+<li>In the Project Explorer, right-click on the test class that you created
+earlier and select <strong>Run As &gt; Android Junit Test</strong>.</li>
+<li>In the Android Device Chooser dialog, select the device that you just
+connected, then click <strong>OK</strong>.</li>
+<li>In the JUnit view, verify that the test passes with no errors or failures.</li>
+</ol>
+<p>For example, if the test case passes with no errors, the result should look
+like this:</p>
+<img src="{@docRoot}images/training/activity-testing_lesson2_MyFirstTestActivityTest_result.png" alt="" />
+<p class="img-caption">
+ <strong>Figure 1.</strong> Result of a test with no errors.
+</p>
+
+
+
diff --git a/docs/html/training/activity-testing/activity-functional-testing.jd b/docs/html/training/activity-testing/activity-functional-testing.jd
new file mode 100644
index 0000000..7c8ff1d
--- /dev/null
+++ b/docs/html/training/activity-testing/activity-functional-testing.jd
@@ -0,0 +1,166 @@
+page.title=Creating Functional Tests
+trainingnavtop=true
+@jd:body
+
+<!-- This is the training bar -->
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>This lesson teaches you to</h2>
+<ol>
+ <li><a href="#test_methods">Add Test Method to Validate Functional Behavior</a>
+ <ol>
+ <li><a href="#activitymonitor">Set Up an ActivityMonitor</a></li>
+ <li><a href="#keyinput">Send Keyboard Input Using Instrumentation</a></li>
+ </ol>
+ </li>
+</ol>
+
+<h2>Try it out</h2>
+<div class="download-box">
+ <a href="http://developer.android.com/shareables/training/AndroidTestingFun.zip"
+class="button">Download the demo</a>
+ <p class="filename">AndroidTestingFun.zip</p>
+</div>
+
+</div>
+</div>
+<p>Functional testing involves verifying that individual application
+components work together as expected by the user. For example, you can create a
+functional test to verify that an {@link android.app.Activity} correctly
+launches a target {@link android.app.Activity} when the user performs a UI
+interaction.</p>
+
+<p>To create a functional test for your {@link android.app.Activity}, your test
+class should extend {@link android.test.ActivityInstrumentationTestCase2}.
+Unlike {@link android.test.ActivityUnitTestCase},
+tests in {@link android.test.ActivityInstrumentationTestCase2} can
+communicate with the Android system and send keyboard input and click events to
+the UI.</p>
+
+<p>For a complete test case example, take a look at
+{@code SenderActivityTest.java} in the sample app.</p>
+
+<h2 id="test_methods">Add Test Method to Validate Functional Behavior</h2>
+<p id="test_goals">Your functional testing goals might include:</p>
+<ul>
+<li>Verifying that a target {@link android.app.Activity} is started when a
+UI control is pushed in the sender {@link android.app.Activity}.</li>
+<li>Verifying that the target {@link android.app.Activity} displays the
+correct data based on the user's input in the sender
+{@link android.app.Activity}.</li>
+</ul>
+<p>You might implement your test method like this:</p>
+
+<pre>
+&#64;MediumTest
+public void testSendMessageToReceiverActivity() {
+ final Button sendToReceiverButton = (Button)
+ mSenderActivity.findViewById(R.id.send_message_button);
+
+ final EditText senderMessageEditText = (EditText)
+ mSenderActivity.findViewById(R.id.message_input_edit_text);
+
+ // Set up an ActivityMonitor
+ ...
+
+ // Send string input value
+ ...
+
+ // Validate that ReceiverActivity is started
+ ...
+
+ // Validate that ReceiverActivity has the correct data
+ ...
+
+ // Remove the ActivityMonitor
+ ...
+}
+</pre>
+<p>The test waits for an {@link android.app.Activity} that matches this monitor,
+otherwise returns null after a timeout elapses. If {@code ReceiverActivity} was
+started, the {@link android.app.Instrumentation.ActivityMonitor ActivityMonitor}
+that you set
+up earlier receives a hit. You can use the assertion methods to verify that
+the {@code ReceiverActivity} is indeed started, and that the hit count on the
+{@link android.app.Instrumentation.ActivityMonitor ActivityMonitor} incremented
+as expected.</p>
+
+<h2 id="activitymonitor">Set up an ActivityMonitor</h2>
+<p>To monitor a single {@link android.app.Activity} in your application, you
+can register an {@link android.app.Instrumentation.ActivityMonitor ActivityMonitor}.
+The {@link android.app.Instrumentation.ActivityMonitor ActivityMonitor} is
+notified by the system whenever an {@link android.app.Activity} that matches your criteria is started.
+If a match is found, the monitor’s hit count is updated.</p>
+<p>Generally, to use an
+{@link android.app.Instrumentation.ActivityMonitor ActivityMonitor}, you should:</p>
+<ol>
+<li>Retrieve the {@link android.app.Instrumentation} instance for your test
+case by using the
+{@link android.test.InstrumentationTestCase#getInstrumentation()} method.</li>
+<li>Add an instance of {@link android.app.Instrumentation.ActivityMonitor} to
+the current instrumentation using one of the {@link android.app.Instrumentation}
+{@code addMonitor()} methods. The match criteria can be specified as an
+{@link android.content.IntentFilter} or a class name string.</li>
+<li>Wait for the {@link android.app.Activity} to start.</li>
+<li>Verify that the monitor hits were incremented.</li>
+<li>Remove the monitor.</li>
+</ol>
+<p>For example:</p>
+<pre>
+// Set up an ActivityMonitor
+ActivityMonitor receiverActivityMonitor =
+ getInstrumentation().addMonitor(ReceiverActivity.class.getName(),
+ null, false);
+
+// Validate that ReceiverActivity is started
+TouchUtils.clickView(this, sendToReceiverButton);
+ReceiverActivity receiverActivity = (ReceiverActivity)
+ receiverActivityMonitor.waitForActivityWithTimeout(TIMEOUT_IN_MS);
+assertNotNull("ReceiverActivity is null", receiverActivity);
+assertEquals("Monitor for ReceiverActivity has not been called",
+ 1, receiverActivityMonitor.getHits());
+assertEquals("Activity is of wrong type",
+ ReceiverActivity.class, receiverActivity.getClass());
+
+// Remove the ActivityMonitor
+getInstrumentation().removeMonitor(receiverActivityMonitor);
+</pre>
+
+<h2 id="keyinput">Send Keyboard Input Using Instrumentation</h2>
+<p>If your {@link android.app.Activity} has an {@link android.widget.EditText}
+field, you might want to test that users can enter values into the
+{@link android.widget.EditText} object.</p>
+<p>Generally, to send a string input value to an {@link android.widget.EditText}
+object in {@link android.test.ActivityInstrumentationTestCase2}, you should:</p>
+<ol>
+<li>Use the {@link android.app.Instrumentation#runOnMainSync(java.lang.Runnable) runOnMainSync()}
+method to run the {@link android.view.View#requestFocus()} call synchronously
+in a loop. This way, the UI thread is blocked until focus is received.</li>
+<li>Call {@link android.app.Instrumentation#waitForIdleSync()} method to wait
+for the main thread to become idle (that is, have no more events to process).</li>
+<li>Send a text string to the {@link android.widget.EditText} by calling
+{@link android.app.Instrumentation#sendStringSync(java.lang.String)
+sendStringSync()} and pass your input string as the parameter.</p>
+</ol>
+<p>For example:</p>
+<pre>
+// Send string input value
+getInstrumentation().runOnMainSync(new Runnable() {
+ &#64;Override
+ public void run() {
+ senderMessageEditText.requestFocus();
+ }
+});
+getInstrumentation().waitForIdleSync();
+getInstrumentation().sendStringSync("Hello Android!");
+getInstrumentation().waitForIdleSync();
+</pre>
+
+
+
+
+
+
+
+
diff --git a/docs/html/training/activity-testing/activity-ui-testing.jd b/docs/html/training/activity-testing/activity-ui-testing.jd
new file mode 100644
index 0000000..644f3ca
--- /dev/null
+++ b/docs/html/training/activity-testing/activity-ui-testing.jd
@@ -0,0 +1,216 @@
+page.title=Testing UI Components
+trainingnavtop=true
+
+@jd:body
+
+<!-- This is the training bar -->
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>This lesson teaches you to</h2>
+<ol>
+ <li><a href="#testcase">Create a Test Case for UI Testing with Instrumentation</a>
+ <li><a href="#test_method">Add Test Methods to Verify UI Behavior</a>
+ <ol>
+ <li><a href="#verify_button_display">Verify Button Layout Parameters</a></li>
+ <li><a href="#verify_TextView">Verify TextView Layout Parameters</a></li>
+ <li><a href="#verify_button_behavior">Verify Button Behavior</a></li>
+ </ol>
+ </li>
+ <li><a href="#annotations">Apply Test Annotations</a></li>
+</ol>
+
+<h2>Try it out</h2>
+<div class="download-box">
+ <a href="http://developer.android.com/shareables/training/AndroidTestingFun.zip"
+class="button">Download the demo</a>
+ <p class="filename">AndroidTestingFun.zip</p>
+</div>
+
+</div>
+</div>
+
+<p>Typically, your {@link android.app.Activity} includes user interface
+components (such as buttons, editable text fields, checkboxes, and pickers) to
+allow users to interact with your Android application. This lesson shows how
+you can test an {@link android.app.Activity} with a simple push-button UI. You
+can use the same general steps to test other, more sophisticated types of UI
+components.</p>
+
+<p class="note"><strong>Note:</strong> The type of UI testing in this lesson is
+called <em>white-box testing</em> because you have the
+source code for the application that you want to test. The Android
+<a href="{@docRoot}tools/testing/testing_android.html#Instrumentation">Instrumentation</a>
+framework is suitable for creating white-box tests for UI components within an
+application. An alternative type of UI testing is <em>black-box testing</em>,
+where you may not have access to the application source. This type of testing
+is useful when you want to test how your app interacts with other apps or with
+the system. Black-box testing is not covered in this training. To learn more
+about how to perform black-box testing on your Android apps, see the
+<a href="{@docRoot}tools/testing/testing_ui.html">UI Testing guide</a>.
+<p>For a complete test case example, take a look at
+{@code ClickFunActivityTest.java} in the sample app.</p>
+
+<h2 id="testcase">Create a Test Case for UI Testing with Instrumentation</h2>
+<p>When testing an {@link android.app.Activity} that has a user interface (UI),
+the {@link android.app.Activity} under test runs in the UI thread. However, the
+test application itself runs in a separate thread in the same process as the
+application under test. This means that your test app can reference objects
+from the UI thread, but if it attempts to change properties on those objects or
+send events to the UI thread, you will usually get a {@code WrongThreadException}
+error.</p>
+<p>To safely inject {@link android.content.Intent} objects into your
+{@link android.app.Activity} or run test methods on the UI thread, you can
+extend your test class to use {@link android.test.ActivityInstrumentationTestCase2}.
+To learn more about how to run test methods on the UI thread, see
+<a href="{@docRoot}tools/testing/activity_testing.html#RunOnUIThread">Testing
+on the UI thread</a>.</p>
+
+<h3 id="fixture">Set Up Your Test Fixture</h3>
+<p>When setting up the test fixture for UI testing, you should specify the
+<a href="{@docRoot}guide/topics/ui/ui-events.html#TouchMode">touch mode</a>
+in your {@link junit.framework.TestCase#setUp()} method. Setting the touch mode
+to {@code true} prevents the UI control from taking focus when you click it
+programmatically in the test method later (for example, a button UI will just
+fire its on-click listener). Make sure that you call
+{@link android.test.ActivityInstrumentationTestCase2#setActivityInitialTouchMode(boolean) setActivityInitialTouchMode()}
+before calling {@link android.test.ActivityInstrumentationTestCase2#getActivity()}.
+</p>
+<p>For example:</ap>
+<pre>
+public class ClickFunActivityTest
+ extends ActivityInstrumentationTestCase2<ClickFunActivity> {
+ ...
+ &#64;Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ setActivityInitialTouchMode(true);
+
+ mClickFunActivity = getActivity();
+ mClickMeButton = (Button)
+ mClickFunActivity
+ .findViewById(R.id.launch_next_activity_button);
+ mInfoTextView = (TextView)
+ mClickFunActivity.findViewById(R.id.info_text_view);
+ }
+}
+</pre>
+
+<h2 id="test_methods">Add Test Methods to Validate UI Behavior</h2>
+<p id="test_goals">Your UI testing goals might include:</p>
+<ul>
+<li>Verifying that a button is displayed with the correct layout when the
+{@link android.app.Activity} is launched.</li>
+<li>Verifying that a {@link android.widget.TextView} is initially hidden.</li>
+<li>Verifying that a {@link android.widget.TextView} displays the expected string
+when a button is pushed.</li>
+</ul>
+<p>The following section demonstrates how you can implement test methods
+to perform these verifications.</p>
+
+<h3 id="verify_button_display">Verify Button Layout Parameters</h3>
+<p>You might add a test method like this to verify that a button is displayed
+correctly in your {@link android.app.Activity}:</p>
+<pre>
+&#64;MediumTest
+public void testClickMeButton_layout() {
+ final View decorView = mClickFunActivity.getWindow().getDecorView();
+
+ ViewAsserts.assertOnScreen(decorView, mClickMeButton);
+
+ final ViewGroup.LayoutParams layoutParams =
+ mClickMeButton.getLayoutParams();
+ assertNotNull(layoutParams);
+ assertEquals(layoutParams.width, WindowManager.LayoutParams.MATCH_PARENT);
+ assertEquals(layoutParams.height, WindowManager.LayoutParams.WRAP_CONTENT);
+}
+</pre>
+
+<p>In the {@link android.test.ViewAsserts#assertOnScreen(android.view.View,android.view.View) assertOnScreen()}
+method call, you should pass in the root view and the view that you are
+expecting to be present on the screen. If the expected view is not found in the
+root view, the assertion method throws an {@link junit.framework.AssertionFailedError}
+exception, otherwise the test passes.</p>
+<p>You can also verify that the layout of a {@link android.widget.Button} is
+correct by getting a reference to its {@link android.view.ViewGroup.LayoutParams}
+object, then call assertion methods to verify that the
+{@link android.widget.Button} object's width and height attributes match the
+expected values.</p>
+<p>The {@code &#64;MediumTest} annotation specifies how the test is categorized,
+relative to its absolute execution time. To learn more about using test size
+annotations, see <a href="#annotations">Apply Test Annotations</a>.</p>
+
+<h3 id="verify_TextView">Verify TextView Layout Parameters</h3>
+<p>You might add a test method like this to verify that a
+{@link android.widget.TextView} initially appears hidden in
+your {@link android.app.Activity}:</p>
+<pre>
+&#64;MediumTest
+public void testInfoTextView_layout() {
+ final View decorView = mClickFunActivity.getWindow().getDecorView();
+ ViewAsserts.assertOnScreen(decorView, mInfoTextView);
+ assertTrue(View.GONE == mInfoTextView.getVisibility());
+}
+</pre>
+<p>You can call {@link android.view.Window#getDecorView()} to get a reference
+to the decor view for the {@link android.app.Activity}. The decor view is the
+top-level ViewGroup ({@link android.widget.FrameLayout}) view in the layout
+hierarchy.</p>
+
+<h3 id="verify_button_behavior">Verify Button Behavior</h3>
+<p>You can use a test method like this to verify that a
+{@link android.widget.TextView} becomes visible when a
+{@link android.widget.Button} is pushed:</p>
+
+<pre>
+&#64;MediumTest
+public void testClickMeButton_clickButtonAndExpectInfoText() {
+ String expectedInfoText = mClickFunActivity.getString(R.string.info_text);
+ TouchUtils.clickView(this, mClickMeButton);
+ assertTrue(View.VISIBLE == mInfoTextView.getVisibility());
+ assertEquals(expectedInfoText, mInfoTextView.getText());
+}
+</pre>
+
+<p>To programmatically click a {@link android.widget.Button} in your
+test, call {@link android.test.TouchUtils#clickView(android.test.InstrumentationTestCase,android.view.View) clickView()}.
+You must pass in a reference to the test case that is being run and a reference
+to the {@link android.widget.Button} to manipulate.</p>
+
+<p class="note"><strong>Note: </strong>The {@link android.test.TouchUtils}
+helper class provides convenience methods for simulating touch interactions
+with your application. You can use these methods to simulate clicking, tapping,
+and dragging of Views or the application screen.</p>
+<p class="caution"><strong>Caution: </strong>The {@link android.test.TouchUtils}
+methods are designed to send events to the UI thread safely from the test thread.
+You should not run {@link android.test.TouchUtils} directly in the UI thread or
+any test method annotated with {@code &#64;UIThread}. Doing so might
+raise the {@code WrongThreadException}.</p>
+
+<h2 id="annotations">Apply Test Annotations</h2>
+<p>The following annotations can be applied to indicate the size of a test
+method:</p>
+<dl>
+<dt>{@link
+android.test.suitebuilder.annotation.SmallTest &#64;SmallTest}</dt>
+<dd>Marks a test that should run as part of the small tests.</dd>
+<dt>{@link
+android.test.suitebuilder.annotation.MediumTest &#64;MediumTest}</dt>
+<dd>Marks a test that should run as part of the medium tests.</dd>
+<dt>{@link android.test.suitebuilder.annotation.LargeTest &#64;LargeTest}</dt>
+<dd>Marks a test that should run as part of the large tests.</dd>
+</dl>
+<p>Typically, a short running test that take only a few milliseconds should be
+marked as a {@code &#64;SmallTest}. Longer running tests (100 milliseconds or
+more) are usually marked as {@code &#64;MediumTest}s or {@code &#64;LargeTest}s,
+depending on whether the test accesses resources on the local system only or
+remote resources over a network. For guidance on using test size annotations,
+see this <a href="https://plus.sandbox.google.com/+AndroidDevelopers/posts/TPy1EeSaSg8">Android Tools Protip</a>.</p>
+<p>You can mark up your test methods with other test annotations to control
+how the tests are organized and run. For more information on other annotations,
+see the {@link java.lang.annotation.Annotation} class reference.</p>
+
+
+
+
diff --git a/docs/html/training/activity-testing/activity-unit-testing.jd b/docs/html/training/activity-testing/activity-unit-testing.jd
new file mode 100644
index 0000000..74dcda9
--- /dev/null
+++ b/docs/html/training/activity-testing/activity-unit-testing.jd
@@ -0,0 +1,134 @@
+page.title=Creating Unit Tests
+trainingnavtop=true
+@jd:body
+
+<!-- This is the training bar -->
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>This lesson teaches you to</h2>
+<ol>
+ <li><a href="#testcase">Create a Test Case for Activity Unit Testing</a>
+ <li><a href="#test_method">Validate Launch of Another Activity</a>
+</ol>
+
+<h2>Try it out</h2>
+<div class="download-box">
+ <a href="http://developer.android.com/shareables/training/AndroidTestingFun.zip"
+class="button">Download the demo</a>
+ <p class="filename">AndroidTestingFun.zip</p>
+</div>
+
+</div>
+</div>
+
+<p>An {@link android.app.Activity} unit test is an excellent way to quickly
+verify the state of an {@link android.app.Activity} and its interactions with
+other components in isolation (that is, disconnected from the rest of the
+system). A unit test generally tests the smallest possible unit of code
+(which could be a method, class, or component), without dependencies on system
+or network resources. For example, you can write a unit test to check
+that an {@link android.app.Activity} has the correct layout or that it
+triggers an {@link android.content.Intent} object correctly.</p>
+<p>Unit tests are generally not suitable for testing complex UI interaction
+events with the system. Instead, you should use
+the {@link android.test.ActivityInstrumentationTestCase2} class, as described
+in <a href="activity-ui-testing.html">Testing UI Components</a>.</p>
+<p>This lesson shows how you can write a unit test to verify that an
+{@link android.content.Intent} is triggered to launch another
+{@link android.app.Activity}.
+Since the test runs in an isolated environment, the
+{@link android.content.Intent}
+is not actually sent to the Android system, but you can inspect that the
+{@link android.content.Intent} object's payload data is accurate.</p>
+<p>For a complete test case example, take a look at
+{@code LaunchActivityTest.java} in the sample app.</p>
+
+<p class="note"><strong>Note: </strong>To test against system or external
+dependencies, you can use mock objects from a mocking
+framework and inject them into your unit tests. To learn more about the mocking
+framework provided by Android, see
+<a href="{@docRoot}tools/testing/testing_android.html#MockObjectClasses}">Mock
+Object Classes</a>.</p>
+
+<h2 id="testcase">Create a Test Case for Activity Unit Testing</h2>
+<p>The {@link android.test.ActivityUnitTestCase} class provides support for
+isolated testing of a single {@link android.app.Activity}. To create a unit
+test for your {@link android.app.Activity}, your test class should extend
+{@link android.test.ActivityUnitTestCase}.</p>
+
+<p>The {@link android.app.Activity} in an {@link android.test.ActivityUnitTestCase}
+is not automatically started by Android Instrumentation. To start the
+{@link android.app.Activity} in isolation, you need to explicitly call the
+{@link android.test.ActivityUnitTestCase#startActivity(android.content.Intent, android.os.Bundle, java.lang.Object) startActivity()}
+method, and pass in the {@link android.content.Intent} to
+launch your target {@link android.app.Activity}.</p>
+
+<p>For example:</p>
+<pre>
+public class LaunchActivityTest
+ extends ActivityUnitTestCase&lt;LaunchActivity&gt; {
+ ...
+
+ &#64;Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mLaunchIntent = new Intent(getInstrumentation()
+ .getTargetContext(), LaunchActivity.class);
+ startActivity(mLaunchIntent, null, null);
+ final Button launchNextButton =
+ (Button) getActivity()
+ .findViewById(R.id.launch_next_activity_button);
+ }
+}
+</pre>
+
+<h2 id="test_method">Validate Launch of Another Activity</h2>
+<p id="test_goals">Your unit testing goals might include:</p>
+<ul>
+<li>Verifying that {@code LaunchActivity} fires an
+{@link android.content.Intent} when a button is pushed clicked.</li>
+<li>Verifying that the launched {@link android.content.Intent} contains the
+correct payload data.</li>
+</ul>
+
+<p>To verify if an {@link android.content.Intent} was triggered
+following the {@link android.widget.Button} click, you can use the
+{@link android.test.ActivityUnitTestCase#getStartedActivityIntent()} method.
+By using assertion methods, you can verify that the returned
+{@link android.content.Intent} is not null, and that it contains the expected
+string value to launch the next {@link android.app.Activity}. If both assertions
+evaluate to {@code true}, you've successfully verified that the
+{@link android.content.Intent} was correctly sent by your
+{@link android.app.Activity}.</p>
+
+<p>You might implement your test method like this:</p>
+<pre>
+&#64;MediumTest
+public void testNextActivityWasLaunchedWithIntent() {
+ startActivity(mLaunchIntent, null, null);
+ final Button launchNextButton =
+ (Button) getActivity()
+ .findViewById(R.id.launch_next_activity_button);
+ launchNextButton.performClick();
+
+ final Intent launchIntent = getStartedActivityIntent();
+ assertNotNull("Intent was null", launchIntent);
+ assertTrue(isFinishCalled());
+
+ final String payload =
+ launchIntent.getStringExtra(NextActivity.EXTRAS_PAYLOAD_KEY);
+ assertEquals("Payload is empty", LaunchActivity.STRING_PAYLOAD, payload);
+}
+</pre>
+<p>Because {@code LaunchActivity} runs in isolation, you cannot use the
+{@link android.test.TouchUtils} library to manipulate UI controls. To directly
+click a {@link android.widget.Button}, you can call the
+{@link android.view.View#performClick()} method instead.</p>
+
+
+
+
+
+
+
diff --git a/docs/html/training/activity-testing/index.jd b/docs/html/training/activity-testing/index.jd
new file mode 100644
index 0000000..ddede71
--- /dev/null
+++ b/docs/html/training/activity-testing/index.jd
@@ -0,0 +1,68 @@
+page.title=Testing Your Android Activity
+page.tags="testing"
+
+trainingnavtop=true
+startpage=true
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<!-- Required platform, tools, add-ons, devices, knowledge, etc. -->
+<h2>Dependencies and prerequisites</h2>
+<ul>
+ <li>Android 2.2 (API Level 8) or higher.</li>
+</ul>
+
+<h2>You Should Also Read</h2>
+<ul>
+<li><a href="{@docRoot}tools/testing/index.html">Testing
+(Developer's Guide)</a></li>
+</ul>
+
+</div>
+</div>
+
+<p>You should be writing and running tests as part of your Android application
+development cycle. Well-written tests can help you to catch bugs early in
+development and give you confidence in your code.</p>
+
+<p>A <em>test case</em> defines a set of objects and methods to run multiple
+tests independently from each other. Test cases can be organized into
+<em>test suites</em> and run programmatically, in a repeatable manner, with
+a <em>test runner</em> provided by a testing framework.</p>
+
+<p>The lessons in this class teaches you how to use the Android's custom
+testing framework that is based on the popular JUnit framework. You can
+write test cases to verify specific behavior in your application, and check for
+consistency across different Android devices. Your test cases also serve as a
+form of internal code documentation by describing the expected behavior of
+app components.</p>
+
+<h2>Lessons</h2>
+
+<!-- Create a list of the lessons in this class along with a short description
+of each lesson. These should be short and to the point. It should be clear from
+reading the summary whether someone will want to jump to a lesson or not.-->
+
+<dl>
+ <dt><b><a href="preparing-activity-testing.html">Setting Up Your Test
+Environment</a></b></dt>
+ <dd>Learn how to create your test project.</dd>
+ <dt><b><a href="activity-basic-testing.html">Creating and Running a Test
+Case</a></b></dt>
+ <dd>Learn how to write test cases to verify the
+expected properties of your {@link android.app.Activity}, and run the test
+cases with the {@code Instrumentation} test runner provided by the Android
+framework.</dd>
+ <dt><b><a href="activity-ui-testing.html">Testing UI Components</a></b></dt>
+ <dd>Learn how to test the behavior of specific UI
+components in your {@link android.app.Activity}.</dd>
+ <dt><b><a href="activity-unit-testing.html">Creating Unit Tests</a></b></dt>
+ <dd>Learn how to how to perform unit testing to
+verify the behavior of an Activity in isolation.</dd>
+ <dt><b><a href="activity-functional-testing.html">Creating Functional Tests</a></b></dt>
+ <dd>Learn how to perform functional testing to
+verify the interaction of multiple Activities.</dd>
+
diff --git a/docs/html/training/activity-testing/preparing-activity-testing.jd b/docs/html/training/activity-testing/preparing-activity-testing.jd
new file mode 100644
index 0000000..c43c9ed
--- /dev/null
+++ b/docs/html/training/activity-testing/preparing-activity-testing.jd
@@ -0,0 +1,95 @@
+page.title=Setting Up Your Test Environment
+trainingnavtop=true
+
+@jd:body
+
+<!-- This is the training bar -->
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>This lesson teaches you to</h2>
+<ol>
+ <li><a href="#eclipse">Set Up Eclipse for Testing</a></li>
+ <li><a href="#cmdline">Set Up the Command Line Interface for Testing</a></li>
+</ol>
+
+<h2>You should also read</h2>
+<ul>
+<li><a href="{@docRoot}sdk/index.html">Getting the SDK Bundle</a></li>
+<li><a href="{@docRoot}tools/testing/testing_eclipse.html">Testing from Eclipse
+with ADT</a></li>
+<li><a href="{@docRoot}tools/testing/testing_otheride.html">Testing from Other
+IDEs</a></li>
+</ul>
+
+<h2>Try it out</h2>
+<div class="download-box">
+ <a href="http://developer.android.com/shareables/training/AndroidTestingFun.zip"
+class="button">Download the demo</a>
+ <p class="filename">AndroidTestingFun.zip</p>
+</div>
+
+</div>
+</div>
+
+<p>Before you start writing and running your tests, you should set up your test
+development environment. This lesson teaches you how to set up the Eclipse
+IDE to build and run tests, and how to
+build and run tests with the Gradle framework by using the command line
+interface.</p>
+
+<p class="note"><strong>Note:</strong> To help you get started, the lessons are
+based on Eclipse with the ADT plugin. However, for your own test development, you
+are free to use the IDE of your choice or the command-line.</p>
+
+<h2 id="eclipse">Set Up Eclipse for Testing</h2>
+<p>Eclipse with the Android Developer Tools (ADT) plugin provides an integrated
+development environment for you to create, build, and run Android application
+test cases from a graphical user interface (GUI). A convenient feature that
+Eclipse provides is the ability to auto-generate a new test project that
+corresponds with your Android application project</a>.
+
+<p>To set up your test environment in Eclipse:</p>
+
+<ol>
+<li><a href="{@docRoot}sdk/installing/bundle.html">Download and install the
+Eclipse ADT plugin</a>, if you haven’t installed it yet.</li>
+<li>Import or create the Android application project that you want to test
+against.</li>
+<li>Generate a test project that corresponds to the application project under
+test. To generate a test project for the app project that you imported:</p>
+ <ol type="a">
+ <li>In the Package Explorer, right-click on your app project, then
+select <strong>Android Tools</strong> &gt; <strong>New Test Project</strong>.</li>
+ <li>In the New Android Test Project wizard, set the property
+values for your test project then click <strong>Finish</strong>.</li>
+ </ol>
+</li>
+</ol>
+<p>You should now be able to create, build, and run test
+cases from your Eclipse environment. To learn how to perform these tasks in
+Eclipse, proceed to <a href="activity-basic-testing.html">Creating and Running
+a Test Case</a>.</p>
+
+<h2 id="cmdline">Set Up the Command Line Interface for Testing</h2>
+<p>If you are using Gradle version 1.6 or higher as your build environment, you
+can build and run your Android application tests from the command line by using
+the Gradle Wrapper. Make sure that in your {@code gradle.build} file, the
+<a href={@docRoot}guide/topics/manifest/uses-sdk-element.html#min>minSdkVersion</a>
+attribute in the {@code defaultConfig} section is set to 8 or higher. You can
+refer to the sample {@code gradle.build} file that is
+included in the download bundle for this training class.</p>
+<p>To run your tests with the Gradle Wrapper:</p>
+<ol>
+ <li>Connect a physical Android device to your machine or launch the Android
+Emulator.</li>
+ <li>Run the following command from your project directory:
+ <pre>./gradlew build connectedCheck</pre>
+ </li>
+</ol>
+<p>To learn more about using Gradle for Android testing, see the
+<a href="//tools.android.com/tech-docs/new-build-system/user-guide#TOC-Testing">Gradle Plugin User Guide</a>.</p>
+<p>To learn more about using command line tools other than Gradle for test
+development, see
+<a href="{@docRoot}tools/testing/testing_otheride.html">Testing from Other IDEs</a>.</p>
+
diff --git a/docs/html/training/testing.jd b/docs/html/training/testing.jd
new file mode 100644
index 0000000..c55370d
--- /dev/null
+++ b/docs/html/training/testing.jd
@@ -0,0 +1,7 @@
+page.title=Best Practices for Testing
+page.trainingcourse=true
+
+@jd:body
+
+<p>These classes and articles provide information about how to
+test your Android application.</p>
diff --git a/docs/html/training/training_toc.cs b/docs/html/training/training_toc.cs
index 40c170e..b884620 100644
--- a/docs/html/training/training_toc.cs
+++ b/docs/html/training/training_toc.cs
@@ -1205,6 +1205,45 @@ include the action bar on devices running Android 2.1 or higher."
</li>
<!-- End security and user info -->
+ <li class="nav-section">
+ <div class="nav-section-header">
+ <a href="<?cs var:toroot ?>training/testing.html">
+ <span class="small">Best Practices for</span><br/>
+ Testing
+ </a>
+ </div>
+ <ul>
+ <li class="nav-section">
+ <div class="nav-section-header"><a href="<?cs var:toroot ?>training/activity-testing/index.html"
+ description="How to test Activities in your Android applications.">
+ Testing Your Activity
+ </a></div>
+ <ul>
+ <li><a href="<?cs var:toroot ?>training/activity-testing/preparing-activity-testing.html">
+ <span class="en">Setting Up Your Test Environment</span>
+ </a>
+ </li>
+ <li><a href="<?cs var:toroot ?>training/activity-testing/activity-basic-testing.html">
+ <span class="en">Creating and Running a Test Case</span>
+ </a>
+ </li>
+ <li><a href="<?cs var:toroot ?>training/activity-testing/activity-ui-testing.html">
+ <span class="en">Testing UI Components</span>
+ </a>
+ </li>
+ <li><a href="<?cs var:toroot ?>training/activity-testing/activity-unit-testing.html">
+ <span class="en">Creating Unit Tests</span>
+ </a>
+ </li>
+ <li><a href="<?cs var:toroot ?>training/activity-testing/activity-functional-testing.html">
+ <span class="en">Creating Functional Tests</span>
+ </a>
+ </li>
+ </ul>
+ </li>
+ </ul>
+ </li>
+ <!-- End best Testing -->
<li class="nav-section">
<div class="nav-section-header">
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java
index 1c426fd..1721bee 100644
--- a/graphics/java/android/graphics/BitmapFactory.java
+++ b/graphics/java/android/graphics/BitmapFactory.java
@@ -23,7 +23,6 @@ import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
-import java.io.BufferedInputStream;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.IOException;
@@ -545,28 +544,28 @@ public class BitmapFactory {
return null;
}
- Bitmap bm;
+ Bitmap bm = null;
Trace.traceBegin(Trace.TRACE_TAG_GRAPHICS, "decodeBitmap");
try {
- // we need mark/reset to work properly
- if (!is.markSupported()) {
- is = new BufferedInputStream(is, DECODE_BUFFER_SIZE);
- }
-
- // so we can call reset() if a given codec gives up after reading up to
- // this many bytes. FIXME: need to find out from the codecs what this
- // value should be.
- is.mark(1024);
-
+ boolean decodeGenericStream = true;
if (is instanceof AssetManager.AssetInputStream) {
final int asset = ((AssetManager.AssetInputStream) is).getAssetInt();
bm = nativeDecodeAsset(asset, outPadding, opts);
- } else {
- // pass some temp storage down to the native code. 1024 is made up,
- // but should be large enough to avoid too many small calls back
- // into is.read(...) This number is not related to the value passed
- // to mark(...) above.
+ // Do not follow the normal case.
+ decodeGenericStream = false;
+ } else if (is instanceof FileInputStream) {
+ try {
+ FileDescriptor fd = ((FileInputStream) is).getFD();
+ // decodeFileDescriptor will take care of throwing the IAE and
+ // calling setDensityFromOptions.
+ return decodeFileDescriptor(fd, outPadding, opts);
+ } catch (IOException e) {
+ // Fall through to nativeDecodeStream.
+ }
+ }
+
+ if (decodeGenericStream) {
byte [] tempStorage = null;
if (opts != null) tempStorage = opts.inTempStorage;
if (tempStorage == null) tempStorage = new byte[DECODE_BUFFER_SIZE];
@@ -610,26 +609,41 @@ public class BitmapFactory {
* no bitmap is returned (null) then padding is
* unchanged.
* @param opts null-ok; Options that control downsampling and whether the
- * image should be completely decoded, or just is size returned.
+ * image should be completely decoded, or just its size returned.
* @return the decoded bitmap, or null
*/
public static Bitmap decodeFileDescriptor(FileDescriptor fd, Rect outPadding, Options opts) {
- if (nativeIsSeekable(fd)) {
- Bitmap bm = nativeDecodeFileDescriptor(fd, outPadding, opts);
+ Bitmap bm;
+
+ Trace.traceBegin(Trace.TRACE_TAG_GRAPHICS, "decodeFileDescriptor");
+ try {
+ if (nativeIsSeekable(fd)) {
+ bm = nativeDecodeFileDescriptor(fd, outPadding, opts);
+ } else {
+ FileInputStream fis = new FileInputStream(fd);
+ // FIXME: If nativeDecodeStream grabbed the pointer to tempStorage
+ // from Options, this code would not need to be duplicated.
+ byte [] tempStorage = null;
+ if (opts != null) tempStorage = opts.inTempStorage;
+ if (tempStorage == null) tempStorage = new byte[DECODE_BUFFER_SIZE];
+ try {
+ bm = nativeDecodeStream(fis, tempStorage, outPadding, opts);
+ } finally {
+ try {
+ fis.close();
+ } catch (Throwable t) {/* ignore */}
+ }
+ }
+
if (bm == null && opts != null && opts.inBitmap != null) {
throw new IllegalArgumentException("Problem decoding into existing bitmap");
}
- return bm;
- } else {
- FileInputStream fis = new FileInputStream(fd);
- try {
- return decodeStream(fis, outPadding, opts);
- } finally {
- try {
- fis.close();
- } catch (Throwable t) {/* ignore */}
- }
+
+ setDensityFromOptions(bm, opts);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_GRAPHICS);
}
+ return bm;
}
/**
diff --git a/graphics/java/android/graphics/BitmapRegionDecoder.java b/graphics/java/android/graphics/BitmapRegionDecoder.java
index b38d107..3524b25 100644
--- a/graphics/java/android/graphics/BitmapRegionDecoder.java
+++ b/graphics/java/android/graphics/BitmapRegionDecoder.java
@@ -17,7 +17,6 @@ package android.graphics;
import android.content.res.AssetManager;
-import java.io.BufferedInputStream;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.IOException;
@@ -108,12 +107,6 @@ public final class BitmapRegionDecoder {
*/
public static BitmapRegionDecoder newInstance(InputStream is,
boolean isShareable) throws IOException {
- // we need mark/reset to work properly in JNI
-
- if (!is.markSupported()) {
- is = new BufferedInputStream(is, 16 * 1024);
- }
-
if (is instanceof AssetManager.AssetInputStream) {
return nativeNewInstance(
((AssetManager.AssetInputStream) is).getAssetInt(),
diff --git a/graphics/java/android/renderscript/Allocation.java b/graphics/java/android/renderscript/Allocation.java
index 7d05a74..ca72c25 100644
--- a/graphics/java/android/renderscript/Allocation.java
+++ b/graphics/java/android/renderscript/Allocation.java
@@ -80,7 +80,7 @@ public class Allocation extends BaseObj {
int mCurrentCount;
static HashMap<Integer, Allocation> mAllocationMap =
new HashMap<Integer, Allocation>();
- IoInputNotifier mBufferNotifier;
+ OnBufferAvailableListener mBufferNotifier;
/**
* The usage of the Allocation. These signal to RenderScript where to place
@@ -1838,26 +1838,22 @@ public class Allocation extends BaseObj {
}
/**
- * @hide
- *
* Interface to handle notification when new buffers are available via
* {@link #USAGE_IO_INPUT}. An application will receive one notification
* when a buffer is available. Additional buffers will not trigger new
* notifications until a buffer is processed.
*/
- public interface IoInputNotifier {
+ public interface OnBufferAvailableListener {
public void onBufferAvailable(Allocation a);
}
/**
- * @hide
- *
* Set a notification handler for {@link #USAGE_IO_INPUT}.
*
- * @param callback instance of the IoInputNotifier class to be called
- * when buffer arrive.
+ * @param callback instance of the OnBufferAvailableListener
+ * class to be called when buffer arrive.
*/
- public void setIoInputNotificationHandler(IoInputNotifier callback) {
+ public void setOnBufferAvailableListener(OnBufferAvailableListener callback) {
synchronized(mAllocationMap) {
mAllocationMap.put(new Integer(getID(mRS)), this);
mBufferNotifier = callback;
diff --git a/graphics/java/android/renderscript/ScriptIntrinsicColorMatrix.java b/graphics/java/android/renderscript/ScriptIntrinsicColorMatrix.java
index 6881627..32c3d15 100644
--- a/graphics/java/android/renderscript/ScriptIntrinsicColorMatrix.java
+++ b/graphics/java/android/renderscript/ScriptIntrinsicColorMatrix.java
@@ -56,8 +56,12 @@ public final class ScriptIntrinsicColorMatrix extends ScriptIntrinsic {
* this parameter is ignored. The Element type check is
* performed in the kernel launch.
*
+ * @deprecated Use the single argument version as Element is now
+ * ignored.
+ *
* @return ScriptIntrinsicColorMatrix
*/
+ @Deprecated
public static ScriptIntrinsicColorMatrix create(RenderScript rs, Element e) {
return create(rs);
}
diff --git a/graphics/java/android/renderscript/ScriptIntrinsicHistogram.java b/graphics/java/android/renderscript/ScriptIntrinsicHistogram.java
index f143326..adc2d95 100644
--- a/graphics/java/android/renderscript/ScriptIntrinsicHistogram.java
+++ b/graphics/java/android/renderscript/ScriptIntrinsicHistogram.java
@@ -151,7 +151,7 @@ public final class ScriptIntrinsicHistogram extends ScriptIntrinsic {
*
* @param ain The input image
*/
- public void forEach_dot(Allocation ain) {
+ public void forEach_Dot(Allocation ain) {
if (mOut.getType().getElement().getVectorSize() != 1) {
throw new RSIllegalArgumentException("Output vector size must be one.");
}
@@ -170,7 +170,7 @@ public final class ScriptIntrinsicHistogram extends ScriptIntrinsic {
*
* @return Script.KernelID The KernelID object.
*/
- public Script.KernelID getKernelID_seperate() {
+ public Script.KernelID getKernelID_Separate() {
return createKernelID(0, 3, null, null);
}
diff --git a/media/jni/android_media_ImageReader.cpp b/media/jni/android_media_ImageReader.cpp
index 7f1d946..92edb8a 100644
--- a/media/jni/android_media_ImageReader.cpp
+++ b/media/jni/android_media_ImageReader.cpp
@@ -155,7 +155,7 @@ CpuConsumer::LockedBuffer* JNIImageReaderContext::getLockedBuffer() {
return buffer;
}
-void JNIImageReaderContext::returnLockedBuffer(CpuConsumer::LockedBuffer * buffer) {
+void JNIImageReaderContext::returnLockedBuffer(CpuConsumer::LockedBuffer* buffer) {
mBuffers.push_back(buffer);
}
@@ -698,8 +698,11 @@ static jboolean ImageReader_imageSetup(JNIEnv* env, jobject thiz,
CpuConsumer* consumer = ctx->getCpuConsumer();
CpuConsumer::LockedBuffer* buffer = ctx->getLockedBuffer();
if (buffer == NULL) {
- ALOGE("Unable to acquire a lockedBuffer, very likely client tries to lock more than"
- "maxImages buffers");
+ ALOGW("Unable to acquire a lockedBuffer, very likely client tries to lock more than"
+ " maxImages buffers");
+ jniThrowException(env, OutOfResourcesException,
+ "Too many outstanding images, close existing images"
+ " to be able to acquire more.");
return false;
}
status_t res = consumer->lockNextBuffer(buffer);
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSelectorView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSelectorView.java
index fbae8b1..40d55cf 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSelectorView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSelectorView.java
@@ -16,6 +16,7 @@
package com.android.keyguard;
import android.animation.ObjectAnimator;
+import android.app.ActivityManager;
import android.app.PendingIntent;
import android.app.SearchManager;
import android.app.admin.DevicePolicyManager;
@@ -23,7 +24,6 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
-import android.os.Build;
import android.os.Bundle;
import android.os.PowerManager;
import android.os.UserHandle;
@@ -41,15 +41,15 @@ import com.android.internal.telephony.IccCardConstants.State;
import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.multiwaveview.GlowPadView;
import com.android.internal.widget.multiwaveview.GlowPadView.OnTriggerListener;
-import com.android.keyguard.KeyguardHostView.OnDismissAction;
public class KeyguardSelectorView extends LinearLayout implements KeyguardSecurityView {
private static final boolean DEBUG = KeyguardHostView.DEBUG;
private static final String TAG = "SecuritySelectorView";
private static final String ASSIST_ICON_METADATA_NAME =
"com.android.systemui.action_assist_icon";
- // Flag to enable/disable hotword detection on lock screen.
- private static final boolean FLAG_HOTWORD = true;
+
+ // Don't enable hotword on limited-memory devices.
+ private static final boolean ENABLE_HOTWORD = !ActivityManager.isLowRamDeviceStatic();
// TODO: Fix this to be non-static.
private static HotwordRecognizer sHotwordClient;
@@ -132,7 +132,7 @@ public class KeyguardSelectorView extends LinearLayout implements KeyguardSecuri
@Override
public void onPhoneStateChanged(int phoneState) {
- if (FLAG_HOTWORD) {
+ if (ENABLE_HOTWORD) {
// We need to stop hotword detection when a call state is not idle anymore.
if (phoneState != TelephonyManager.CALL_STATE_IDLE) {
if (DEBUG) Log.d(TAG, "Stopping due to call state not being idle");
@@ -183,7 +183,7 @@ public class KeyguardSelectorView extends LinearLayout implements KeyguardSecuri
mSecurityMessageDisplay = new KeyguardMessageArea.Helper(this);
View bouncerFrameView = findViewById(R.id.keyguard_selector_view_frame);
mBouncerFrame = bouncerFrameView.getBackground();
- if (FLAG_HOTWORD && sHotwordClient == null) {
+ if (ENABLE_HOTWORD && sHotwordClient == null) {
sHotwordClient = HotwordRecognizer.createHotwordRecognizer(getContext());
}
}
@@ -334,7 +334,7 @@ public class KeyguardSelectorView extends LinearLayout implements KeyguardSecuri
* it attempts to stop hotword detection if it's running.
*/
private void maybeStartHotwordDetector() {
- if (FLAG_HOTWORD && sHotwordClient != null) {
+ if (ENABLE_HOTWORD && sHotwordClient != null) {
if (DEBUG) Log.d(TAG, "maybeStartHotwordDetector()");
// Don't start it if the screen is off or not showing
PowerManager powerManager = (PowerManager) getContext().getSystemService(
@@ -364,7 +364,7 @@ public class KeyguardSelectorView extends LinearLayout implements KeyguardSecuri
* Stop hotword detector if HOTWORDING_ENABLED is true.
*/
private void maybeStopHotwordDetector() {
- if (FLAG_HOTWORD && sHotwordClient != null) {
+ if (ENABLE_HOTWORD && sHotwordClient != null) {
if (DEBUG) Log.d(TAG, "maybeStopHotwordDetector()");
try {
sHotwordClient.stopRecognition();
diff --git a/packages/PrintSpooler/Android.mk b/packages/PrintSpooler/Android.mk
index 8ae0302..f65fe4b 100644
--- a/packages/PrintSpooler/Android.mk
+++ b/packages/PrintSpooler/Android.mk
@@ -24,8 +24,6 @@ LOCAL_PACKAGE_NAME := PrintSpooler
LOCAL_JAVA_LIBRARIES := framework-base
-LOCAL_CERTIFICATE := platform
-
LOCAL_PROGUARD_ENABLED := disabled
include $(BUILD_PACKAGE)
diff --git a/packages/PrintSpooler/AndroidManifest.xml b/packages/PrintSpooler/AndroidManifest.xml
index ab7ea09..6fa3ed4 100644
--- a/packages/PrintSpooler/AndroidManifest.xml
+++ b/packages/PrintSpooler/AndroidManifest.xml
@@ -20,18 +20,22 @@
package="com.android.printspooler"
android:sharedUserId="android.uid.printspooler"
android:versionName="1"
- android:versionCode="1"
- coreApp="true">
+ android:versionCode="1">
- <uses-sdk android:minSdkVersion="18" android:targetSdkVersion="18"/>
+ <!-- Allows an application to call APIs that give it access to all print jobs
+ on the device. Usually an app can access only the print jobs it created.
+ -->
+ <permission
+ android:name="com.android.printspooler.permission.ACCESS_ALL_PRINT_JOBS"
+ android:label="@string/permlab_accessAllPrintJobs"
+ android:description="@string/permdesc_accessAllPrintJobs"
+ android:protectionLevel="signature" />
+ <uses-permission android:name="com.android.printspooler.permission.ACCESS_ALL_PRINT_JOBS"/>
<uses-permission android:name="android.permission.ACCESS_ALL_PRINT_JOBS"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
- <permission android:name="android.permission.BIND_PRINT_SPOOLER_SERVICE"
- android:label="@string/permlab_bindPrintSpoolerService"
- android:description="@string/permdesc_bindPrintSpoolerService"
- android:protectionLevel="signature" />
+ <uses-sdk android:minSdkVersion="18" android:targetSdkVersion="18"/>
<application
android:allowClearUserData="false"
diff --git a/packages/PrintSpooler/res/values/strings.xml b/packages/PrintSpooler/res/values/strings.xml
index ee3cf84..235a7a1 100644
--- a/packages/PrintSpooler/res/values/strings.xml
+++ b/packages/PrintSpooler/res/values/strings.xml
@@ -94,6 +94,9 @@
<!-- Template for the notificaiton label for a failed print job. [CHAR LIMIT=25] -->
<string name="failed_notification_title_template">Printer error <xliff:g id="print_job_name" example="foo.jpg">%1$s</xliff:g></string>
+ <!-- Template for the notificaiton label for a blocked print job. [CHAR LIMIT=25] -->
+ <string name="blocked_notification_title_template">Printer blocked <xliff:g id="print_job_name" example="foo.jpg">%1$s</xliff:g></string>
+
<!-- Label for the notification button for cancelling a print job. [CHAR LIMIT=25] -->
<string name="cancel">Cancel</string>
@@ -103,6 +106,9 @@
<!-- Message that there is no connection to a printer. [CHAR LIMIT=40] -->
<string name="no_connection_to_printer">No connection to printer</string>
+ <!-- Label for an unknown reason for failed or blocked print job. [CHAR LIMIT=25] -->
+ <string name="reason_unknown">unknown</string>
+
<!-- Arrays -->
<!-- Color mode labels. -->
@@ -129,12 +135,14 @@
<item>Range</item>
</string-array>
- <!-- Title of an application permission, listed so the user can choose
- whether they want to allow the application to do this. -->
- <string name="permlab_bindPrintSpoolerService">bind to a print spooler 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_bindPrintSpoolerService">Allows the holder to bind to the top-level
- interface of a print spooler service. Should never be needed for normal apps.</string>
+ <!-- Permissions -->
+
+ <!-- Title of an application permission, listed so the user can choose whether they want
+ to allow the application to do this. -->
+ <string name="permlab_accessAllPrintJobs">access all print jobs</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_accessAllPrintJobs">Allows the holder to access print jobs
+ created by another app. Should never be needed for normal apps.</string>
</resources>
diff --git a/packages/PrintSpooler/src/com/android/printspooler/FusedPrintersProvider.java b/packages/PrintSpooler/src/com/android/printspooler/FusedPrintersProvider.java
index 28fd0e0..ad8d95a 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/FusedPrintersProvider.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/FusedPrintersProvider.java
@@ -75,6 +75,8 @@ public class FusedPrintersProvider extends Loader<List<PrinterInfo>> {
private List<PrinterInfo> mFavoritePrinters;
+ private PrinterId mTrackedPrinter;
+
public FusedPrintersProvider(Context context) {
super(context);
mPersistenceManager = new PersistenceManager(context);
@@ -166,6 +168,10 @@ public class FusedPrintersProvider extends Loader<List<PrinterInfo>> {
private boolean cancelInternal() {
if (mDiscoverySession != null
&& mDiscoverySession.isPrinterDiscoveryStarted()) {
+ if (mTrackedPrinter != null) {
+ mDiscoverySession.stopPrinterStateTracking(mTrackedPrinter);
+ mTrackedPrinter = null;
+ }
mDiscoverySession.stopPrinterDiscovery();
return true;
} else if (mPersistenceManager.isReadHistoryInProgress()) {
@@ -195,10 +201,14 @@ public class FusedPrintersProvider extends Loader<List<PrinterInfo>> {
onStopLoading();
}
- public void refreshPrinter(PrinterId printerId) {
+ public void setTrackedPrinter(PrinterId printerId) {
if (isStarted() && mDiscoverySession != null
&& mDiscoverySession.isPrinterDiscoveryStarted()) {
- mDiscoverySession.requestPrinterUpdate(printerId);
+ if (mTrackedPrinter != null) {
+ mDiscoverySession.stopPrinterStateTracking(mTrackedPrinter);
+ }
+ mTrackedPrinter = printerId;
+ mDiscoverySession.startPrinterStateTracking(printerId);
}
}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/NotificationController.java b/packages/PrintSpooler/src/com/android/printspooler/NotificationController.java
index c116d37..43a751c 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/NotificationController.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/NotificationController.java
@@ -32,6 +32,7 @@ import android.os.UserHandle;
import android.print.IPrintManager;
import android.print.PrintJobInfo;
import android.print.PrintManager;
+import android.text.TextUtils;
import android.util.Log;
/**
@@ -64,22 +65,27 @@ public class NotificationController {
+ " state:" + PrintJobInfo.stateToString(printJob.getState()));
}
switch (printJob.getState()) {
- case PrintJobInfo.STATE_QUEUED: {
- createPrintingNotificaiton(printJob);
+ case PrintJobInfo.STATE_QUEUED:
+ case PrintJobInfo.STATE_STARTED: {
+ createPrintingNotification(printJob);
} break;
case PrintJobInfo.STATE_FAILED: {
- createFailedNotificaiton(printJob);
+ createFailedNotification(printJob);
} break;
case PrintJobInfo.STATE_COMPLETED:
case PrintJobInfo.STATE_CANCELED: {
removeNotification(printJob.getId());
} break;
+
+ case PrintJobInfo.STATE_BLOCKED: {
+ createBlockedNotification(printJob);
+ } break;
}
}
- private void createPrintingNotificaiton(PrintJobInfo printJob) {
+ private void createPrintingNotification(PrintJobInfo printJob) {
Notification.Builder builder = new Notification.Builder(mContext)
.setSmallIcon(R.drawable.stat_notify_print)
.setContentTitle(mContext.getString(R.string.printing_notification_title_template,
@@ -93,17 +99,36 @@ public class NotificationController {
mNotificationManager.notify(printJob.getId(), builder.build());
}
- private void createFailedNotificaiton(PrintJobInfo printJob) {
+ private void createFailedNotification(PrintJobInfo printJob) {
+ String reason = !TextUtils.isEmpty(printJob.getStateReason())
+ ? printJob.getStateReason() : mContext.getString(R.string.reason_unknown);
+
Notification.Builder builder = new Notification.Builder(mContext)
.setSmallIcon(R.drawable.stat_notify_error)
.setContentTitle(mContext.getString(R.string.failed_notification_title_template,
printJob.getLabel()))
.addAction(R.drawable.stat_notify_cancelling, mContext.getString(R.string.cancel),
createCancelIntent(printJob))
- // TODO: Use appropriate icon when assets are ready
.addAction(android.R.drawable.ic_secure, mContext.getString(R.string.restart),
createRestartIntent(printJob.getId()))
- .setContentText(printJob.getFailureReason())
+ .setContentText(reason)
+ .setWhen(System.currentTimeMillis())
+ .setOngoing(true)
+ .setShowWhen(true);
+ mNotificationManager.notify(printJob.getId(), builder.build());
+ }
+
+ private void createBlockedNotification(PrintJobInfo printJob) {
+ String reason = !TextUtils.isEmpty(printJob.getStateReason())
+ ? printJob.getStateReason() : mContext.getString(R.string.reason_unknown);
+
+ Notification.Builder builder = new Notification.Builder(mContext)
+ .setSmallIcon(R.drawable.stat_notify_error)
+ .setContentTitle(mContext.getString(R.string.blocked_notification_title_template,
+ printJob.getLabel()))
+ .addAction(R.drawable.stat_notify_cancelling, mContext.getString(R.string.cancel),
+ createCancelIntent(printJob))
+ .setContentText(reason)
.setWhen(System.currentTimeMillis())
.setOngoing(true)
.setShowWhen(true);
diff --git a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
index 607be90..520331c 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
@@ -473,6 +473,11 @@ public class PrintJobConfigActivity extends Activity {
mControllerState = CONTROLLER_STATE_WRITE_COMPLETED;
+ // Update the document size.
+ File file = PrintSpoolerService.peekInstance()
+ .generateFileForPrintJob(mPrintJobId);
+ mDocument.info.setDataSize(file.length());
+
// Update which pages we have fetched.
mDocument.pages = PageRangeUtils.normalize(pages);
@@ -1117,7 +1122,7 @@ public class PrintJobConfigActivity extends Activity {
(Loader<?>) getLoaderManager().getLoader(
LOADER_ID_PRINTERS_LOADER);
if (printersLoader != null) {
- printersLoader.refreshPrinter(printer.getId());
+ printersLoader.setTrackedPrinter(printer.getId());
}
}
}
@@ -1351,10 +1356,6 @@ public class PrintJobConfigActivity extends Activity {
return mEditorState == EDITOR_STATE_CONFIRMED_PRINT;
}
-// public void confirmPreview() {
-// mEditorState = EDITOR_STATE_CONFIRMED_PREVIEW;
-// }
-
public PageRange[] getRequestedPages() {
if (hasErrors()) {
return null;
@@ -1374,7 +1375,7 @@ public class PrintJobConfigActivity extends Activity {
toIndex = Integer.parseInt(range.substring(
dashIndex + 1, range.length())) - 1;
} else {
- fromIndex = toIndex = Integer.parseInt(range);
+ fromIndex = toIndex = Integer.parseInt(range) - 1;
}
PageRange pageRange = new PageRange(fromIndex, toIndex);
diff --git a/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java b/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java
index c1f4180..dd2598c 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java
@@ -335,7 +335,9 @@ public final class PrintSpoolerService extends Service {
final boolean sameState = (state == printJob.getState())
|| (state == PrintJobInfo.STATE_ANY)
|| (state == PrintJobInfo.STATE_ANY_VISIBLE_TO_CLIENTS
- && printJob.getState() > PrintJobInfo.STATE_CREATED);
+ && isStateVisibleToUser(printJob.getState()))
+ || (state == PrintJobInfo.STATE_ANY_ACTIVE
+ && isActiveState(printJob.getState()));
if (sameComponent && sameAppId && sameState) {
if (foundPrintJobs == null) {
foundPrintJobs = new ArrayList<PrintJobInfo>();
@@ -347,6 +349,11 @@ public final class PrintSpoolerService extends Service {
return foundPrintJobs;
}
+ private boolean isStateVisibleToUser(int state) {
+ return (isActiveState(state) && (state == PrintJobInfo.STATE_FAILED
+ || state == PrintJobInfo.STATE_COMPLETED|| state == PrintJobInfo.STATE_CANCELED));
+ }
+
public PrintJobInfo getPrintJobInfo(int printJobId, int appId) {
synchronized (mLock) {
final int printJobCount = mPrintJobs.size();
@@ -389,14 +396,12 @@ public final class PrintSpoolerService extends Service {
switch (printJob.getState()) {
case PrintJobInfo.STATE_QUEUED:
- case PrintJobInfo.STATE_STARTED: {
- // We have a print job that was queued or started in the
- // past
- // but the device battery died or a crash occurred. In this
- // case
- // we assume the print job failed and let the user decide
- // whether
- // to restart the job or just
+ case PrintJobInfo.STATE_STARTED:
+ case PrintJobInfo.STATE_BLOCKED: {
+ // We have a print job that was queued or started or blocked in
+ // the past but the device battery died or a crash occurred. In
+ // this case we assume the print job failed and let the user
+ // decide whether to restart the job or just cancel it.
setPrintJobState(printJob.getId(), PrintJobInfo.STATE_FAILED,
getString(R.string.no_connection_to_printer));
}
@@ -501,7 +506,7 @@ public final class PrintSpoolerService extends Service {
success = true;
printJob.setState(state);
- printJob.setFailureReason(error);
+ printJob.setStateReason(error);
mNotificationController.onPrintJobStateChanged(printJob);
if (DEBUG_PRINT_JOB_LIFECYCLE) {
@@ -568,7 +573,8 @@ public final class PrintSpoolerService extends Service {
private boolean isActiveState(int printJobState) {
return printJobState == PrintJobInfo.STATE_CREATED
|| printJobState == PrintJobInfo.STATE_QUEUED
- || printJobState == PrintJobInfo.STATE_STARTED;
+ || printJobState == PrintJobInfo.STATE_STARTED
+ || printJobState == PrintJobInfo.STATE_BLOCKED;
}
public boolean setPrintJobTag(int printJobId, String tag) {
diff --git a/packages/SystemUI/res/drawable-hdpi/arrow_dashed.png b/packages/SystemUI/res/drawable-hdpi/arrow_dashed.png
deleted file mode 100644
index a8075d5..0000000
--- a/packages/SystemUI/res/drawable-hdpi/arrow_dashed.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/btn_cling_normal.9.png b/packages/SystemUI/res/drawable-hdpi/btn_cling_normal.9.png
deleted file mode 100644
index aea8beb..0000000
--- a/packages/SystemUI/res/drawable-hdpi/btn_cling_normal.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/btn_cling_pressed.9.png b/packages/SystemUI/res/drawable-hdpi/btn_cling_pressed.9.png
deleted file mode 100644
index ebefd20..0000000
--- a/packages/SystemUI/res/drawable-hdpi/btn_cling_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/btn_default_small_normal.9.png b/packages/SystemUI/res/drawable-hdpi/btn_default_small_normal.9.png
deleted file mode 100644
index 6f456f3..0000000
--- a/packages/SystemUI/res/drawable-hdpi/btn_default_small_normal.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/btn_default_small_normal_disable.9.png b/packages/SystemUI/res/drawable-hdpi/btn_default_small_normal_disable.9.png
deleted file mode 100644
index e592ae6..0000000
--- a/packages/SystemUI/res/drawable-hdpi/btn_default_small_normal_disable.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/btn_default_small_normal_disable_focused.9.png b/packages/SystemUI/res/drawable-hdpi/btn_default_small_normal_disable_focused.9.png
deleted file mode 100644
index c1f87a7..0000000
--- a/packages/SystemUI/res/drawable-hdpi/btn_default_small_normal_disable_focused.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/btn_default_small_pressed.9.png b/packages/SystemUI/res/drawable-hdpi/btn_default_small_pressed.9.png
deleted file mode 100644
index 2d16eda..0000000
--- a/packages/SystemUI/res/drawable-hdpi/btn_default_small_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/btn_default_small_selected.9.png b/packages/SystemUI/res/drawable-hdpi/btn_default_small_selected.9.png
deleted file mode 100644
index 0749413..0000000
--- a/packages/SystemUI/res/drawable-hdpi/btn_default_small_selected.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/recents_blue_glow.9.png b/packages/SystemUI/res/drawable-hdpi/recents_blue_glow.9.png
deleted file mode 100644
index b5d8518..0000000
--- a/packages/SystemUI/res/drawable-hdpi/recents_blue_glow.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/recents_thumbnail_bg_dragging.9.png b/packages/SystemUI/res/drawable-hdpi/recents_thumbnail_bg_dragging.9.png
index 652f66f..080f2f2 100644
--- a/packages/SystemUI/res/drawable-hdpi/recents_thumbnail_bg_dragging.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/recents_thumbnail_bg_dragging.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/recents_thumbnail_bg_normal.9.png b/packages/SystemUI/res/drawable-hdpi/recents_thumbnail_bg_normal.9.png
index d000f7e..8b45500 100644
--- a/packages/SystemUI/res/drawable-hdpi/recents_thumbnail_bg_normal.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/recents_thumbnail_bg_normal.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/recents_thumbnail_bg_press.9.png b/packages/SystemUI/res/drawable-hdpi/recents_thumbnail_bg_press.9.png
index 288d818..e591a7b 100644
--- a/packages/SystemUI/res/drawable-hdpi/recents_thumbnail_bg_press.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/recents_thumbnail_bg_press.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/screenshot_panel.9.png b/packages/SystemUI/res/drawable-hdpi/screenshot_panel.9.png
index 2509321..da56dcc 100644
--- a/packages/SystemUI/res/drawable-hdpi/screenshot_panel.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/screenshot_panel.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_alarm.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_alarm.png
index 773d418..2c55017 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_alarm.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_alarm.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_device_access_location_found.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_device_access_location_found.png
index ddf6b12..9befc34 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_device_access_location_found.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_device_access_location_found.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_ringer_silent.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_ringer_silent.png
index 859f7b1..58f67d0 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_ringer_silent.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_ringer_silent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_ringer_vibrate.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_ringer_vibrate.png
index 2f2f291..b794c9a 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_ringer_vibrate.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_ringer_vibrate.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0.png
index de6988f..6253d9a 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully.png
index e322aa1..6253d9a 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1.png
index cf9c992..0bed6d9 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully.png
index 4892842..0b27331 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2.png
index 4273a52..6bb92a3 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully.png
index 201689b..c77c37f 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3.png
index 0457c50..92e6837 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully.png
index 22dc516..269eae2 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4.png
index 2fdea79..ac2eaf0 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully.png
index 8c4ed12..d9da0d9 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_null.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_null.png
index 56c497a..e02a84b 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_null.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_null.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_sync.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_sync.png
index 9013bc6..2dc2b17 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_sync.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_sync.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_sync_error.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_sync_error.png
index 38d04f2..70f839f 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_sync_error.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_sync_error.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/status_bar_bg_tile.png b/packages/SystemUI/res/drawable-hdpi/status_bar_bg_tile.png
deleted file mode 100644
index aee197c..0000000
--- a/packages/SystemUI/res/drawable-hdpi/status_bar_bg_tile.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/status_bar_close_off.9.png b/packages/SystemUI/res/drawable-hdpi/status_bar_close_off.9.png
index 0c301ab..6feb622 100644
--- a/packages/SystemUI/res/drawable-hdpi/status_bar_close_off.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/status_bar_close_off.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/status_bar_close_on.9.png b/packages/SystemUI/res/drawable-hdpi/status_bar_close_on.9.png
index ec0424a..eeee60f 100644
--- a/packages/SystemUI/res/drawable-hdpi/status_bar_close_on.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/status_bar_close_on.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/title_bar_shadow.9.png b/packages/SystemUI/res/drawable-hdpi/title_bar_shadow.9.png
deleted file mode 100644
index 4650417..0000000
--- a/packages/SystemUI/res/drawable-hdpi/title_bar_shadow.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/arrow_dashed.png b/packages/SystemUI/res/drawable-mdpi/arrow_dashed.png
deleted file mode 100644
index c17c668..0000000
--- a/packages/SystemUI/res/drawable-mdpi/arrow_dashed.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/btn_cling_normal.9.png b/packages/SystemUI/res/drawable-mdpi/btn_cling_normal.9.png
deleted file mode 100644
index 43a407e..0000000
--- a/packages/SystemUI/res/drawable-mdpi/btn_cling_normal.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/btn_cling_pressed.9.png b/packages/SystemUI/res/drawable-mdpi/btn_cling_pressed.9.png
deleted file mode 100644
index bf0c8cb..0000000
--- a/packages/SystemUI/res/drawable-mdpi/btn_cling_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/btn_default_small_normal.9.png b/packages/SystemUI/res/drawable-mdpi/btn_default_small_normal.9.png
deleted file mode 100644
index 9b59b05..0000000
--- a/packages/SystemUI/res/drawable-mdpi/btn_default_small_normal.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/btn_default_small_normal_disable.9.png b/packages/SystemUI/res/drawable-mdpi/btn_default_small_normal_disable.9.png
deleted file mode 100644
index b517af6..0000000
--- a/packages/SystemUI/res/drawable-mdpi/btn_default_small_normal_disable.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/btn_default_small_normal_disable_focused.9.png b/packages/SystemUI/res/drawable-mdpi/btn_default_small_normal_disable_focused.9.png
deleted file mode 100644
index 019f33a..0000000
--- a/packages/SystemUI/res/drawable-mdpi/btn_default_small_normal_disable_focused.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/btn_default_small_pressed.9.png b/packages/SystemUI/res/drawable-mdpi/btn_default_small_pressed.9.png
deleted file mode 100644
index 6ce1bd3..0000000
--- a/packages/SystemUI/res/drawable-mdpi/btn_default_small_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/btn_default_small_selected.9.png b/packages/SystemUI/res/drawable-mdpi/btn_default_small_selected.9.png
deleted file mode 100644
index 0633543..0000000
--- a/packages/SystemUI/res/drawable-mdpi/btn_default_small_selected.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/recents_blue_glow.9.png b/packages/SystemUI/res/drawable-mdpi/recents_blue_glow.9.png
deleted file mode 100644
index 5744885..0000000
--- a/packages/SystemUI/res/drawable-mdpi/recents_blue_glow.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/recents_thumbnail_bg_dragging.9.png b/packages/SystemUI/res/drawable-mdpi/recents_thumbnail_bg_dragging.9.png
index 6f4d658..60dc3f2 100644
--- a/packages/SystemUI/res/drawable-mdpi/recents_thumbnail_bg_dragging.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/recents_thumbnail_bg_dragging.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/recents_thumbnail_bg_normal.9.png b/packages/SystemUI/res/drawable-mdpi/recents_thumbnail_bg_normal.9.png
index f19dc93..4b7de52 100644
--- a/packages/SystemUI/res/drawable-mdpi/recents_thumbnail_bg_normal.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/recents_thumbnail_bg_normal.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/recents_thumbnail_bg_press.9.png b/packages/SystemUI/res/drawable-mdpi/recents_thumbnail_bg_press.9.png
index 10e4fd2..7dfea4c 100644
--- a/packages/SystemUI/res/drawable-mdpi/recents_thumbnail_bg_press.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/recents_thumbnail_bg_press.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/screenshot_panel.9.png b/packages/SystemUI/res/drawable-mdpi/screenshot_panel.9.png
index be1cd31..295e91f 100644
--- a/packages/SystemUI/res/drawable-mdpi/screenshot_panel.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/screenshot_panel.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_alarm.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_alarm.png
index 7640c87..c6dc466 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_alarm.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_alarm.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_device_access_location_found.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_device_access_location_found.png
index f698605..2e24f6f 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_device_access_location_found.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_device_access_location_found.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_ringer_silent.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_ringer_silent.png
index 24717d7..1e05a91 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_ringer_silent.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_ringer_silent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_ringer_vibrate.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_ringer_vibrate.png
index a77fe7f..f4afa52 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_ringer_vibrate.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_ringer_vibrate.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0.png
index 43f5468..55173f8 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully.png
index cadcd03..55173f8 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1.png
index 54e0685..6649d7c 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully.png
index 2efaf45..dcfe5b4 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2.png
index d3bc458..be3fe62 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully.png
index 9c3f44c..734c52a 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3.png
index a7ba08a..0deb868 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully.png
index e16bee6..d808990 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4.png
index 7e1e8de..f890c2b 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully.png
index e599443..0e11ce8 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_null.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_null.png
index 688b6d6..1ffeaa3 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_null.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_null.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_sync.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_sync.png
index 1cacf93..ad5b2ff 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_sync.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_sync.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_sync_error.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_sync_error.png
index 5425af4..6db607d 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_sync_error.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_sync_error.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_bg_tile.png b/packages/SystemUI/res/drawable-mdpi/status_bar_bg_tile.png
deleted file mode 100644
index 6579ff9..0000000
--- a/packages/SystemUI/res/drawable-mdpi/status_bar_bg_tile.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_close_off.9.png b/packages/SystemUI/res/drawable-mdpi/status_bar_close_off.9.png
index 5c577cb..bd1cd12 100644
--- a/packages/SystemUI/res/drawable-mdpi/status_bar_close_off.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/status_bar_close_off.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_close_on.9.png b/packages/SystemUI/res/drawable-mdpi/status_bar_close_on.9.png
index 7efb502..c73ff35 100644
--- a/packages/SystemUI/res/drawable-mdpi/status_bar_close_on.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/status_bar_close_on.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/title_bar_shadow.9.png b/packages/SystemUI/res/drawable-mdpi/title_bar_shadow.9.png
deleted file mode 100644
index f334023..0000000
--- a/packages/SystemUI/res/drawable-mdpi/title_bar_shadow.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/heads_up_window_bg.9.png b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/heads_up_window_bg.9.png
new file mode 100644
index 0000000..586a738
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/heads_up_window_bg.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/notification_panel_bg.9.png b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/notification_panel_bg.9.png
new file mode 100644
index 0000000..8703e1d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/notification_panel_bg.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/notify_panel_clock_bg_normal.9.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/notify_panel_clock_bg_normal.9.png
deleted file mode 100644
index 88137e8..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/notify_panel_clock_bg_normal.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/notify_panel_clock_bg_pressed.9.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/notify_panel_clock_bg_pressed.9.png
deleted file mode 100644
index 6507a51..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/notify_panel_clock_bg_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/recents_blue_glow.9.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/recents_blue_glow.9.png
deleted file mode 100644
index 4ac131a..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/recents_blue_glow.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-hdpi/sysbar_notification_panel_bg.9.png b/packages/SystemUI/res/drawable-sw720dp-hdpi/sysbar_notification_panel_bg.9.png
deleted file mode 100644
index 0c20ba2..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-hdpi/sysbar_notification_panel_bg.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/notify_panel_clock_bg_normal.9.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/notify_panel_clock_bg_normal.9.png
deleted file mode 100644
index 798f589..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/notify_panel_clock_bg_normal.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/notify_panel_clock_bg_pressed.9.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/notify_panel_clock_bg_pressed.9.png
deleted file mode 100644
index 73247e5..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/notify_panel_clock_bg_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/recents_blue_glow.9.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/recents_blue_glow.9.png
deleted file mode 100644
index 4362836..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/recents_blue_glow.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-mdpi/sysbar_notification_panel_bg.9.png b/packages/SystemUI/res/drawable-sw720dp-mdpi/sysbar_notification_panel_bg.9.png
deleted file mode 100644
index 56cd238..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-mdpi/sysbar_notification_panel_bg.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-tvdpi/sysbar_notification_panel_bg.9.png b/packages/SystemUI/res/drawable-sw720dp-tvdpi/sysbar_notification_panel_bg.9.png
deleted file mode 100644
index 571a7a5..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-tvdpi/sysbar_notification_panel_bg.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/notify_panel_clock_bg_normal.9.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/notify_panel_clock_bg_normal.9.png
deleted file mode 100644
index 2b46c89..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/notify_panel_clock_bg_normal.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/notify_panel_clock_bg_pressed.9.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/notify_panel_clock_bg_pressed.9.png
deleted file mode 100644
index dd476b7..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/notify_panel_clock_bg_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/recents_blue_glow.9.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/recents_blue_glow.9.png
deleted file mode 100644
index 3938502..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/recents_blue_glow.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw720dp-xhdpi/sysbar_notification_panel_bg.9.png b/packages/SystemUI/res/drawable-sw720dp-xhdpi/sysbar_notification_panel_bg.9.png
deleted file mode 100644
index 3f05767..0000000
--- a/packages/SystemUI/res/drawable-sw720dp-xhdpi/sysbar_notification_panel_bg.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/arrow_dashed.png b/packages/SystemUI/res/drawable-xhdpi/arrow_dashed.png
deleted file mode 100644
index c26ed9c..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/arrow_dashed.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/btn_cling_normal.9.png b/packages/SystemUI/res/drawable-xhdpi/btn_cling_normal.9.png
deleted file mode 100644
index 35511d6..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/btn_cling_normal.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/btn_cling_pressed.9.png b/packages/SystemUI/res/drawable-xhdpi/btn_cling_pressed.9.png
deleted file mode 100644
index a38b40f..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/btn_cling_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/btn_default_small_normal.9.png b/packages/SystemUI/res/drawable-xhdpi/btn_default_small_normal.9.png
deleted file mode 100644
index 5e601d2..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/btn_default_small_normal.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/btn_default_small_normal_disable.9.png b/packages/SystemUI/res/drawable-xhdpi/btn_default_small_normal_disable.9.png
deleted file mode 100644
index ed92cd0..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/btn_default_small_normal_disable.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/btn_default_small_normal_disable_focused.9.png b/packages/SystemUI/res/drawable-xhdpi/btn_default_small_normal_disable_focused.9.png
deleted file mode 100644
index f77dbfb..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/btn_default_small_normal_disable_focused.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/btn_default_small_pressed.9.png b/packages/SystemUI/res/drawable-xhdpi/btn_default_small_pressed.9.png
deleted file mode 100644
index e34107b..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/btn_default_small_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/btn_default_small_selected.9.png b/packages/SystemUI/res/drawable-xhdpi/btn_default_small_selected.9.png
deleted file mode 100644
index 8f70177..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/btn_default_small_selected.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/recents_blue_glow.9.png b/packages/SystemUI/res/drawable-xhdpi/recents_blue_glow.9.png
deleted file mode 100644
index e1e08c6..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/recents_blue_glow.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/recents_thumbnail_bg_dragging.9.png b/packages/SystemUI/res/drawable-xhdpi/recents_thumbnail_bg_dragging.9.png
index 1d097c5..79d1b3c 100644
--- a/packages/SystemUI/res/drawable-xhdpi/recents_thumbnail_bg_dragging.9.png
+++ b/packages/SystemUI/res/drawable-xhdpi/recents_thumbnail_bg_dragging.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/recents_thumbnail_bg_normal.9.png b/packages/SystemUI/res/drawable-xhdpi/recents_thumbnail_bg_normal.9.png
index 80fc849..c57ec67 100644
--- a/packages/SystemUI/res/drawable-xhdpi/recents_thumbnail_bg_normal.9.png
+++ b/packages/SystemUI/res/drawable-xhdpi/recents_thumbnail_bg_normal.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/recents_thumbnail_bg_press.9.png b/packages/SystemUI/res/drawable-xhdpi/recents_thumbnail_bg_press.9.png
index 5bae56d..f01a79e 100644
--- a/packages/SystemUI/res/drawable-xhdpi/recents_thumbnail_bg_press.9.png
+++ b/packages/SystemUI/res/drawable-xhdpi/recents_thumbnail_bg_press.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/screenshot_panel.9.png b/packages/SystemUI/res/drawable-xhdpi/screenshot_panel.9.png
index c096c7a..511537a 100644
--- a/packages/SystemUI/res/drawable-xhdpi/screenshot_panel.9.png
+++ b/packages/SystemUI/res/drawable-xhdpi/screenshot_panel.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_alarm.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_alarm.png
index c8882e0..8bca860 100644
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_alarm.png
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_alarm.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_device_access_location_found.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_device_access_location_found.png
index dbd370d..a7f0017 100644
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_device_access_location_found.png
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_device_access_location_found.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_ringer_silent.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_ringer_silent.png
index 19fa2e8..662d062 100644
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_ringer_silent.png
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_ringer_silent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_ringer_vibrate.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_ringer_vibrate.png
index bc41395..18be9c0 100644
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_ringer_vibrate.png
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_ringer_vibrate.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0.png
index f5843ad..8b34373 100644
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0.png
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_fully.png
index df5138e..8b34373 100644
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_fully.png
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1.png
index 41a46ed..610e78f 100644
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1.png
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_fully.png
index a76bca3..f682a0e 100644
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_fully.png
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2.png
index d4dca0b..5bb372e 100644
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2.png
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_fully.png
index a91f099..ef05975 100644
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_fully.png
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3.png
index 33e8072..d556733 100644
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3.png
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_fully.png
index e1c0f71..c5088b5 100644
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_fully.png
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4.png
index cad7427..e1bd8bd 100644
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4.png
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_fully.png
index c36c6d9..c82a435 100644
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_fully.png
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_null.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_null.png
index 674be33..298b27d 100644
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_null.png
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_null.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_sync.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_sync.png
index ab6f812..75b002d 100644
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_sync.png
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_sync.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_sync_error.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_sync_error.png
index a7780cf..6276f47 100644
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_sync_error.png
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_sync_error.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/status_bar_bg_tile.png b/packages/SystemUI/res/drawable-xhdpi/status_bar_bg_tile.png
deleted file mode 100644
index d01b117..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/status_bar_bg_tile.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/status_bar_close_off.9.png b/packages/SystemUI/res/drawable-xhdpi/status_bar_close_off.9.png
index 98d0cfb..1fed081 100644
--- a/packages/SystemUI/res/drawable-xhdpi/status_bar_close_off.9.png
+++ b/packages/SystemUI/res/drawable-xhdpi/status_bar_close_off.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/status_bar_close_on.9.png b/packages/SystemUI/res/drawable-xhdpi/status_bar_close_on.9.png
index 17f4169..e931314 100644
--- a/packages/SystemUI/res/drawable-xhdpi/status_bar_close_on.9.png
+++ b/packages/SystemUI/res/drawable-xhdpi/status_bar_close_on.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/title_bar_shadow.9.png b/packages/SystemUI/res/drawable-xhdpi/title_bar_shadow.9.png
deleted file mode 100644
index 89f14db..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/title_bar_shadow.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/heads_up_window_bg.9.png b/packages/SystemUI/res/drawable-xxhdpi/heads_up_window_bg.9.png
new file mode 100644
index 0000000..586a738
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/heads_up_window_bg.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_menu_share.png b/packages/SystemUI/res/drawable-xxhdpi/ic_menu_share.png
new file mode 100644
index 0000000..d450531
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_menu_share.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_15.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_15.png
new file mode 100644
index 0000000..0a46dde
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_bang_orange.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_bang_orange.png
new file mode 100644
index 0000000..2b333d7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_bang_orange.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_bang_red.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_bang_red.png
new file mode 100644
index 0000000..4c71154
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_bang_red.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_bang_white.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_bang_white.png
new file mode 100644
index 0000000..976a36b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_bang_white.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_charge_0.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_charge_0.png
new file mode 100644
index 0000000..82d4806
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_charge_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_charge_15.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_charge_15.png
new file mode 100644
index 0000000..96d39db
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_charge_15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_highlight.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_highlight.png
new file mode 100644
index 0000000..0df6203
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_highlight.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_highlight_land.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_highlight_land.png
new file mode 100644
index 0000000..b400b14
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_highlight_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/notification_panel_bg.9.png b/packages/SystemUI/res/drawable-xxhdpi/notification_panel_bg.9.png
new file mode 100644
index 0000000..adcdcb7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/notification_panel_bg.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/recents_thumbnail_bg_dragging.9.png b/packages/SystemUI/res/drawable-xxhdpi/recents_thumbnail_bg_dragging.9.png
new file mode 100644
index 0000000..c424ffe
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/recents_thumbnail_bg_dragging.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/recents_thumbnail_bg_normal.9.png b/packages/SystemUI/res/drawable-xxhdpi/recents_thumbnail_bg_normal.9.png
new file mode 100644
index 0000000..a446448
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/recents_thumbnail_bg_normal.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/recents_thumbnail_bg_press.9.png b/packages/SystemUI/res/drawable-xxhdpi/recents_thumbnail_bg_press.9.png
new file mode 100644
index 0000000..b7bbd82
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/recents_thumbnail_bg_press.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/screenshot_panel.9.png b/packages/SystemUI/res/drawable-xxhdpi/screenshot_panel.9.png
new file mode 100644
index 0000000..45259d7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/screenshot_panel.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_alarm.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_alarm.png
index ed4b8c4..d42d9d6 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_alarm.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_alarm.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_device_access_location_found.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_device_access_location_found.png
index 8e00f6d..ad34d49 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_device_access_location_found.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_device_access_location_found.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_ringer_silent.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_ringer_silent.png
index 4e511c6..aabf0aa 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_ringer_silent.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_ringer_silent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_ringer_vibrate.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_ringer_vibrate.png
index efd0ca6..654c2a5 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_ringer_vibrate.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_ringer_vibrate.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_0.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_0.png
index 18f63e5..361ff48 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_0.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_0_fully.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_0_fully.png
index 8106087..937839b 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_0_fully.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_0_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_1.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_1.png
index d863597..d185a4d 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_1.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_1_fully.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_1_fully.png
index 01fce1a..2bd6eb1 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_1_fully.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_2.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_2.png
index f9ee187..9594607 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_2.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_2_fully.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_2_fully.png
index e72fda6..aad369e 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_2_fully.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_3.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_3.png
index a1540d7..6f9f50c 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_3.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_3_fully.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_3_fully.png
index eebc585..c76e188 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_3_fully.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_4.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_4.png
index bf22fbb..75a182f 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_4.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_4_fully.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_4_fully.png
index 754e3b9..1889813 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_4_fully.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_null.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_null.png
index 78e94c6..b388b8f 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_null.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_null.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_sync.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_sync.png
index e36bf10..99b2fff 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_sync.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_sync.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_sync_error.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_sync_error.png
index 274b02f..2f6a4c0 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_sync_error.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_sync_error.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/status_bar_close_off.9.png b/packages/SystemUI/res/drawable-xxhdpi/status_bar_close_off.9.png
new file mode 100644
index 0000000..d50ff85
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/status_bar_close_off.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/status_bar_close_on.9.png b/packages/SystemUI/res/drawable-xxhdpi/status_bar_close_on.9.png
new file mode 100644
index 0000000..5d27ccd
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/status_bar_close_on.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/title_bar_shadow.9.png b/packages/SystemUI/res/drawable-xxhdpi/title_bar_shadow.9.png
new file mode 100644
index 0000000..e86f891
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/title_bar_shadow.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable/btn_default_small.xml b/packages/SystemUI/res/drawable/btn_default_small.xml
deleted file mode 100644
index 5485ea0..0000000
--- a/packages/SystemUI/res/drawable/btn_default_small.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_window_focused="false" android:state_enabled="true"
- android:drawable="@drawable/btn_default_small_normal" />
- <item android:state_window_focused="false" android:state_enabled="false"
- android:drawable="@drawable/btn_default_small_normal_disable" />
- <item android:state_pressed="true"
- android:drawable="@drawable/btn_default_small_pressed" />
- <item android:state_focused="true" android:state_enabled="true"
- android:drawable="@drawable/btn_default_small_selected" />
- <item android:state_enabled="true"
- android:drawable="@drawable/btn_default_small_normal" />
- <item android:state_focused="true"
- android:drawable="@drawable/btn_default_small_normal_disable_focused" />
- <item
- android:drawable="@drawable/btn_default_small_normal_disable" />
-</selector>
-
diff --git a/packages/SystemUI/res/drawable/cling_button_bg.xml b/packages/SystemUI/res/drawable/cling_button_bg.xml
deleted file mode 100644
index d175f53..0000000
--- a/packages/SystemUI/res/drawable/cling_button_bg.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_pressed="true" android:drawable="@drawable/btn_cling_pressed" />
- <item android:drawable="@drawable/btn_cling_normal" />
-</selector> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/notify_panel_clock_bg.xml b/packages/SystemUI/res/drawable/notify_panel_clock_bg.xml
deleted file mode 100644
index c83d878..0000000
--- a/packages/SystemUI/res/drawable/notify_panel_clock_bg.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_pressed="true"
- android:drawable="@drawable/notify_panel_clock_bg_pressed" />
- <item android:drawable="@drawable/notify_panel_clock_bg_normal" />
-</selector>
-
diff --git a/packages/SystemUI/res/drawable/status_bar_bg.xml b/packages/SystemUI/res/drawable/status_bar_bg.xml
deleted file mode 100644
index 403493b..0000000
--- a/packages/SystemUI/res/drawable/status_bar_bg.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<bitmap
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:tileMode="repeat"
- android:src="@drawable/status_bar_bg_tile"
- />
diff --git a/packages/SystemUI/res/layout-land/status_bar_help.xml b/packages/SystemUI/res/layout-land/status_bar_help.xml
deleted file mode 100644
index a885b86..0000000
--- a/packages/SystemUI/res/layout-land/status_bar_help.xml
+++ /dev/null
@@ -1,71 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<!-- This is the combined status bar / notification panel window. -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
- xmlns:tools="http://schemas.android.com/tools"
- android:id="@+id/status_bar_cling"
- android:paddingStart="40dp"
- android:paddingEnd="40dp"
- android:background="#DD000000"
- android:focusable="true"
- android:orientation="horizontal"
- android:gravity="top|start"
- >
-
- <ImageView
- android:layout_width="wrap_content"
- android:layout_weight="0"
- android:layout_height="wrap_content"
- android:layout_marginEnd="50dp"
- android:gravity="center"
- android:src="@drawable/arrow_dashed"
- tools:ignore="ContentDescription" />
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:orientation="vertical"
- android:layout_marginTop="40dp"
- >
- <TextView
- style="@style/ClingTitleText"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/status_bar_help_title" />
-
- <TextView
- style="@style/ClingText"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginBottom="30dp"
- android:text="@string/status_bar_help_text" />
-
- <Button
- android:id="@+id/ok"
- style="@style/ClingButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:paddingStart="50dp"
- android:paddingEnd="50dp"
- android:text="@android:string/ok" />
- </LinearLayout>
-</LinearLayout>
diff --git a/packages/SystemUI/res/layout/status_bar_help.xml b/packages/SystemUI/res/layout/status_bar_help.xml
deleted file mode 100644
index f638767..0000000
--- a/packages/SystemUI/res/layout/status_bar_help.xml
+++ /dev/null
@@ -1,63 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<!-- This is the combined status bar / notification panel window. -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
- xmlns:tools="http://schemas.android.com/tools"
- android:id="@+id/status_bar_cling"
- android:paddingStart="40dp"
- android:paddingEnd="40dp"
- android:background="#DD000000"
- android:focusable="true"
- android:orientation="vertical"
- android:gravity="top|start"
- >
-
- <ImageView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginBottom="50dp"
- android:gravity="center"
- android:src="@drawable/arrow_dashed"
- tools:ignore="ContentDescription" />
-
- <TextView
- style="@style/ClingTitleText"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/status_bar_help_title" />
-
- <TextView
- style="@style/ClingText"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginBottom="30dp"
- android:text="@string/status_bar_help_text" />
-
- <Button
- android:id="@+id/ok"
- style="@style/ClingButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:paddingStart="50dp"
- android:paddingEnd="50dp"
- android:text="@android:string/ok" />
-
-</LinearLayout> \ No newline at end of file
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
deleted file mode 100644
index d876a95..0000000
--- a/packages/SystemUI/res/values/ids.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2012 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<resources>
- <item type="id" name="status_bar_cling_stub" />
-</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 8e88610..3ffa6f4 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -493,10 +493,6 @@
<!-- QuickSettings: Brightness dialog auto brightness button [CHAR LIMIT=NONE] -->
<string name="quick_settings_brightness_dialog_auto_brightness_label">AUTO</string>
- <!-- Title of help text shown when the notification panel is pulled down for the very first time. [CHAR LIMIT=NONE] -->
- <string name="status_bar_help_title">Notifications appear here</string>
- <!-- Body of help text shown when the notification panel is pulled down for the very first time. [CHAR LIMIT=NONE] -->
- <string name="status_bar_help_text">Access them anytime by swiping down.\nSwipe down again for system controls.</string>
<!-- Glyph to be overlaid atop the battery when the level is extremely low. Do not translate. -->
<string name="battery_meter_very_low_overlay_symbol">!</string>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index cd78041..134f228 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -159,33 +159,4 @@
<item name="android:textSize">14dp</item>
</style>
- <style name="ClingButton">
- <item name="android:layout_width">wrap_content</item>
- <item name="android:layout_height">wrap_content</item>
- <item name="android:paddingTop">10dp</item>
- <item name="android:paddingBottom">15dp</item>
- <item name="android:paddingLeft">35dp</item>
- <item name="android:paddingRight">35dp</item>
- <item name="android:textStyle">bold</item>
- <item name="android:background">@drawable/cling_button_bg</item>
- </style>
- <style name="ClingTitleText">
- <item name="android:layout_width">wrap_content</item>
- <item name="android:layout_height">wrap_content</item>
- <item name="android:layout_marginBottom">5dp</item>
- <item name="android:textSize">23sp</item>
- <item name="android:textColor">#49C0EC</item>
- <item name="android:shadowColor">#000000</item>
- <item name="android:shadowDy">2</item>
- <item name="android:shadowRadius">2.0</item>
- </style>
- <style name="ClingText">
- <item name="android:textSize">15sp</item>
- <item name="android:textColor">#FFFFFF</item>
- <item name="android:shadowColor">#000000</item>
- <item name="android:shadowDy">2</item>
- <item name="android:shadowRadius">2.0</item>
- <item name="android:lineSpacingMultiplier">1.1</item>
- </style>
-
</resources>
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 4b0a2b7..870202a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -37,7 +37,6 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.SharedPreferences;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.graphics.Canvas;
@@ -97,7 +96,6 @@ import com.android.systemui.statusbar.policy.LocationController;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.NotificationRowLayout;
import com.android.systemui.statusbar.policy.OnSizeChangedListener;
-import com.android.systemui.statusbar.policy.Prefs;
import com.android.systemui.statusbar.policy.RotationLockController;
import java.io.FileDescriptor;
@@ -111,11 +109,8 @@ public class PhoneStatusBar extends BaseStatusBar {
public static final boolean DUMPTRUCK = true; // extra dumpsys info
public static final boolean DEBUG_GESTURES = false;
- public static final boolean DEBUG_CLINGS = false;
public static final boolean DEBUG_WINDOW_STATE = true;
- public static final boolean ENABLE_NOTIFICATION_PANEL_CLING = false;
-
public static final boolean SETTINGS_DRAG_SHORTCUT = true;
// additional instrumentation for testing purposes; intended to be left on during development
@@ -251,11 +246,6 @@ public class PhoneStatusBar extends BaseStatusBar {
boolean mTracking;
VelocityTracker mVelocityTracker;
- // help screen
- private boolean mClingShown;
- private ViewGroup mCling;
- private boolean mSuppressStatusBarDrags; // while a cling is up, briefly deaden the bar to give things time to settle
-
int[] mAbsPos = new int[2];
Runnable mPostCollapseCleanup = null;
@@ -615,13 +605,6 @@ public class PhoneStatusBar extends BaseStatusBar {
}
}
- mClingShown = ! (DEBUG_CLINGS
- || !Prefs.read(mContext).getBoolean(Prefs.SHOWN_QUICK_SETTINGS_HELP, false));
-
- if (!ENABLE_NOTIFICATION_PANEL_CLING || ActivityManager.isRunningInTestHarness()) {
- mClingShown = true;
- }
-
// final ImageView wimaxRSSI =
// (ImageView)sb.findViewById(R.id.wimax_signal);
// if (wimaxRSSI != null) {
@@ -1733,63 +1716,6 @@ public class PhoneStatusBar extends BaseStatusBar {
}
}
- public boolean isClinging() {
- return mCling != null && mCling.getVisibility() == View.VISIBLE;
- }
-
- public void hideCling() {
- if (isClinging()) {
- mCling.animate().alpha(0f).setDuration(250).start();
- mCling.setVisibility(View.GONE);
- mSuppressStatusBarDrags = false;
- }
- }
-
- public void showCling() {
- // lazily inflate this to accommodate orientation change
- final ViewStub stub = (ViewStub) mStatusBarWindow.findViewById(R.id.status_bar_cling_stub);
- if (stub == null) {
- mClingShown = true;
- return; // no clings on this device
- }
-
- mSuppressStatusBarDrags = true;
-
- mHandler.postDelayed(new Runnable() {
- @Override
- public void run() {
- mCling = (ViewGroup) stub.inflate();
-
- mCling.setOnTouchListener(new View.OnTouchListener() {
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- return true; // e eats everything
- }});
- mCling.findViewById(R.id.ok).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- hideCling();
- }});
-
- mCling.setAlpha(0f);
- mCling.setVisibility(View.VISIBLE);
- mCling.animate().alpha(1f);
-
- mClingShown = true;
- SharedPreferences.Editor editor = Prefs.edit(mContext);
- editor.putBoolean(Prefs.SHOWN_QUICK_SETTINGS_HELP, true);
- editor.apply();
-
- makeExpandedVisible(); // enforce visibility in case the shade is still animating closed
- animateExpandNotificationsPanel();
-
- mSuppressStatusBarDrags = false;
- }
- }, 500);
-
- animateExpandNotificationsPanel();
- }
-
public boolean interceptTouchEvent(MotionEvent event) {
if (DEBUG_GESTURES) {
if (event.getActionMasked() != MotionEvent.ACTION_MOVE) {
@@ -1815,21 +1741,6 @@ public class PhoneStatusBar extends BaseStatusBar {
mGestureRec.add(event);
}
- // Cling (first-run help) handling.
- // The cling is supposed to show the first time you drag, or even tap, the status bar.
- // It should show the notification panel, then fade in after half a second, giving you
- // an explanation of what just happened, as well as teach you how to access quick
- // settings (another drag). The user can dismiss the cling by clicking OK or by
- // dragging quick settings into view.
- final int act = event.getActionMasked();
- if (mSuppressStatusBarDrags) {
- return true;
- } else if (act == MotionEvent.ACTION_UP && !mClingShown) {
- showCling();
- } else {
- hideCling();
- }
-
setInteracting(true);
return false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Prefs.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Prefs.java
index 73979a6..f339401 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Prefs.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Prefs.java
@@ -22,8 +22,6 @@ import android.content.SharedPreferences;
public class Prefs {
private static final String SHARED_PREFS_NAME = "status_bar";
- public static final String SHOWN_QUICK_SETTINGS_HELP = "shown_quick_settings_help";
-
public static SharedPreferences read(Context context) {
return context.getSharedPreferences(Prefs.SHARED_PREFS_NAME, Context.MODE_PRIVATE);
}
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 136a85e..9c14654 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -36,6 +36,7 @@ import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.bluetooth.BluetoothTetheringDataTracker;
+import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
@@ -152,6 +153,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
/**
@@ -424,9 +426,6 @@ public class ConnectivityService extends IConnectivityManager.Stub {
TelephonyManager mTelephonyManager;
- // We only want one checkMobileProvisioning after booting.
- volatile boolean mFirstProvisioningCheckStarted = false;
-
public ConnectivityService(Context context, INetworkManagementService netd,
INetworkStatsService statsService, INetworkPolicyManager policyManager) {
// Currently, omitting a NetworkFactory will create one internally
@@ -656,9 +655,6 @@ public class ConnectivityService extends IConnectivityManager.Stub {
mSettingsObserver = new SettingsObserver(mHandler, EVENT_APPLY_GLOBAL_HTTP_PROXY);
mSettingsObserver.observe(mContext);
- mCaptivePortalTracker = CaptivePortalTracker.makeCaptivePortalTracker(mContext, this);
- loadGlobalProxy();
-
mDataConnectionStats = new DataConnectionStats(mContext);
mDataConnectionStats.startMonitoring();
@@ -686,6 +682,10 @@ public class ConnectivityService extends IConnectivityManager.Stub {
new IntentFilter(filter));
mPacManager = new PacManager(mContext);
+
+ filter = new IntentFilter();
+ filter.addAction(CONNECTED_TO_PROVISIONING_NETWORK_ACTION);
+ mContext.registerReceiver(mProvisioningReceiver, filter);
}
/**
@@ -954,6 +954,46 @@ public class ConnectivityService extends IConnectivityManager.Stub {
return getNetworkInfo(mActiveDefaultNetwork, uid);
}
+ /**
+ * Find the first Provisioning network.
+ *
+ * @return NetworkInfo or null if none.
+ */
+ private NetworkInfo getProvisioningNetworkInfo() {
+ enforceAccessPermission();
+
+ // Find the first Provisioning Network
+ NetworkInfo provNi = null;
+ for (NetworkInfo ni : getAllNetworkInfo()) {
+ if (ni.getDetailedState()
+ == NetworkInfo.DetailedState.CONNECTED_TO_PROVISIONING_NETWORK) {
+ provNi = ni;
+ break;
+ }
+ }
+ if (DBG) log("getProvisioningNetworkInfo: X provNi=" + provNi);
+ return provNi;
+ }
+
+ /**
+ * Find the first Provisioning network or the ActiveDefaultNetwork
+ * if there is no Provisioning network
+ *
+ * @return NetworkInfo or null if none.
+ */
+ @Override
+ public NetworkInfo getProvisioningOrActiveNetworkInfo() {
+ enforceAccessPermission();
+
+ NetworkInfo provNi = getProvisioningNetworkInfo();
+ if (provNi == null) {
+ final int uid = Binder.getCallingUid();
+ provNi = getNetworkInfo(mActiveDefaultNetwork, uid);
+ }
+ if (DBG) log("getProvisioningOrActiveNetworkInfo: X provNi=" + provNi);
+ return provNi;
+ }
+
public NetworkInfo getActiveNetworkInfoUnfiltered() {
enforceAccessPermission();
if (isNetworkTypeValid(mActiveDefaultNetwork)) {
@@ -1316,8 +1356,10 @@ public class ConnectivityService extends IConnectivityManager.Stub {
feature);
}
if (network.reconnect()) {
+ if (DBG) log("startUsingNetworkFeature X: return APN_REQUEST_STARTED");
return PhoneConstants.APN_REQUEST_STARTED;
} else {
+ if (DBG) log("startUsingNetworkFeature X: return APN_REQUEST_FAILED");
return PhoneConstants.APN_REQUEST_FAILED;
}
} else {
@@ -1329,9 +1371,11 @@ public class ConnectivityService extends IConnectivityManager.Stub {
mNetRequestersPids[usedNetworkType].add(currentPid);
}
}
+ if (DBG) log("startUsingNetworkFeature X: return -1 unsupported feature.");
return -1;
}
}
+ if (DBG) log("startUsingNetworkFeature X: return APN_TYPE_NOT_AVAILABLE");
return PhoneConstants.APN_TYPE_NOT_AVAILABLE;
} finally {
if (DBG) {
@@ -1365,11 +1409,12 @@ public class ConnectivityService extends IConnectivityManager.Stub {
}
}
if (found && u != null) {
+ if (VDBG) log("stopUsingNetworkFeature: X");
// stop regardless of how many other time this proc had called start
return stopUsingNetworkFeature(u, true);
} else {
// none found!
- if (VDBG) log("stopUsingNetworkFeature - not a live request, ignoring");
+ if (VDBG) log("stopUsingNetworkFeature: X not a live request, ignoring");
return 1;
}
}
@@ -1952,6 +1997,9 @@ public class ConnectivityService extends IConnectivityManager.Stub {
*/
if (mNetConfigs[prevNetType].isDefault()) {
if (mActiveDefaultNetwork == prevNetType) {
+ if (DBG) {
+ log("tryFailover: set mActiveDefaultNetwork=-1, prevNetType=" + prevNetType);
+ }
mActiveDefaultNetwork = -1;
}
@@ -2146,6 +2194,9 @@ public class ConnectivityService extends IConnectivityManager.Stub {
}
void systemReady() {
+ mCaptivePortalTracker = CaptivePortalTracker.makeCaptivePortalTracker(mContext, this);
+ loadGlobalProxy();
+
synchronized(this) {
mSystemReady = true;
if (mInitialBroadcast != null) {
@@ -2176,10 +2227,11 @@ public class ConnectivityService extends IConnectivityManager.Stub {
};
private boolean isNewNetTypePreferredOverCurrentNetType(int type) {
- if ((type != mNetworkPreference &&
- mNetConfigs[mActiveDefaultNetwork].priority >
- mNetConfigs[type].priority) ||
- mNetworkPreference == mActiveDefaultNetwork) return false;
+ if (((type != mNetworkPreference)
+ && (mNetConfigs[mActiveDefaultNetwork].priority > mNetConfigs[type].priority))
+ || (mNetworkPreference == mActiveDefaultNetwork)) {
+ return false;
+ }
return true;
}
@@ -2193,6 +2245,11 @@ public class ConnectivityService extends IConnectivityManager.Stub {
final NetworkStateTracker thisNet = mNetTrackers[newNetType];
final String thisIface = thisNet.getLinkProperties().getInterfaceName();
+ if (VDBG) {
+ log("handleConnect: E newNetType=" + newNetType + " thisIface=" + thisIface
+ + " isFailover" + isFailover);
+ }
+
// if this is a default net and other default is running
// kill the one not preferred
if (mNetConfigs[newNetType].isDefault()) {
@@ -2355,6 +2412,10 @@ public class ConnectivityService extends IConnectivityManager.Stub {
private void handleConnectivityChange(int netType, boolean doReset) {
int resetMask = doReset ? NetworkUtils.RESET_ALL_ADDRESSES : 0;
boolean exempt = ConnectivityManager.isNetworkTypeExempt(netType);
+ if (VDBG) {
+ log("handleConnectivityChange: netType=" + netType + " doReset=" + doReset
+ + " resetMask=" + resetMask);
+ }
/*
* If a non-default network is enabled, add the host routes that
@@ -2422,7 +2483,9 @@ public class ConnectivityService extends IConnectivityManager.Stub {
boolean resetDns = updateRoutes(newLp, curLp, mNetConfigs[netType].isDefault(), exempt);
if (resetMask != 0 || resetDns) {
+ if (VDBG) log("handleConnectivityChange: resetting");
if (curLp != null) {
+ if (VDBG) log("handleConnectivityChange: resetting curLp=" + curLp);
for (String iface : curLp.getAllInterfaceNames()) {
if (TextUtils.isEmpty(iface) == false) {
if (resetMask != 0) {
@@ -2459,6 +2522,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
// Update 464xlat state.
NetworkStateTracker tracker = mNetTrackers[netType];
if (mClat.requiresClat(netType, tracker)) {
+
// If the connection was previously using clat, but is not using it now, stop the clat
// daemon. Normally, this happens automatically when the connection disconnects, but if
// the disconnect is not reported, or if the connection's LinkProperties changed for
@@ -2512,6 +2576,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
for (RouteInfo r : routeDiff.removed) {
if (isLinkDefault || ! r.isDefaultRoute()) {
+ if (VDBG) log("updateRoutes: default remove route r=" + r);
removeRoute(curLp, r, TO_DEFAULT_TABLE);
}
if (isLinkDefault == false) {
@@ -2849,9 +2914,8 @@ public class ConnectivityService extends IConnectivityManager.Stub {
public void handleMessage(Message msg) {
NetworkInfo info;
switch (msg.what) {
- case NetworkStateTracker.EVENT_STATE_CHANGED:
+ case NetworkStateTracker.EVENT_STATE_CHANGED: {
info = (NetworkInfo) msg.obj;
- int type = info.getType();
NetworkInfo.State state = info.getState();
if (VDBG || (state == NetworkInfo.State.CONNECTED) ||
@@ -2861,15 +2925,17 @@ public class ConnectivityService extends IConnectivityManager.Stub {
state + "/" + info.getDetailedState());
}
- // After booting we'll check once for mobile provisioning
- // if we've provisioned by and connected.
- if (!mFirstProvisioningCheckStarted
+ // Since mobile has the notion of a network/apn that can be used for
+ // provisioning we need to check every time we're connected as
+ // CaptiveProtalTracker won't detected it because DCT doesn't report it
+ // as connected as ACTION_ANY_DATA_CONNECTION_STATE_CHANGED instead its
+ // reported as ACTION_DATA_CONNECTION_CONNECTED_TO_PROVISIONING_APN. Which
+ // is received by MDST and sent here as EVENT_STATE_CHANGED.
+ if (ConnectivityManager.isNetworkTypeMobile(info.getType())
&& (0 != Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.DEVICE_PROVISIONED, 0))
&& (state == NetworkInfo.State.CONNECTED)) {
- log("check provisioning after booting");
- mFirstProvisioningCheckStarted = true;
- checkMobileProvisioning(true, CheckMp.MAX_TIMEOUT_MS, null);
+ checkMobileProvisioning(CheckMp.MAX_TIMEOUT_MS);
}
EventLogTags.writeConnectivityStateChanged(
@@ -2881,6 +2947,30 @@ public class ConnectivityService extends IConnectivityManager.Stub {
} else if (info.getDetailedState() ==
DetailedState.CAPTIVE_PORTAL_CHECK) {
handleCaptivePortalTrackerCheck(info);
+ } else if (info.getDetailedState() ==
+ DetailedState.CONNECTED_TO_PROVISIONING_NETWORK) {
+ /**
+ * TODO: Create ConnectivityManager.TYPE_MOBILE_PROVISIONING
+ * for now its an in between network, its a network that
+ * is actually a default network but we don't want it to be
+ * announced as such to keep background applications from
+ * trying to use it. It turns out that some still try so we
+ * take the additional step of clearing any default routes
+ * to the link that may have incorrectly setup by the lower
+ * levels.
+ */
+ LinkProperties lp = getLinkProperties(info.getType());
+ if (DBG) {
+ log("EVENT_STATE_CHANGED: connected to provisioning network, lp=" + lp);
+ }
+
+ // Clear any default routes setup by the radio so
+ // any activity by applications trying to use this
+ // connection will fail until the provisioning network
+ // is enabled.
+ for (RouteInfo r : lp.getRoutes()) {
+ removeRoute(lp, r, TO_DEFAULT_TABLE);
+ }
} else if (state == NetworkInfo.State.DISCONNECTED) {
handleDisconnect(info);
} else if (state == NetworkInfo.State.SUSPENDED) {
@@ -2899,18 +2989,21 @@ public class ConnectivityService extends IConnectivityManager.Stub {
mLockdownTracker.onNetworkInfoChanged(info);
}
break;
- case NetworkStateTracker.EVENT_CONFIGURATION_CHANGED:
+ }
+ case NetworkStateTracker.EVENT_CONFIGURATION_CHANGED: {
info = (NetworkInfo) msg.obj;
// TODO: Temporary allowing network configuration
// change not resetting sockets.
// @see bug/4455071
handleConnectivityChange(info.getType(), false);
break;
- case NetworkStateTracker.EVENT_NETWORK_SUBTYPE_CHANGED:
+ }
+ case NetworkStateTracker.EVENT_NETWORK_SUBTYPE_CHANGED: {
info = (NetworkInfo) msg.obj;
- type = info.getType();
+ int type = info.getType();
updateNetworkSettings(mNetTrackers[type]);
break;
+ }
}
}
}
@@ -3806,76 +3899,153 @@ public class ConnectivityService extends IConnectivityManager.Stub {
enabled));
}
- @Override
- public int checkMobileProvisioning(final boolean sendNotification, int suggestedTimeOutMs,
- final ResultReceiver resultReceiver) {
- log("checkMobileProvisioning: E sendNotification=" + sendNotification
- + " suggestedTimeOutMs=" + suggestedTimeOutMs
- + " resultReceiver=" + resultReceiver);
- enforceChangePermission();
+ private boolean isMobileDataStateTrackerReady() {
+ MobileDataStateTracker mdst =
+ (MobileDataStateTracker) mNetTrackers[ConnectivityManager.TYPE_MOBILE_HIPRI];
+ return (mdst != null) && (mdst.isReady());
+ }
- mFirstProvisioningCheckStarted = true;
+ /**
+ * The ResultReceiver resultCode for checkMobileProvisioning (CMP_RESULT_CODE)
+ */
- int timeOutMs = suggestedTimeOutMs;
- if (suggestedTimeOutMs > CheckMp.MAX_TIMEOUT_MS) {
- timeOutMs = CheckMp.MAX_TIMEOUT_MS;
- }
+ /**
+ * No connection was possible to the network.
+ */
+ public static final int CMP_RESULT_CODE_NO_CONNECTION = 0;
- // Check that mobile networks are supported
- if (!isNetworkSupported(ConnectivityManager.TYPE_MOBILE)
- || !isNetworkSupported(ConnectivityManager.TYPE_MOBILE_HIPRI)) {
- log("checkMobileProvisioning: X no mobile network");
- if (resultReceiver != null) {
- resultReceiver.send(ConnectivityManager.CMP_RESULT_CODE_NO_CONNECTION, null);
- }
- return timeOutMs;
- }
+ /**
+ * A connection was made to the internet, all is well.
+ */
+ public static final int CMP_RESULT_CODE_CONNECTABLE = 1;
+
+ /**
+ * A connection was made but there was a redirection, we appear to be in walled garden.
+ * This is an indication of a warm sim on a mobile network.
+ */
+ public static final int CMP_RESULT_CODE_REDIRECTED = 2;
+
+ /**
+ * A connection was made but no dns server was available to resolve a name to address.
+ * This is an indication of a warm sim on a mobile network.
+ */
+ public static final int CMP_RESULT_CODE_NO_DNS = 3;
+
+ /**
+ * A connection was made but could not open a TCP connection.
+ * This is an indication of a warm sim on a mobile network.
+ */
+ public static final int CMP_RESULT_CODE_NO_TCP_CONNECTION = 4;
+
+ /**
+ * The mobile network is a provisioning network.
+ * This is an indication of a warm sim on a mobile network.
+ */
+ public static final int CMP_RESULT_CODE_PROVISIONING_NETWORK = 5;
+
+ AtomicBoolean mIsCheckingMobileProvisioning = new AtomicBoolean(false);
+
+ @Override
+ public int checkMobileProvisioning(int suggestedTimeOutMs) {
+ int timeOutMs = -1;
+ if (DBG) log("checkMobileProvisioning: E suggestedTimeOutMs=" + suggestedTimeOutMs);
+ enforceConnectivityInternalPermission();
final long token = Binder.clearCallingIdentity();
try {
+ timeOutMs = suggestedTimeOutMs;
+ if (suggestedTimeOutMs > CheckMp.MAX_TIMEOUT_MS) {
+ timeOutMs = CheckMp.MAX_TIMEOUT_MS;
+ }
+
+ // Check that mobile networks are supported
+ if (!isNetworkSupported(ConnectivityManager.TYPE_MOBILE)
+ || !isNetworkSupported(ConnectivityManager.TYPE_MOBILE_HIPRI)) {
+ if (DBG) log("checkMobileProvisioning: X no mobile network");
+ return timeOutMs;
+ }
+
+ // If we're already checking don't do it again
+ // TODO: Add a queue of results...
+ if (mIsCheckingMobileProvisioning.getAndSet(true)) {
+ if (DBG) log("checkMobileProvisioning: X already checking ignore for the moment");
+ return timeOutMs;
+ }
+
+ // Start off with notification off
+ setProvNotificationVisible(false, ConnectivityManager.TYPE_NONE, null, null);
+
+ // See if we've alreadying determined if we've got a provsioning connection
+ // if so we don't need to do anything active
+ MobileDataStateTracker mdstDefault = (MobileDataStateTracker)
+ mNetTrackers[ConnectivityManager.TYPE_MOBILE];
+ boolean isDefaultProvisioning = mdstDefault.isProvisioningNetwork();
+
+ MobileDataStateTracker mdstHipri = (MobileDataStateTracker)
+ mNetTrackers[ConnectivityManager.TYPE_MOBILE_HIPRI];
+ boolean isHipriProvisioning = mdstHipri.isProvisioningNetwork();
+
+ if (isDefaultProvisioning || isHipriProvisioning) {
+ if (mIsNotificationVisible) {
+ if (DBG) {
+ log("checkMobileProvisioning: provisioning-ignore notification is visible");
+ }
+ } else {
+ NetworkInfo ni = null;
+ if (isDefaultProvisioning) {
+ ni = mdstDefault.getNetworkInfo();
+ }
+ if (isHipriProvisioning) {
+ ni = mdstHipri.getNetworkInfo();
+ }
+ String url = getMobileProvisioningUrl();
+ if ((ni != null) && (!TextUtils.isEmpty(url))) {
+ setProvNotificationVisible(true, ni.getType(), ni.getExtraInfo(), url);
+ } else {
+ if (DBG) log("checkMobileProvisioning: provisioning but no url, ignore");
+ }
+ }
+ mIsCheckingMobileProvisioning.set(false);
+ return timeOutMs;
+ }
+
CheckMp checkMp = new CheckMp(mContext, this);
CheckMp.CallBack cb = new CheckMp.CallBack() {
@Override
void onComplete(Integer result) {
- log("CheckMp.onComplete: result=" + result);
- if (resultReceiver != null) {
- log("CheckMp.onComplete: send result");
- resultReceiver.send(result, null);
- }
- if (!sendNotification) {
- log("CheckMp.onComplete: done, not sending notification");
- return;
- }
+ if (DBG) log("CheckMp.onComplete: result=" + result);
NetworkInfo ni =
mNetTrackers[ConnectivityManager.TYPE_MOBILE_HIPRI].getNetworkInfo();
switch(result) {
- case ConnectivityManager.CMP_RESULT_CODE_CONNECTABLE:
- case ConnectivityManager.CMP_RESULT_CODE_NO_CONNECTION: {
- log("CheckMp.onComplete: ignore, connected or no connection");
+ case CMP_RESULT_CODE_CONNECTABLE:
+ case CMP_RESULT_CODE_NO_CONNECTION: {
+ if (DBG) log("CheckMp.onComplete: ignore, connected or no connection");
break;
}
- case ConnectivityManager.CMP_RESULT_CODE_REDIRECTED: {
- log("CheckMp.onComplete: warm sim");
+ case CMP_RESULT_CODE_REDIRECTED: {
+ if (DBG) log("CheckMp.onComplete: warm sim");
String url = getMobileProvisioningUrl();
if (TextUtils.isEmpty(url)) {
url = getMobileRedirectedProvisioningUrl();
}
if (TextUtils.isEmpty(url) == false) {
- log("CheckMp.onComplete: warm sim (redirected), url=" + url);
- setNotificationVisible(true, ni, url);
+ if (DBG) log("CheckMp.onComplete: warm (redirected), url=" + url);
+ setProvNotificationVisible(true, ni.getType(), ni.getExtraInfo(),
+ url);
} else {
- log("CheckMp.onComplete: warm sim (redirected), no url");
+ if (DBG) log("CheckMp.onComplete: warm (redirected), no url");
}
break;
}
- case ConnectivityManager.CMP_RESULT_CODE_NO_DNS:
- case ConnectivityManager.CMP_RESULT_CODE_NO_TCP_CONNECTION: {
+ case CMP_RESULT_CODE_NO_DNS:
+ case CMP_RESULT_CODE_NO_TCP_CONNECTION: {
String url = getMobileProvisioningUrl();
if (TextUtils.isEmpty(url) == false) {
- log("CheckMp.onComplete: warm sim (no dns/tcp), url=" + url);
- setNotificationVisible(true, ni, url);
+ if (DBG) log("CheckMp.onComplete: warm (no dns/tcp), url=" + url);
+ setProvNotificationVisible(true, ni.getType(), ni.getExtraInfo(),
+ url);
} else {
- log("CheckMp.onComplete: warm sim (no dns/tcp), no url");
+ if (DBG) log("CheckMp.onComplete: warm (no dns/tcp), no url");
}
break;
}
@@ -3884,16 +4054,16 @@ public class ConnectivityService extends IConnectivityManager.Stub {
break;
}
}
+ mIsCheckingMobileProvisioning.set(false);
}
};
CheckMp.Params params =
new CheckMp.Params(checkMp.getDefaultUrl(), timeOutMs, cb);
- log("checkMobileProvisioning: params=" + params);
- setNotificationVisible(false, null, null);
+ if (DBG) log("checkMobileProvisioning: params=" + params);
checkMp.execute(params);
} finally {
Binder.restoreCallingIdentity(token);
- log("checkMobileProvisioning: X");
+ if (DBG) log("checkMobileProvisioning: X");
}
return timeOutMs;
}
@@ -3965,26 +4135,38 @@ public class ConnectivityService extends IConnectivityManager.Stub {
* a known address that fetches the data we expect.
*/
private synchronized Integer isMobileOk(Params params) {
- Integer result = ConnectivityManager.CMP_RESULT_CODE_NO_CONNECTION;
+ Integer result = CMP_RESULT_CODE_NO_CONNECTION;
Uri orgUri = Uri.parse(params.mUrl);
Random rand = new Random();
mParams = params;
if (mCs.isNetworkSupported(ConnectivityManager.TYPE_MOBILE) == false) {
log("isMobileOk: not mobile capable");
- result = ConnectivityManager.CMP_RESULT_CODE_NO_CONNECTION;
+ result = CMP_RESULT_CODE_NO_CONNECTION;
return result;
}
try {
- // Enable fail fast as we'll do retries here and use a
- // hipri connection so the default connection stays active.
- log("isMobileOk: start hipri url=" + params.mUrl);
- mCs.setEnableFailFastMobileData(DctConstants.ENABLED);
-
// Continue trying to connect until time has run out
long endTime = SystemClock.elapsedRealtime() + params.mTimeOutMs;
+ if (!mCs.isMobileDataStateTrackerReady()) {
+ // Wait for MobileDataStateTracker to be ready.
+ if (DBG) log("isMobileOk: mdst is not ready");
+ while(SystemClock.elapsedRealtime() < endTime) {
+ if (mCs.isMobileDataStateTrackerReady()) {
+ // Enable fail fast as we'll do retries here and use a
+ // hipri connection so the default connection stays active.
+ if (DBG) log("isMobileOk: mdst ready, enable fail fast of mobile data");
+ mCs.setEnableFailFastMobileData(DctConstants.ENABLED);
+ break;
+ }
+ sleep(1);
+ }
+ }
+
+ log("isMobileOk: start hipri url=" + params.mUrl);
+
// First wait until we can start using hipri
Binder binder = new Binder();
while(SystemClock.elapsedRealtime() < endTime) {
@@ -3996,7 +4178,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
break;
}
if (VDBG) log("isMobileOk: hipri not started yet");
- result = ConnectivityManager.CMP_RESULT_CODE_NO_CONNECTION;
+ result = CMP_RESULT_CODE_NO_CONNECTION;
sleep(1);
}
@@ -4009,15 +4191,26 @@ public class ConnectivityService extends IConnectivityManager.Stub {
NetworkInfo.State state = mCs
.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_HIPRI).getState();
if (state != NetworkInfo.State.CONNECTED) {
- if (VDBG) {
+ if (true/*VDBG*/) {
log("isMobileOk: not connected ni=" +
mCs.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_HIPRI));
}
sleep(1);
- result = ConnectivityManager.CMP_RESULT_CODE_NO_CONNECTION;
+ result = CMP_RESULT_CODE_NO_CONNECTION;
continue;
}
+ // Hipri has started check if this is a provisioning url
+ MobileDataStateTracker mdst = (MobileDataStateTracker)
+ mCs.mNetTrackers[ConnectivityManager.TYPE_MOBILE_HIPRI];
+ if (mdst.isProvisioningNetwork()) {
+ if (DBG) log("isMobileOk: isProvisioningNetwork is true, no TCP conn");
+ result = CMP_RESULT_CODE_NO_TCP_CONNECTION;
+ return result;
+ } else {
+ if (DBG) log("isMobileOk: isProvisioningNetwork is false, continue");
+ }
+
// Get of the addresses associated with the url host. We need to use the
// address otherwise HttpURLConnection object will use the name to get
// the addresses and is will try every address but that will bypass the
@@ -4028,7 +4221,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
addresses = InetAddress.getAllByName(orgUri.getHost());
} catch (UnknownHostException e) {
log("isMobileOk: UnknownHostException");
- result = ConnectivityManager.CMP_RESULT_CODE_NO_DNS;
+ result = CMP_RESULT_CODE_NO_DNS;
return result;
}
log("isMobileOk: addresses=" + inetAddressesToString(addresses));
@@ -4093,9 +4286,9 @@ public class ConnectivityService extends IConnectivityManager.Stub {
urlConn.setRequestProperty("Connection", "close");
int responseCode = urlConn.getResponseCode();
if (responseCode == 204) {
- result = ConnectivityManager.CMP_RESULT_CODE_CONNECTABLE;
+ result = CMP_RESULT_CODE_CONNECTABLE;
} else {
- result = ConnectivityManager.CMP_RESULT_CODE_REDIRECTED;
+ result = CMP_RESULT_CODE_REDIRECTED;
}
log("isMobileOk: connected responseCode=" + responseCode);
urlConn.disconnect();
@@ -4109,7 +4302,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
}
}
}
- result = ConnectivityManager.CMP_RESULT_CODE_NO_TCP_CONNECTION;
+ result = CMP_RESULT_CODE_NO_TCP_CONNECTION;
log("isMobileOk: loops|timed out");
return result;
} catch (Exception e) {
@@ -4123,6 +4316,23 @@ public class ConnectivityService extends IConnectivityManager.Stub {
mCs.setEnableFailFastMobileData(DctConstants.DISABLED);
mCs.stopUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
Phone.FEATURE_ENABLE_HIPRI);
+
+ // Wait for hipri to disconnect.
+ long endTime = SystemClock.elapsedRealtime() + 5000;
+
+ while(SystemClock.elapsedRealtime() < endTime) {
+ NetworkInfo.State state = mCs
+ .getNetworkInfo(ConnectivityManager.TYPE_MOBILE_HIPRI).getState();
+ if (state != NetworkInfo.State.DISCONNECTED) {
+ if (VDBG) {
+ log("isMobileOk: connected ni=" +
+ mCs.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_HIPRI));
+ }
+ sleep(1);
+ continue;
+ }
+ }
+
log("isMobileOk: X result=" + result);
}
return result;
@@ -4188,10 +4398,55 @@ public class ConnectivityService extends IConnectivityManager.Stub {
}
}
+ // TODO: Move to ConnectivityManager and make public?
+ private static final String CONNECTED_TO_PROVISIONING_NETWORK_ACTION =
+ "com.android.server.connectivityservice.CONNECTED_TO_PROVISIONING_NETWORK_ACTION";
+
+ private BroadcastReceiver mProvisioningReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent.getAction().equals(CONNECTED_TO_PROVISIONING_NETWORK_ACTION)) {
+ handleMobileProvisioningAction(intent.getStringExtra("EXTRA_URL"));
+ }
+ }
+ };
+
+ private void handleMobileProvisioningAction(String url) {
+ // Notication mark notification as not visible
+ setProvNotificationVisible(false, ConnectivityManager.TYPE_NONE, null, null);
+
+ // If provisioning network handle as a special case,
+ // otherwise launch browser with the intent directly.
+ NetworkInfo ni = getProvisioningNetworkInfo();
+ if ((ni != null) && ni.getDetailedState() ==
+ NetworkInfo.DetailedState.CONNECTED_TO_PROVISIONING_NETWORK) {
+ if (DBG) log("handleMobileProvisioningAction: on provisioning network");
+ MobileDataStateTracker mdst = (MobileDataStateTracker)
+ mNetTrackers[ConnectivityManager.TYPE_MOBILE];
+ mdst.enableMobileProvisioning(url);
+ } else {
+ if (DBG) log("handleMobileProvisioningAction: on default network");
+ Intent newIntent =
+ new Intent(Intent.ACTION_VIEW, Uri.parse(url));
+ newIntent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT |
+ Intent.FLAG_ACTIVITY_NEW_TASK);
+ try {
+ mContext.startActivity(newIntent);
+ } catch (ActivityNotFoundException e) {
+ loge("handleMobileProvisioningAction: startActivity failed" + e);
+ }
+ }
+ }
+
private static final String NOTIFICATION_ID = "CaptivePortal.Notification";
+ private volatile boolean mIsNotificationVisible = false;
- private void setNotificationVisible(boolean visible, NetworkInfo networkInfo, String url) {
- log("setNotificationVisible: E visible=" + visible + " ni=" + networkInfo + " url=" + url);
+ private void setProvNotificationVisible(boolean visible, int networkType, String extraInfo,
+ String url) {
+ if (DBG) {
+ log("setProvNotificationVisible: E visible=" + visible + " networkType=" + networkType
+ + " extraInfo=" + extraInfo + " url=" + url);
+ }
Resources r = Resources.getSystem();
NotificationManager notificationManager = (NotificationManager) mContext
@@ -4201,50 +4456,64 @@ public class ConnectivityService extends IConnectivityManager.Stub {
CharSequence title;
CharSequence details;
int icon;
- switch (networkInfo.getType()) {
+ Intent intent;
+ Notification notification = new Notification();
+ switch (networkType) {
case ConnectivityManager.TYPE_WIFI:
- log("setNotificationVisible: TYPE_WIFI");
title = r.getString(R.string.wifi_available_sign_in, 0);
details = r.getString(R.string.network_available_sign_in_detailed,
- networkInfo.getExtraInfo());
+ extraInfo);
icon = R.drawable.stat_notify_wifi_in_range;
+ intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
+ intent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT |
+ Intent.FLAG_ACTIVITY_NEW_TASK);
+ notification.contentIntent = PendingIntent.getActivity(mContext, 0, intent, 0);
break;
case ConnectivityManager.TYPE_MOBILE:
case ConnectivityManager.TYPE_MOBILE_HIPRI:
- log("setNotificationVisible: TYPE_MOBILE|HIPRI");
title = r.getString(R.string.network_available_sign_in, 0);
// TODO: Change this to pull from NetworkInfo once a printable
// name has been added to it
details = mTelephonyManager.getNetworkOperatorName();
icon = R.drawable.stat_notify_rssi_in_range;
+ intent = new Intent(CONNECTED_TO_PROVISIONING_NETWORK_ACTION);
+ intent.putExtra("EXTRA_URL", url);
+ intent.setFlags(0);
+ notification.contentIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
break;
default:
- log("setNotificationVisible: other type=" + networkInfo.getType());
title = r.getString(R.string.network_available_sign_in, 0);
details = r.getString(R.string.network_available_sign_in_detailed,
- networkInfo.getExtraInfo());
+ extraInfo);
icon = R.drawable.stat_notify_rssi_in_range;
+ intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
+ intent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT |
+ Intent.FLAG_ACTIVITY_NEW_TASK);
+ notification.contentIntent = PendingIntent.getActivity(mContext, 0, intent, 0);
break;
}
- Notification notification = new Notification();
notification.when = 0;
notification.icon = icon;
notification.flags = Notification.FLAG_AUTO_CANCEL;
- Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
- intent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT |
- Intent.FLAG_ACTIVITY_NEW_TASK);
- notification.contentIntent = PendingIntent.getActivity(mContext, 0, intent, 0);
notification.tickerText = title;
notification.setLatestEventInfo(mContext, title, details, notification.contentIntent);
- log("setNotificaitionVisible: notify notificaiton=" + notification);
- notificationManager.notify(NOTIFICATION_ID, 1, notification);
+ try {
+ notificationManager.notify(NOTIFICATION_ID, 1, notification);
+ } catch (NullPointerException npe) {
+ loge("setNotificaitionVisible: visible notificationManager npe=" + npe);
+ npe.printStackTrace();
+ }
} else {
- log("setNotificaitionVisible: cancel");
- notificationManager.cancel(NOTIFICATION_ID, 1);
+ try {
+ notificationManager.cancel(NOTIFICATION_ID, 1);
+ } catch (NullPointerException npe) {
+ loge("setNotificaitionVisible: cancel notificationManager npe=" + npe);
+ npe.printStackTrace();
+ }
}
- log("setNotificationVisible: X visible=" + visible + " ni=" + networkInfo + " url=" + url);
+ mIsNotificationVisible = visible;
}
/** Location to an updatable file listing carrier provisioning urls.
@@ -4373,6 +4642,13 @@ public class ConnectivityService extends IConnectivityManager.Stub {
return url;
}
+ @Override
+ public void setProvisioningNotificationVisible(boolean visible, int networkType,
+ String extraInfo, String url) {
+ enforceConnectivityInternalPermission();
+ setProvNotificationVisible(visible, networkType, extraInfo, url);
+ }
+
private void onUserStart(int userId) {
synchronized(mVpns) {
Vpn userVpn = mVpns.get(userId);
diff --git a/services/java/com/android/server/PreferredComponent.java b/services/java/com/android/server/PreferredComponent.java
index bb22545..134b198 100644
--- a/services/java/com/android/server/PreferredComponent.java
+++ b/services/java/com/android/server/PreferredComponent.java
@@ -33,8 +33,16 @@ import java.io.PrintWriter;
import java.util.List;
public class PreferredComponent {
+ private static final String TAG_SET = "set";
+ private static final String ATTR_ALWAYS = "always"; // boolean
+ private static final String ATTR_MATCH = "match"; // number
+ private static final String ATTR_NAME = "name"; // component name
+ private static final String ATTR_SET = "set"; // number
+
public final int mMatch;
public final ComponentName mComponent;
+ // Whether this is to be the one that's always chosen. If false, it's the most recently chosen.
+ public boolean mAlways;
private final String[] mSetPackages;
private final String[] mSetClasses;
@@ -50,10 +58,11 @@ public class PreferredComponent {
}
public PreferredComponent(Callbacks callbacks, int match, ComponentName[] set,
- ComponentName component) {
+ ComponentName component, boolean always) {
mCallbacks = callbacks;
mMatch = match&IntentFilter.MATCH_CATEGORY_MASK;
mComponent = component;
+ mAlways = always;
mShortComponent = component.flattenToShortString();
mParseError = null;
if (set != null) {
@@ -86,15 +95,17 @@ public class PreferredComponent {
public PreferredComponent(Callbacks callbacks, XmlPullParser parser)
throws XmlPullParserException, IOException {
mCallbacks = callbacks;
- mShortComponent = parser.getAttributeValue(null, "name");
+ mShortComponent = parser.getAttributeValue(null, ATTR_NAME);
mComponent = ComponentName.unflattenFromString(mShortComponent);
if (mComponent == null) {
mParseError = "Bad activity name " + mShortComponent;
}
- String matchStr = parser.getAttributeValue(null, "match");
+ String matchStr = parser.getAttributeValue(null, ATTR_MATCH);
mMatch = matchStr != null ? Integer.parseInt(matchStr, 16) : 0;
- String setCountStr = parser.getAttributeValue(null, "set");
+ String setCountStr = parser.getAttributeValue(null, ATTR_SET);
int setCount = setCountStr != null ? Integer.parseInt(setCountStr) : 0;
+ String alwaysStr = parser.getAttributeValue(null, ATTR_ALWAYS);
+ mAlways = alwaysStr != null ? Boolean.parseBoolean(alwaysStr) : true;
String[] myPackages = setCount > 0 ? new String[setCount] : null;
String[] myClasses = setCount > 0 ? new String[setCount] : null;
@@ -115,8 +126,8 @@ public class PreferredComponent {
String tagName = parser.getName();
//Log.i(TAG, "Parse outerDepth=" + outerDepth + " depth="
// + parser.getDepth() + " tag=" + tagName);
- if (tagName.equals("set")) {
- String name = parser.getAttributeValue(null, "name");
+ if (tagName.equals(TAG_SET)) {
+ String name = parser.getAttributeValue(null, ATTR_NAME);
if (name == null) {
if (mParseError == null) {
mParseError = "No name in set tag in preferred activity "
@@ -166,16 +177,17 @@ public class PreferredComponent {
public void writeToXml(XmlSerializer serializer, boolean full) throws IOException {
final int NS = mSetClasses != null ? mSetClasses.length : 0;
- serializer.attribute(null, "name", mShortComponent);
+ serializer.attribute(null, ATTR_NAME, mShortComponent);
if (full) {
if (mMatch != 0) {
- serializer.attribute(null, "match", Integer.toHexString(mMatch));
+ serializer.attribute(null, ATTR_MATCH, Integer.toHexString(mMatch));
}
- serializer.attribute(null, "set", Integer.toString(NS));
+ serializer.attribute(null, ATTR_ALWAYS, Boolean.toString(mAlways));
+ serializer.attribute(null, ATTR_SET, Integer.toString(NS));
for (int s=0; s<NS; s++) {
- serializer.startTag(null, "set");
- serializer.attribute(null, "name", mSetComponents[s]);
- serializer.endTag(null, "set");
+ serializer.startTag(null, TAG_SET);
+ serializer.attribute(null, ATTR_NAME, mSetComponents[s]);
+ serializer.endTag(null, TAG_SET);
}
}
}
diff --git a/services/java/com/android/server/am/ActivityStackSupervisor.java b/services/java/com/android/server/am/ActivityStackSupervisor.java
index 250ab4a..3e0b5eb 100644
--- a/services/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1426,8 +1426,7 @@ public final class ActivityStackSupervisor {
if ((launchFlags &
(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
== (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
- // Caller wants to appear on home activity, so before starting
- // their own activity we will bring home to the front.
+ // Caller wants to appear on home activity.
r.mLaunchHomeTaskNext = true;
}
targetStack.moveTaskToFrontLocked(intentActivity.task, r, options);
@@ -1541,6 +1540,8 @@ public final class ActivityStackSupervisor {
// don't use that intent!) And for paranoia, make
// sure we have correctly resumed the top activity.
if (doResume) {
+ // Reset flag so it gets correctly reevaluated.
+ intentActivity.mLaunchHomeTaskNext = false;
setLaunchHomeTaskNextFlag(sourceRecord, intentActivity, targetStack);
targetStack.resumeTopActivityLocked(null, options);
} else {
diff --git a/services/java/com/android/server/content/SyncStorageEngine.java b/services/java/com/android/server/content/SyncStorageEngine.java
index e3693f8..1b9ed98 100644
--- a/services/java/com/android/server/content/SyncStorageEngine.java
+++ b/services/java/com/android/server/content/SyncStorageEngine.java
@@ -71,7 +71,7 @@ import java.util.TimeZone;
public class SyncStorageEngine extends Handler {
private static final String TAG = "SyncManager";
- private static final boolean DEBUG = true;
+ private static final boolean DEBUG = false;
private static final String TAG_FILE = "SyncManagerFile";
private static final String XML_ATTR_NEXT_AUTHORITY_ID = "nextAuthorityId";
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 4942141..686b64e 100755
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -122,6 +122,7 @@ import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.Log;
import android.util.LogPrinter;
+import android.util.PrintStreamPrinter;
import android.util.Slog;
import android.util.SparseArray;
import android.util.Xml;
@@ -2595,6 +2596,37 @@ public class PackageManagerService extends IPackageManager.Stub {
return chooseBestActivity(intent, resolvedType, flags, query, userId);
}
+ @Override
+ public void setLastChosenActivity(Intent intent, String resolvedType, int flags,
+ IntentFilter filter, int match, ComponentName activity) {
+ final int userId = UserHandle.getCallingUserId();
+ if (DEBUG_PREFERRED) {
+ Log.v(TAG, "setLastChosenActivity intent=" + intent
+ + " resolvedType=" + resolvedType
+ + " flags=" + flags
+ + " filter=" + filter
+ + " match=" + match
+ + " activity=" + activity);
+ filter.dump(new PrintStreamPrinter(System.out), " ");
+ }
+ intent.setComponent(null);
+ List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags, userId);
+ // Find any earlier preferred or last chosen entries and nuke them
+ findPreferredActivity(intent, resolvedType,
+ flags, query, 0, false, true, userId);
+ // Add the new activity as the last chosen for this filter
+ addPreferredActivityInternal(filter, match, null, activity, false, userId);
+ }
+
+ @Override
+ public ResolveInfo getLastChosenActivity(Intent intent, String resolvedType, int flags) {
+ final int userId = UserHandle.getCallingUserId();
+ if (DEBUG_PREFERRED) Log.v(TAG, "Querying last chosen activity for " + intent);
+ List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags, userId);
+ return findPreferredActivity(intent, resolvedType, flags, query, 0,
+ false, false, userId);
+ }
+
private ResolveInfo chooseBestActivity(Intent intent, String resolvedType,
int flags, List<ResolveInfo> query, int userId) {
if (query != null) {
@@ -2620,7 +2652,7 @@ public class PackageManagerService extends IPackageManager.Stub {
// If we have saved a preference for a preferred activity for
// this Intent, use that.
ResolveInfo ri = findPreferredActivity(intent, resolvedType,
- flags, query, r0.priority, userId);
+ flags, query, r0.priority, true, false, userId);
if (ri != null) {
return ri;
}
@@ -2639,16 +2671,18 @@ public class PackageManagerService extends IPackageManager.Stub {
return null;
}
- ResolveInfo findPreferredActivity(Intent intent, String resolvedType,
- int flags, List<ResolveInfo> query, int priority, int userId) {
+ ResolveInfo findPreferredActivity(Intent intent, String resolvedType, int flags,
+ List<ResolveInfo> query, int priority, boolean always,
+ boolean removeMatches, int userId) {
if (!sUserManager.exists(userId)) return null;
// writer
synchronized (mPackages) {
if (intent.getSelector() != null) {
- intent = intent.getSelector();
+ intent = intent.getSelector();
}
if (DEBUG_PREFERRED) intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
PreferredIntentResolver pir = mSettings.mPreferredActivities.get(userId);
+ // Get the list of preferred activities that handle the intent
List<PreferredActivity> prefs = pir != null
? pir.queryIntent(intent, resolvedType,
(flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId)
@@ -2683,7 +2717,25 @@ public class PackageManagerService extends IPackageManager.Stub {
final int M = prefs.size();
for (int i=0; i<M; i++) {
final PreferredActivity pa = prefs.get(i);
+ if (DEBUG_PREFERRED) {
+ Log.v(TAG, "Checking PreferredActivity ds="
+ + (pa.countDataSchemes() > 0 ? pa.getDataScheme(0) : "<none>")
+ + "\n component=" + pa.mPref.mComponent);
+ pa.dump(new PrintStreamPrinter(System.out), " ");
+ }
if (pa.mPref.mMatch != match) {
+ if (DEBUG_PREFERRED) {
+ Log.v(TAG, "Skipping bad match "
+ + Integer.toHexString(pa.mPref.mMatch));
+ }
+ continue;
+ }
+ // If it's not an "always" type preferred activity and that's what we're
+ // looking for, skip it.
+ if (always && !pa.mPref.mAlways) {
+ if (DEBUG_PREFERRED) {
+ Log.v(TAG, "Skipping lastChosen entry");
+ }
continue;
}
final ActivityInfo ai = getActivityInfo(pa.mPref.mComponent,
@@ -2717,22 +2769,41 @@ public class PackageManagerService extends IPackageManager.Stub {
continue;
}
- // Okay we found a previously set preferred app.
+ if (removeMatches) {
+ pir.removeFilter(pa);
+ if (DEBUG_PREFERRED) {
+ Log.v(TAG, "Removing match " + pa.mPref.mComponent);
+ }
+ break;
+ }
+
+ // Okay we found a previously set preferred or last chosen app.
// If the result set is different from when this
// was created, we need to clear it and re-ask the
- // user their preference.
- if (!pa.mPref.sameSet(query, priority)) {
+ // user their preference, if we're looking for an "always" type entry.
+ if (always && !pa.mPref.sameSet(query, priority)) {
Slog.i(TAG, "Result set changed, dropping preferred activity for "
+ intent + " type " + resolvedType);
+ if (DEBUG_PREFERRED) {
+ Log.v(TAG, "Removing preferred activity since set changed "
+ + pa.mPref.mComponent);
+ }
pir.removeFilter(pa);
+ // Re-add the filter as a "last chosen" entry (!always)
+ PreferredActivity lastChosen = new PreferredActivity(
+ pa, pa.mPref.mMatch, null, pa.mPref.mComponent, false);
+ pir.addFilter(lastChosen);
+ mSettings.writePackageRestrictionsLPr(userId);
return null;
}
- // Yay!
+ // Yay! Either the set matched or we're looking for the last chosen
+ mSettings.writePackageRestrictionsLPr(userId);
return ri;
}
}
}
+ mSettings.writePackageRestrictionsLPr(userId);
}
return null;
}
@@ -9606,9 +9677,14 @@ public class PackageManagerService extends IPackageManager.Stub {
}
return Build.VERSION_CODES.CUR_DEVELOPMENT;
}
-
+
public void addPreferredActivity(IntentFilter filter, int match,
ComponentName[] set, ComponentName activity, int userId) {
+ addPreferredActivityInternal(filter, match, set, activity, true, userId);
+ }
+
+ private void addPreferredActivityInternal(IntentFilter filter, int match,
+ ComponentName[] set, ComponentName activity, boolean always, int userId) {
// writer
int callingUid = Binder.getCallingUid();
enforceCrossUserPermission(callingUid, userId, true, "add preferred activity");
@@ -9629,7 +9705,7 @@ public class PackageManagerService extends IPackageManager.Stub {
Slog.i(TAG, "Adding preferred activity " + activity + " for user " + userId + " :");
filter.dump(new LogPrinter(Log.INFO, TAG), " ");
mSettings.editPreferredActivitiesLPw(userId).addFilter(
- new PreferredActivity(filter, match, set, activity));
+ new PreferredActivity(filter, match, set, activity, always));
mSettings.writePackageRestrictionsLPr(userId);
}
}
@@ -9691,7 +9767,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
}
- addPreferredActivity(filter, match, set, activity, callingUserId);
+ addPreferredActivityInternal(filter, match, set, activity, true, callingUserId);
}
}
@@ -9736,8 +9812,11 @@ public class PackageManagerService extends IPackageManager.Stub {
Iterator<PreferredActivity> it = pir.filterIterator();
while (it.hasNext()) {
PreferredActivity pa = it.next();
+ // Mark entry for removal only if it matches the package name
+ // and the entry is of type "always".
if (packageName == null ||
- pa.mPref.mComponent.getPackageName().equals(packageName)) {
+ (pa.mPref.mComponent.getPackageName().equals(packageName)
+ && pa.mPref.mAlways)) {
if (removed == null) {
removed = new ArrayList<PreferredActivity>();
}
@@ -9781,7 +9860,8 @@ public class PackageManagerService extends IPackageManager.Stub {
while (it.hasNext()) {
final PreferredActivity pa = it.next();
if (packageName == null
- || pa.mPref.mComponent.getPackageName().equals(packageName)) {
+ || (pa.mPref.mComponent.getPackageName().equals(packageName)
+ && pa.mPref.mAlways)) {
if (outFilters != null) {
outFilters.add(new IntentFilter(pa));
}
diff --git a/services/java/com/android/server/pm/PreferredActivity.java b/services/java/com/android/server/pm/PreferredActivity.java
index c655bb1..963cbe4 100644
--- a/services/java/com/android/server/pm/PreferredActivity.java
+++ b/services/java/com/android/server/pm/PreferredActivity.java
@@ -33,13 +33,13 @@ class PreferredActivity extends IntentFilter implements PreferredComponent.Callb
private static final String TAG = "PreferredActivity";
private static final boolean DEBUG_FILTERS = false;
- static final String ATTR_USER_ID = "userId";
final PreferredComponent mPref;
- PreferredActivity(IntentFilter filter, int match, ComponentName[] set, ComponentName activity) {
+ PreferredActivity(IntentFilter filter, int match, ComponentName[] set, ComponentName activity,
+ boolean always) {
super(filter);
- mPref = new PreferredComponent(this, match, set, activity);
+ mPref = new PreferredComponent(this, match, set, activity, always);
}
PreferredActivity(XmlPullParser parser) throws XmlPullParserException, IOException {
diff --git a/services/java/com/android/server/pm/PreferredIntentResolver.java b/services/java/com/android/server/pm/PreferredIntentResolver.java
index 7fe6a05..bce24d7 100644
--- a/services/java/com/android/server/pm/PreferredIntentResolver.java
+++ b/services/java/com/android/server/pm/PreferredIntentResolver.java
@@ -26,10 +26,12 @@ public class PreferredIntentResolver
protected PreferredActivity[] newArray(int size) {
return new PreferredActivity[size];
}
+
@Override
protected boolean isPackageForFilter(String packageName, PreferredActivity filter) {
return packageName.equals(filter.mPref.mComponent.getPackageName());
}
+
@Override
protected void dumpFilter(PrintWriter out, String prefix,
PreferredActivity filter) {
diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java
index e18202b..ff1128d 100644
--- a/services/java/com/android/server/pm/Settings.java
+++ b/services/java/com/android/server/pm/Settings.java
@@ -2071,7 +2071,7 @@ final class Settings {
if (path != null) {
filter.addDataPath(path);
}
- PreferredActivity pa = new PreferredActivity(filter, match, set, cn);
+ PreferredActivity pa = new PreferredActivity(filter, match, set, cn, true);
editPreferredActivitiesLPw(userId).addFilter(pa);
} else if (!haveNonSys) {
Slog.w(TAG, "No component found for default preferred activity " + cn);
diff --git a/services/java/com/android/server/pm/UserManagerService.java b/services/java/com/android/server/pm/UserManagerService.java
index bb37917..af60f84 100644
--- a/services/java/com/android/server/pm/UserManagerService.java
+++ b/services/java/com/android/server/pm/UserManagerService.java
@@ -26,8 +26,6 @@ import android.app.IStopUserCallback;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.RestrictionEntry;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
@@ -42,7 +40,6 @@ import android.os.Handler;
import android.os.IUserManager;
import android.os.Process;
import android.os.RemoteException;
-import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.AtomicFile;
@@ -50,7 +47,6 @@ import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
-import android.util.SparseLongArray;
import android.util.TimeUtils;
import android.util.Xml;
@@ -163,8 +159,6 @@ public class UserManagerService extends IUserManager.Stub {
private boolean mGuestEnabled;
private int mNextSerialNumber;
private int mUserVersion = 0;
- // Temporary cleanup variable, this and associated code should be removed later.
- private boolean mUnblockAppsTemp;
private static UserManagerService sInstance;
@@ -241,8 +235,6 @@ public class UserManagerService extends IUserManager.Stub {
final Context context = ActivityThread.systemMain().getSystemContext();
mUserPackageMonitor.register(context,
null, UserHandle.ALL, false);
- context.registerReceiver(mBootCompletedReceiver,
- new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
userForeground(UserHandle.USER_OWNER);
}
@@ -502,12 +494,6 @@ public class UserManagerService extends IUserManager.Stub {
return mUserIds;
}
- private void readUserList() {
- synchronized (mPackagesLock) {
- readUserListLocked();
- }
- }
-
private void readUserListLocked() {
mGuestEnabled = false;
if (!mUserListFile.exists()) {
@@ -601,20 +587,8 @@ public class UserManagerService extends IUserManager.Stub {
userVersion = 2;
}
- if (userVersion < 3) {
- // Remove restrictions PIN for all users
- for (int i = 0; i < mRestrictionsPinStates.size(); i++) {
- int userId = mRestrictionsPinStates.keyAt(i);
- RestrictionsPinState state = mRestrictionsPinStates.valueAt(i);
- if (state.salt != 0 && state.pinHash != null) {
- removeRestrictionsForUser(userId, false);
- }
- }
- userVersion = 3;
- }
if (userVersion < 4) {
- mUnblockAppsTemp = true;
userVersion = 4;
}
@@ -634,6 +608,7 @@ public class UserManagerService extends IUserManager.Stub {
UserInfo.FLAG_ADMIN | UserInfo.FLAG_PRIMARY | UserInfo.FLAG_INITIALIZED);
mUsers.put(0, primary);
mNextSerialNumber = MIN_USER_ID;
+ mUserVersion = USER_VERSION;
Bundle restrictions = new Bundle();
mUserRestrictions.append(UserHandle.USER_OWNER, restrictions);
@@ -1588,19 +1563,4 @@ public class UserManagerService extends IUserManager.Stub {
}
}
};
-
- private BroadcastReceiver mBootCompletedReceiver = new BroadcastReceiver() {
- @Override public void onReceive(Context context, Intent intent) {
- // This code block can be removed after cleanup
- if (mUnblockAppsTemp) {
- synchronized (mPackagesLock) {
- // Unblock apps due to removal of restrictions feature
- for (int i = 0; i < mUsers.size(); i++) {
- int userId = mUsers.keyAt(i);
- unblockAllAppsForUser(userId);
- }
- }
- }
- }
- };
}
diff --git a/services/java/com/android/server/print/PrintManagerService.java b/services/java/com/android/server/print/PrintManagerService.java
index 671a5dc..2563b58 100644
--- a/services/java/com/android/server/print/PrintManagerService.java
+++ b/services/java/com/android/server/print/PrintManagerService.java
@@ -254,7 +254,7 @@ public final class PrintManagerService extends IPrintManager.Stub {
}
@Override
- public void requestPrinterUpdate(PrinterId printerId, int userId) {
+ public void validatePrinters(List<PrinterId> printerIds, int userId) {
final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
final UserState userState;
synchronized (mLock) {
@@ -262,7 +262,37 @@ public final class PrintManagerService extends IPrintManager.Stub {
}
final long identity = Binder.clearCallingIdentity();
try {
- userState.requestPrinterUpdate(printerId);
+ userState.validatePrinters(printerIds);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public void startPrinterStateTracking(PrinterId printerId, int userId) {
+ final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
+ final UserState userState;
+ synchronized (mLock) {
+ userState = getOrCreateUserStateLocked(resolvedUserId);
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ userState.startPrinterStateTracking(printerId);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public void stopPrinterStateTracking(PrinterId printerId, int userId) {
+ final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
+ final UserState userState;
+ synchronized (mLock) {
+ userState = getOrCreateUserStateLocked(resolvedUserId);
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ userState.stopPrinterStateTracking(printerId);
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -432,10 +462,12 @@ public final class PrintManagerService extends IPrintManager.Stub {
if (appId == callingAppId) {
return appId;
}
- if (mContext.checkCallingPermission(Manifest.permission.ACCESS_ALL_PRINT_JOBS)
+ if (mContext.checkCallingPermission(
+ "com.android.printspooler.permission.ACCESS_ALL_PRINT_JOBS")
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Call from app " + callingAppId + " as app "
- + appId + " without permission ACCESS_ALL_PRINT_JOBS");
+ + appId + " without com.android.printspooler.permission"
+ + ".ACCESS_ALL_PRINT_JOBS");
}
return appId;
}
diff --git a/services/java/com/android/server/print/RemotePrintService.java b/services/java/com/android/server/print/RemotePrintService.java
index 7f4b343..14af9d8 100644
--- a/services/java/com/android/server/print/RemotePrintService.java
+++ b/services/java/com/android/server/print/RemotePrintService.java
@@ -25,6 +25,7 @@ import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.IBinder.DeathRecipient;
+import android.os.AsyncTask;
import android.os.Looper;
import android.os.Message;
import android.os.ParcelFileDescriptor;
@@ -38,6 +39,8 @@ import android.printservice.IPrintService;
import android.printservice.IPrintServiceClient;
import android.util.Slog;
+import com.android.internal.R;
+
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
@@ -121,6 +124,36 @@ final class RemotePrintService implements DeathRecipient {
mHasPrinterDiscoverySession = false;
mPendingCommands.clear();
ensureUnbound();
+
+ // Makes sure all active print jobs are failed since the service
+ // just died. Do this off the main thread since we do to allow
+ // calls into the spooler on the main thread.
+ new AsyncTask<Void, Void, Void>() {
+ @Override
+ protected Void doInBackground(Void... params) {
+ failAllActivePrintJobs();
+ return null;
+ }
+ }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null);
+ }
+
+ private void failAllActivePrintJobs() {
+ List<PrintJobInfo> printJobs = mSpooler.getPrintJobInfos(mComponentName,
+ PrintJobInfo.STATE_ANY_ACTIVE, PrintManager.APP_ID_ANY);
+ if (printJobs == null) {
+ return;
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ final int printJobCount = printJobs.size();
+ for (int i = 0; i < printJobCount; i++) {
+ PrintJobInfo printJob = printJobs.get(i);
+ mSpooler.setPrintJobState(printJob.getId(), PrintJobInfo.STATE_FAILED,
+ mContext.getString(R.string.reason_unknown));
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
}
private void handleOnAllPrintJobsHandled() {
@@ -308,29 +341,83 @@ final class RemotePrintService implements DeathRecipient {
}
}
- public void requestPrinterUpdate(PrinterId printerId) {
- mHandler.obtainMessage(MyHandler.MSG_REQUEST_PRINTER_UPDATE,
+ public void validatePrinters(List<PrinterId> printerIds) {
+ mHandler.obtainMessage(MyHandler.MSG_VALIDATE_PRINTERS,
+ printerIds).sendToTarget();
+ }
+
+ private void handleValidatePrinters(final List<PrinterId> printerIds) {
+ throwIfDestroyed();
+ if (!isBound()) {
+ ensureBound();
+ mPendingCommands.add(new Runnable() {
+ @Override
+ public void run() {
+ handleValidatePrinters(printerIds);
+ }
+ });
+ } else {
+ if (DEBUG) {
+ Slog.i(LOG_TAG, "[user: " + mUserId + "] handleValidatePrinters()");
+ }
+ try {
+ mPrintService.validatePrinters(printerIds);
+ } catch (RemoteException re) {
+ Slog.e(LOG_TAG, "Error requesting printers validation.", re);
+ }
+ }
+ }
+
+ public void startPrinterStateTracking(PrinterId printerId) {
+ mHandler.obtainMessage(MyHandler.MSG_START_PRINTER_STATE_TRACKING,
+ printerId).sendToTarget();
+ }
+
+ private void handleStartPrinterStateTracking(final PrinterId printerId) {
+ throwIfDestroyed();
+ if (!isBound()) {
+ ensureBound();
+ mPendingCommands.add(new Runnable() {
+ @Override
+ public void run() {
+ handleStartPrinterStateTracking(printerId);
+ }
+ });
+ } else {
+ if (DEBUG) {
+ Slog.i(LOG_TAG, "[user: " + mUserId + "] handleStartPrinterTracking()");
+ }
+ try {
+ mPrintService.startPrinterStateTracking(printerId);
+ } catch (RemoteException re) {
+ Slog.e(LOG_TAG, "Error requesting start printer tracking.", re);
+ }
+ }
+ }
+
+ public void stopPrinterStateTracking(PrinterId printerId) {
+ mHandler.obtainMessage(MyHandler.MSG_STOP_PRINTER_STATE_TRACKING,
printerId).sendToTarget();
}
- private void handleRequestPrinterUpdate(final PrinterId printerId) {
+ private void handleStopPrinterStateTracking(final PrinterId printerId) {
throwIfDestroyed();
if (!isBound()) {
ensureBound();
mPendingCommands.add(new Runnable() {
@Override
public void run() {
- handleRequestPrinterUpdate(printerId);
+ handleStopPrinterStateTracking(printerId);
}
});
} else {
if (DEBUG) {
- Slog.i(LOG_TAG, "[user: " + mUserId + "] requestPrinterUpdate()");
+ Slog.i(LOG_TAG, "[user: " + mUserId + "] handleStopPrinterTracking()");
}
try {
- mPrintService.requestPrinterUpdate(printerId);
+ mPrintService.stopPrinterStateTracking(printerId);
} catch (RemoteException re) {
- Slog.e(LOG_TAG, "Error requesting a printer update.", re);
+ Slog.e(LOG_TAG, "Error requesting stop printer tracking.", re);
}
}
}
@@ -417,12 +504,14 @@ final class RemotePrintService implements DeathRecipient {
public static final int MSG_DESTROY_PRINTER_DISCOVERY_SESSION = 2;
public static final int MSG_START_PRINTER_DISCOVERY = 3;
public static final int MSG_STOP_PRINTER_DISCOVERY = 4;
- public static final int MSG_REQUEST_PRINTER_UPDATE = 5;
- public static final int MSG_ON_ALL_PRINT_JOBS_HANDLED = 6;
- public static final int MSG_ON_REQUEST_CANCEL_PRINT_JOB = 7;
- public static final int MSG_ON_PRINT_JOB_QUEUED = 8;
- public static final int MSG_DESTROY = 9;
- public static final int MSG_BINDER_DIED = 10;
+ public static final int MSG_VALIDATE_PRINTERS = 5;
+ public static final int MSG_START_PRINTER_STATE_TRACKING = 6;
+ public static final int MSG_STOP_PRINTER_STATE_TRACKING = 7;
+ public static final int MSG_ON_ALL_PRINT_JOBS_HANDLED = 8;
+ public static final int MSG_ON_REQUEST_CANCEL_PRINT_JOB = 9;
+ public static final int MSG_ON_PRINT_JOB_QUEUED = 10;
+ public static final int MSG_DESTROY = 11;
+ public static final int MSG_BINDER_DIED = 12;
public MyHandler(Looper looper) {
super(looper, null, false);
@@ -449,9 +538,19 @@ final class RemotePrintService implements DeathRecipient {
handleStopPrinterDiscovery();
} break;
- case MSG_REQUEST_PRINTER_UPDATE: {
+ case MSG_VALIDATE_PRINTERS: {
+ List<PrinterId> printerIds = (List<PrinterId>) message.obj;
+ handleValidatePrinters(printerIds);
+ } break;
+
+ case MSG_START_PRINTER_STATE_TRACKING: {
+ PrinterId printerId = (PrinterId) message.obj;
+ handleStartPrinterStateTracking(printerId);
+ } break;
+
+ case MSG_STOP_PRINTER_STATE_TRACKING: {
PrinterId printerId = (PrinterId) message.obj;
- handleRequestPrinterUpdate(printerId);
+ handleStopPrinterStateTracking(printerId);
} break;
case MSG_ON_ALL_PRINT_JOBS_HANDLED: {
diff --git a/services/java/com/android/server/print/UserState.java b/services/java/com/android/server/print/UserState.java
index c979a11..4a1b96b 100644
--- a/services/java/com/android/server/print/UserState.java
+++ b/services/java/com/android/server/print/UserState.java
@@ -19,8 +19,12 @@ package com.android.server.print;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
@@ -46,6 +50,7 @@ import com.android.server.print.RemotePrintSpooler.PrintSpoolerCallbacks;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -63,6 +68,11 @@ final class UserState implements PrintSpoolerCallbacks {
private static final char COMPONENT_NAME_SEPARATOR = ':';
+ private static final String SHARED_PREFERENCES_FILE = "shared_prefs";
+
+ private static final String KEY_SYSTEM_PRINT_SERVICES_ENABLED =
+ "KEY_SYSTEM_PRINT_SERVICES_ENABLED";
+
private final SimpleStringSplitter mStringColonSplitter =
new SimpleStringSplitter(COMPONENT_NAME_SEPARATOR);
@@ -95,6 +105,7 @@ final class UserState implements PrintSpoolerCallbacks {
mUserId = userId;
mLock = lock;
mSpooler = new RemotePrintSpooler(context, userId, this);
+ enableSystemPrintServicesOnce();
}
@Override
@@ -190,7 +201,7 @@ final class UserState implements PrintSpoolerCallbacks {
}
}
- public void requestPrinterUpdate(PrinterId printerId) {
+ public void validatePrinters(List<PrinterId> printerIds) {
synchronized (mLock) {
throwIfDestroyedLocked();
// No services - nothing to do.
@@ -202,7 +213,39 @@ final class UserState implements PrintSpoolerCallbacks {
return;
}
// Request an updated.
- mPrinterDiscoverySession.requestPrinterUpdateLocked(printerId);
+ mPrinterDiscoverySession.validatePrintersLocked(printerIds);
+ }
+ }
+
+ public void startPrinterStateTracking(PrinterId printerId) {
+ synchronized (mLock) {
+ throwIfDestroyedLocked();
+ // No services - nothing to do.
+ if (mActiveServices.isEmpty()) {
+ return;
+ }
+ // No session - nothing to do.
+ if (mPrinterDiscoverySession == null) {
+ return;
+ }
+ // Request start tracking the printer.
+ mPrinterDiscoverySession.startPrinterStateTrackingLocked(printerId);
+ }
+ }
+
+ public void stopPrinterStateTracking(PrinterId printerId) {
+ synchronized (mLock) {
+ throwIfDestroyedLocked();
+ // No services - nothing to do.
+ if (mActiveServices.isEmpty()) {
+ return;
+ }
+ // No session - nothing to do.
+ if (mPrinterDiscoverySession == null) {
+ return;
+ }
+ // Request stop tracking the printer.
+ mPrinterDiscoverySession.stopPrinterStateTrackingLocked(printerId);
}
}
@@ -365,6 +408,36 @@ final class UserState implements PrintSpoolerCallbacks {
return false;
}
+ private void enableSystemPrintServicesOnce() {
+ SharedPreferences preferences = mContext.getSharedPreferences(
+ SHARED_PREFERENCES_FILE, Context.MODE_PRIVATE);
+ if (preferences.getInt(KEY_SYSTEM_PRINT_SERVICES_ENABLED, 0) == 0) {
+ Editor editor = preferences.edit();
+ editor.putInt(KEY_SYSTEM_PRINT_SERVICES_ENABLED, 1);
+ editor.commit();
+
+ readInstalledPrintServicesLocked();
+
+ StringBuilder builder = new StringBuilder();
+
+ final int serviceCount = mInstalledServices.size();
+ for (int i = 0; i < serviceCount; i++) {
+ ServiceInfo serviceInfo = mInstalledServices.get(i).getResolveInfo().serviceInfo;
+ if ((serviceInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+ ComponentName serviceName = new ComponentName(
+ serviceInfo.packageName, serviceInfo.name);
+ if (builder.length() > 0) {
+ builder.append(":");
+ }
+ builder.append(serviceName.flattenToString());
+ }
+ }
+
+ Settings.Secure.putStringForUser(mContext.getContentResolver(),
+ Settings.Secure.ENABLED_PRINT_SERVICES, builder.toString(), mUserId);
+ }
+ }
+
private void onConfigurationChangedLocked() {
final int installedCount = mInstalledServices.size();
for (int i = 0; i < installedCount; i++) {
@@ -415,6 +488,8 @@ final class UserState implements PrintSpoolerCallbacks {
private final List<IBinder> mStartedPrinterDiscoveryTokens = new ArrayList<IBinder>();
+ private final List<PrinterId> mStateTrackedPrinters = new ArrayList<PrinterId>();
+
private final Handler mHandler;
private boolean mIsDestroyed;
@@ -461,14 +536,10 @@ final class UserState implements PrintSpoolerCallbacks {
}
// If printer discovery is ongoing and the start request has a list
- // of printer to be checked, then we just request refreshing each of
- // them rather making another start discovery request.
+ // of printer to be checked, then we just request validating them.
if (!mStartedPrinterDiscoveryTokens.isEmpty()
&& priorityList != null && !priorityList.isEmpty()) {
- final int priorityIdCount = priorityList.size();
- for (int i = 0; i < priorityIdCount; i++) {
- requestPrinterUpdate(priorityList.get(i));
- }
+ validatePrinters(priorityList);
return;
}
@@ -508,20 +579,97 @@ final class UserState implements PrintSpoolerCallbacks {
.sendToTarget();
}
- public void requestPrinterUpdateLocked(PrinterId printerId) {
+ public void validatePrintersLocked(List<PrinterId> printerIds) {
if (mIsDestroyed) {
- Log.w(LOG_TAG, "Not updating pritner - session destroyed");
+ Log.w(LOG_TAG, "Not validating pritners - session destroyed");
return;
}
+
+ List<PrinterId> remainingList = new ArrayList<PrinterId>(printerIds);
+ while (!remainingList.isEmpty()) {
+ Iterator<PrinterId> iterator = remainingList.iterator();
+ // Gather the printers per service and request a validation.
+ List<PrinterId> updateList = new ArrayList<PrinterId>();
+ ComponentName serviceName = null;
+ while (iterator.hasNext()) {
+ PrinterId printerId = iterator.next();
+ if (updateList.isEmpty()) {
+ updateList.add(printerId);
+ serviceName = printerId.getServiceName();
+ iterator.remove();
+ } else if (printerId.getServiceName().equals(serviceName)) {
+ updateList.add(printerId);
+ iterator.remove();
+ }
+ }
+ // Schedule a notification of the service.
+ RemotePrintService service = mActiveServices.get(serviceName);
+ if (service != null) {
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = service;
+ args.arg2 = updateList;
+ mHandler.obtainMessage(SessionHandler
+ .MSG_VALIDATE_PRINTERS, args)
+ .sendToTarget();
+ }
+ }
+ }
+
+ public final void startPrinterStateTrackingLocked(PrinterId printerId) {
+ if (mIsDestroyed) {
+ Log.w(LOG_TAG, "Not starting printer state tracking - session destroyed");
+ return;
+ }
+ // If printer discovery is not started - nothing to do.
+ if (mStartedPrinterDiscoveryTokens.isEmpty()) {
+ return;
+ }
+ final boolean containedPrinterId = mStateTrackedPrinters.contains(printerId);
+ // Keep track of the number of requests to track this one.
+ mStateTrackedPrinters.add(printerId);
+ // If we were tracking this printer - nothing to do.
+ if (containedPrinterId) {
+ return;
+ }
+ // No service - nothing to do.
RemotePrintService service = mActiveServices.get(printerId.getServiceName());
- if (service != null) {
- SomeArgs args = SomeArgs.obtain();
- args.arg1 = service;
- args.arg2 = printerId;
- mHandler.obtainMessage(SessionHandler
- .MSG_REQUEST_PRINTER_UPDATE, args)
- .sendToTarget();
+ if (service == null) {
+ return;
}
+ // Ask the service to start tracking.
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = service;
+ args.arg2 = printerId;
+ mHandler.obtainMessage(SessionHandler
+ .MSG_START_PRINTER_STATE_TRACKING, args)
+ .sendToTarget();
+ }
+
+ public final void stopPrinterStateTrackingLocked(PrinterId printerId) {
+ if (mIsDestroyed) {
+ Log.w(LOG_TAG, "Not stopping printer state tracking - session destroyed");
+ return;
+ }
+ // If printer discovery is not started - nothing to do.
+ if (mStartedPrinterDiscoveryTokens.isEmpty()) {
+ return;
+ }
+ // If we did not track this printer - nothing to do.
+ if (!mStateTrackedPrinters.remove(printerId)) {
+ return;
+ }
+ // No service - nothing to do.
+ RemotePrintService service = mActiveServices.get(printerId.getServiceName());
+ if (service == null) {
+ return;
+ }
+ // Ask the service to start tracking.
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = service;
+ args.arg2 = printerId;
+ mHandler.obtainMessage(SessionHandler
+ .MSG_STOP_PRINTER_STATE_TRACKING, args)
+ .sendToTarget();
}
public void onDestroyed() {
@@ -533,6 +681,12 @@ final class UserState implements PrintSpoolerCallbacks {
Log.w(LOG_TAG, "Not destroying - session destroyed");
return;
}
+ // Make sure printer tracking is stopped.
+ final int printerCount = mStateTrackedPrinters.size();
+ for (int i = 0; i < printerCount; i++) {
+ PrinterId printerId = mStateTrackedPrinters.get(i);
+ stopPrinterStateTracking(printerId);
+ }
// Make sure discovery is stopped.
final int observerCount = mStartedPrinterDiscoveryTokens.size();
for (int i = 0; i < observerCount; i++) {
@@ -744,9 +898,19 @@ final class UserState implements PrintSpoolerCallbacks {
}
}
- private void handleRequestPrinterUpdate(RemotePrintService service,
+ private void handleValidatePrinters(RemotePrintService service,
+ List<PrinterId> printerIds) {
+ service.validatePrinters(printerIds);
+ }
+
+ private void handleStartPrinterStateTracking(RemotePrintService service,
+ PrinterId printerId) {
+ service.startPrinterStateTracking(printerId);
+ }
+
+ private void handleStopPrinterStateTracking(RemotePrintService service,
PrinterId printerId) {
- service.requestPrinterUpdate(printerId);
+ service.stopPrinterStateTracking(printerId);
}
private void handlePrintersAdded(IPrinterDiscoveryObserver observer,
@@ -804,7 +968,9 @@ final class UserState implements PrintSpoolerCallbacks {
public static final int MSG_DISPATCH_DESTROY_PRINTER_DISCOVERY_SESSION = 9;
public static final int MSG_DISPATCH_START_PRINTER_DISCOVERY = 10;
public static final int MSG_DISPATCH_STOP_PRINTER_DISCOVERY = 11;
- public static final int MSG_REQUEST_PRINTER_UPDATE = 12;
+ public static final int MSG_VALIDATE_PRINTERS = 12;
+ public static final int MSG_START_PRINTER_STATE_TRACKING = 13;
+ public static final int MSG_STOP_PRINTER_STATE_TRACKING = 14;
SessionHandler(Looper looper) {
super(looper, null, false);
@@ -878,13 +1044,29 @@ final class UserState implements PrintSpoolerCallbacks {
handleDispatchStopPrinterDiscovery(services);
} break;
- case MSG_REQUEST_PRINTER_UPDATE: {
+ case MSG_VALIDATE_PRINTERS: {
+ SomeArgs args = (SomeArgs) message.obj;
+ RemotePrintService service = (RemotePrintService) args.arg1;
+ List<PrinterId> printerIds = (List<PrinterId>) args.arg2;
+ args.recycle();
+ handleValidatePrinters(service, printerIds);
+ } break;
+
+ case MSG_START_PRINTER_STATE_TRACKING: {
SomeArgs args = (SomeArgs) message.obj;
RemotePrintService service = (RemotePrintService) args.arg1;
PrinterId printerId = (PrinterId) args.arg2;
args.recycle();
- handleRequestPrinterUpdate(service, printerId);
+ handleStartPrinterStateTracking(service, printerId);
} break;
+
+ case MSG_STOP_PRINTER_STATE_TRACKING: {
+ SomeArgs args = (SomeArgs) message.obj;
+ RemotePrintService service = (RemotePrintService) args.arg1;
+ PrinterId printerId = (PrinterId) args.arg2;
+ args.recycle();
+ handleStopPrinterStateTracking(service, printerId);
+ }
}
}
}
diff --git a/telephony/java/com/android/internal/telephony/DctConstants.java b/telephony/java/com/android/internal/telephony/DctConstants.java
index 4f1ae11..c661b00 100644
--- a/telephony/java/com/android/internal/telephony/DctConstants.java
+++ b/telephony/java/com/android/internal/telephony/DctConstants.java
@@ -94,6 +94,8 @@ public class DctConstants {
public static final int EVENT_DISCONNECT_DC_RETRYING = BASE + 34;
public static final int EVENT_DATA_SETUP_COMPLETE_ERROR = BASE + 35;
public static final int CMD_SET_ENABLE_FAIL_FAST_MOBILE_DATA = BASE + 36;
+ public static final int CMD_ENABLE_MOBILE_PROVISIONING = BASE + 37;
+ public static final int CMD_IS_PROVISIONING_APN = BASE + 38;
/***** Constants *****/
@@ -113,4 +115,5 @@ public class DctConstants {
public static final int ENABLED = 1;
public static final String APN_TYPE_KEY = "apnType";
+ public static final String PROVISIONING_URL_KEY = "provisioningUrl";
}
diff --git a/telephony/java/com/android/internal/telephony/TelephonyIntents.java b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
index 65bdacf..a7baf1c 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyIntents.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
@@ -145,6 +145,29 @@ public class TelephonyIntents {
public static final String ACTION_ANY_DATA_CONNECTION_STATE_CHANGED
= "android.intent.action.ANY_DATA_STATE";
+ /**
+ * Broadcast Action: Occurs when a data connection connects to a provisioning apn
+ * and is broadcast by the low level data connection code.
+ * The intent will have the following extra values:</p>
+ * <ul>
+ * <li><em>apn</em> - A string that is the APN associated with this
+ * connection.</li>
+ * <li><em>apnType</em> - A string array of APN types associated with
+ * this connection. The APN type <code>"*"</code> is a special
+ * type that means this APN services all types.</li>
+ * <li><em>linkProperties</em> - The <code>LinkProperties</code> for this APN</li>
+ * <li><em>linkCapabilities</em> - The <code>linkCapabilities</code> for this APN</li>
+ * <li><em>iface</em> - A string that is the name of the interface</li>
+ * </ul>
+ *
+ * <p class="note">
+ * Requires the READ_PHONE_STATE permission.
+ *
+ * <p class="note">This is a protected intent that can only be sent
+ * by the system.
+ */
+ public static final String ACTION_DATA_CONNECTION_CONNECTED_TO_PROVISIONING_APN
+ = "android.intent.action.DATA_CONNECTION_CONNECTED_TO_PROVISIONING_APN";
/**
* Broadcast Action: An attempt to establish a data connection has failed.