summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Android.mk1
-rw-r--r--api/current.txt108
-rw-r--r--cmds/pm/src/com/android/commands/pm/Pm.java22
-rw-r--r--core/java/android/app/ApplicationPackageManager.java2
-rw-r--r--core/java/android/app/EnterTransitionCoordinator.java4
-rw-r--r--core/java/android/app/ExitTransitionCoordinator.java4
-rw-r--r--core/java/android/app/Service.java2
-rw-r--r--core/java/android/app/UiModeManager.java13
-rw-r--r--core/java/android/content/pm/ApplicationInfo.java3
-rw-r--r--core/java/android/content/pm/ComponentInfo.java3
-rw-r--r--core/java/android/content/pm/IPackageInstallerCallback.aidl2
-rw-r--r--core/java/android/content/pm/IPackageInstallerSession.aidl2
-rw-r--r--core/java/android/content/pm/InstallSessionInfo.java30
-rw-r--r--core/java/android/content/pm/InstallSessionParams.java33
-rw-r--r--core/java/android/content/pm/PackageInstaller.java109
-rw-r--r--core/java/android/content/pm/PackageItemInfo.java2
-rw-r--r--core/java/android/hardware/camera2/legacy/CaptureCollector.java8
-rw-r--r--core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java231
-rw-r--r--core/java/android/hardware/camera2/legacy/LegacyRequestMapper.java56
-rw-r--r--core/java/android/hardware/camera2/legacy/LegacyResultMapper.java46
-rw-r--r--core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java3
-rw-r--r--core/java/android/hardware/camera2/utils/ArrayUtils.java24
-rw-r--r--core/java/android/hardware/location/GeofenceHardware.java61
-rw-r--r--core/java/android/hardware/location/GeofenceHardwareImpl.java78
-rw-r--r--core/java/android/hardware/location/GeofenceHardwareMonitorCallback.java26
-rw-r--r--core/java/android/hardware/location/GeofenceHardwareMonitorEvent.aidl19
-rw-r--r--core/java/android/hardware/location/GeofenceHardwareMonitorEvent.java116
-rw-r--r--core/java/android/hardware/location/GeofenceHardwareRequest.java30
-rw-r--r--core/java/android/hardware/location/GeofenceHardwareRequestParcelable.java40
-rw-r--r--core/java/android/hardware/location/GeofenceHardwareService.java11
-rw-r--r--core/java/android/hardware/location/IGeofenceHardware.aidl8
-rw-r--r--core/java/android/hardware/location/IGeofenceHardwareMonitorCallback.aidl3
-rw-r--r--core/java/android/net/Network.java92
-rw-r--r--core/java/android/net/NetworkBoundURLFactory.java35
-rw-r--r--core/java/android/nfc/INfcAdapter.aidl3
-rw-r--r--core/java/android/nfc/INfcUnlockHandler.aidl12
-rw-r--r--core/java/android/nfc/NfcAdapter.java97
-rw-r--r--core/java/android/nfc/Tag.java2
-rw-r--r--core/java/android/os/Process.java6
-rw-r--r--core/java/android/os/UserManager.java5
-rw-r--r--core/java/android/text/TextUtils.java2
-rw-r--r--core/java/android/transition/Visibility.java2
-rw-r--r--core/java/android/transition/VisibilityPropagation.java6
-rw-r--r--core/java/android/view/IWindowManager.aidl5
-rw-r--r--core/java/android/view/Window.java95
-rw-r--r--core/java/android/widget/Switch.java169
-rw-r--r--core/java/com/android/internal/util/XmlUtils.java77
-rw-r--r--core/jni/android/graphics/MinikinUtils.cpp1
-rw-r--r--core/jni/android/graphics/Paint.cpp11
-rw-r--r--core/jni/android/graphics/Paint.h10
-rw-r--r--core/jni/android/graphics/PaintImpl.cpp8
-rw-r--r--core/jni/android/graphics/Picture.cpp4
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_000.pngbin740 -> 0 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00001.9.pngbin0 -> 16827 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00002.9.pngbin0 -> 16800 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00003.9.pngbin0 -> 16877 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00004.9.pngbin0 -> 16566 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00005.9.pngbin0 -> 16610 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00006.9.pngbin0 -> 16599 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00007.9.pngbin0 -> 16610 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00008.9.pngbin0 -> 16576 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00009.9.pngbin0 -> 16603 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00010.9.pngbin0 -> 16571 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00011.9.pngbin0 -> 16732 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00012.9.pngbin0 -> 16772 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_001.pngbin714 -> 0 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_002.pngbin788 -> 0 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_003.pngbin819 -> 0 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_004.pngbin836 -> 0 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_005.pngbin852 -> 0 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_006.pngbin952 -> 0 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_007.pngbin952 -> 0 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_008.pngbin912 -> 0 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_009.pngbin918 -> 0 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_010.pngbin870 -> 0 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_011.pngbin870 -> 0 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_012.pngbin870 -> 0 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_013.pngbin870 -> 0 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_014.pngbin870 -> 0 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_000.pngbin870 -> 0 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00001.9.pngbin0 -> 16781 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00002.9.pngbin0 -> 16817 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00003.9.pngbin0 -> 16785 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00004.9.pngbin0 -> 16517 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00005.9.pngbin0 -> 16608 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00006.9.pngbin0 -> 16611 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00007.9.pngbin0 -> 16610 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00008.9.pngbin0 -> 16551 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00009.9.pngbin0 -> 16837 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00010.9.pngbin0 -> 16780 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00011.9.pngbin0 -> 16858 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00012.9.pngbin0 -> 16798 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_001.pngbin918 -> 0 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_002.pngbin893 -> 0 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_003.pngbin773 -> 0 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_004.pngbin739 -> 0 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_005.pngbin697 -> 0 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_006.pngbin713 -> 0 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_007.pngbin714 -> 0 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_008.pngbin740 -> 0 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_009.pngbin740 -> 0 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_010.pngbin740 -> 0 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_011.pngbin740 -> 0 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_012.pngbin740 -> 0 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_013.pngbin740 -> 0 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_014.pngbin740 -> 0 bytes
-rw-r--r--core/res/res/drawable-hdpi/ic_corp_icon.pngbin1298 -> 3043 bytes
-rw-r--r--core/res/res/drawable-hdpi/switch_track_mtrl_alpha.9.pngbin153 -> 468 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_000.pngbin546 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00001.9.pngbin0 -> 16178 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00002.9.pngbin0 -> 16194 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00003.9.pngbin0 -> 16062 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00004.9.pngbin0 -> 15897 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00005.9.pngbin0 -> 15978 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00006.9.pngbin0 -> 16049 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00007.9.pngbin0 -> 16058 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00008.9.pngbin0 -> 15993 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00009.9.pngbin0 -> 16154 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00010.9.pngbin0 -> 16106 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00011.9.pngbin0 -> 16004 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00012.9.pngbin0 -> 16008 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_001.pngbin533 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_002.pngbin605 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_003.pngbin600 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_004.pngbin601 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_005.pngbin600 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_006.pngbin698 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_007.pngbin698 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_008.pngbin651 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_009.pngbin616 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_010.pngbin612 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_011.pngbin612 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_012.pngbin612 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_013.pngbin612 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_014.pngbin612 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_000.pngbin612 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00001.9.pngbin0 -> 16097 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00002.9.pngbin0 -> 15990 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00003.9.pngbin0 -> 16068 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00004.9.pngbin0 -> 15963 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00005.9.pngbin0 -> 15982 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00006.9.pngbin0 -> 16046 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00007.9.pngbin0 -> 16049 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00008.9.pngbin0 -> 16014 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00009.9.pngbin0 -> 16117 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00010.9.pngbin0 -> 16166 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00011.9.pngbin0 -> 16154 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00012.9.pngbin0 -> 16172 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_001.pngbin616 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_002.pngbin621 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_003.pngbin603 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_004.pngbin538 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_005.pngbin569 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_006.pngbin573 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_007.pngbin533 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_008.pngbin546 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_009.pngbin546 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_010.pngbin546 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_011.pngbin546 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_012.pngbin546 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_013.pngbin546 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_014.pngbin546 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/ic_corp_icon.pngbin906 -> 2184 bytes
-rw-r--r--core/res/res/drawable-mdpi/switch_track_mtrl_alpha.9.pngbin148 -> 351 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_000.pngbin902 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00001.9.pngbin0 -> 17668 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00002.9.pngbin0 -> 17513 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00003.9.pngbin0 -> 17330 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00004.9.pngbin0 -> 17309 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00005.9.pngbin0 -> 17040 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00006.9.pngbin0 -> 17015 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00007.9.pngbin0 -> 17028 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00008.9.pngbin0 -> 17077 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00009.9.pngbin0 -> 17151 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00010.9.pngbin0 -> 17347 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00011.9.pngbin0 -> 17524 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00012.9.pngbin0 -> 17532 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_001.pngbin865 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_002.pngbin1010 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_003.pngbin1073 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_004.pngbin1082 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_005.pngbin1084 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_006.pngbin1310 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_007.pngbin1310 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_008.pngbin1143 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_009.pngbin1188 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_010.pngbin1161 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_011.pngbin1161 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_012.pngbin1161 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_013.pngbin1161 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_014.pngbin1161 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_000.pngbin1161 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00001.9.pngbin0 -> 17548 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00002.9.pngbin0 -> 17499 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00003.9.pngbin0 -> 17427 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00004.9.pngbin0 -> 17146 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00005.9.pngbin0 -> 17068 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00006.9.pngbin0 -> 17053 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00007.9.pngbin0 -> 17028 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00008.9.pngbin0 -> 17232 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00009.9.pngbin0 -> 17375 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00010.9.pngbin0 -> 17386 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00011.9.pngbin0 -> 17626 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00012.9.pngbin0 -> 17693 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_001.pngbin1187 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_002.pngbin1129 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_003.pngbin988 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_004.pngbin842 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_005.pngbin843 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_006.pngbin875 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_007.pngbin867 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_008.pngbin902 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_009.pngbin902 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_010.pngbin902 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_011.pngbin902 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_012.pngbin902 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_013.pngbin902 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_014.pngbin902 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ic_corp_icon.pngbin1488 -> 4016 bytes
-rw-r--r--core/res/res/drawable-xhdpi/switch_track_mtrl_alpha.9.pngbin158 -> 708 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_000.pngbin1248 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00001.9.pngbin0 -> 19243 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00002.9.pngbin0 -> 19072 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00003.9.pngbin0 -> 18651 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00004.9.pngbin0 -> 18542 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00005.9.pngbin0 -> 18256 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00006.9.pngbin0 -> 18070 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00007.9.pngbin0 -> 18132 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00008.9.pngbin0 -> 18328 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00009.9.pngbin0 -> 18469 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00010.9.pngbin0 -> 18712 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00011.9.pngbin0 -> 18756 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00012.9.pngbin0 -> 18864 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_001.pngbin1290 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_002.pngbin1544 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_003.pngbin1716 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_004.pngbin1738 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_005.pngbin1706 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_006.pngbin2028 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_007.pngbin2028 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_008.pngbin1817 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_009.pngbin1863 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_010.pngbin1856 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_011.pngbin1856 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_012.pngbin1856 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_013.pngbin1856 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_014.pngbin1856 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_000.pngbin1856 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00001.9.pngbin0 -> 18906 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00002.9.pngbin0 -> 18919 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00003.9.pngbin0 -> 18645 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00004.9.pngbin0 -> 18572 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00005.9.pngbin0 -> 18294 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00006.9.pngbin0 -> 18097 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00007.9.pngbin0 -> 18132 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00008.9.pngbin0 -> 18369 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00009.9.pngbin0 -> 18729 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00010.9.pngbin0 -> 18944 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00011.9.pngbin0 -> 19164 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00012.9.pngbin0 -> 19303 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_001.pngbin1863 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_002.pngbin1710 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_003.pngbin1481 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_004.pngbin1315 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_005.pngbin1274 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_006.pngbin1246 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_007.pngbin1290 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_008.pngbin1248 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_009.pngbin1248 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_010.pngbin1248 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_011.pngbin1248 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_012.pngbin1248 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_013.pngbin1248 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_014.pngbin1248 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/ic_corp_icon.pngbin2137 -> 2668 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/switch_track_mtrl_alpha.9.pngbin165 -> 1105 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_000.pngbin1908 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00001.9.pngbin0 -> 18768 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00002.9.pngbin0 -> 18687 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00003.9.pngbin0 -> 18164 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00004.9.pngbin0 -> 17798 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00005.9.pngbin0 -> 17512 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00006.9.pngbin0 -> 17479 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00007.9.pngbin0 -> 17440 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00008.9.pngbin0 -> 17495 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00009.9.pngbin0 -> 17759 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00010.9.pngbin0 -> 18097 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00011.9.pngbin0 -> 18132 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00012.9.pngbin0 -> 18285 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_001.pngbin1841 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_002.pngbin2033 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_003.pngbin2148 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_004.pngbin2257 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_005.pngbin2223 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_006.pngbin2411 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_007.pngbin2401 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_008.pngbin2298 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_009.pngbin2364 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_010.pngbin2295 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_011.pngbin2295 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_012.pngbin2296 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_013.pngbin2295 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_014.pngbin2329 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_000.pngbin2295 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00001.9.pngbin0 -> 18433 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00002.9.pngbin0 -> 18301 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00003.9.pngbin0 -> 18030 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00004.9.pngbin0 -> 17612 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00005.9.pngbin0 -> 17540 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00006.9.pngbin0 -> 17442 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00007.9.pngbin0 -> 17440 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00008.9.pngbin0 -> 17612 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00009.9.pngbin0 -> 18080 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00010.9.pngbin0 -> 18507 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00011.9.pngbin0 -> 18721 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00012.9.pngbin0 -> 18734 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_001.pngbin2373 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_002.pngbin2188 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_003.pngbin1982 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_004.pngbin1894 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_005.pngbin1853 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_006.pngbin1859 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_007.pngbin1952 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_008.pngbin1908 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_009.pngbin1908 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_010.pngbin1931 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_011.pngbin1908 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_012.pngbin1908 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_013.pngbin1891 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_014.pngbin1908 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/switch_track_mtrl_alpha.9.pngbin1060 -> 1874 bytes
-rw-r--r--core/res/res/drawable/switch_thumb_material_anim.xml90
-rw-r--r--core/res/res/drawable/switch_track_material.xml12
-rw-r--r--core/res/res/values/arrays.xml54
-rw-r--r--core/res/res/values/attrs.xml56
-rw-r--r--core/res/res/values/public.xml5
-rw-r--r--core/res/res/values/styles_material.xml3
-rw-r--r--data/fonts/Roboto-Black.ttfbin280624 -> 242180 bytes
-rw-r--r--data/fonts/Roboto-BlackItalic.ttfbin304372 -> 263984 bytes
-rw-r--r--data/fonts/Roboto-Bold.ttfbin279564 -> 242312 bytes
-rw-r--r--data/fonts/Roboto-BoldItalic.ttfbin303836 -> 264076 bytes
-rw-r--r--data/fonts/Roboto-Italic.ttfbin302296 -> 263064 bytes
-rw-r--r--data/fonts/Roboto-Light.ttfbin280792 -> 243796 bytes
-rw-r--r--data/fonts/Roboto-LightItalic.ttfbin304764 -> 266088 bytes
-rw-r--r--data/fonts/Roboto-Medium.ttfbin277964 -> 241648 bytes
-rw-r--r--data/fonts/Roboto-MediumItalic.ttfbin303052 -> 263556 bytes
-rw-r--r--data/fonts/Roboto-Regular.ttfbin278336 -> 241016 bytes
-rw-r--r--data/fonts/Roboto-Thin.ttfbin285416 -> 246252 bytes
-rw-r--r--data/fonts/Roboto-ThinItalic.ttfbin303808 -> 266876 bytes
-rw-r--r--data/fonts/RobotoCondensed-Bold.ttfbin277424 -> 239604 bytes
-rw-r--r--data/fonts/RobotoCondensed-BoldItalic.ttfbin306324 -> 261668 bytes
-rw-r--r--data/fonts/RobotoCondensed-Italic.ttfbin306084 -> 262000 bytes
-rw-r--r--data/fonts/RobotoCondensed-Light.ttfbin278364 -> 240828 bytes
-rw-r--r--data/fonts/RobotoCondensed-LightItalic.ttfbin308840 -> 264508 bytes
-rw-r--r--data/fonts/RobotoCondensed-Regular.ttfbin275896 -> 238812 bytes
-rw-r--r--docs/html/google/google_toc.cs7
-rw-r--r--docs/html/google/play/billing/billing_subscriptions.jd18
-rw-r--r--docs/html/google/play/billing/gp-purchase-status-api.jd263
-rw-r--r--docs/html/google/play/billing/index.jd6
-rw-r--r--docs/html/google/play/dist.jd10
-rw-r--r--docs/html/preview/preview_toc.cs2
-rw-r--r--docs/html/preview/tv/adt-1/index.jd50
-rw-r--r--docs/html/preview/tv/images/tif-overview.pngbin0 -> 74477 bytes
-rw-r--r--docs/html/preview/tv/tif/index.jd38
-rw-r--r--graphics/java/android/graphics/Paint.java33
-rw-r--r--graphics/java/android/graphics/drawable/NinePatchDrawable.java25
-rw-r--r--graphics/java/android/graphics/drawable/VectorDrawable.java24
-rw-r--r--media/java/android/media/AudioDevicePort.java8
-rw-r--r--media/java/android/media/AudioHandle.java5
-rw-r--r--media/java/android/media/AudioPort.java8
-rw-r--r--media/java/android/media/AudioPortConfig.java10
-rw-r--r--media/java/android/media/MediaCodec.java230
-rw-r--r--media/java/android/media/browse/MediaBrowserItem.java13
-rw-r--r--media/java/android/media/tv/ITvInputClient.aidl1
-rw-r--r--media/java/android/media/tv/ITvInputSessionCallback.aidl1
-rw-r--r--media/java/android/media/tv/TvInputManager.java53
-rw-r--r--media/java/android/media/tv/TvInputService.java36
-rw-r--r--media/java/android/media/tv/TvStreamConfig.java10
-rw-r--r--media/java/android/media/tv/TvTrackInfo.java316
-rw-r--r--media/java/android/media/tv/TvView.java77
-rw-r--r--packages/SystemUI/res/layout/keyguard_status_bar.xml78
-rw-r--r--packages/SystemUI/res/layout/status_bar.xml28
-rw-r--r--packages/SystemUI/res/layout/status_bar_expanded.xml4
-rw-r--r--packages/SystemUI/res/layout/status_bar_expanded_header.xml14
-rw-r--r--packages/SystemUI/res/layout/system_icons.xml41
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java150
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java111
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java60
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java254
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java22
-rw-r--r--policy/src/com/android/internal/policy/impl/PhoneWindow.java93
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java20
-rw-r--r--services/core/java/com/android/server/LocationManagerService.java53
-rw-r--r--services/core/java/com/android/server/UiModeManagerService.java16
-rw-r--r--services/core/java/com/android/server/accounts/AccountManagerService.java3
-rwxr-xr-xservices/core/java/com/android/server/am/ActivityManagerService.java40
-rwxr-xr-xservices/core/java/com/android/server/am/ActivityStack.java4
-rw-r--r--services/core/java/com/android/server/connectivity/Vpn.java5
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiControlService.java6
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java67
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerService.java424
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerSession.java202
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java8
-rw-r--r--services/core/java/com/android/server/tv/TvInputHal.java102
-rw-r--r--services/core/java/com/android/server/tv/TvInputManagerService.java18
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java41
-rw-r--r--services/core/jni/com_android_server_location_FlpHardwareProvider.cpp4
-rw-r--r--services/core/jni/com_android_server_tv_TvInputHal.cpp2
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java28
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java59
-rw-r--r--telephony/java/android/telephony/IccOpenLogicalChannelResponse.aidl20
-rw-r--r--telephony/java/android/telephony/IccOpenLogicalChannelResponse.java121
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java63
-rw-r--r--telephony/java/com/android/internal/telephony/ITelephony.aidl41
-rw-r--r--tests/SharedLibrary/lib/AndroidManifest.xml3
-rw-r--r--tests/SharedLibrary/lib/res/drawable/size_48x48.jpgbin0 -> 1572 bytes
-rw-r--r--tools/aapt/Command.cpp27
-rw-r--r--tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java2
-rw-r--r--tools/layoutlib/create/src/com/android/tools/layoutlib/create/ReplaceMethodCallsAdapter.java2
-rw-r--r--wifi/java/android/net/wifi/ScanResult.java8
-rw-r--r--wifi/java/android/net/wifi/WifiScanner.java67
422 files changed, 4113 insertions, 1413 deletions
diff --git a/Android.mk b/Android.mk
index 4376ed6..8309301 100644
--- a/Android.mk
+++ b/Android.mk
@@ -186,6 +186,7 @@ LOCAL_SRC_FILES += \
core/java/android/nfc/INfcTag.aidl \
core/java/android/nfc/INfcCardEmulation.aidl \
core/java/android/nfc/INfcLockscreenDispatch.aidl \
+ core/java/android/nfc/INfcUnlockHandler.aidl \
core/java/android/os/IBatteryPropertiesListener.aidl \
core/java/android/os/IBatteryPropertiesRegistrar.aidl \
core/java/android/os/ICancellationSignal.aidl \
diff --git a/api/current.txt b/api/current.txt
index a3a99c7..56b0bf0 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -1123,6 +1123,7 @@ package android {
field public static final int showDividers = 16843561; // 0x1010329
field public static final int showOnLockScreen = 16843721; // 0x10103c9
field public static final int showSilent = 16843259; // 0x10101fb
+ field public static final int showText = 16843952; // 0x10104b0
field public static final int showWeekNumber = 16843582; // 0x101033e
field public static final int shownWeekCount = 16843585; // 0x1010341
field public static final int shrinkColumns = 16843082; // 0x101014a
@@ -1434,8 +1435,12 @@ package android {
field public static final int windowNoDisplay = 16843294; // 0x101021e
field public static final int windowNoTitle = 16842838; // 0x1010056
field public static final int windowOverscan = 16843727; // 0x10103cf
+ field public static final int windowReenterTransition = 16843954; // 0x10104b2
+ field public static final int windowReturnTransition = 16843953; // 0x10104b1
field public static final int windowSharedElementEnterTransition = 16843835; // 0x101043b
field public static final int windowSharedElementExitTransition = 16843836; // 0x101043c
+ field public static final int windowSharedElementReenterTransition = 16843956; // 0x10104b4
+ field public static final int windowSharedElementReturnTransition = 16843955; // 0x10104b3
field public static final int windowShowAnimation = 16842934; // 0x10100b6
field public static final int windowShowWallpaper = 16843410; // 0x1010292
field public static final int windowSoftInputMode = 16843307; // 0x101022b
@@ -5219,6 +5224,7 @@ package android.app {
field public static java.lang.String ACTION_EXIT_DESK_MODE;
field public static final int DISABLE_CAR_MODE_GO_HOME = 1; // 0x1
field public static final int ENABLE_CAR_MODE_GO_CAR_HOME = 1; // 0x1
+ field public static final int ENABLE_CAR_MODE_NO_WAKE_LOCK = 2; // 0x2
field public static final int MODE_NIGHT_AUTO = 0; // 0x0
field public static final int MODE_NIGHT_NO = 1; // 0x1
field public static final int MODE_NIGHT_YES = 2; // 0x2
@@ -8513,9 +8519,11 @@ package android.content.pm {
method public android.graphics.Bitmap getAppIcon();
method public java.lang.CharSequence getAppLabel();
method public java.lang.String getAppPackageName();
+ method public android.content.Intent getDetailsIntent();
method public java.lang.String getInstallerPackageName();
method public float getProgress();
method public int getSessionId();
+ method public boolean isOpen();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator CREATOR;
}
@@ -8529,7 +8537,6 @@ package android.content.pm {
method public void setInstallLocation(int);
method public void setOriginatingUri(android.net.Uri);
method public void setReferrerUri(android.net.Uri);
- method public void setSignatures(android.content.pm.Signature[]);
method public void setSize(long);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator CREATOR;
@@ -8645,6 +8652,8 @@ package android.content.pm {
method public android.content.pm.PackageInstaller.Session openSession(int);
method public void removeSessionCallback(android.content.pm.PackageInstaller.SessionCallback);
method public void uninstall(java.lang.String, android.content.pm.PackageInstaller.UninstallCallback);
+ field public static final java.lang.String ACTION_SESSION_DETAILS = "android.content.pm.action.SESSION_DETAILS";
+ field public static final java.lang.String EXTRA_SESSION_ID = "android.content.pm.extra.SESSION_ID";
}
public static abstract class PackageInstaller.CommitCallback {
@@ -8664,14 +8673,18 @@ package android.content.pm {
method public void close();
method public void commit(android.content.pm.PackageInstaller.CommitCallback);
method public void fsync(java.io.OutputStream) throws java.io.IOException;
+ method public java.lang.String[] list();
+ method public java.io.InputStream openRead(java.lang.String) throws java.io.IOException;
method public java.io.OutputStream openWrite(java.lang.String, long, long) throws java.io.IOException;
method public void setProgress(float);
}
public static abstract class PackageInstaller.SessionCallback {
ctor public PackageInstaller.SessionCallback();
+ method public abstract void onClosed(int);
method public abstract void onCreated(int);
method public abstract void onFinished(int, boolean);
+ method public abstract void onOpened(int);
method public abstract void onProgressChanged(int, float);
}
@@ -13276,6 +13289,11 @@ package android.hardware.location {
field public static final int MONITOR_CURRENTLY_AVAILABLE = 0; // 0x0
field public static final int MONITOR_CURRENTLY_UNAVAILABLE = 1; // 0x1
field public static final int MONITOR_UNSUPPORTED = 2; // 0x2
+ field public static final int SOURCE_TECHNOLOGY_BLUETOOTH = 16; // 0x10
+ field public static final int SOURCE_TECHNOLOGY_CELL = 8; // 0x8
+ field public static final int SOURCE_TECHNOLOGY_GNSS = 1; // 0x1
+ field public static final int SOURCE_TECHNOLOGY_SENSORS = 4; // 0x4
+ field public static final int SOURCE_TECHNOLOGY_WIFI = 2; // 0x2
}
public abstract class GeofenceHardwareCallback {
@@ -13289,7 +13307,19 @@ package android.hardware.location {
public abstract class GeofenceHardwareMonitorCallback {
ctor public GeofenceHardwareMonitorCallback();
- method public void onMonitoringSystemChange(int, boolean, android.location.Location);
+ method public deprecated void onMonitoringSystemChange(int, boolean, android.location.Location);
+ method public void onMonitoringSystemChange(android.hardware.location.GeofenceHardwareMonitorEvent);
+ }
+
+ public class GeofenceHardwareMonitorEvent implements android.os.Parcelable {
+ ctor public GeofenceHardwareMonitorEvent(int, int, int, android.location.Location);
+ method public int describeContents();
+ method public android.location.Location getLocation();
+ method public int getMonitoringStatus();
+ method public int getMonitoringType();
+ method public int getSourceTechnologies();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator CREATOR;
}
public final class GeofenceHardwareRequest {
@@ -13301,10 +13331,12 @@ package android.hardware.location {
method public int getMonitorTransitions();
method public int getNotificationResponsiveness();
method public double getRadius();
+ method public int getSourceTechnologies();
method public int getUnknownTimer();
method public void setLastTransition(int);
method public void setMonitorTransitions(int);
method public void setNotificationResponsiveness(int);
+ method public void setSourceTechnologies(int);
method public void setUnknownTimer(int);
}
@@ -17044,6 +17076,7 @@ package android.media.tv {
method public void notifyContentAllowed();
method public void notifyContentBlocked(android.media.tv.TvContentRating);
method public void notifyTrackInfoChanged(java.util.List<android.media.tv.TvTrackInfo>);
+ method public void notifyTrackSelectionChanged(java.util.List<android.media.tv.TvTrackInfo>);
method public void notifyVideoAvailable();
method public void notifyVideoUnavailable(int);
method public android.view.View onCreateOverlayView();
@@ -17067,33 +17100,30 @@ package android.media.tv {
}
public final class TvTrackInfo implements android.os.Parcelable {
- method public boolean containsKey(java.lang.String);
method public int describeContents();
- method public boolean getBoolean(java.lang.String);
- method public int getInt(java.lang.String);
- method public java.lang.String getString(java.lang.String);
+ method public final int getAudioChannelCount();
+ method public final int getAudioSampleRate();
+ method public final android.os.Bundle getExtra();
+ method public final java.lang.String getLanguage();
+ method public final int getType();
+ method public final int getVideoHeight();
+ method public final int getVideoWidth();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator CREATOR;
- field public static final java.lang.String KEY_CHANNEL_COUNT = "channel-count";
- field public static final java.lang.String KEY_HEIGHT = "height";
- field public static final java.lang.String KEY_IS_SELECTED = "is-selected";
- field public static final java.lang.String KEY_LANGUAGE = "language";
- field public static final java.lang.String KEY_SAMPLE_RATE = "sample-rate";
- field public static final java.lang.String KEY_TAG = "tag";
- field public static final java.lang.String KEY_TYPE = "type";
- field public static final java.lang.String KEY_WIDTH = "width";
- field public static final int VALUE_TYPE_AUDIO = 0; // 0x0
- field public static final int VALUE_TYPE_SUBTITLE = 2; // 0x2
- field public static final int VALUE_TYPE_VIDEO = 1; // 0x1
+ field public static final int TYPE_AUDIO = 0; // 0x0
+ field public static final int TYPE_SUBTITLE = 2; // 0x2
+ field public static final int TYPE_VIDEO = 1; // 0x1
}
public static final class TvTrackInfo.Builder {
- ctor public TvTrackInfo.Builder(int, java.lang.String, boolean);
- ctor public TvTrackInfo.Builder(android.media.tv.TvTrackInfo);
+ ctor public TvTrackInfo.Builder(int);
method public android.media.tv.TvTrackInfo build();
- method public android.media.tv.TvTrackInfo.Builder putBoolean(java.lang.String, boolean);
- method public android.media.tv.TvTrackInfo.Builder putInt(java.lang.String, int);
- method public android.media.tv.TvTrackInfo.Builder putString(java.lang.String, java.lang.String);
+ method public final android.media.tv.TvTrackInfo.Builder setAudioChannelCount(int);
+ method public final android.media.tv.TvTrackInfo.Builder setAudioSampleRate(int);
+ method public final android.media.tv.TvTrackInfo.Builder setExtra(android.os.Bundle);
+ method public final android.media.tv.TvTrackInfo.Builder setLanguage(java.lang.String);
+ method public final android.media.tv.TvTrackInfo.Builder setVideoHeight(int);
+ method public final android.media.tv.TvTrackInfo.Builder setVideoWidth(int);
}
public class TvView extends android.view.ViewGroup {
@@ -17101,6 +17131,7 @@ package android.media.tv {
ctor public TvView(android.content.Context, android.util.AttributeSet);
ctor public TvView(android.content.Context, android.util.AttributeSet, int);
method public boolean dispatchUnhandledInputEvent(android.view.InputEvent);
+ method public java.util.List<android.media.tv.TvTrackInfo> getSelectedTracks();
method public java.util.List<android.media.tv.TvTrackInfo> getTracks();
method protected void onLayout(boolean, int, int, int, int);
method public boolean onUnhandledInputEvent(android.view.InputEvent);
@@ -17127,6 +17158,7 @@ package android.media.tv {
method public void onContentBlocked(java.lang.String, android.media.tv.TvContentRating);
method public void onError(java.lang.String, int);
method public void onTrackInfoChanged(java.lang.String, java.util.List<android.media.tv.TvTrackInfo>);
+ method public void onTrackSelectionChanged(java.lang.String, java.util.List<android.media.tv.TvTrackInfo>);
method public void onVideoAvailable(java.lang.String);
method public void onVideoSizeChanged(java.lang.String, int, int);
method public void onVideoUnavailable(java.lang.String, int);
@@ -17453,10 +17485,15 @@ package android.net {
method public java.net.URL getBoundURL(java.net.URL) throws java.net.MalformedURLException;
method public java.net.InetAddress getByName(java.lang.String) throws java.net.UnknownHostException;
method public javax.net.SocketFactory getSocketFactory();
+ method public static void setNetworkBoundURLFactory(android.net.NetworkBoundURLFactory);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator CREATOR;
}
+ public abstract interface NetworkBoundURLFactory {
+ method public abstract java.net.URL getBoundURL(android.net.Network, java.net.URL) throws java.net.MalformedURLException;
+ }
+
public final class NetworkCapabilities implements android.os.Parcelable {
ctor public NetworkCapabilities(android.net.NetworkCapabilities);
method public int describeContents();
@@ -29216,6 +29253,20 @@ package android.telephony {
field public static final int VOICEMAIL_NUMBER_MISSING = 40; // 0x28
}
+ public class IccOpenLogicalChannelResponse implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getChannel();
+ method public byte[] getSelectResponse();
+ method public int getStatus();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator CREATOR;
+ field public static int INVALID_CHANNEL;
+ field public static int MISSING_RESOURCE;
+ field public static int NO_ERROR;
+ field public static int NO_SUCH_ELEMENT;
+ field public static int UNKNOWN_ERROR;
+ }
+
public class MessagingConfigurationManager {
method public boolean getCarrierConfigBoolean(java.lang.String, boolean);
method public int getCarrierConfigInt(java.lang.String, int);
@@ -29538,7 +29589,8 @@ package android.telephony {
method public int hasCarrierPrivileges();
method public boolean hasIccCard();
method public boolean iccCloseLogicalChannel(int);
- method public int iccOpenLogicalChannel(java.lang.String);
+ method public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannel(java.lang.String);
+ method public java.lang.String iccTransmitApduBasicChannel(int, int, int, int, int, java.lang.String);
method public java.lang.String iccTransmitApduLogicalChannel(int, int, int, int, int, int, java.lang.String);
method public boolean isNetworkRoaming();
method public boolean isSmsCapable();
@@ -35278,8 +35330,12 @@ package android.view {
method protected final int getLocalFeatures();
method public android.media.session.MediaController getMediaController();
method public abstract int getNavigationBarColor();
+ method public android.transition.Transition getReenterTransition();
+ method public android.transition.Transition getReturnTransition();
method public android.transition.Transition getSharedElementEnterTransition();
method public android.transition.Transition getSharedElementExitTransition();
+ method public android.transition.Transition getSharedElementReenterTransition();
+ method public android.transition.Transition getSharedElementReturnTransition();
method public abstract int getStatusBarColor();
method public long getTransitionBackgroundFadeDuration();
method public android.transition.TransitionManager getTransitionManager();
@@ -35335,8 +35391,12 @@ package android.view {
method public void setLogo(int);
method public void setMediaController(android.media.session.MediaController);
method public abstract void setNavigationBarColor(int);
+ method public void setReenterTransition(android.transition.Transition);
+ method public void setReturnTransition(android.transition.Transition);
method public void setSharedElementEnterTransition(android.transition.Transition);
method public void setSharedElementExitTransition(android.transition.Transition);
+ method public void setSharedElementReenterTransition(android.transition.Transition);
+ method public void setSharedElementReturnTransition(android.transition.Transition);
method public void setSoftInputMode(int);
method public abstract void setStatusBarColor(int);
method public abstract void setTitle(java.lang.CharSequence);
@@ -39379,6 +39439,7 @@ package android.widget {
ctor public Switch(android.content.Context, android.util.AttributeSet);
ctor public Switch(android.content.Context, android.util.AttributeSet, int);
ctor public Switch(android.content.Context, android.util.AttributeSet, int, int);
+ method public boolean getShowText();
method public boolean getSplitTrack();
method public int getSwitchMinWidth();
method public int getSwitchPadding();
@@ -39388,6 +39449,7 @@ package android.widget {
method public int getThumbTextPadding();
method public android.graphics.drawable.Drawable getTrackDrawable();
method public void onMeasure(int, int);
+ method public void setShowText(boolean);
method public void setSplitTrack(boolean);
method public void setSwitchMinWidth(int);
method public void setSwitchPadding(int);
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index bc16800..1f25dd0 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -59,7 +59,6 @@ import com.android.internal.util.ArrayUtils;
import com.android.internal.util.SizedInputStream;
import libcore.io.IoUtils;
-import libcore.io.Streams;
import java.io.File;
import java.io.FileDescriptor;
@@ -1068,6 +1067,8 @@ public final class Pm {
}
}
+ final InstallSessionInfo info = mInstaller.getSessionInfo(sessionId);
+
PackageInstaller.Session session = null;
InputStream in = null;
OutputStream out = null;
@@ -1081,16 +1082,21 @@ public final class Pm {
}
out = session.openWrite(splitName, 0, sizeBytes);
- final int n = Streams.copy(in, out);
- session.fsync(out);
+ int total = 0;
+ byte[] buffer = new byte[65536];
+ int c;
+ while ((c = in.read(buffer)) != -1) {
+ total += c;
+ out.write(buffer, 0, c);
- final InstallSessionInfo info = mInstaller.getSessionInfo(sessionId);
- if (info.sizeBytes > 0) {
- final float fraction = ((float) n / (float) info.sizeBytes);
- session.addProgress(fraction);
+ if (info.sizeBytes > 0) {
+ final float fraction = ((float) c / (float) info.sizeBytes);
+ session.addProgress(fraction);
+ }
}
+ session.fsync(out);
- System.out.println("Success: streamed " + n + " bytes");
+ System.out.println("Success: streamed " + total + " bytes");
} finally {
IoUtils.closeQuietly(out);
IoUtils.closeQuietly(in);
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index f18507e..18ba8c4 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -1624,7 +1624,7 @@ final class ApplicationPackageManager extends PackageManager {
}
Drawable dr = getDrawable(itemInfo.packageName, itemInfo.icon, appInfo);
if (dr == null) {
- dr = getDefaultActivityIcon();
+ dr = itemInfo.loadDefaultIcon(this);
}
return getUserManager().getBadgedDrawableForUser(dr,
new UserHandle(mContext.getUserId()));
diff --git a/core/java/android/app/EnterTransitionCoordinator.java b/core/java/android/app/EnterTransitionCoordinator.java
index 1326064..b5d362d 100644
--- a/core/java/android/app/EnterTransitionCoordinator.java
+++ b/core/java/android/app/EnterTransitionCoordinator.java
@@ -256,7 +256,7 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator {
@Override
protected Transition getViewsTransition() {
if (mIsReturning) {
- return getWindow().getExitTransition();
+ return getWindow().getReenterTransition();
} else {
return getWindow().getEnterTransition();
}
@@ -264,7 +264,7 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator {
protected Transition getSharedElementTransition() {
if (mIsReturning) {
- return getWindow().getSharedElementExitTransition();
+ return getWindow().getSharedElementReenterTransition();
} else {
return getWindow().getSharedElementEnterTransition();
}
diff --git a/core/java/android/app/ExitTransitionCoordinator.java b/core/java/android/app/ExitTransitionCoordinator.java
index 2ce6018..b3fdcc7 100644
--- a/core/java/android/app/ExitTransitionCoordinator.java
+++ b/core/java/android/app/ExitTransitionCoordinator.java
@@ -395,7 +395,7 @@ class ExitTransitionCoordinator extends ActivityTransitionCoordinator {
@Override
protected Transition getViewsTransition() {
if (mIsReturning) {
- return getWindow().getEnterTransition();
+ return getWindow().getReturnTransition();
} else {
return getWindow().getExitTransition();
}
@@ -403,7 +403,7 @@ class ExitTransitionCoordinator extends ActivityTransitionCoordinator {
protected Transition getSharedElementTransition() {
if (mIsReturning) {
- return getWindow().getSharedElementEnterTransition();
+ return getWindow().getSharedElementReturnTransition();
} else {
return getWindow().getSharedElementExitTransition();
}
diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java
index 3967740..ec9960d 100644
--- a/core/java/android/app/Service.java
+++ b/core/java/android/app/Service.java
@@ -401,7 +401,7 @@ public abstract class Service extends ContextWrapper implements ComponentCallbac
/**
* This flag is set in {@link #onStartCommand} if the Intent is a
- * a retry because the original attempt never got to or returned from
+ * retry because the original attempt never got to or returned from
* {@link #onStartCommand(Intent, int, int)}.
*/
public static final int START_FLAG_RETRY = 0x0002;
diff --git a/core/java/android/app/UiModeManager.java b/core/java/android/app/UiModeManager.java
index c6731c9..f79eb04 100644
--- a/core/java/android/app/UiModeManager.java
+++ b/core/java/android/app/UiModeManager.java
@@ -123,7 +123,18 @@ public class UiModeManager {
* will switch to the car home activity even if we are already in car mode.
*/
public static final int ENABLE_CAR_MODE_GO_CAR_HOME = 0x0001;
-
+
+ /**
+ * Flag for use with {@link #enableCarMode(int)}: do not hold full wake lock
+ * while in car mode. By default, when this flag is not set, the system may hold
+ * a full wake lock to keep the screen turned on while in car mode.
+ * Setting this flag disables such behavior and the screen may be turned off if
+ * there is no other user activity and no other full wake lock held.
+ * Setting this flag can be relevant for a car dock application that does not require the
+ * screen kept on.
+ */
+ public static final int ENABLE_CAR_MODE_NO_WAKE_LOCK = 0x0002;
+
/**
* Force device into car mode, like it had been placed in the car dock.
* This will cause the device to switch to the car home UI as part of
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 482ad6e..548a0c9 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -839,7 +839,8 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
/**
* @hide
*/
- @Override protected Drawable loadDefaultIcon(PackageManager pm) {
+ @Override
+ public Drawable loadDefaultIcon(PackageManager pm) {
if ((flags & FLAG_EXTERNAL_STORAGE) != 0
&& isPackageUnavailable(pm)) {
return Resources.getSystem().getDrawable(
diff --git a/core/java/android/content/pm/ComponentInfo.java b/core/java/android/content/pm/ComponentInfo.java
index 7e8f285..cc06b67 100644
--- a/core/java/android/content/pm/ComponentInfo.java
+++ b/core/java/android/content/pm/ComponentInfo.java
@@ -179,7 +179,8 @@ public class ComponentInfo extends PackageItemInfo {
/**
* @hide
*/
- @Override protected Drawable loadDefaultIcon(PackageManager pm) {
+ @Override
+ public Drawable loadDefaultIcon(PackageManager pm) {
return applicationInfo.loadIcon(pm);
}
diff --git a/core/java/android/content/pm/IPackageInstallerCallback.aidl b/core/java/android/content/pm/IPackageInstallerCallback.aidl
index a31ae54..39ae1a0 100644
--- a/core/java/android/content/pm/IPackageInstallerCallback.aidl
+++ b/core/java/android/content/pm/IPackageInstallerCallback.aidl
@@ -19,6 +19,8 @@ package android.content.pm;
/** {@hide} */
oneway interface IPackageInstallerCallback {
void onSessionCreated(int sessionId);
+ void onSessionOpened(int sessionId);
void onSessionProgressChanged(int sessionId, float progress);
+ void onSessionClosed(int sessionId);
void onSessionFinished(int sessionId, boolean success);
}
diff --git a/core/java/android/content/pm/IPackageInstallerSession.aidl b/core/java/android/content/pm/IPackageInstallerSession.aidl
index 2fd7ddb..af0323f 100644
--- a/core/java/android/content/pm/IPackageInstallerSession.aidl
+++ b/core/java/android/content/pm/IPackageInstallerSession.aidl
@@ -24,7 +24,9 @@ interface IPackageInstallerSession {
void setClientProgress(float progress);
void addClientProgress(float progress);
+ String[] list();
ParcelFileDescriptor openWrite(String name, long offsetBytes, long lengthBytes);
+ ParcelFileDescriptor openRead(String name);
void close();
void commit(in IPackageInstallObserver2 observer);
diff --git a/core/java/android/content/pm/InstallSessionInfo.java b/core/java/android/content/pm/InstallSessionInfo.java
index a9c574a..f263885 100644
--- a/core/java/android/content/pm/InstallSessionInfo.java
+++ b/core/java/android/content/pm/InstallSessionInfo.java
@@ -16,7 +16,9 @@
package android.content.pm;
+import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Parcel;
import android.os.Parcelable;
@@ -32,6 +34,8 @@ public class InstallSessionInfo implements Parcelable {
public String installerPackageName;
/** {@hide} */
public float progress;
+ /** {@hide} */
+ public boolean open;
/** {@hide} */
public int mode;
@@ -53,6 +57,7 @@ public class InstallSessionInfo implements Parcelable {
sessionId = source.readInt();
installerPackageName = source.readString();
progress = source.readFloat();
+ open = source.readInt() != 0;
mode = source.readInt();
sizeBytes = source.readLong();
@@ -88,6 +93,13 @@ public class InstallSessionInfo implements Parcelable {
}
/**
+ * Return if this session is currently open.
+ */
+ public boolean isOpen() {
+ return open;
+ }
+
+ /**
* Return the package name this session is working with. May be {@code null}
* if unknown.
*/
@@ -111,6 +123,23 @@ public class InstallSessionInfo implements Parcelable {
return appLabel;
}
+ /**
+ * Return an Intent that can be started to view details about this install
+ * session. This may surface actions such as pause, resume, or cancel.
+ * <p>
+ * In some cases, a matching Activity may not exist, so ensure you safeguard
+ * against this.
+ *
+ * @see PackageInstaller#ACTION_SESSION_DETAILS
+ */
+ public @Nullable Intent getDetailsIntent() {
+ final Intent intent = new Intent(PackageInstaller.ACTION_SESSION_DETAILS);
+ intent.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId);
+ intent.setPackage(installerPackageName);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ return intent;
+ }
+
@Override
public int describeContents() {
return 0;
@@ -121,6 +150,7 @@ public class InstallSessionInfo implements Parcelable {
dest.writeInt(sessionId);
dest.writeString(installerPackageName);
dest.writeFloat(progress);
+ dest.writeInt(open ? 1 : 0);
dest.writeInt(mode);
dest.writeLong(sizeBytes);
diff --git a/core/java/android/content/pm/InstallSessionParams.java b/core/java/android/content/pm/InstallSessionParams.java
index 3de9863..1716e39 100644
--- a/core/java/android/content/pm/InstallSessionParams.java
+++ b/core/java/android/content/pm/InstallSessionParams.java
@@ -17,6 +17,7 @@
package android.content.pm;
import android.annotation.Nullable;
+import android.app.ActivityManager;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
@@ -30,6 +31,9 @@ import com.android.internal.util.IndentingPrintWriter;
*/
public class InstallSessionParams implements Parcelable {
+ /** {@hide} */
+ public static final int MODE_INVALID = -1;
+
/**
* Mode for an install session whose staged APKs should fully replace any
* existing APKs for the target app.
@@ -48,21 +52,19 @@ public class InstallSessionParams implements Parcelable {
public static final int MODE_INHERIT_EXISTING = 2;
/** {@hide} */
- public int mode;
+ public int mode = MODE_INVALID;
/** {@hide} */
public int installFlags;
/** {@hide} */
public int installLocation = PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY;
/** {@hide} */
- public Signature[] signatures;
- /** {@hide} */
public long sizeBytes = -1;
/** {@hide} */
public String appPackageName;
/** {@hide} */
public Bitmap appIcon;
/** {@hide} */
- public CharSequence appLabel;
+ public String appLabel;
/** {@hide} */
public Uri originatingUri;
/** {@hide} */
@@ -86,7 +88,6 @@ public class InstallSessionParams implements Parcelable {
mode = source.readInt();
installFlags = source.readInt();
installLocation = source.readInt();
- signatures = (Signature[]) source.readParcelableArray(null);
sizeBytes = source.readLong();
appPackageName = source.readString();
appIcon = source.readParcelable(null);
@@ -106,16 +107,13 @@ public class InstallSessionParams implements Parcelable {
}
/**
- * Optionally provide a set of certificates for the app being installed.
- * <p>
- * If the APKs staged in the session aren't consistent with these
- * signatures, the install will fail. Regardless of this value, all APKs in
- * the app must have the same signing certificates.
- *
- * @see PackageInfo#signatures
+ * @deprecated use {@link PackageInstaller.Session#openRead(String)} to
+ * calculate message digest instead.
+ * @hide
*/
+ @Deprecated
public void setSignatures(@Nullable Signature[] signatures) {
- this.signatures = signatures;
+ throw new UnsupportedOperationException();
}
/**
@@ -146,7 +144,8 @@ public class InstallSessionParams implements Parcelable {
/**
* Optionally set an icon representing the app being installed. This should
- * be at least {@link android.R.dimen#app_icon_size} in both dimensions.
+ * be roughly {@link ActivityManager#getLauncherLargeIconSize()} in both
+ * dimensions.
*/
public void setAppIcon(@Nullable Bitmap appIcon) {
this.appIcon = appIcon;
@@ -156,7 +155,7 @@ public class InstallSessionParams implements Parcelable {
* Optionally set a label representing the app being installed.
*/
public void setAppLabel(@Nullable CharSequence appLabel) {
- this.appLabel = appLabel;
+ this.appLabel = (appLabel != null) ? appLabel.toString() : null;
}
/**
@@ -184,7 +183,6 @@ public class InstallSessionParams implements Parcelable {
pw.printPair("mode", mode);
pw.printHexPair("installFlags", installFlags);
pw.printPair("installLocation", installLocation);
- pw.printPair("signatures", (signatures != null));
pw.printPair("sizeBytes", sizeBytes);
pw.printPair("appPackageName", appPackageName);
pw.printPair("appIcon", (appIcon != null));
@@ -205,11 +203,10 @@ public class InstallSessionParams implements Parcelable {
dest.writeInt(mode);
dest.writeInt(installFlags);
dest.writeInt(installLocation);
- dest.writeParcelableArray(signatures, flags);
dest.writeLong(sizeBytes);
dest.writeString(appPackageName);
dest.writeParcelable(appIcon, flags);
- dest.writeString(appLabel != null ? appLabel.toString() : null);
+ dest.writeString(appLabel);
dest.writeParcelable(originatingUri, flags);
dest.writeParcelable(referrerUri, flags);
dest.writeString(abiOverride);
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index a114bb8..8af827e 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -18,9 +18,10 @@ package android.content.pm;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
import android.app.PackageInstallObserver;
import android.app.PackageUninstallObserver;
-import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Bundle;
import android.os.FileBridge;
import android.os.Handler;
@@ -32,7 +33,9 @@ import android.util.ExceptionUtils;
import java.io.Closeable;
import java.io.IOException;
+import java.io.InputStream;
import java.io.OutputStream;
+import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@@ -63,6 +66,27 @@ import java.util.List;
* </ul>
*/
public class PackageInstaller {
+ /**
+ * Activity Action: Show details about a particular install session. This
+ * may surface actions such as pause, resume, or cancel.
+ * <p>
+ * This should always be scoped to the installer package that owns the
+ * session. Clients should use {@link InstallSessionInfo#getDetailsIntent()}
+ * to build this intent correctly.
+ * <p>
+ * In some cases, a matching Activity may not exist, so ensure you safeguard
+ * against this.
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_SESSION_DETAILS = "android.content.pm.action.SESSION_DETAILS";
+
+ /**
+ * An integer session ID.
+ *
+ * @see #ACTION_SESSION_DETAILS
+ */
+ public static final String EXTRA_SESSION_ID = "android.content.pm.extra.SESSION_ID";
+
private final PackageManager mPm;
private final IPackageInstaller mInstaller;
private final int mUserId;
@@ -180,14 +204,32 @@ public class PackageInstaller {
/**
* Events for observing session lifecycle.
+ * <p>
+ * A typical session lifecycle looks like this:
+ * <ul>
+ * <li>An installer creates a session to indicate pending app delivery. All
+ * install details are available at this point.
+ * <li>The installer opens the session to deliver APK data. Note that a
+ * session may be opened and closed multiple times as network connectivity
+ * changes. The installer may deliver periodic progress updates.
+ * <li>The installer commits or abandons the session, resulting in the
+ * session being finished.
+ * </ul>
*/
public static abstract class SessionCallback {
/**
- * New session has been created.
+ * New session has been created. Details about the session can be
+ * obtained from {@link PackageInstaller#getSessionInfo(int)}.
*/
public abstract void onCreated(int sessionId);
/**
+ * Session has been opened. A session is usually opened when the
+ * installer is actively writing data.
+ */
+ public abstract void onOpened(int sessionId);
+
+ /**
* Progress for given session has been updated.
* <p>
* Note that this progress may not directly correspond to the value
@@ -198,6 +240,11 @@ public class PackageInstaller {
public abstract void onProgressChanged(int sessionId, float progress);
/**
+ * Session has been closed.
+ */
+ public abstract void onClosed(int sessionId);
+
+ /**
* Session has completely finished, either with success or failure.
*/
public abstract void onFinished(int sessionId, boolean success);
@@ -207,8 +254,10 @@ public class PackageInstaller {
private static class SessionCallbackDelegate extends IPackageInstallerCallback.Stub implements
Handler.Callback {
private static final int MSG_SESSION_CREATED = 1;
- private static final int MSG_SESSION_PROGRESS_CHANGED = 2;
- private static final int MSG_SESSION_FINISHED = 3;
+ private static final int MSG_SESSION_OPENED = 2;
+ private static final int MSG_SESSION_PROGRESS_CHANGED = 3;
+ private static final int MSG_SESSION_CLOSED = 4;
+ private static final int MSG_SESSION_FINISHED = 5;
final SessionCallback mCallback;
final Handler mHandler;
@@ -224,9 +273,15 @@ public class PackageInstaller {
case MSG_SESSION_CREATED:
mCallback.onCreated(msg.arg1);
return true;
+ case MSG_SESSION_OPENED:
+ mCallback.onOpened(msg.arg1);
+ return true;
case MSG_SESSION_PROGRESS_CHANGED:
mCallback.onProgressChanged(msg.arg1, (float) msg.obj);
return true;
+ case MSG_SESSION_CLOSED:
+ mCallback.onClosed(msg.arg1);
+ return true;
case MSG_SESSION_FINISHED:
mCallback.onFinished(msg.arg1, msg.arg2 != 0);
return true;
@@ -240,12 +295,22 @@ public class PackageInstaller {
}
@Override
+ public void onSessionOpened(int sessionId) {
+ mHandler.obtainMessage(MSG_SESSION_OPENED, sessionId, 0).sendToTarget();
+ }
+
+ @Override
public void onSessionProgressChanged(int sessionId, float progress) {
mHandler.obtainMessage(MSG_SESSION_PROGRESS_CHANGED, sessionId, 0, progress)
.sendToTarget();
}
@Override
+ public void onSessionClosed(int sessionId) {
+ mHandler.obtainMessage(MSG_SESSION_CLOSED, sessionId, 0).sendToTarget();
+ }
+
+ @Override
public void onSessionFinished(int sessionId, boolean success) {
mHandler.obtainMessage(MSG_SESSION_FINISHED, sessionId, success ? 1 : 0)
.sendToTarget();
@@ -373,7 +438,7 @@ public class PackageInstaller {
ExceptionUtils.maybeUnwrapIOException(e);
throw e;
} catch (RemoteException e) {
- throw new IOException(e);
+ throw e.rethrowAsRuntimeException();
}
}
@@ -391,6 +456,40 @@ public class PackageInstaller {
}
/**
+ * List all APK names contained in this session.
+ * <p>
+ * This returns all names which have been previously written through
+ * {@link #openWrite(String, long, long)} as part of this session.
+ */
+ public @NonNull String[] list() {
+ try {
+ return mSession.list();
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
+ /**
+ * Open a stream to read an APK file from the session.
+ * <p>
+ * This is only valid for names which have been previously written
+ * through {@link #openWrite(String, long, long)} as part of this
+ * session. For example, this stream may be used to calculate a
+ * {@link MessageDigest} of a written APK before committing.
+ */
+ public @NonNull InputStream openRead(@NonNull String name) throws IOException {
+ try {
+ final ParcelFileDescriptor pfd = mSession.openRead(name);
+ return new ParcelFileDescriptor.AutoCloseInputStream(pfd);
+ } catch (RuntimeException e) {
+ ExceptionUtils.maybeUnwrapIOException(e);
+ throw e;
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
+ /**
* Attempt to commit everything staged in this session. This may require
* user intervention, and so it may not happen immediately. The final
* result of the commit will be reported through the given callback.
diff --git a/core/java/android/content/pm/PackageItemInfo.java b/core/java/android/content/pm/PackageItemInfo.java
index 4b5bdda..cacdf8e 100644
--- a/core/java/android/content/pm/PackageItemInfo.java
+++ b/core/java/android/content/pm/PackageItemInfo.java
@@ -187,7 +187,7 @@ public class PackageItemInfo {
*
* @hide
*/
- protected Drawable loadDefaultIcon(PackageManager pm) {
+ public Drawable loadDefaultIcon(PackageManager pm) {
return pm.getDefaultActivityIcon();
}
diff --git a/core/java/android/hardware/camera2/legacy/CaptureCollector.java b/core/java/android/hardware/camera2/legacy/CaptureCollector.java
index af58a8a..307e466 100644
--- a/core/java/android/hardware/camera2/legacy/CaptureCollector.java
+++ b/core/java/android/hardware/camera2/legacy/CaptureCollector.java
@@ -236,6 +236,11 @@ public class CaptureCollector {
Log.d(TAG, "queueRequest for request " + holder.getRequestId() +
" - " + mInFlight + " requests remain in flight.");
}
+
+ if (!(h.needsJpeg || h.needsPreview)) {
+ throw new IllegalStateException("Request must target at least one output surface!");
+ }
+
if (h.needsJpeg) {
// Wait for all current requests to finish before queueing jpeg.
while (mInFlight > 0) {
@@ -259,9 +264,6 @@ public class CaptureCollector {
mInFlightPreviews++;
}
- if (!(h.needsJpeg || h.needsPreview)) {
- throw new IllegalStateException("Request must target at least one output surface!");
- }
mInFlight++;
return true;
diff --git a/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java b/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
index 633bada..986f9a8 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
@@ -27,6 +27,7 @@ import android.hardware.camera2.CameraMetadata;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.impl.CameraMetadataNative;
+import android.hardware.camera2.params.MeteringRectangle;
import android.hardware.camera2.params.StreamConfiguration;
import android.hardware.camera2.params.StreamConfigurationDuration;
import android.hardware.camera2.utils.ArrayUtils;
@@ -78,6 +79,8 @@ public class LegacyMetadataMapper {
private static final long APPROXIMATE_SENSOR_AREA_PX = (1 << 23); // 8 megapixels
private static final long APPROXIMATE_JPEG_ENCODE_TIME_MS = 600; // 600 milliseconds
+ static final int UNKNOWN_MODE = -1;
+
/*
* Development hijinks: Lie about not supporting certain capabilities
*
@@ -458,7 +461,22 @@ public class LegacyMetadataMapper {
m.set(CONTROL_MAX_REGIONS, maxRegions);
- // TODO rest of control fields
+ /*
+ * android.control.availableEffects
+ */
+ List<String> effectModes = p.getSupportedColorEffects();
+ int[] supportedEffectModes = (effectModes == null) ? new int[0] :
+ ArrayUtils.convertStringListToIntArray(effectModes, sLegacyEffectMode,
+ sEffectModes);
+ m.set(CONTROL_AVAILABLE_EFFECTS, supportedEffectModes);
+
+ /*
+ * android.control.availableSceneModes
+ */
+ List<String> sceneModes = p.getSupportedSceneModes();
+ int[] supportedSceneModes = (sceneModes == null) ? new int[0] :
+ ArrayUtils.convertStringListToIntArray(sceneModes, sLegacySceneModes, sSceneModes);
+ m.set(CONTROL_AVAILABLE_SCENE_MODES, supportedSceneModes);
}
private static void mapLens(CameraMetadataNative m, Camera.Parameters p) {
@@ -472,6 +490,9 @@ public class LegacyMetadataMapper {
*/
m.set(LENS_INFO_MINIMUM_FOCUS_DISTANCE, LENS_INFO_MINIMUM_FOCUS_DISTANCE_FIXED_FOCUS);
}
+
+ float[] focalLengths = new float[] { p.getFocalLength() };
+ m.set(LENS_INFO_AVAILABLE_FOCAL_LENGTHS, focalLengths);
}
private static void mapFlash(CameraMetadataNative m, Camera.Parameters p) {
@@ -680,6 +701,106 @@ public class LegacyMetadataMapper {
}
}
+ private final static String[] sLegacySceneModes = {
+ Parameters.SCENE_MODE_AUTO,
+ Parameters.SCENE_MODE_ACTION,
+ Parameters.SCENE_MODE_PORTRAIT,
+ Parameters.SCENE_MODE_LANDSCAPE,
+ Parameters.SCENE_MODE_NIGHT,
+ Parameters.SCENE_MODE_NIGHT_PORTRAIT,
+ Parameters.SCENE_MODE_THEATRE,
+ Parameters.SCENE_MODE_BEACH,
+ Parameters.SCENE_MODE_SNOW,
+ Parameters.SCENE_MODE_SUNSET,
+ Parameters.SCENE_MODE_STEADYPHOTO,
+ Parameters.SCENE_MODE_FIREWORKS,
+ Parameters.SCENE_MODE_SPORTS,
+ Parameters.SCENE_MODE_PARTY,
+ Parameters.SCENE_MODE_CANDLELIGHT,
+ Parameters.SCENE_MODE_BARCODE,
+ };
+
+ private final static int[] sSceneModes = {
+ CameraCharacteristics.CONTROL_SCENE_MODE_DISABLED,
+ CameraCharacteristics.CONTROL_SCENE_MODE_ACTION,
+ CameraCharacteristics.CONTROL_SCENE_MODE_PORTRAIT,
+ CameraCharacteristics.CONTROL_SCENE_MODE_LANDSCAPE,
+ CameraCharacteristics.CONTROL_SCENE_MODE_NIGHT,
+ CameraCharacteristics.CONTROL_SCENE_MODE_NIGHT_PORTRAIT,
+ CameraCharacteristics.CONTROL_SCENE_MODE_THEATRE,
+ CameraCharacteristics.CONTROL_SCENE_MODE_BEACH,
+ CameraCharacteristics.CONTROL_SCENE_MODE_SNOW,
+ CameraCharacteristics.CONTROL_SCENE_MODE_SUNSET,
+ CameraCharacteristics.CONTROL_SCENE_MODE_STEADYPHOTO,
+ CameraCharacteristics.CONTROL_SCENE_MODE_FIREWORKS,
+ CameraCharacteristics.CONTROL_SCENE_MODE_SPORTS,
+ CameraCharacteristics.CONTROL_SCENE_MODE_PARTY,
+ CameraCharacteristics.CONTROL_SCENE_MODE_CANDLELIGHT,
+ CameraCharacteristics.CONTROL_SCENE_MODE_BARCODE,
+ };
+
+ static int convertSceneModeFromLegacy(String mode) {
+ if (mode == null) {
+ return CameraCharacteristics.CONTROL_SCENE_MODE_DISABLED;
+ }
+ int index = ArrayUtils.getArrayIndex(sLegacySceneModes, mode);
+ if (index < 0) {
+ return UNKNOWN_MODE;
+ }
+ return sSceneModes[index];
+ }
+
+ static String convertSceneModeToLegacy(int mode) {
+ int index = ArrayUtils.getArrayIndex(sSceneModes, mode);
+ if (index < 0) {
+ return null;
+ }
+ return sLegacySceneModes[index];
+ }
+
+ private final static String[] sLegacyEffectMode = {
+ Parameters.EFFECT_NONE,
+ Parameters.EFFECT_MONO,
+ Parameters.EFFECT_NEGATIVE,
+ Parameters.EFFECT_SOLARIZE,
+ Parameters.EFFECT_SEPIA,
+ Parameters.EFFECT_POSTERIZE,
+ Parameters.EFFECT_WHITEBOARD,
+ Parameters.EFFECT_BLACKBOARD,
+ Parameters.EFFECT_AQUA,
+ };
+
+ private final static int[] sEffectModes = {
+ CameraCharacteristics.CONTROL_EFFECT_MODE_OFF,
+ CameraCharacteristics.CONTROL_EFFECT_MODE_MONO,
+ CameraCharacteristics.CONTROL_EFFECT_MODE_NEGATIVE,
+ CameraCharacteristics.CONTROL_EFFECT_MODE_SOLARIZE,
+ CameraCharacteristics.CONTROL_EFFECT_MODE_SEPIA,
+ CameraCharacteristics.CONTROL_EFFECT_MODE_POSTERIZE,
+ CameraCharacteristics.CONTROL_EFFECT_MODE_WHITEBOARD,
+ CameraCharacteristics.CONTROL_EFFECT_MODE_BLACKBOARD,
+ CameraCharacteristics.CONTROL_EFFECT_MODE_AQUA,
+ };
+
+ static int convertEffectModeFromLegacy(String mode) {
+ if (mode == null) {
+ return CameraCharacteristics.CONTROL_EFFECT_MODE_OFF;
+ }
+ int index = ArrayUtils.getArrayIndex(sLegacyEffectMode, mode);
+ if (index < 0) {
+ return UNKNOWN_MODE;
+ }
+ return sEffectModes[index];
+ }
+
+ static String convertEffectModeToLegacy(int mode) {
+ int index = ArrayUtils.getArrayIndex(sEffectModes, mode);
+ if (index < 0) {
+ return null;
+ }
+ return sLegacyEffectMode[index];
+ }
+
/**
* Convert the ae antibanding mode from api1 into api2.
*
@@ -760,6 +881,16 @@ public class LegacyMetadataMapper {
LegacyRequestMapper.convertRequestMetadata(request);
}
+ private static final int[] sAllowedTemplates = {
+ CameraDevice.TEMPLATE_PREVIEW,
+ CameraDevice.TEMPLATE_STILL_CAPTURE,
+ CameraDevice.TEMPLATE_RECORD,
+ // Disallowed templates in legacy mode:
+ // CameraDevice.TEMPLATE_VIDEO_SNAPSHOT,
+ // CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG,
+ // CameraDevice.TEMPLATE_MANUAL
+ };
+
/**
* Create a request template
*
@@ -774,7 +905,7 @@ public class LegacyMetadataMapper {
*/
public static CameraMetadataNative createRequestTemplate(
CameraCharacteristics c, int templateId) {
- if (templateId < 0 || templateId > CameraDevice.TEMPLATE_MANUAL) {
+ if (!ArrayUtils.contains(sAllowedTemplates, templateId)) {
throw new IllegalArgumentException("templateId out of range");
}
@@ -786,16 +917,58 @@ public class LegacyMetadataMapper {
* to create our own templates in the framework
*/
+ /*
+ * control.*
+ */
+
if (LIE_ABOUT_AWB) {
m.set(CaptureRequest.CONTROL_AWB_MODE, CameraMetadata.CONTROL_AWB_MODE_AUTO);
} else {
throw new AssertionError("Valid control.awbMode not implemented yet");
}
+ // control.aeAntibandingMode
+ m.set(CaptureRequest.CONTROL_AE_ANTIBANDING_MODE, CONTROL_AE_ANTIBANDING_MODE_AUTO);
+
+ // control.aeExposureCompensation
+ m.set(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION, 0);
+
+ // control.aeLock
+ m.set(CaptureRequest.CONTROL_AE_LOCK, false);
+
+ // control.aePrecaptureTrigger
+ m.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, CONTROL_AE_PRECAPTURE_TRIGGER_IDLE);
+
+ // control.afTrigger
+ m.set(CaptureRequest.CONTROL_AF_TRIGGER, CONTROL_AF_TRIGGER_IDLE);
+
+ // control.awbMode
+ m.set(CaptureRequest.CONTROL_AWB_MODE, CONTROL_AWB_MODE_AUTO);
+
+ // control.awbLock
+ m.set(CaptureRequest.CONTROL_AWB_LOCK, false);
+
+ // control.aeRegions, control.awbRegions, control.afRegions
+ {
+ Rect activeArray = c.get(SENSOR_INFO_ACTIVE_ARRAY_SIZE);
+ MeteringRectangle[] activeRegions = new MeteringRectangle[] {
+ new MeteringRectangle(/*x*/0, /*y*/0, /*width*/activeArray.width() - 1,
+ /*height*/activeArray.height() - 1,/*weight*/1)};
+ m.set(CaptureRequest.CONTROL_AE_REGIONS, activeRegions);
+ m.set(CaptureRequest.CONTROL_AWB_REGIONS, activeRegions);
+ m.set(CaptureRequest.CONTROL_AF_REGIONS, activeRegions);
+ }
+
+ // control.captureIntent
+ m.set(CaptureRequest.CONTROL_CAPTURE_INTENT, templateId);
+
// control.aeMode
m.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON);
// AE is always unconditionally available in API1 devices
+ // control.mode
+ m.set(CaptureRequest.CONTROL_MODE, CONTROL_MODE_AUTO);
+
// control.afMode
{
Float minimumFocusDistance = c.get(LENS_INFO_MINIMUM_FOCUS_DISTANCE);
@@ -808,11 +981,65 @@ public class LegacyMetadataMapper {
} else {
// If a minimum focus distance is reported; the camera must have AF
afMode = CameraMetadata.CONTROL_AF_MODE_AUTO;
+
+ if (templateId == CameraDevice.TEMPLATE_RECORD ||
+ templateId == CameraDevice.TEMPLATE_VIDEO_SNAPSHOT) {
+ if (ArrayUtils.contains(c.get(CONTROL_AF_AVAILABLE_MODES),
+ CONTROL_AF_MODE_CONTINUOUS_VIDEO)) {
+ afMode = CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_VIDEO;
+ }
+ } else if (templateId == CameraDevice.TEMPLATE_PREVIEW ||
+ templateId == CameraDevice.TEMPLATE_STILL_CAPTURE) {
+ if (ArrayUtils.contains(c.get(CONTROL_AF_AVAILABLE_MODES),
+ CONTROL_AF_MODE_CONTINUOUS_PICTURE)) {
+ afMode = CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE;
+ }
+ }
}
m.set(CaptureRequest.CONTROL_AF_MODE, afMode);
}
+ {
+ // control.aeTargetFpsRange
+ Range<Integer>[] availableFpsRange = c.
+ get(CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES);
+
+ // Pick FPS range with highest max value, tiebreak on higher min value
+ Range<Integer> bestRange = availableFpsRange[0];
+ for (Range<Integer> r : availableFpsRange) {
+ if (bestRange.getUpper() < r.getUpper()) {
+ bestRange = r;
+ } else if (bestRange.getUpper() == r.getUpper() &&
+ bestRange.getLower() < r.getLower()) {
+ bestRange = r;
+ }
+ }
+ m.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, bestRange);
+ }
+
+ /*
+ * statistics.*
+ */
+
+ // statistics.faceDetectMode
+ m.set(CaptureRequest.STATISTICS_FACE_DETECT_MODE, STATISTICS_FACE_DETECT_MODE_OFF);
+
+ /*
+ * flash.*
+ */
+
+ // flash.mode
+ m.set(CaptureRequest.FLASH_MODE, FLASH_MODE_OFF);
+
+ /*
+ * lens.*
+ */
+
+ // lens.focalLength
+ m.set(CaptureRequest.LENS_FOCAL_LENGTH,
+ c.get(CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS)[0]);
+
// TODO: map other request template values
return m;
}
diff --git a/core/java/android/hardware/camera2/legacy/LegacyRequestMapper.java b/core/java/android/hardware/camera2/legacy/LegacyRequestMapper.java
index fbfc39f..dfec9008 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyRequestMapper.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyRequestMapper.java
@@ -108,7 +108,12 @@ public class LegacyRequestMapper {
{
// aeRegions
{
+ // Use aeRegions if available, fall back to using awbRegions if present
MeteringRectangle[] aeRegions = request.get(CONTROL_AE_REGIONS);
+ if (request.get(CONTROL_AWB_REGIONS) != null) {
+ Log.w(TAG, "convertRequestMetadata - control.awbRegions setting is not " +
+ "supported, ignoring value");
+ }
int maxNumMeteringAreas = params.getMaxNumMeteringAreas();
List<Camera.Area> meteringAreaList = convertMeteringRegionsToLegacy(
activeArray, zoomData, aeRegions, maxNumMeteringAreas,
@@ -238,6 +243,57 @@ public class LegacyRequestMapper {
+ infinityFocusSupported + ", only 0.0f is supported");
}
}
+
+ // control.sceneMode, control.mode
+ {
+ // TODO: Map FACE_PRIORITY scene mode to face detection.
+
+ if (params.getSupportedSceneModes() != null) {
+ int controlMode = ParamsUtils.getOrDefault(request, CONTROL_MODE,
+ /*defaultValue*/CONTROL_MODE_AUTO);
+ String modeToSet;
+ switch (controlMode) {
+ case CONTROL_MODE_USE_SCENE_MODE: {
+ int sceneMode = ParamsUtils.getOrDefault(request, CONTROL_SCENE_MODE,
+ /*defaultValue*/CONTROL_SCENE_MODE_DISABLED);
+ String legacySceneMode = LegacyMetadataMapper.
+ convertSceneModeToLegacy(sceneMode);
+ if (legacySceneMode != null) {
+ modeToSet = legacySceneMode;
+ } else {
+ modeToSet = Parameters.SCENE_MODE_AUTO;
+ Log.w(TAG, "Skipping unknown requested scene mode: " + sceneMode);
+ }
+ break;
+ }
+ case CONTROL_MODE_AUTO: {
+ modeToSet = Parameters.SCENE_MODE_AUTO;
+ break;
+ }
+ default: {
+ Log.w(TAG, "Control mode " + controlMode +
+ " is unsupported, defaulting to AUTO");
+ modeToSet = Parameters.SCENE_MODE_AUTO;
+ }
+ }
+ params.setSceneMode(modeToSet);
+ }
+ }
+
+ // control.effectMode
+ {
+ if (params.getSupportedColorEffects() != null) {
+ int effectMode = ParamsUtils.getOrDefault(request, CONTROL_EFFECT_MODE,
+ /*defaultValue*/CONTROL_EFFECT_MODE_OFF);
+ String legacyEffectMode = LegacyMetadataMapper.convertEffectModeToLegacy(effectMode);
+ if (legacyEffectMode != null) {
+ params.setColorEffect(legacyEffectMode);
+ } else {
+ params.setColorEffect(Parameters.EFFECT_NONE);
+ Log.w(TAG, "Skipping unknown requested effect mode: " + effectMode);
+ }
+ }
+ }
}
private static List<Camera.Area> convertMeteringRegionsToLegacy(
diff --git a/core/java/android/hardware/camera2/legacy/LegacyResultMapper.java b/core/java/android/hardware/camera2/legacy/LegacyResultMapper.java
index 07852b9..6da5dd0 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyResultMapper.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyResultMapper.java
@@ -28,6 +28,7 @@ import android.hardware.camera2.legacy.ParameterUtils.WeightedRectangle;
import android.hardware.camera2.legacy.ParameterUtils.ZoomData;
import android.hardware.camera2.params.MeteringRectangle;
import android.hardware.camera2.utils.ListUtils;
+import android.hardware.camera2.utils.ParamsUtils;
import android.util.Log;
import android.util.Size;
@@ -153,6 +154,51 @@ public class LegacyResultMapper {
request.get(CaptureRequest.CONTROL_AWB_MODE));
}
+
+ /*
+ * control.mode
+ */
+ {
+ int controlMode = ParamsUtils.getOrDefault(request, CaptureRequest.CONTROL_MODE,
+ CONTROL_MODE_AUTO);
+ if (controlMode == CaptureResult.CONTROL_MODE_USE_SCENE_MODE) {
+ result.set(CONTROL_MODE, CONTROL_MODE_USE_SCENE_MODE);
+ } else {
+ result.set(CONTROL_MODE, CONTROL_MODE_AUTO);
+ }
+ }
+
+ /*
+ * control.sceneMode
+ */
+ {
+ String legacySceneMode = params.getSceneMode();
+ int mode = LegacyMetadataMapper.convertSceneModeFromLegacy(legacySceneMode);
+ if (mode != LegacyMetadataMapper.UNKNOWN_MODE) {
+ result.set(CaptureResult.CONTROL_SCENE_MODE, mode);
+ } else {
+ Log.w(TAG, "Unknown scene mode " + legacySceneMode +
+ " returned by camera HAL, setting to disabled.");
+ result.set(CaptureResult.CONTROL_SCENE_MODE, CONTROL_SCENE_MODE_DISABLED);
+ }
+ }
+
+
+ /*
+ * control.effectMode
+ */
+ {
+ String legacyEffectMode = params.getColorEffect();
+ int mode = LegacyMetadataMapper.convertEffectModeFromLegacy(legacyEffectMode);
+ if (mode != LegacyMetadataMapper.UNKNOWN_MODE) {
+ result.set(CaptureResult.CONTROL_EFFECT_MODE, mode);
+ } else {
+ Log.w(TAG, "Unknown effect mode " + legacyEffectMode +
+ " returned by camera HAL, setting to off.");
+ result.set(CaptureResult.CONTROL_EFFECT_MODE, CONTROL_EFFECT_MODE_OFF);
+ }
+ }
+
/*
* flash
*/
diff --git a/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java b/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java
index 0687264..3f24b2c 100644
--- a/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java
+++ b/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java
@@ -329,6 +329,9 @@ public class SurfaceTextureRenderer {
mSurfaces.clear();
mConversionSurfaces.clear();
mPBufferPixels = null;
+ if (mSurfaceTexture != null) {
+ mSurfaceTexture.release();
+ }
mSurfaceTexture = null;
}
diff --git a/core/java/android/hardware/camera2/utils/ArrayUtils.java b/core/java/android/hardware/camera2/utils/ArrayUtils.java
index 24c85d0..ae97079 100644
--- a/core/java/android/hardware/camera2/utils/ArrayUtils.java
+++ b/core/java/android/hardware/camera2/utils/ArrayUtils.java
@@ -47,6 +47,19 @@ public class ArrayUtils {
return -1;
}
+ /** Return the index of {@code needle} in the {@code array}, or else {@code -1} */
+ public static int getArrayIndex(int[] array, int needle) {
+ if (array == null) {
+ return -1;
+ }
+ for (int i = 0; i < array.length; ++i) {
+ if (array[i] == needle) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
/**
* Create an {@code int[]} from the {@code List<>} by using {@code convertFrom} and
* {@code convertTo} as a one-to-one map (via the index).
@@ -143,6 +156,17 @@ public class ArrayUtils {
return arr;
}
+ /**
+ * Returns true if the given {@code array} contains the given element.
+ *
+ * @param array {@code array} to check for {@code elem}
+ * @param elem {@code elem} to test for
+ * @return {@code true} if the given element is contained
+ */
+ public static boolean contains(int[] array, int elem) {
+ return getArrayIndex(array, elem) != -1;
+ }
+
private ArrayUtils() {
throw new AssertionError();
}
diff --git a/core/java/android/hardware/location/GeofenceHardware.java b/core/java/android/hardware/location/GeofenceHardware.java
index 2d7b7e1..2d82cba 100644
--- a/core/java/android/hardware/location/GeofenceHardware.java
+++ b/core/java/android/hardware/location/GeofenceHardware.java
@@ -16,6 +16,7 @@
package android.hardware.location;
import android.location.Location;
+import android.os.Build;
import android.os.RemoteException;
import java.lang.ref.WeakReference;
@@ -60,19 +61,19 @@ public final class GeofenceHardware {
public static final int MONITORING_TYPE_FUSED_HARDWARE = 1;
/**
- * Constant to indiciate that the monitoring system is currently
+ * Constant to indicate that the monitoring system is currently
* available for monitoring geofences.
*/
public static final int MONITOR_CURRENTLY_AVAILABLE = 0;
/**
- * Constant to indiciate that the monitoring system is currently
+ * Constant to indicate that the monitoring system is currently
* unavailable for monitoring geofences.
*/
public static final int MONITOR_CURRENTLY_UNAVAILABLE = 1;
/**
- * Constant to indiciate that the monitoring system is unsupported
+ * Constant to indicate that the monitoring system is unsupported
* for hardware geofence monitoring.
*/
public static final int MONITOR_UNSUPPORTED = 2;
@@ -129,6 +130,33 @@ public final class GeofenceHardware {
*/
public static final int GEOFENCE_ERROR_INSUFFICIENT_MEMORY = 6;
+ // the following values must match the definitions in fused_location.h
+
+ /**
+ * The constant used to indicate that the monitoring system supports GNSS.
+ */
+ public static final int SOURCE_TECHNOLOGY_GNSS = (1<<0);
+
+ /**
+ * The constant used to indicate that the monitoring system supports WiFi.
+ */
+ public static final int SOURCE_TECHNOLOGY_WIFI = (1<<1);
+
+ /**
+ * The constant used to indicate that the monitoring system supports Sensors.
+ */
+ public static final int SOURCE_TECHNOLOGY_SENSORS = (1<<2);
+
+ /**
+ * The constant used to indicate that the monitoring system supports Cell.
+ */
+ public static final int SOURCE_TECHNOLOGY_CELL = (1<<3);
+
+ /**
+ * The constant used to indicate that the monitoring system supports Bluetooth.
+ */
+ public static final int SOURCE_TECHNOLOGY_BLUETOOTH = (1<<4);
+
private HashMap<GeofenceHardwareCallback, GeofenceHardwareCallbackWrapper>
mCallbacks = new HashMap<GeofenceHardwareCallback, GeofenceHardwareCallbackWrapper>();
private HashMap<GeofenceHardwareMonitorCallback, GeofenceHardwareMonitorCallbackWrapper>
@@ -238,13 +266,9 @@ public final class GeofenceHardware {
geofenceRequest, GeofenceHardwareCallback callback) {
try {
if (geofenceRequest.getType() == GeofenceHardwareRequest.GEOFENCE_TYPE_CIRCLE) {
- return mService.addCircularFence(geofenceId, monitoringType,
- geofenceRequest.getLatitude(),
- geofenceRequest.getLongitude(), geofenceRequest.getRadius(),
- geofenceRequest.getLastTransition(),
- geofenceRequest.getMonitorTransitions(),
- geofenceRequest.getNotificationResponsiveness(),
- geofenceRequest.getUnknownTimer(),
+ return mService.addCircularFence(
+ monitoringType,
+ new GeofenceHardwareRequestParcelable(geofenceId, geofenceRequest),
getCallbackWrapper(callback));
} else {
throw new IllegalArgumentException("Geofence Request type not supported");
@@ -452,10 +476,21 @@ public final class GeofenceHardware {
mCallback = new WeakReference<GeofenceHardwareMonitorCallback>(c);
}
- public void onMonitoringSystemChange(int monitoringType, boolean available,
- Location location) {
+ public void onMonitoringSystemChange(GeofenceHardwareMonitorEvent event) {
GeofenceHardwareMonitorCallback c = mCallback.get();
- if (c != null) c.onMonitoringSystemChange(monitoringType, available, location);
+ if (c == null) return;
+
+ // report the legacy event first, so older clients are not broken
+ c.onMonitoringSystemChange(
+ event.getMonitoringType(),
+ event.getMonitoringStatus() == GeofenceHardware.MONITOR_CURRENTLY_AVAILABLE,
+ event.getLocation());
+
+ // and only call the updated callback on on L and above, this complies with the
+ // documentation of GeofenceHardwareMonitorCallback
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.L) {
+ c.onMonitoringSystemChange(event);
+ }
}
}
diff --git a/core/java/android/hardware/location/GeofenceHardwareImpl.java b/core/java/android/hardware/location/GeofenceHardwareImpl.java
index 6b61690..5c7a8da 100644
--- a/core/java/android/hardware/location/GeofenceHardwareImpl.java
+++ b/core/java/android/hardware/location/GeofenceHardwareImpl.java
@@ -139,8 +139,8 @@ public final class GeofenceHardwareImpl {
private void updateFusedHardwareAvailability() {
boolean fusedSupported;
try {
- fusedSupported = mFusedService.isSupported();
- } catch(RemoteException e) {
+ fusedSupported = (mFusedService != null ? mFusedService.isSupported() : false);
+ } catch (RemoteException e) {
Log.e(TAG, "RemoteException calling LocationManagerService");
fusedSupported = false;
}
@@ -210,18 +210,20 @@ public final class GeofenceHardwareImpl {
}
}
- public boolean addCircularFence(int geofenceId, int monitoringType, double latitude,
- double longitude, double radius, int lastTransition,int monitorTransitions,
- int notificationResponsivenes, int unknownTimer, IGeofenceHardwareCallback callback) {
+ public boolean addCircularFence(
+ int monitoringType,
+ GeofenceHardwareRequestParcelable request,
+ IGeofenceHardwareCallback callback) {
+ int geofenceId = request.getId();
+
// This API is not thread safe. Operations on the same geofence need to be serialized
// by upper layers
if (DEBUG) {
- Log.d(TAG, "addCircularFence: GeofenceId: " + geofenceId + " Latitude: " + latitude +
- " Longitude: " + longitude + " Radius: " + radius + " LastTransition: "
- + lastTransition + " MonitorTransition: " + monitorTransitions +
- " NotificationResponsiveness: " + notificationResponsivenes +
- " UnKnown Timer: " + unknownTimer + " MonitoringType: " + monitoringType);
-
+ String message = String.format(
+ "addCircularFence: monitoringType=%d, %s",
+ monitoringType,
+ request);
+ Log.d(TAG, message);
}
boolean result;
@@ -237,9 +239,15 @@ public final class GeofenceHardwareImpl {
case GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE:
if (mGpsService == null) return false;
try {
- result = mGpsService.addCircularHardwareGeofence(geofenceId, latitude,
- longitude, radius, lastTransition, monitorTransitions,
- notificationResponsivenes, unknownTimer);
+ result = mGpsService.addCircularHardwareGeofence(
+ request.getId(),
+ request.getLatitude(),
+ request.getLongitude(),
+ request.getRadius(),
+ request.getLastTransition(),
+ request.getMonitorTransitions(),
+ request.getNotificationResponsiveness(),
+ request.getUnknownTimer());
} catch (RemoteException e) {
Log.e(TAG, "AddGeofence: Remote Exception calling LocationManagerService");
result = false;
@@ -249,20 +257,9 @@ public final class GeofenceHardwareImpl {
if(mFusedService == null) {
return false;
}
- GeofenceHardwareRequest request = GeofenceHardwareRequest.createCircularGeofence(
- latitude,
- longitude,
- radius);
- request.setUnknownTimer(unknownTimer);
- request.setNotificationResponsiveness(notificationResponsivenes);
- request.setMonitorTransitions(monitorTransitions);
- request.setLastTransition(lastTransition);
-
- GeofenceHardwareRequestParcelable parcelableRequest =
- new GeofenceHardwareRequestParcelable(geofenceId, request);
try {
mFusedService.addGeofences(
- new GeofenceHardwareRequestParcelable[] { parcelableRequest });
+ new GeofenceHardwareRequestParcelable[] { request });
result = true;
} catch(RemoteException e) {
Log.e(TAG, "AddGeofence: RemoteException calling LocationManagerService");
@@ -471,12 +468,14 @@ public final class GeofenceHardwareImpl {
int monitoringStatus,
Location location,
int source) {
- // TODO: use the source if needed in the future
setMonitorAvailability(monitoringType, monitoringStatus);
acquireWakeLock();
- Message message = mCallbacksHandler.obtainMessage(GEOFENCE_STATUS, location);
- message.arg1 = monitoringStatus;
- message.arg2 = monitoringType;
+ GeofenceHardwareMonitorEvent event = new GeofenceHardwareMonitorEvent(
+ monitoringType,
+ monitoringStatus,
+ source,
+ location);
+ Message message = mCallbacksHandler.obtainMessage(GEOFENCE_STATUS, event);
message.sendToTarget();
}
@@ -644,20 +643,17 @@ public final class GeofenceHardwareImpl {
switch (msg.what) {
case GEOFENCE_STATUS:
- Location location = (Location) msg.obj;
- int val = msg.arg1;
- monitoringType = msg.arg2;
- boolean available;
- available = (val == GeofenceHardware.MONITOR_CURRENTLY_AVAILABLE ?
- true : false);
- callbackList = mCallbacks[monitoringType];
+ GeofenceHardwareMonitorEvent event = (GeofenceHardwareMonitorEvent) msg.obj;
+ callbackList = mCallbacks[event.getMonitoringType()];
if (callbackList != null) {
- if (DEBUG) Log.d(TAG, "MonitoringSystemChangeCallback: GPS : " + available);
+ if (DEBUG) Log.d(TAG, "MonitoringSystemChangeCallback: " + event);
- for (IGeofenceHardwareMonitorCallback c: callbackList) {
+ for (IGeofenceHardwareMonitorCallback c : callbackList) {
try {
- c.onMonitoringSystemChange(monitoringType, available, location);
- } catch (RemoteException e) {}
+ c.onMonitoringSystemChange(event);
+ } catch (RemoteException e) {
+ Log.d(TAG, "Error reporting onMonitoringSystemChange.", e);
+ }
}
}
releaseWakeLock();
diff --git a/core/java/android/hardware/location/GeofenceHardwareMonitorCallback.java b/core/java/android/hardware/location/GeofenceHardwareMonitorCallback.java
index b8e927e..f927027 100644
--- a/core/java/android/hardware/location/GeofenceHardwareMonitorCallback.java
+++ b/core/java/android/hardware/location/GeofenceHardwareMonitorCallback.java
@@ -19,19 +19,39 @@ package android.hardware.location;
import android.location.Location;
/**
- * The callback class associated with the status change of hardware montiors
+ * The callback class associated with the status change of hardware monitors
* in {@link GeofenceHardware}
*/
public abstract class GeofenceHardwareMonitorCallback {
/**
* The callback called when the state of a monitoring system changes.
* {@link GeofenceHardware#MONITORING_TYPE_GPS_HARDWARE} is an example of a
- * monitoring system
+ * monitoring system.
+ *
+ * @deprecated use {@link #onMonitoringSystemChange(GeofenceHardwareMonitorEvent)} instead.
+ * NOTE: this API is will remain to be called on Android API 21 and above for backwards
+ * compatibility. But clients must stop implementing it when updating their code.
*
* @param monitoringType The type of the monitoring system.
- * @param available Indicates whether the system is currenty available or not.
+ * @param available Indicates whether the system is currently available or not.
* @param location The last known location according to the monitoring system.
*/
+ @Deprecated
public void onMonitoringSystemChange(int monitoringType, boolean available, Location location) {
}
+
+ /**
+ * The callback called when the sate of a monitoring system changes.
+ * {@link GeofenceHardware#MONITORING_TYPE_GPS_HARDWARE} is an example of a monitoring system.
+ * {@link GeofenceHardware#MONITOR_CURRENTLY_AVAILABLE} is an example of a monitoring status.
+ * {@link GeofenceHardware#SOURCE_TECHNOLOGY_GNSS} is an example of a source.
+ *
+ * This callback must be used instead of
+ * {@link #onMonitoringSystemChange(int, boolean, android.location.Location)}.
+ *
+ * NOTE: this API is only called on Android API 21 and above.
+ *
+ * @param event An object representing the monitoring system change event.
+ */
+ public void onMonitoringSystemChange(GeofenceHardwareMonitorEvent event) {}
}
diff --git a/core/java/android/hardware/location/GeofenceHardwareMonitorEvent.aidl b/core/java/android/hardware/location/GeofenceHardwareMonitorEvent.aidl
new file mode 100644
index 0000000..008953e
--- /dev/null
+++ b/core/java/android/hardware/location/GeofenceHardwareMonitorEvent.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.hardware.location;
+
+parcelable GeofenceHardwareMonitorEvent; \ No newline at end of file
diff --git a/core/java/android/hardware/location/GeofenceHardwareMonitorEvent.java b/core/java/android/hardware/location/GeofenceHardwareMonitorEvent.java
new file mode 100644
index 0000000..9c460d2
--- /dev/null
+++ b/core/java/android/hardware/location/GeofenceHardwareMonitorEvent.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.location;
+
+import android.location.Location;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * A class that represents an event for each change in the state of a monitoring system.
+ */
+public class GeofenceHardwareMonitorEvent implements Parcelable {
+ private final int mMonitoringType;
+ private final int mMonitoringStatus;
+ private final int mSourceTechnologies;
+ private final Location mLocation;
+
+ public GeofenceHardwareMonitorEvent(
+ int monitoringType,
+ int monitoringStatus,
+ int sourceTechnologies,
+ Location location) {
+ mMonitoringType = monitoringType;
+ mMonitoringStatus = monitoringStatus;
+ mSourceTechnologies = sourceTechnologies;
+ mLocation = location;
+ }
+
+ /**
+ * Returns the type of the monitoring system that has a change on its state.
+ */
+ public int getMonitoringType() {
+ return mMonitoringType;
+ }
+
+ /**
+ * Returns the new status associated with the monitoring system.
+ */
+ public int getMonitoringStatus() {
+ return mMonitoringStatus;
+ }
+
+ /**
+ * Returns the source technologies that the status is associated to.
+ */
+ public int getSourceTechnologies() {
+ return mSourceTechnologies;
+ }
+
+ /**
+ * Returns the last known location according to the monitoring system.
+ */
+ public Location getLocation() {
+ return mLocation;
+ }
+
+ public static final Creator<GeofenceHardwareMonitorEvent> CREATOR =
+ new Creator<GeofenceHardwareMonitorEvent>() {
+ @Override
+ public GeofenceHardwareMonitorEvent createFromParcel(Parcel source) {
+ ClassLoader classLoader = GeofenceHardwareMonitorEvent.class.getClassLoader();
+ int monitoringType = source.readInt();
+ int monitoringStatus = source.readInt();
+ int sourceTechnologies = source.readInt();
+ Location location = source.readParcelable(classLoader);
+
+ return new GeofenceHardwareMonitorEvent(
+ monitoringType,
+ monitoringStatus,
+ sourceTechnologies,
+ location);
+ }
+
+ @Override
+ public GeofenceHardwareMonitorEvent[] newArray(int size) {
+ return new GeofenceHardwareMonitorEvent[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel parcel, int flags) {
+ parcel.writeInt(mMonitoringType);
+ parcel.writeInt(mMonitoringStatus);
+ parcel.writeInt(mSourceTechnologies);
+ parcel.writeParcelable(mLocation, flags);
+ }
+
+ @Override
+ public String toString() {
+ return String.format(
+ "GeofenceHardwareMonitorEvent: type=%d, status=%d, sources=%d, location=%s",
+ mMonitoringType,
+ mMonitoringStatus,
+ mSourceTechnologies,
+ mLocation);
+ }
+}
diff --git a/core/java/android/hardware/location/GeofenceHardwareRequest.java b/core/java/android/hardware/location/GeofenceHardwareRequest.java
index 796d7f8..887c4ad 100644
--- a/core/java/android/hardware/location/GeofenceHardwareRequest.java
+++ b/core/java/android/hardware/location/GeofenceHardwareRequest.java
@@ -33,6 +33,7 @@ public final class GeofenceHardwareRequest {
private int mMonitorTransitions = GeofenceHardware.GEOFENCE_UNCERTAIN |
GeofenceHardware.GEOFENCE_ENTERED | GeofenceHardware.GEOFENCE_EXITED;
private int mNotificationResponsiveness = 5000; // 5 secs
+ private int mSourceTechnologies = GeofenceHardware.SOURCE_TECHNOLOGY_GNSS;
private void setCircularGeofence(double latitude, double longitude, double radius) {
mLatitude = latitude;
@@ -102,6 +103,28 @@ public final class GeofenceHardwareRequest {
}
/**
+ * Set the source technologies to use while tracking the geofence.
+ * The value is the bit-wise of one or several source fields defined in
+ * {@link GeofenceHardware}.
+ *
+ * @param sourceTechnologies The set of source technologies to use.
+ */
+ public void setSourceTechnologies(int sourceTechnologies) {
+ int sourceTechnologiesAll = GeofenceHardware.SOURCE_TECHNOLOGY_GNSS
+ | GeofenceHardware.SOURCE_TECHNOLOGY_WIFI
+ | GeofenceHardware.SOURCE_TECHNOLOGY_SENSORS
+ | GeofenceHardware.SOURCE_TECHNOLOGY_CELL
+ | GeofenceHardware.SOURCE_TECHNOLOGY_BLUETOOTH;
+
+ int sanitizedSourceTechnologies = (sourceTechnologies & sourceTechnologiesAll);
+ if (sanitizedSourceTechnologies == 0) {
+ throw new IllegalArgumentException("At least one valid source technology must be set.");
+ }
+
+ mSourceTechnologies = sanitizedSourceTechnologies;
+ }
+
+ /**
* Returns the latitude of this geofence.
*/
public double getLatitude() {
@@ -150,6 +173,13 @@ public final class GeofenceHardwareRequest {
return mLastTransition;
}
+ /**
+ * Returns the source technologies to track this geofence.
+ */
+ public int getSourceTechnologies() {
+ return mSourceTechnologies;
+ }
+
int getType() {
return mType;
}
diff --git a/core/java/android/hardware/location/GeofenceHardwareRequestParcelable.java b/core/java/android/hardware/location/GeofenceHardwareRequestParcelable.java
index 40e7fc4..d3311f5 100644
--- a/core/java/android/hardware/location/GeofenceHardwareRequestParcelable.java
+++ b/core/java/android/hardware/location/GeofenceHardwareRequestParcelable.java
@@ -98,9 +98,43 @@ public final class GeofenceHardwareRequestParcelable implements Parcelable {
}
/**
+ * Returns the source technologies to track this geofence.
+ */
+ int getSourceTechnologies() {
+ return mRequest.getSourceTechnologies();
+ }
+
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("id=");
+ builder.append(mId);
+ builder.append(", type=");
+ builder.append(mRequest.getType());
+ builder.append(", latitude=");
+ builder.append(mRequest.getLatitude());
+ builder.append(", longitude=");
+ builder.append(mRequest.getLongitude());
+ builder.append(", radius=");
+ builder.append(mRequest.getRadius());
+ builder.append(", lastTransition=");
+ builder.append(mRequest.getLastTransition());
+ builder.append(", unknownTimer=");
+ builder.append(mRequest.getUnknownTimer());
+ builder.append(", monitorTransitions=");
+ builder.append(mRequest.getMonitorTransitions());
+ builder.append(", notificationResponsiveness=");
+ builder.append(mRequest.getNotificationResponsiveness());
+ builder.append(", sourceTechnologies=");
+ builder.append(mRequest.getSourceTechnologies());
+ return builder.toString();
+ }
+
+ /**
* Method definitions to support Parcelable operations.
*/
- public static final Parcelable.Creator<GeofenceHardwareRequestParcelable> CREATOR =
+ public static final Parcelable.Creator<GeofenceHardwareRequestParcelable> CREATOR =
new Parcelable.Creator<GeofenceHardwareRequestParcelable>() {
@Override
public GeofenceHardwareRequestParcelable createFromParcel(Parcel parcel) {
@@ -120,7 +154,8 @@ public final class GeofenceHardwareRequestParcelable implements Parcelable {
request.setMonitorTransitions(parcel.readInt());
request.setUnknownTimer(parcel.readInt());
request.setNotificationResponsiveness(parcel.readInt());
-
+ request.setSourceTechnologies(parcel.readInt());
+
int id = parcel.readInt();
return new GeofenceHardwareRequestParcelable(id, request);
}
@@ -146,6 +181,7 @@ public final class GeofenceHardwareRequestParcelable implements Parcelable {
parcel.writeInt(getMonitorTransitions());
parcel.writeInt(getUnknownTimer());
parcel.writeInt(getNotificationResponsiveness());
+ parcel.writeInt(getSourceTechnologies());
parcel.writeInt(getId());
}
}
diff --git a/core/java/android/hardware/location/GeofenceHardwareService.java b/core/java/android/hardware/location/GeofenceHardwareService.java
index fb238bd..4816c5f 100644
--- a/core/java/android/hardware/location/GeofenceHardwareService.java
+++ b/core/java/android/hardware/location/GeofenceHardwareService.java
@@ -86,15 +86,14 @@ public class GeofenceHardwareService extends Service {
return mGeofenceHardwareImpl.getStatusOfMonitoringType(monitoringType);
}
- public boolean addCircularFence(int id, int monitoringType, double lat, double longitude,
- double radius, int lastTransition, int monitorTransitions, int
- notificationResponsiveness, int unknownTimer, IGeofenceHardwareCallback callback) {
+ public boolean addCircularFence(
+ int monitoringType,
+ GeofenceHardwareRequestParcelable request,
+ IGeofenceHardwareCallback callback) {
mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE,
"Location Hardware permission not granted to access hardware geofence");
checkPermission(Binder.getCallingPid(), Binder.getCallingUid(), monitoringType);
- return mGeofenceHardwareImpl.addCircularFence(id, monitoringType, lat, longitude,
- radius, lastTransition, monitorTransitions, notificationResponsiveness,
- unknownTimer, callback);
+ return mGeofenceHardwareImpl.addCircularFence(monitoringType, request, callback);
}
public boolean removeGeofence(int id, int monitoringType) {
diff --git a/core/java/android/hardware/location/IGeofenceHardware.aidl b/core/java/android/hardware/location/IGeofenceHardware.aidl
index 8900166..0e840c4 100644
--- a/core/java/android/hardware/location/IGeofenceHardware.aidl
+++ b/core/java/android/hardware/location/IGeofenceHardware.aidl
@@ -18,6 +18,7 @@ package android.hardware.location;
import android.location.IFusedGeofenceHardware;
import android.location.IGpsGeofenceHardware;
+import android.hardware.location.GeofenceHardwareRequestParcelable;
import android.hardware.location.IGeofenceHardwareCallback;
import android.hardware.location.IGeofenceHardwareMonitorCallback;
@@ -27,9 +28,10 @@ interface IGeofenceHardware {
void setFusedGeofenceHardware(in IFusedGeofenceHardware service);
int[] getMonitoringTypes();
int getStatusOfMonitoringType(int monitoringType);
- boolean addCircularFence(int id, int monitoringType, double lat, double longitude,
- double radius, int lastTransition, int monitorTransitions,
- int notificationResponsiveness, int unknownTimer,in IGeofenceHardwareCallback callback);
+ boolean addCircularFence(
+ int monitoringType,
+ in GeofenceHardwareRequestParcelable request,
+ in IGeofenceHardwareCallback callback);
boolean removeGeofence(int id, int monitoringType);
boolean pauseGeofence(int id, int monitoringType);
boolean resumeGeofence(int id, int monitoringType, int monitorTransitions);
diff --git a/core/java/android/hardware/location/IGeofenceHardwareMonitorCallback.aidl b/core/java/android/hardware/location/IGeofenceHardwareMonitorCallback.aidl
index 0b6e04b..811ecd0 100644
--- a/core/java/android/hardware/location/IGeofenceHardwareMonitorCallback.aidl
+++ b/core/java/android/hardware/location/IGeofenceHardwareMonitorCallback.aidl
@@ -16,9 +16,10 @@
package android.hardware.location;
+import android.hardware.location.GeofenceHardwareMonitorEvent;
import android.location.Location;
/** @hide */
oneway interface IGeofenceHardwareMonitorCallback {
- void onMonitoringSystemChange(int monitoringType, boolean available, in Location location);
+ void onMonitoringSystemChange(in GeofenceHardwareMonitorEvent event);
}
diff --git a/core/java/android/net/Network.java b/core/java/android/net/Network.java
index 5e3decd..0de3f26 100644
--- a/core/java/android/net/Network.java
+++ b/core/java/android/net/Network.java
@@ -16,6 +16,7 @@
package android.net;
+import android.net.NetworkBoundURLFactory;
import android.net.NetworkUtils;
import android.os.Parcelable;
import android.os.Parcel;
@@ -29,6 +30,8 @@ import java.net.SocketAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.net.URL;
+import java.net.URLStreamHandler;
+import java.util.concurrent.atomic.AtomicReference;
import javax.net.SocketFactory;
import com.android.okhttp.HostResolver;
@@ -52,8 +55,8 @@ public class Network implements Parcelable {
// Objects used to perform per-network operations such as getSocketFactory
// and getBoundURL, and a lock to protect access to them.
- private NetworkBoundSocketFactory mNetworkBoundSocketFactory = null;
- private OkHttpClient mOkHttpClient = null;
+ private volatile NetworkBoundSocketFactory mNetworkBoundSocketFactory = null;
+ private volatile OkHttpClient mOkHttpClient = null;
private Object mLock = new Object();
/**
@@ -174,36 +177,83 @@ public class Network implements Parcelable {
* {@code Network}.
*/
public SocketFactory getSocketFactory() {
- synchronized (mLock) {
- if (mNetworkBoundSocketFactory == null) {
- mNetworkBoundSocketFactory = new NetworkBoundSocketFactory(netId);
+ if (mNetworkBoundSocketFactory == null) {
+ synchronized (mLock) {
+ if (mNetworkBoundSocketFactory == null) {
+ mNetworkBoundSocketFactory = new NetworkBoundSocketFactory(netId);
+ }
}
}
return mNetworkBoundSocketFactory;
}
+ /** The default NetworkBoundURLFactory, used if setNetworkBoundURLFactory is never called. */
+ private static final NetworkBoundURLFactory DEFAULT_URL_FACTORY = new NetworkBoundURLFactory() {
+ public URL getBoundURL(final Network network, URL url) throws MalformedURLException {
+ if (network.mOkHttpClient == null) {
+ synchronized (network.mLock) {
+ if (network.mOkHttpClient == null) {
+ HostResolver hostResolver = new HostResolver() {
+ @Override
+ public InetAddress[] getAllByName(String host)
+ throws UnknownHostException {
+ return network.getAllByName(host);
+ }
+ };
+ network.mOkHttpClient = new OkHttpClient()
+ .setSocketFactory(network.getSocketFactory())
+ .setHostResolver(hostResolver);
+ }
+ }
+ }
+
+ String protocol = url.getProtocol();
+ URLStreamHandler handler = network.mOkHttpClient.createURLStreamHandler(protocol);
+ if (handler == null) {
+ // OkHttpClient only supports HTTP and HTTPS and returns a null URLStreamHandler if
+ // passed another protocol.
+ throw new MalformedURLException("Invalid URL or unrecognized protocol " + protocol);
+ }
+ return new URL(url, "", handler);
+ }
+ };
+
+ private static AtomicReference<NetworkBoundURLFactory> sNetworkBoundURLFactory =
+ new AtomicReference <NetworkBoundURLFactory>(DEFAULT_URL_FACTORY);
+
/**
- * Returns a {@link URL} based on the given URL but bound to this {@code Network}.
- * Note that if this {@code Network} ever disconnects, this factory and any URL object it
- * produced in the past or future will cease to work.
+ * Returns a {@link URL} based on the given URL but bound to this {@code Network},
+ * such that opening the URL will send all network traffic on this Network.
+ *
+ * Note that if this {@code Network} ever disconnects, any URL object generated by this method
+ * in the past or future will cease to work.
+ *
+ * The returned URL may have a {@link URLStreamHandler} explicitly set, which may not be the
+ * handler generated by the factory set with {@link java.net.URL#setURLStreamHandlerFactory}. To
+ * affect the {@code URLStreamHandler}s of URLs returned by this method, call
+ * {@link #setNetworkBoundURLFactory}.
+ *
+ * Because the returned URLs may have an explicit {@code URLStreamHandler} set, using them as a
+ * context when constructing other URLs and explicitly specifying a {@code URLStreamHandler} may
+ * result in URLs that are no longer bound to the same {@code Network}.
+ *
+ * The default implementation only supports {@code HTTP} and {@code HTTPS} URLs.
*
* @return a {@link URL} bound to this {@code Network}.
*/
public URL getBoundURL(URL url) throws MalformedURLException {
- synchronized (mLock) {
- if (mOkHttpClient == null) {
- HostResolver hostResolver = new HostResolver() {
- @Override
- public InetAddress[] getAllByName(String host) throws UnknownHostException {
- return Network.this.getAllByName(host);
- }
- };
- mOkHttpClient = new OkHttpClient()
- .setSocketFactory(getSocketFactory())
- .setHostResolver(hostResolver);
- }
+ return sNetworkBoundURLFactory.get().getBoundURL(this, url);
+ }
+
+ /**
+ * Sets the {@link NetworkBoundURLFactory} to be used by future {@link #getBoundURL} calls.
+ * If {@code null}, clears any factory that was previously specified.
+ */
+ public static void setNetworkBoundURLFactory(NetworkBoundURLFactory factory) {
+ if (factory == null) {
+ factory = DEFAULT_URL_FACTORY;
}
- return new URL(url, "", mOkHttpClient.createURLStreamHandler(url.getProtocol()));
+ sNetworkBoundURLFactory.set(factory);
}
// implement the Parcelable interface
diff --git a/core/java/android/net/NetworkBoundURLFactory.java b/core/java/android/net/NetworkBoundURLFactory.java
new file mode 100644
index 0000000..356100e
--- /dev/null
+++ b/core/java/android/net/NetworkBoundURLFactory.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+/**
+ * An interface that describes a factory for network-specific {@link URL} objects.
+ */
+public interface NetworkBoundURLFactory {
+ /**
+ * Returns a {@link URL} based on the given URL but bound to the specified {@code Network},
+ * such that opening the URL will send all network traffic on the specified Network.
+ *
+ * @return a {@link URL} bound to this {@code Network}.
+ * @throws MalformedURLException if the URL was not valid, or this factory cannot handle the
+ * specified URL (e.g., if it does not support the protocol of the URL).
+ */
+ public URL getBoundURL(Network network, URL url) throws MalformedURLException;
+}
diff --git a/core/java/android/nfc/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl
index 541b700..ee4d45e 100644
--- a/core/java/android/nfc/INfcAdapter.aidl
+++ b/core/java/android/nfc/INfcAdapter.aidl
@@ -27,6 +27,7 @@ import android.nfc.INfcAdapterExtras;
import android.nfc.INfcTag;
import android.nfc.INfcCardEmulation;
import android.nfc.INfcLockscreenDispatch;
+import android.nfc.INfcUnlockHandler;
import android.os.Bundle;
/**
@@ -57,4 +58,6 @@ interface INfcAdapter
void setP2pModes(int initatorModes, int targetModes);
void registerLockscreenDispatch(INfcLockscreenDispatch lockscreenDispatch, in int[] techList);
+ void addNfcUnlockHandler(INfcUnlockHandler unlockHandler, in int[] techList);
+ void removeNfcUnlockHandler(IBinder b);
}
diff --git a/core/java/android/nfc/INfcUnlockHandler.aidl b/core/java/android/nfc/INfcUnlockHandler.aidl
new file mode 100644
index 0000000..e1cace9
--- /dev/null
+++ b/core/java/android/nfc/INfcUnlockHandler.aidl
@@ -0,0 +1,12 @@
+package android.nfc;
+
+import android.nfc.Tag;
+
+/**
+ * @hide
+ */
+interface INfcUnlockHandler {
+
+ boolean onUnlockAttempted(in Tag tag);
+
+}
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index b0397d5..dde2cf1 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -20,6 +20,7 @@ import java.util.HashMap;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SystemApi;
import android.app.Activity;
import android.app.ActivityThread;
import android.app.OnActivityPausedListener;
@@ -29,7 +30,6 @@ import android.content.IntentFilter;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.net.Uri;
-import android.nfc.BeamShareData;
import android.nfc.tech.MifareClassic;
import android.nfc.tech.Ndef;
import android.nfc.tech.NfcA;
@@ -261,6 +261,7 @@ public final class NfcAdapter {
public static final String EXTRA_READER_PRESENCE_CHECK_DELAY = "presence";
/** @hide */
+ @SystemApi
public static final int FLAG_NDEF_PUSH_NO_CONFIRM = 0x1;
/** @hide */
@@ -310,6 +311,8 @@ public final class NfcAdapter {
final NfcActivityManager mNfcActivityManager;
final Context mContext;
+ final HashMap<NfcUnlockHandler, IBinder> mNfcUnlockHandlers;
+ final Object mLock;
/**
* A callback to be invoked when the system finds a tag while the foreground activity is
@@ -392,6 +395,22 @@ public final class NfcAdapter {
/**
+ * A callback to be invoked when an application has registered as a
+ * handler to unlock the device given an NFC tag at the lockscreen.
+ * @hide
+ */
+ @SystemApi
+ public interface NfcUnlockHandler {
+ /**
+ * Called at the lock screen to attempt to unlock the device with the given tag.
+ * @param tag the detected tag, to be used to unlock the device
+ * @return true if the device was successfully unlocked
+ */
+ public boolean onUnlockAttempted(Tag tag);
+ }
+
+
+ /**
* Helper to check if this device has FEATURE_NFC, but without using
* a context.
* Equivalent to
@@ -523,6 +542,8 @@ public final class NfcAdapter {
NfcAdapter(Context context) {
mContext = context;
mNfcActivityManager = new NfcActivityManager(this);
+ mNfcUnlockHandlers = new HashMap<NfcUnlockHandler, IBinder>();
+ mLock = new Object();
}
/**
@@ -652,6 +673,7 @@ public final class NfcAdapter {
*
* @hide
*/
+ @SystemApi
public boolean enable() {
try {
return sService.enable();
@@ -679,7 +701,7 @@ public final class NfcAdapter {
*
* @hide
*/
-
+ @SystemApi
public boolean disable() {
try {
return sService.disable(true);
@@ -932,6 +954,7 @@ public final class NfcAdapter {
/**
* @hide
*/
+ @SystemApi
public void setNdefPushMessage(NdefMessage message, Activity activity, int flags) {
if (activity == null) {
throw new NullPointerException("activity cannot be null");
@@ -1359,6 +1382,7 @@ public final class NfcAdapter {
* <p>This API is for the Settings application.
* @hide
*/
+ @SystemApi
public boolean enableNdefPush() {
try {
return sService.enableNdefPush();
@@ -1373,6 +1397,7 @@ public final class NfcAdapter {
* <p>This API is for the Settings application.
* @hide
*/
+ @SystemApi
public boolean disableNdefPush() {
try {
return sService.disableNdefPush();
@@ -1451,7 +1476,50 @@ public final class NfcAdapter {
public boolean onTagDetected(Tag tag) throws RemoteException {
return lockscreenDispatch.onTagDetected(tag);
}
- }, Tag.techListFromStrings(techList));
+ }, Tag.getTechCodesFromStrings(techList));
+ } catch (RemoteException e) {
+ attemptDeadServiceRecovery(e);
+ return false;
+ } catch (IllegalArgumentException e) {
+ Log.e(TAG, "Unable to register LockscreenDispatch", e);
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Registers a new NFC unlock handler with the NFC service.
+ *
+ * <p />NFC unlock handlers are intended to unlock the keyguard in the presence of a trusted
+ * NFC device. The handler should return true if it successfully authenticates the user and
+ * unlocks the keyguard.
+ *
+ * <p /> The parameter {@code tagTechnologies} determines which Tag technologies will be polled for
+ * at the lockscreen. Polling for less tag technologies reduces latency, and so it is
+ * strongly recommended to only provide the Tag technologies that the handler is expected to
+ * receive.
+ *
+ * @hide
+ */
+ @SystemApi
+ public boolean addNfcUnlockHandler(final NfcUnlockHandler unlockHandler,
+ String[] tagTechnologies) {
+ try {
+ INfcUnlockHandler.Stub iHandler = new INfcUnlockHandler.Stub() {
+ @Override
+ public boolean onUnlockAttempted(Tag tag) throws RemoteException {
+ return unlockHandler.onUnlockAttempted(tag);
+ }
+ };
+
+ synchronized (mLock) {
+ if (mNfcUnlockHandlers.containsKey(unlockHandler)) {
+ return true;
+ }
+ sService.addNfcUnlockHandler(iHandler, Tag.getTechCodesFromStrings(tagTechnologies));
+ mNfcUnlockHandlers.put(unlockHandler, iHandler.asBinder());
+ }
} catch (RemoteException e) {
attemptDeadServiceRecovery(e);
return false;
@@ -1464,6 +1532,29 @@ public final class NfcAdapter {
}
/**
+ * Removes a previously registered unlock handler. Also removes the tag technologies
+ * associated with the removed unlock handler.
+ *
+ * @hide
+ */
+ @SystemApi
+ public boolean removeNfcUnlockHandler(NfcUnlockHandler unlockHandler) {
+ try {
+ synchronized (mLock) {
+ if (mNfcUnlockHandlers.containsKey(unlockHandler)) {
+ sService.removeNfcUnlockHandler(mNfcUnlockHandlers.get(unlockHandler));
+ mNfcUnlockHandlers.remove(unlockHandler);
+ }
+
+ return true;
+ }
+ } catch (RemoteException e) {
+ attemptDeadServiceRecovery(e);
+ return false;
+ }
+ }
+
+ /**
* @hide
*/
public INfcAdapterExtras getNfcAdapterExtrasInterface() {
diff --git a/core/java/android/nfc/Tag.java b/core/java/android/nfc/Tag.java
index 43be702..154d5a1 100644
--- a/core/java/android/nfc/Tag.java
+++ b/core/java/android/nfc/Tag.java
@@ -196,7 +196,7 @@ public final class Tag implements Parcelable {
return strings;
}
- static int[] techListFromStrings(String[] techStringList) throws IllegalArgumentException {
+ static int[] getTechCodesFromStrings(String[] techStringList) throws IllegalArgumentException {
if (techStringList == null) {
throw new IllegalArgumentException("List cannot be null");
}
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index afac239..c3ac012 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -61,6 +61,12 @@ public class Process {
public static final String SECONDARY_ZYGOTE_SOCKET = "zygote_secondary";
/**
+ * Defines the root UID.
+ * @hide
+ */
+ public static final int ROOT_UID = 0;
+
+ /**
* Defines the UID/GID under which system code runs.
*/
public static final int SYSTEM_UID = 1000;
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index d385131..13f93a7 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -625,8 +625,9 @@ public class UserManager {
Settings.Secure.putStringForUser(context.getContentResolver(),
Settings.Secure.SKIP_FIRST_USE_HINTS, "1", guest.id);
try {
- mService.setUserRestrictions(
- mService.getDefaultGuestRestrictions(), guest.id);
+ Bundle guestRestrictions = mService.getDefaultGuestRestrictions();
+ guestRestrictions.putBoolean(DISALLOW_SMS, true);
+ mService.setUserRestrictions(guestRestrictions, guest.id);
} catch (RemoteException re) {
Log.w(TAG, "Could not update guest restrictions");
}
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index 1d1aafb..3502b52 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -1750,7 +1750,7 @@ public class TextUtils {
*/
public static int getLayoutDirectionFromLocale(Locale locale) {
if (locale != null && !locale.equals(Locale.ROOT)) {
- final String scriptSubtag = ICU.getScript(ICU.addLikelySubtags(locale.toString()));
+ final String scriptSubtag = ICU.addLikelySubtags(locale).getScript();
if (scriptSubtag == null) return getLayoutDirectionFromFirstChar(locale);
if (scriptSubtag.equalsIgnoreCase(ARAB_SCRIPT_SUBTAG) ||
diff --git a/core/java/android/transition/Visibility.java b/core/java/android/transition/Visibility.java
index af2016c..79dbb49 100644
--- a/core/java/android/transition/Visibility.java
+++ b/core/java/android/transition/Visibility.java
@@ -43,7 +43,7 @@ import android.view.ViewGroup;
*/
public abstract class Visibility extends Transition {
- private static final String PROPNAME_VISIBILITY = "android:visibility:visibility";
+ static final String PROPNAME_VISIBILITY = "android:visibility:visibility";
private static final String PROPNAME_PARENT = "android:visibility:parent";
private static final String PROPNAME_SCREEN_LOCATION = "android:visibility:screenLocation";
diff --git a/core/java/android/transition/VisibilityPropagation.java b/core/java/android/transition/VisibilityPropagation.java
index 0326d47..183e036 100644
--- a/core/java/android/transition/VisibilityPropagation.java
+++ b/core/java/android/transition/VisibilityPropagation.java
@@ -42,7 +42,11 @@ public abstract class VisibilityPropagation extends TransitionPropagation {
@Override
public void captureValues(TransitionValues values) {
View view = values.view;
- values.values.put(PROPNAME_VISIBILITY, view.getVisibility());
+ Integer visibility = (Integer) values.values.get(Visibility.PROPNAME_VISIBILITY);
+ if (visibility == null) {
+ visibility = view.getVisibility();
+ }
+ values.values.put(PROPNAME_VISIBILITY, visibility);
int[] loc = new int[2];
view.getLocationOnScreen(loc);
loc[0] += Math.round(view.getTranslationX());
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 5157c41..83767cb 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -150,10 +150,9 @@ interface IWindowManager
void setStrictModeVisualIndicatorPreference(String enabled);
/**
- * Update the windowmanagers cached value of
- * {@link android.app.admin.DevicePolicyManager#getScreenCaptureDisabled(null, userId)}
+ * Set whether screen capture is disabled for all windows of a specific user
*/
- void updateScreenCaptureDisabled(int userId);
+ void setScreenCaptureDisabled(int userId, boolean disabled);
// These can only be called with the SET_ORIENTATION permission.
/**
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index c169d35..e7b3152 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -1425,6 +1425,21 @@ public abstract class Window {
public void setEnterTransition(Transition transition) {}
/**
+ * Sets the Transition that will be used to move Views out of the scene when the Window is
+ * preparing to close, for example after a call to
+ * {@link android.app.Activity#finishAfterTransition()}. The exiting
+ * Views will be those that are regular Views or ViewGroups that have
+ * {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend
+ * {@link android.transition.Visibility} as entering is governed by changing visibility from
+ * {@link View#VISIBLE} to {@link View#INVISIBLE}. If <code>transition</code> is null,
+ * entering Views will remain unaffected. If nothing is set, the default will be to
+ * use the same value as set in {@link #setEnterTransition(android.transition.Transition)}.
+ * @param transition The Transition to use to move Views out of the Scene when the Window
+ * is preparing to close.
+ */
+ public void setReturnTransition(Transition transition) {}
+
+ /**
* Sets the Transition that will be used to move Views out of the scene when starting a
* new Activity. The exiting Views will be those that are regular Views or ViewGroups that
* have {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend
@@ -1437,6 +1452,20 @@ public abstract class Window {
public void setExitTransition(Transition transition) {}
/**
+ * Sets the Transition that will be used to move Views in to the scene when returning from
+ * a previously-started Activity. The entering Views will be those that are regular Views
+ * or ViewGroups that have {@link ViewGroup#isTransitionGroup} return true. Typical Transitions
+ * will extend {@link android.transition.Visibility} as exiting is governed by changing
+ * visibility from {@link View#VISIBLE} to {@link View#INVISIBLE}. If transition is null,
+ * the views will remain unaffected. If nothing is set, the default will be to use the same
+ * transition as {@link #setExitTransition(android.transition.Transition)}.
+ * Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
+ * @param transition The Transition to use to move Views into the scene when reentering from a
+ * previously-started Activity.
+ */
+ public void setReenterTransition(Transition transition) {}
+
+ /**
* Returns the transition used to move Views into the initial scene. The entering
* Views will be those that are regular Views or ViewGroups that have
* {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend
@@ -1449,6 +1478,19 @@ public abstract class Window {
public Transition getEnterTransition() { return null; }
/**
+ * Returns he Transition that will be used to move Views out of the scene when the Window is
+ * preparing to close, for example after a call to
+ * {@link android.app.Activity#finishAfterTransition()}. The exiting
+ * Views will be those that are regular Views or ViewGroups that have
+ * {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend
+ * {@link android.transition.Visibility} as entering is governed by changing visibility from
+ * {@link View#VISIBLE} to {@link View#INVISIBLE}.
+ * @return The Transition to use to move Views out of the Scene when the Window
+ * is preparing to close.
+ */
+ public Transition getReturnTransition() { return null; }
+
+ /**
* Returns the Transition that will be used to move Views out of the scene when starting a
* new Activity. The exiting Views will be those that are regular Views or ViewGroups that
* have {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend
@@ -1461,6 +1503,18 @@ public abstract class Window {
public Transition getExitTransition() { return null; }
/**
+ * Returns the Transition that will be used to move Views in to the scene when returning from
+ * a previously-started Activity. The entering Views will be those that are regular Views
+ * or ViewGroups that have {@link ViewGroup#isTransitionGroup} return true. Typical Transitions
+ * will extend {@link android.transition.Visibility} as exiting is governed by changing
+ * visibility from {@link View#VISIBLE} to {@link View#INVISIBLE}.
+ * Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
+ * @return The Transition to use to move Views into the scene when reentering from a
+ * previously-started Activity.
+ */
+ public Transition getReenterTransition() { return null; }
+
+ /**
* Sets the Transition that will be used for shared elements transferred into the content
* Scene. Typical Transitions will affect size and location, such as
* {@link android.transition.ChangeBounds}. A null
@@ -1472,6 +1526,19 @@ public abstract class Window {
public void setSharedElementEnterTransition(Transition transition) {}
/**
+ * Sets the Transition that will be used for shared elements transferred back to a
+ * calling Activity. Typical Transitions will affect size and location, such as
+ * {@link android.transition.ChangeBounds}. A null
+ * value will cause transferred shared elements to blink to the final position.
+ * If no value is set, the default will be to use the same value as
+ * {@link #setSharedElementEnterTransition(android.transition.Transition)}.
+ * Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
+ * @param transition The Transition to use for shared elements transferred out of the content
+ * Scene.
+ */
+ public void setSharedElementReturnTransition(Transition transition) {}
+
+ /**
* Returns the Transition that will be used for shared elements transferred into the content
* Scene. Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
* @return Transition to use for sharend elements transferred into the content Scene.
@@ -1479,6 +1546,13 @@ public abstract class Window {
public Transition getSharedElementEnterTransition() { return null; }
/**
+ * Returns the Transition that will be used for shared elements transferred back to a
+ * calling Activity. Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
+ * @return Transition to use for sharend elements transferred into the content Scene.
+ */
+ public Transition getSharedElementReturnTransition() { return null; }
+
+ /**
* Sets the Transition that will be used for shared elements after starting a new Activity
* before the shared elements are transferred to the called Activity. If the shared elements
* must animate during the exit transition, this Transition should be used. Upon completion,
@@ -1490,6 +1564,17 @@ public abstract class Window {
public void setSharedElementExitTransition(Transition transition) {}
/**
+ * Sets the Transition that will be used for shared elements reentering from a started
+ * Activity after it has returned the shared element to it start location. If no value
+ * is set, this will default to
+ * {@link #setSharedElementExitTransition(android.transition.Transition)}.
+ * Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
+ * @param transition The Transition to use for shared elements in the launching Window
+ * after the shared element has returned to the Window.
+ */
+ public void setSharedElementReenterTransition(Transition transition) {}
+
+ /**
* Returns the Transition to use for shared elements in the launching Window prior
* to transferring to the launched Activity's Window.
* Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
@@ -1500,6 +1585,16 @@ public abstract class Window {
public Transition getSharedElementExitTransition() { return null; }
/**
+ * Returns the Transition that will be used for shared elements reentering from a started
+ * Activity after it has returned the shared element to it start location.
+ * Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
+ *
+ * @return the Transition that will be used for shared elements reentering from a started
+ * Activity after it has returned the shared element to it start location.
+ */
+ public Transition getSharedElementReenterTransition() { return null; }
+
+ /**
* Controls how the transition set in
* {@link #setEnterTransition(android.transition.Transition)} overlaps with the exit
* transition of the calling Activity. When true, the transition will start as soon as possible.
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index 8ea1090..682f2ae 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -100,13 +100,35 @@ public class Switch extends CompoundButton {
private int mMinFlingVelocity;
private float mThumbPosition;
+
+ /**
+ * Width required to draw the switch track and thumb. Includes padding and
+ * optical bounds for both the track and thumb.
+ */
private int mSwitchWidth;
+
+ /**
+ * Height required to draw the switch track and thumb. Includes padding and
+ * optical bounds for both the track and thumb.
+ */
private int mSwitchHeight;
- private int mThumbWidth; // Does not include padding
+ /**
+ * Width of the thumb's content region. Does not include padding or
+ * optical bounds.
+ */
+ private int mThumbWidth;
+
+ /** Left bound for drawing the switch track and thumb. */
private int mSwitchLeft;
+
+ /** Top bound for drawing the switch track and thumb. */
private int mSwitchTop;
+
+ /** Right bound for drawing the switch track and thumb. */
private int mSwitchRight;
+
+ /** Bottom bound for drawing the switch track and thumb. */
private int mSwitchBottom;
private TextPaint mTextPaint;
@@ -539,7 +561,7 @@ public class Switch extends CompoundButton {
* Sets whether the on/off text should be displayed.
*
* @param showText {@code true} to display on/off text
- * @hide
+ * @attr ref android.R.styleable#Switch_showText
*/
public void setShowText(boolean showText) {
if (mShowText != showText) {
@@ -550,7 +572,7 @@ public class Switch extends CompoundButton {
/**
* @return whether the on/off text should be displayed
- * @hide
+ * @attr ref android.R.styleable#Switch_showText
*/
public boolean getShowText() {
return mShowText;
@@ -568,32 +590,50 @@ public class Switch extends CompoundButton {
}
}
- final int trackHeight;
final Rect padding = mTempRect;
- if (mTrackDrawable != null) {
- mTrackDrawable.getPadding(padding);
- trackHeight = mTrackDrawable.getIntrinsicHeight();
- } else {
- padding.setEmpty();
- trackHeight = 0;
- }
-
final int thumbWidth;
final int thumbHeight;
if (mThumbDrawable != null) {
- thumbWidth = mThumbDrawable.getIntrinsicWidth();
+ // Cached thumb width does not include padding.
+ mThumbDrawable.getPadding(padding);
+ thumbWidth = mThumbDrawable.getIntrinsicWidth() - padding.left - padding.right;
thumbHeight = mThumbDrawable.getIntrinsicHeight();
} else {
thumbWidth = 0;
thumbHeight = 0;
}
- final int maxTextWidth = mShowText ? Math.max(mOnLayout.getWidth(), mOffLayout.getWidth())
- + mThumbTextPadding * 2 : 0;
+ final int maxTextWidth;
+ if (mShowText) {
+ maxTextWidth = Math.max(mOnLayout.getWidth(), mOffLayout.getWidth())
+ + mThumbTextPadding * 2;
+ } else {
+ maxTextWidth = 0;
+ }
+
mThumbWidth = Math.max(maxTextWidth, thumbWidth);
+ final int trackHeight;
+ if (mTrackDrawable != null) {
+ mTrackDrawable.getPadding(padding);
+ trackHeight = mTrackDrawable.getIntrinsicHeight();
+ } else {
+ padding.setEmpty();
+ trackHeight = 0;
+ }
+
+ // Adjust left and right padding to ensure there's enough room for the
+ // thumb's padding (when present).
+ int paddingLeft = padding.left;
+ int paddingRight = padding.right;
+ if (mThumbDrawable != null) {
+ final Insets inset = mThumbDrawable.getOpticalInsets();
+ paddingLeft = Math.max(paddingLeft, inset.left);
+ paddingRight = Math.max(paddingRight, inset.right);
+ }
+
final int switchWidth = Math.max(mSwitchMinWidth,
- 2 * mThumbWidth + padding.left + padding.right);
+ 2 * mThumbWidth + paddingLeft + paddingRight);
final int switchHeight = Math.max(trackHeight, thumbHeight);
mSwitchWidth = switchWidth;
mSwitchHeight = switchHeight;
@@ -806,19 +846,33 @@ public class Switch extends CompoundButton {
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
- int switchRight;
- int switchLeft;
+ int opticalInsetLeft = 0;
+ int opticalInsetRight = 0;
+ if (mThumbDrawable != null) {
+ final Rect trackPadding = mTempRect;
+ if (mTrackDrawable != null) {
+ mTrackDrawable.getPadding(trackPadding);
+ } else {
+ trackPadding.setEmpty();
+ }
+
+ final Insets insets = mThumbDrawable.getOpticalInsets();
+ opticalInsetLeft = Math.max(0, insets.left - trackPadding.left);
+ opticalInsetRight = Math.max(0, insets.right - trackPadding.right);
+ }
+ final int switchRight;
+ final int switchLeft;
if (isLayoutRtl()) {
- switchLeft = getPaddingLeft();
- switchRight = switchLeft + mSwitchWidth;
+ switchLeft = getPaddingLeft() + opticalInsetLeft;
+ switchRight = switchLeft + mSwitchWidth - opticalInsetLeft - opticalInsetRight;
} else {
- switchRight = getWidth() - getPaddingRight();
- switchLeft = switchRight - mSwitchWidth;
+ switchRight = getWidth() - getPaddingRight() - opticalInsetRight;
+ switchLeft = switchRight - mSwitchWidth + opticalInsetLeft + opticalInsetRight;
}
- int switchTop = 0;
- int switchBottom = 0;
+ final int switchTop;
+ final int switchBottom;
switch (getGravity() & Gravity.VERTICAL_GRAVITY_MASK) {
default:
case Gravity.TOP:
@@ -847,27 +901,55 @@ public class Switch extends CompoundButton {
@Override
public void draw(Canvas c) {
final Rect padding = mTempRect;
-
- // Layout the track.
final int switchLeft = mSwitchLeft;
final int switchTop = mSwitchTop;
final int switchRight = mSwitchRight;
final int switchBottom = mSwitchBottom;
- if (mTrackDrawable != null) {
- mTrackDrawable.setBounds(switchLeft, switchTop, switchRight, switchBottom);
- mTrackDrawable.getPadding(padding);
+
+ int thumbInitialLeft = switchLeft + getThumbOffset();
+
+ final Insets thumbInsets;
+ if (mThumbDrawable != null) {
+ thumbInsets = mThumbDrawable.getOpticalInsets();
+ } else {
+ thumbInsets = Insets.NONE;
}
- final int switchInnerLeft = switchLeft + padding.left;
+ // Layout the track.
+ if (mTrackDrawable != null) {
+ mTrackDrawable.getPadding(padding);
- // Relies on mTempRect, MUST be called first!
- final int thumbPos = getThumbOffset();
+ // Adjust thumb position for track padding.
+ thumbInitialLeft += padding.left;
+
+ // If necessary, offset by the optical insets of the thumb asset.
+ int trackLeft = switchLeft;
+ int trackTop = switchTop;
+ int trackRight = switchRight;
+ int trackBottom = switchBottom;
+ if (thumbInsets != Insets.NONE) {
+ if (thumbInsets.left > padding.left) {
+ trackLeft += thumbInsets.left - padding.left;
+ }
+ if (thumbInsets.top > padding.top) {
+ trackTop += thumbInsets.top - padding.top;
+ }
+ if (thumbInsets.right > padding.right) {
+ trackRight -= thumbInsets.right - padding.right;
+ }
+ if (thumbInsets.bottom > padding.bottom) {
+ trackBottom -= thumbInsets.bottom - padding.bottom;
+ }
+ }
+ mTrackDrawable.setBounds(trackLeft, trackTop, trackRight, trackBottom);
+ }
// Layout the thumb.
if (mThumbDrawable != null) {
mThumbDrawable.getPadding(padding);
- final int thumbLeft = switchInnerLeft - padding.left + thumbPos;
- final int thumbRight = switchInnerLeft + thumbPos + mThumbWidth + padding.right;
+
+ final int thumbLeft = thumbInitialLeft - padding.left;
+ final int thumbRight = thumbInitialLeft + mThumbWidth + padding.right;
mThumbDrawable.setBounds(thumbLeft, switchTop, thumbRight, switchBottom);
final Drawable background = getBackground();
@@ -894,9 +976,7 @@ public class Switch extends CompoundButton {
final int switchTop = mSwitchTop;
final int switchBottom = mSwitchBottom;
- final int switchInnerLeft = mSwitchLeft + padding.left;
final int switchInnerTop = switchTop + padding.top;
- final int switchInnerRight = mSwitchRight - padding.right;
final int switchInnerBottom = switchBottom - padding.bottom;
final Drawable thumbDrawable = mThumbDrawable;
@@ -919,7 +999,6 @@ public class Switch extends CompoundButton {
final int saveCount = canvas.save();
if (thumbDrawable != null) {
- canvas.clipRect(switchInnerLeft, switchTop, switchInnerRight, switchBottom);
thumbDrawable.draw(canvas);
}
@@ -974,7 +1053,7 @@ public class Switch extends CompoundButton {
/**
* Translates thumb position to offset according to current RTL setting and
- * thumb scroll range.
+ * thumb scroll range. Accounts for both track and thumb padding.
*
* @return thumb offset
*/
@@ -990,8 +1069,18 @@ public class Switch extends CompoundButton {
private int getThumbScrollRange() {
if (mTrackDrawable != null) {
- mTrackDrawable.getPadding(mTempRect);
- return mSwitchWidth - mThumbWidth - mTempRect.left - mTempRect.right;
+ final Rect padding = mTempRect;
+ mTrackDrawable.getPadding(padding);
+
+ final Insets insets;
+ if (mThumbDrawable != null) {
+ insets = mThumbDrawable.getOpticalInsets();
+ } else {
+ insets = Insets.NONE;
+ }
+
+ return mSwitchWidth - mThumbWidth - padding.left - padding.right
+ - insets.left - insets.right;
} else {
return 0;
}
diff --git a/core/java/com/android/internal/util/XmlUtils.java b/core/java/com/android/internal/util/XmlUtils.java
index dca9921..7db70ba 100644
--- a/core/java/com/android/internal/util/XmlUtils.java
+++ b/core/java/com/android/internal/util/XmlUtils.java
@@ -16,12 +16,18 @@
package com.android.internal.util;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Bitmap.CompressFormat;
+import android.net.Uri;
+import android.util.Base64;
import android.util.Xml;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -1415,6 +1421,20 @@ public class XmlUtils {
out.attribute(null, name, Long.toString(value));
}
+ public static float readFloatAttribute(XmlPullParser in, String name) throws IOException {
+ final String value = in.getAttributeValue(null, name);
+ try {
+ return Float.parseFloat(value);
+ } catch (NumberFormatException e) {
+ throw new ProtocolException("problem parsing " + name + "=" + value + " as long");
+ }
+ }
+
+ public static void writeFloatAttribute(XmlSerializer out, String name, float value)
+ throws IOException {
+ out.attribute(null, name, Float.toString(value));
+ }
+
public static boolean readBooleanAttribute(XmlPullParser in, String name) {
final String value = in.getAttributeValue(null, name);
return Boolean.parseBoolean(value);
@@ -1425,6 +1445,63 @@ public class XmlUtils {
out.attribute(null, name, Boolean.toString(value));
}
+ public static Uri readUriAttribute(XmlPullParser in, String name) {
+ final String value = in.getAttributeValue(null, name);
+ return (value != null) ? Uri.parse(value) : null;
+ }
+
+ public static void writeUriAttribute(XmlSerializer out, String name, Uri value)
+ throws IOException {
+ if (value != null) {
+ out.attribute(null, name, value.toString());
+ }
+ }
+
+ public static String readStringAttribute(XmlPullParser in, String name) {
+ return in.getAttributeValue(null, name);
+ }
+
+ public static void writeStringAttribute(XmlSerializer out, String name, String value)
+ throws IOException {
+ if (value != null) {
+ out.attribute(null, name, value);
+ }
+ }
+
+ public static byte[] readByteArrayAttribute(XmlPullParser in, String name) {
+ final String value = in.getAttributeValue(null, name);
+ if (value != null) {
+ return Base64.decode(value, Base64.DEFAULT);
+ } else {
+ return null;
+ }
+ }
+
+ public static void writeByteArrayAttribute(XmlSerializer out, String name, byte[] value)
+ throws IOException {
+ if (value != null) {
+ out.attribute(null, name, Base64.encodeToString(value, Base64.DEFAULT));
+ }
+ }
+
+ public static Bitmap readBitmapAttribute(XmlPullParser in, String name) {
+ final byte[] value = readByteArrayAttribute(in, name);
+ if (value != null) {
+ return BitmapFactory.decodeByteArray(value, 0, value.length);
+ } else {
+ return null;
+ }
+ }
+
+ public static void writeBitmapAttribute(XmlSerializer out, String name, Bitmap value)
+ throws IOException {
+ if (value != null) {
+ final ByteArrayOutputStream os = new ByteArrayOutputStream();
+ value.compress(CompressFormat.PNG, 90, os);
+ writeByteArrayAttribute(out, name, os.toByteArray());
+ }
+ }
+
/** @hide */
public interface WriteMapCallback {
/**
diff --git a/core/jni/android/graphics/MinikinUtils.cpp b/core/jni/android/graphics/MinikinUtils.cpp
index 47f72c4..b00e1ab 100644
--- a/core/jni/android/graphics/MinikinUtils.cpp
+++ b/core/jni/android/graphics/MinikinUtils.cpp
@@ -59,6 +59,7 @@ void MinikinUtils::doLayout(Layout* layout, const Paint* paint, int bidiFlags, T
minikinPaint.skewX = paint->getTextSkewX();
minikinPaint.letterSpacing = paint->getLetterSpacing();
minikinPaint.paintFlags = MinikinFontSkia::packPaintFlags(paint);
+ minikinPaint.fontFeatureSettings = paint->getFontFeatureSettings();
layout->doLayout(buf, start, count, bufSize, bidiFlags, minikinStyle, minikinPaint);
}
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index 2b0d68c..235e4f2 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -428,6 +428,16 @@ public:
paint->setLetterSpacing(letterSpacing);
}
+ static void setFontFeatureSettings(JNIEnv* env, jobject clazz, jlong paintHandle, jstring settings) {
+ Paint* paint = reinterpret_cast<Paint*>(paintHandle);
+ if (!settings)
+ paint->setFontFeatureSettings(std::string());
+ else {
+ ScopedUtfChars settingsChars(env, settings);
+ paint->setFontFeatureSettings(std::string(settingsChars.c_str(), settingsChars.size()));
+ }
+ }
+
static SkScalar getMetricsInternal(JNIEnv* env, jobject jpaint, Paint::FontMetrics *metrics) {
const int kElegantTop = 2500;
const int kElegantBottom = -1000;
@@ -987,6 +997,7 @@ static JNINativeMethod methods[] = {
{"setTextSkewX","(F)V", (void*) PaintGlue::setTextSkewX},
{"native_getLetterSpacing","(J)F", (void*) PaintGlue::getLetterSpacing},
{"native_setLetterSpacing","(JF)V", (void*) PaintGlue::setLetterSpacing},
+ {"native_setFontFeatureSettings","(JLjava/lang/String;)V", (void*) PaintGlue::setFontFeatureSettings},
{"ascent","()F", (void*) PaintGlue::ascent},
{"descent","()F", (void*) PaintGlue::descent},
{"getFontMetrics", "(Landroid/graphics/Paint$FontMetrics;)F", (void*)PaintGlue::getFontMetrics},
diff --git a/core/jni/android/graphics/Paint.h b/core/jni/android/graphics/Paint.h
index 7235cc4..efc65be 100644
--- a/core/jni/android/graphics/Paint.h
+++ b/core/jni/android/graphics/Paint.h
@@ -18,6 +18,7 @@
#define ANDROID_GRAPHICS_PAINT_H
#include <SkPaint.h>
+#include <string>
namespace android {
@@ -42,8 +43,17 @@ public:
return mLetterSpacing;
}
+ void setFontFeatureSettings(const std::string &fontFeatureSettings) {
+ mFontFeatureSettings = fontFeatureSettings;
+ }
+
+ std::string getFontFeatureSettings() const {
+ return mFontFeatureSettings;
+ }
+
private:
float mLetterSpacing;
+ std::string mFontFeatureSettings;
};
} // namespace android
diff --git a/core/jni/android/graphics/PaintImpl.cpp b/core/jni/android/graphics/PaintImpl.cpp
index ff2bbc5..05020d2 100644
--- a/core/jni/android/graphics/PaintImpl.cpp
+++ b/core/jni/android/graphics/PaintImpl.cpp
@@ -23,11 +23,11 @@
namespace android {
Paint::Paint() : SkPaint(),
- mLetterSpacing(0) {
+ mLetterSpacing(0), mFontFeatureSettings() {
}
Paint::Paint(const Paint& paint) : SkPaint(paint),
- mLetterSpacing(0) {
+ mLetterSpacing(0), mFontFeatureSettings() {
}
Paint::~Paint() {
@@ -36,12 +36,14 @@ Paint::~Paint() {
Paint& Paint::operator=(const Paint& other) {
SkPaint::operator=(other);
mLetterSpacing = other.mLetterSpacing;
+ mFontFeatureSettings = other.mFontFeatureSettings;
return *this;
}
bool operator==(const Paint& a, const Paint& b) {
return static_cast<const SkPaint&>(a) == static_cast<const SkPaint&>(b)
- && a.mLetterSpacing == b.mLetterSpacing;
+ && a.mLetterSpacing == b.mLetterSpacing
+ && a.mFontFeatureSettings == b.mFontFeatureSettings;
}
}
diff --git a/core/jni/android/graphics/Picture.cpp b/core/jni/android/graphics/Picture.cpp
index d214575..630999c 100644
--- a/core/jni/android/graphics/Picture.cpp
+++ b/core/jni/android/graphics/Picture.cpp
@@ -42,6 +42,10 @@ Canvas* Picture::beginRecording(int width, int height) {
mWidth = width;
mHeight = height;
SkCanvas* canvas = mRecorder->beginRecording(width, height, NULL, 0);
+ // the java side will wrap this guy in a Canvas.java, which will call
+ // unref in its finalizer, so we have to ref it here, so that both that
+ // Canvas.java and our picture can both be owners
+ canvas->ref();
return Canvas::create_canvas(canvas);
}
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_000.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_000.png
deleted file mode 100644
index c54f8d7..0000000
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_000.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00001.9.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00001.9.png
new file mode 100644
index 0000000..9076900
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00001.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00002.9.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00002.9.png
new file mode 100644
index 0000000..3c72bf8
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00002.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00003.9.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00003.9.png
new file mode 100644
index 0000000..d31e113
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00003.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00004.9.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00004.9.png
new file mode 100644
index 0000000..d0c693e
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00004.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00005.9.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00005.9.png
new file mode 100644
index 0000000..dfa19b4
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00005.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00006.9.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00006.9.png
new file mode 100644
index 0000000..151f205
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00006.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00007.9.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00007.9.png
new file mode 100644
index 0000000..ad3ee2c
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00007.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00008.9.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00008.9.png
new file mode 100644
index 0000000..43d66d7
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00008.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00009.9.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00009.9.png
new file mode 100644
index 0000000..13e4f8b
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00009.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00010.9.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00010.9.png
new file mode 100644
index 0000000..a09b6b2
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00010.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00011.9.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00011.9.png
new file mode 100644
index 0000000..be02e53
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00011.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00012.9.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00012.9.png
new file mode 100644
index 0000000..655d387
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_00012.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_001.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_001.png
deleted file mode 100644
index e062f61..0000000
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_001.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_002.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_002.png
deleted file mode 100644
index 7737646..0000000
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_002.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_003.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_003.png
deleted file mode 100644
index 65ff45e..0000000
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_003.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_004.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_004.png
deleted file mode 100644
index 11aaec0..0000000
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_004.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_005.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_005.png
deleted file mode 100644
index 9e1b60f..0000000
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_005.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_006.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_006.png
deleted file mode 100644
index 1e45687..0000000
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_006.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_007.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_007.png
deleted file mode 100644
index 1e45687..0000000
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_007.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_008.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_008.png
deleted file mode 100644
index 6c48456..0000000
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_008.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_009.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_009.png
deleted file mode 100644
index a4d084b..0000000
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_009.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_010.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_010.png
deleted file mode 100644
index 1e1a1b0..0000000
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_010.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_011.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_011.png
deleted file mode 100644
index 1e1a1b0..0000000
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_011.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_012.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_012.png
deleted file mode 100644
index 1e1a1b0..0000000
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_012.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_013.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_013.png
deleted file mode 100644
index 1e1a1b0..0000000
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_013.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_014.png b/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_014.png
deleted file mode 100644
index 1e1a1b0..0000000
--- a/core/res/res/drawable-hdpi/btn_switch_to_off_mtrl_014.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_000.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_000.png
deleted file mode 100644
index cf09f97..0000000
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_000.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00001.9.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00001.9.png
new file mode 100644
index 0000000..e870a0a
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00001.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00002.9.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00002.9.png
new file mode 100644
index 0000000..1d8f805
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00002.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00003.9.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00003.9.png
new file mode 100644
index 0000000..d348871
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00003.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00004.9.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00004.9.png
new file mode 100644
index 0000000..941e91e
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00004.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00005.9.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00005.9.png
new file mode 100644
index 0000000..adee78d
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00005.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00006.9.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00006.9.png
new file mode 100644
index 0000000..e6b4ca3
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00006.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00007.9.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00007.9.png
new file mode 100644
index 0000000..6c2bc0d
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00007.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00008.9.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00008.9.png
new file mode 100644
index 0000000..763833c
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00008.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00009.9.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00009.9.png
new file mode 100644
index 0000000..9a87fbc
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00009.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00010.9.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00010.9.png
new file mode 100644
index 0000000..6ccf70b
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00010.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00011.9.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00011.9.png
new file mode 100644
index 0000000..d1c14a5
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00011.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00012.9.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00012.9.png
new file mode 100644
index 0000000..c2290f0
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_00012.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_001.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_001.png
deleted file mode 100644
index 3218e66..0000000
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_001.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_002.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_002.png
deleted file mode 100644
index 0acff03..0000000
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_002.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_003.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_003.png
deleted file mode 100644
index c93adf4..0000000
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_003.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_004.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_004.png
deleted file mode 100644
index 5d8ddc96..0000000
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_004.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_005.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_005.png
deleted file mode 100644
index 47206a4..0000000
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_005.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_006.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_006.png
deleted file mode 100644
index 7d6a91f..0000000
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_006.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_007.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_007.png
deleted file mode 100644
index e062f61..0000000
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_007.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_008.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_008.png
deleted file mode 100644
index b0f0dde..0000000
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_008.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_009.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_009.png
deleted file mode 100644
index c54f8d7..0000000
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_009.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_010.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_010.png
deleted file mode 100644
index c54f8d7..0000000
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_010.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_011.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_011.png
deleted file mode 100644
index c54f8d7..0000000
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_011.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_012.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_012.png
deleted file mode 100644
index c54f8d7..0000000
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_012.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_013.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_013.png
deleted file mode 100644
index c54f8d7..0000000
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_013.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_014.png b/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_014.png
deleted file mode 100644
index c54f8d7..0000000
--- a/core/res/res/drawable-hdpi/btn_switch_to_on_mtrl_014.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_corp_icon.png b/core/res/res/drawable-hdpi/ic_corp_icon.png
index fc986fe..829962c 100644
--- a/core/res/res/drawable-hdpi/ic_corp_icon.png
+++ b/core/res/res/drawable-hdpi/ic_corp_icon.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/switch_track_mtrl_alpha.9.png b/core/res/res/drawable-hdpi/switch_track_mtrl_alpha.9.png
index ac1fc23..0ebe65e 100644
--- a/core/res/res/drawable-hdpi/switch_track_mtrl_alpha.9.png
+++ b/core/res/res/drawable-hdpi/switch_track_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_000.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_000.png
deleted file mode 100644
index 8c3f26c..0000000
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_000.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00001.9.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00001.9.png
new file mode 100644
index 0000000..0238898
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00001.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00002.9.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00002.9.png
new file mode 100644
index 0000000..ada1be9
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00002.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00003.9.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00003.9.png
new file mode 100644
index 0000000..82aec64
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00003.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00004.9.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00004.9.png
new file mode 100644
index 0000000..1c6ea9f
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00004.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00005.9.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00005.9.png
new file mode 100644
index 0000000..ac11400
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00005.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00006.9.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00006.9.png
new file mode 100644
index 0000000..2025972
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00006.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00007.9.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00007.9.png
new file mode 100644
index 0000000..7420fd8
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00007.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00008.9.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00008.9.png
new file mode 100644
index 0000000..1f40832
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00008.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00009.9.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00009.9.png
new file mode 100644
index 0000000..cf58e44
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00009.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00010.9.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00010.9.png
new file mode 100644
index 0000000..930a280
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00010.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00011.9.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00011.9.png
new file mode 100644
index 0000000..ed9bc37
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00011.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00012.9.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00012.9.png
new file mode 100644
index 0000000..cddb5b0
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_00012.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_001.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_001.png
deleted file mode 100644
index 3617168..0000000
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_001.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_002.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_002.png
deleted file mode 100644
index e4366f4..0000000
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_002.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_003.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_003.png
deleted file mode 100644
index ea4533b..0000000
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_003.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_004.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_004.png
deleted file mode 100644
index 94aedbb..0000000
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_004.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_005.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_005.png
deleted file mode 100644
index ef84578..0000000
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_005.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_006.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_006.png
deleted file mode 100644
index 4de2321..0000000
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_006.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_007.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_007.png
deleted file mode 100644
index 4de2321..0000000
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_007.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_008.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_008.png
deleted file mode 100644
index d62fbd5..0000000
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_008.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_009.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_009.png
deleted file mode 100644
index 3d87c4e..0000000
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_009.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_010.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_010.png
deleted file mode 100644
index 536ed46..0000000
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_010.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_011.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_011.png
deleted file mode 100644
index 536ed46..0000000
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_011.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_012.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_012.png
deleted file mode 100644
index 536ed46..0000000
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_012.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_013.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_013.png
deleted file mode 100644
index 536ed46..0000000
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_013.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_014.png b/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_014.png
deleted file mode 100644
index 536ed46..0000000
--- a/core/res/res/drawable-mdpi/btn_switch_to_off_mtrl_014.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_000.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_000.png
deleted file mode 100644
index f5b660d..0000000
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_000.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00001.9.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00001.9.png
new file mode 100644
index 0000000..bc1f979
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00001.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00002.9.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00002.9.png
new file mode 100644
index 0000000..e6fdbcc
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00002.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00003.9.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00003.9.png
new file mode 100644
index 0000000..3d60b43
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00003.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00004.9.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00004.9.png
new file mode 100644
index 0000000..b9afdc2
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00004.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00005.9.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00005.9.png
new file mode 100644
index 0000000..c3c8bf2
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00005.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00006.9.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00006.9.png
new file mode 100644
index 0000000..1c7e5e1
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00006.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00007.9.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00007.9.png
new file mode 100644
index 0000000..6329b73
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00007.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00008.9.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00008.9.png
new file mode 100644
index 0000000..424202c
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00008.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00009.9.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00009.9.png
new file mode 100644
index 0000000..313beca
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00009.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00010.9.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00010.9.png
new file mode 100644
index 0000000..f18d86a
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00010.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00011.9.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00011.9.png
new file mode 100644
index 0000000..8ab48c0
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00011.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00012.9.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00012.9.png
new file mode 100644
index 0000000..fbc2c16
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_00012.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_001.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_001.png
deleted file mode 100644
index 9e4db6c..0000000
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_001.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_002.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_002.png
deleted file mode 100644
index 7de2128..0000000
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_002.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_003.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_003.png
deleted file mode 100644
index 1980c2c..0000000
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_003.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_004.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_004.png
deleted file mode 100644
index 6e73ef0..0000000
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_004.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_005.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_005.png
deleted file mode 100644
index f897392..0000000
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_005.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_006.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_006.png
deleted file mode 100644
index 74a6ebd..0000000
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_006.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_007.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_007.png
deleted file mode 100644
index 3617168..0000000
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_007.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_008.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_008.png
deleted file mode 100644
index 884eb66..0000000
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_008.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_009.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_009.png
deleted file mode 100644
index 8c3f26c..0000000
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_009.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_010.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_010.png
deleted file mode 100644
index 8c3f26c..0000000
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_010.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_011.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_011.png
deleted file mode 100644
index 8c3f26c..0000000
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_011.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_012.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_012.png
deleted file mode 100644
index 8c3f26c..0000000
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_012.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_013.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_013.png
deleted file mode 100644
index 8c3f26c..0000000
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_013.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_014.png b/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_014.png
deleted file mode 100644
index 8c3f26c..0000000
--- a/core/res/res/drawable-mdpi/btn_switch_to_on_mtrl_014.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_corp_icon.png b/core/res/res/drawable-mdpi/ic_corp_icon.png
index deb7966..44eb2d5 100644
--- a/core/res/res/drawable-mdpi/ic_corp_icon.png
+++ b/core/res/res/drawable-mdpi/ic_corp_icon.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/switch_track_mtrl_alpha.9.png b/core/res/res/drawable-mdpi/switch_track_mtrl_alpha.9.png
index b6538e4..4918d33 100644
--- a/core/res/res/drawable-mdpi/switch_track_mtrl_alpha.9.png
+++ b/core/res/res/drawable-mdpi/switch_track_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_000.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_000.png
deleted file mode 100644
index 2494fd4..0000000
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_000.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00001.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00001.9.png
new file mode 100644
index 0000000..265aeb7
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00001.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00002.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00002.9.png
new file mode 100644
index 0000000..2f036ad
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00002.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00003.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00003.9.png
new file mode 100644
index 0000000..bb26440
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00003.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00004.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00004.9.png
new file mode 100644
index 0000000..1b70047
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00004.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00005.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00005.9.png
new file mode 100644
index 0000000..b544b98
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00005.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00006.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00006.9.png
new file mode 100644
index 0000000..c461f3d
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00006.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00007.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00007.9.png
new file mode 100644
index 0000000..f57da14
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00007.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00008.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00008.9.png
new file mode 100644
index 0000000..22c6fbc
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00008.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00009.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00009.9.png
new file mode 100644
index 0000000..cd21ac9
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00009.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00010.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00010.9.png
new file mode 100644
index 0000000..a38dc87
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00010.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00011.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00011.9.png
new file mode 100644
index 0000000..d84a342
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00011.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00012.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00012.9.png
new file mode 100644
index 0000000..b82a2eb
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_00012.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_001.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_001.png
deleted file mode 100644
index 7bd99fe..0000000
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_001.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_002.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_002.png
deleted file mode 100644
index 2ef623b..0000000
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_002.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_003.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_003.png
deleted file mode 100644
index 19db3e0..0000000
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_003.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_004.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_004.png
deleted file mode 100644
index 984c3c5..0000000
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_004.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_005.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_005.png
deleted file mode 100644
index 6454190..0000000
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_005.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_006.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_006.png
deleted file mode 100644
index cee9393..0000000
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_006.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_007.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_007.png
deleted file mode 100644
index cee9393..0000000
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_007.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_008.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_008.png
deleted file mode 100644
index 437ffdd..0000000
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_008.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_009.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_009.png
deleted file mode 100644
index d2e14ad..0000000
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_009.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_010.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_010.png
deleted file mode 100644
index 4e2f5bc..0000000
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_010.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_011.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_011.png
deleted file mode 100644
index 4e2f5bc..0000000
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_011.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_012.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_012.png
deleted file mode 100644
index 4e2f5bc..0000000
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_012.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_013.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_013.png
deleted file mode 100644
index 4e2f5bc..0000000
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_013.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_014.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_014.png
deleted file mode 100644
index 4e2f5bc..0000000
--- a/core/res/res/drawable-xhdpi/btn_switch_to_off_mtrl_014.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_000.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_000.png
deleted file mode 100644
index f1bcfa3..0000000
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_000.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00001.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00001.9.png
new file mode 100644
index 0000000..6a33ebf
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00001.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00002.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00002.9.png
new file mode 100644
index 0000000..dafc250
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00002.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00003.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00003.9.png
new file mode 100644
index 0000000..27df6ff
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00003.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00004.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00004.9.png
new file mode 100644
index 0000000..cb4121c
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00004.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00005.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00005.9.png
new file mode 100644
index 0000000..c5cbb75
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00005.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00006.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00006.9.png
new file mode 100644
index 0000000..c69ef41
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00006.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00007.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00007.9.png
new file mode 100644
index 0000000..aff03d1
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00007.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00008.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00008.9.png
new file mode 100644
index 0000000..fb56ae6
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00008.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00009.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00009.9.png
new file mode 100644
index 0000000..88b9d28
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00009.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00010.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00010.9.png
new file mode 100644
index 0000000..8451958
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00010.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00011.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00011.9.png
new file mode 100644
index 0000000..6f57654
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00011.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00012.9.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00012.9.png
new file mode 100644
index 0000000..21bfc28
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_00012.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_001.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_001.png
deleted file mode 100644
index ede2fec..0000000
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_001.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_002.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_002.png
deleted file mode 100644
index 94ce017..0000000
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_002.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_003.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_003.png
deleted file mode 100644
index 647cfe3..0000000
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_003.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_004.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_004.png
deleted file mode 100644
index b3bf923..0000000
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_004.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_005.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_005.png
deleted file mode 100644
index ae95b2b..0000000
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_005.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_006.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_006.png
deleted file mode 100644
index b8e4bd6..0000000
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_006.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_007.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_007.png
deleted file mode 100644
index ec6d6d7..0000000
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_007.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_008.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_008.png
deleted file mode 100644
index c0e493f..0000000
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_008.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_009.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_009.png
deleted file mode 100644
index 2494fd4..0000000
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_009.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_010.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_010.png
deleted file mode 100644
index 2494fd4..0000000
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_010.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_011.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_011.png
deleted file mode 100644
index 2494fd4..0000000
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_011.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_012.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_012.png
deleted file mode 100644
index 2494fd4..0000000
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_012.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_013.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_013.png
deleted file mode 100644
index 2494fd4..0000000
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_013.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_014.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_014.png
deleted file mode 100644
index 2494fd4..0000000
--- a/core/res/res/drawable-xhdpi/btn_switch_to_on_mtrl_014.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_corp_icon.png b/core/res/res/drawable-xhdpi/ic_corp_icon.png
index ec4f44b..04faf00 100644
--- a/core/res/res/drawable-xhdpi/ic_corp_icon.png
+++ b/core/res/res/drawable-xhdpi/ic_corp_icon.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/switch_track_mtrl_alpha.9.png b/core/res/res/drawable-xhdpi/switch_track_mtrl_alpha.9.png
index d6a0ab2..fd47f15 100644
--- a/core/res/res/drawable-xhdpi/switch_track_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xhdpi/switch_track_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_000.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_000.png
deleted file mode 100644
index 198ac07..0000000
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_000.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00001.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00001.9.png
new file mode 100644
index 0000000..c30cb5a
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00001.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00002.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00002.9.png
new file mode 100644
index 0000000..eaba558
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00002.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00003.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00003.9.png
new file mode 100644
index 0000000..17c18c9
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00003.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00004.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00004.9.png
new file mode 100644
index 0000000..0fce07a
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00004.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00005.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00005.9.png
new file mode 100644
index 0000000..c29b837
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00005.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00006.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00006.9.png
new file mode 100644
index 0000000..ae56a41
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00006.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00007.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00007.9.png
new file mode 100644
index 0000000..85290ac
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00007.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00008.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00008.9.png
new file mode 100644
index 0000000..1e8513b
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00008.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00009.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00009.9.png
new file mode 100644
index 0000000..8810a12
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00009.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00010.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00010.9.png
new file mode 100644
index 0000000..717207f
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00010.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00011.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00011.9.png
new file mode 100644
index 0000000..db046f3
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00011.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00012.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00012.9.png
new file mode 100644
index 0000000..c5c07a4
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_00012.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_001.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_001.png
deleted file mode 100644
index eff3dd0..0000000
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_001.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_002.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_002.png
deleted file mode 100644
index 000a23a..0000000
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_002.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_003.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_003.png
deleted file mode 100644
index 394d661..0000000
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_003.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_004.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_004.png
deleted file mode 100644
index 4e7311d..0000000
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_004.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_005.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_005.png
deleted file mode 100644
index d9dcf91..0000000
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_005.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_006.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_006.png
deleted file mode 100644
index 674142e..0000000
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_006.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_007.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_007.png
deleted file mode 100644
index 674142e..0000000
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_007.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_008.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_008.png
deleted file mode 100644
index 9d4026a..0000000
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_008.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_009.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_009.png
deleted file mode 100644
index bb4b426..0000000
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_009.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_010.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_010.png
deleted file mode 100644
index a37076d..0000000
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_010.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_011.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_011.png
deleted file mode 100644
index a37076d..0000000
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_011.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_012.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_012.png
deleted file mode 100644
index a37076d..0000000
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_012.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_013.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_013.png
deleted file mode 100644
index a37076d..0000000
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_013.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_014.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_014.png
deleted file mode 100644
index a37076d..0000000
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_off_mtrl_014.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_000.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_000.png
deleted file mode 100644
index 22e9951..0000000
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_000.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00001.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00001.9.png
new file mode 100644
index 0000000..c9bdf1f
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00001.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00002.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00002.9.png
new file mode 100644
index 0000000..6bfd943
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00002.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00003.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00003.9.png
new file mode 100644
index 0000000..a1d3fbb
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00003.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00004.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00004.9.png
new file mode 100644
index 0000000..40c3a5b
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00004.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00005.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00005.9.png
new file mode 100644
index 0000000..26b8736
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00005.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00006.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00006.9.png
new file mode 100644
index 0000000..88c027e
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00006.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00007.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00007.9.png
new file mode 100644
index 0000000..02567c6
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00007.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00008.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00008.9.png
new file mode 100644
index 0000000..037d3bf
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00008.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00009.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00009.9.png
new file mode 100644
index 0000000..0252769
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00009.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00010.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00010.9.png
new file mode 100644
index 0000000..3ae501d
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00010.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00011.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00011.9.png
new file mode 100644
index 0000000..ecf2831
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00011.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00012.9.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00012.9.png
new file mode 100644
index 0000000..0877749
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_00012.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_001.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_001.png
deleted file mode 100644
index 14e6b39..0000000
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_001.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_002.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_002.png
deleted file mode 100644
index 86b2c01..0000000
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_002.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_003.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_003.png
deleted file mode 100644
index 1c565df..0000000
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_003.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_004.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_004.png
deleted file mode 100644
index b825449..0000000
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_004.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_005.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_005.png
deleted file mode 100644
index 170c234..0000000
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_005.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_006.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_006.png
deleted file mode 100644
index 5477007..0000000
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_006.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_007.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_007.png
deleted file mode 100644
index eff3dd0..0000000
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_007.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_008.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_008.png
deleted file mode 100644
index e3fd96a..0000000
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_008.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_009.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_009.png
deleted file mode 100644
index 198ac07..0000000
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_009.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_010.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_010.png
deleted file mode 100644
index 198ac07..0000000
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_010.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_011.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_011.png
deleted file mode 100644
index 198ac07..0000000
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_011.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_012.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_012.png
deleted file mode 100644
index 198ac07..0000000
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_012.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_013.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_013.png
deleted file mode 100644
index 198ac07..0000000
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_013.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_014.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_014.png
deleted file mode 100644
index 198ac07..0000000
--- a/core/res/res/drawable-xxhdpi/btn_switch_to_on_mtrl_014.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_corp_icon.png b/core/res/res/drawable-xxhdpi/ic_corp_icon.png
index 6888377..68400ea 100644
--- a/core/res/res/drawable-xxhdpi/ic_corp_icon.png
+++ b/core/res/res/drawable-xxhdpi/ic_corp_icon.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/switch_track_mtrl_alpha.9.png b/core/res/res/drawable-xxhdpi/switch_track_mtrl_alpha.9.png
index a8067cb..3e3174d 100644
--- a/core/res/res/drawable-xxhdpi/switch_track_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xxhdpi/switch_track_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_000.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_000.png
deleted file mode 100644
index 8b202c6..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_000.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00001.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00001.9.png
new file mode 100644
index 0000000..bc21279
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00001.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00002.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00002.9.png
new file mode 100644
index 0000000..b57b592
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00002.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00003.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00003.9.png
new file mode 100644
index 0000000..0fb9277
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00003.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00004.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00004.9.png
new file mode 100644
index 0000000..340722d
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00004.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00005.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00005.9.png
new file mode 100644
index 0000000..8554a76
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00005.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00006.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00006.9.png
new file mode 100644
index 0000000..a05e335
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00006.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00007.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00007.9.png
new file mode 100644
index 0000000..a5ded14
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00007.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00008.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00008.9.png
new file mode 100644
index 0000000..0300a49
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00008.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00009.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00009.9.png
new file mode 100644
index 0000000..37dd7ce
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00009.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00010.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00010.9.png
new file mode 100644
index 0000000..6bc549a
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00010.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00011.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00011.9.png
new file mode 100644
index 0000000..b026d5d
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00011.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00012.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00012.9.png
new file mode 100644
index 0000000..89238dc
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_00012.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_001.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_001.png
deleted file mode 100644
index 3b497f3..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_001.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_002.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_002.png
deleted file mode 100644
index 532b6de..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_002.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_003.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_003.png
deleted file mode 100644
index 403b2fe..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_003.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_004.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_004.png
deleted file mode 100644
index 8c5086c..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_004.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_005.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_005.png
deleted file mode 100644
index d4870f8..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_005.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_006.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_006.png
deleted file mode 100644
index c05adf5..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_006.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_007.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_007.png
deleted file mode 100644
index 99b2056..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_007.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_008.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_008.png
deleted file mode 100644
index d839358..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_008.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_009.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_009.png
deleted file mode 100644
index 913f94d..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_009.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_010.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_010.png
deleted file mode 100644
index 7f325b3..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_010.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_011.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_011.png
deleted file mode 100644
index 149a9aa..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_011.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_012.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_012.png
deleted file mode 100644
index 95c219e..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_012.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_013.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_013.png
deleted file mode 100644
index 462a128..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_013.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_014.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_014.png
deleted file mode 100644
index 5911d16..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_mtrl_014.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_000.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_000.png
deleted file mode 100644
index e0c6d85..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_000.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00001.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00001.9.png
new file mode 100644
index 0000000..1d309fe
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00001.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00002.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00002.9.png
new file mode 100644
index 0000000..2e58fa9
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00002.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00003.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00003.9.png
new file mode 100644
index 0000000..2ebe7a7
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00003.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00004.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00004.9.png
new file mode 100644
index 0000000..04bab76
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00004.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00005.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00005.9.png
new file mode 100644
index 0000000..3497e48
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00005.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00006.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00006.9.png
new file mode 100644
index 0000000..42333b4
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00006.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00007.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00007.9.png
new file mode 100644
index 0000000..732e175
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00007.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00008.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00008.9.png
new file mode 100644
index 0000000..12eddd8
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00008.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00009.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00009.9.png
new file mode 100644
index 0000000..95cbc61
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00009.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00010.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00010.9.png
new file mode 100644
index 0000000..105ec07
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00010.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00011.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00011.9.png
new file mode 100644
index 0000000..fac253a
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00011.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00012.9.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00012.9.png
new file mode 100644
index 0000000..1b8d11c
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_00012.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_001.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_001.png
deleted file mode 100644
index 5679943..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_001.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_002.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_002.png
deleted file mode 100644
index 54b636d..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_002.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_003.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_003.png
deleted file mode 100644
index bf9fac0..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_003.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_004.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_004.png
deleted file mode 100644
index 25d5319..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_004.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_005.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_005.png
deleted file mode 100644
index d2df595..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_005.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_006.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_006.png
deleted file mode 100644
index 7700bde..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_006.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_007.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_007.png
deleted file mode 100644
index 883f98b..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_007.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_008.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_008.png
deleted file mode 100644
index b3b2108..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_008.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_009.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_009.png
deleted file mode 100644
index 3aad596..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_009.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_010.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_010.png
deleted file mode 100644
index 2017e17..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_010.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_011.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_011.png
deleted file mode 100644
index 1fc2700..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_011.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_012.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_012.png
deleted file mode 100644
index bb8b0f2..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_012.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_013.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_013.png
deleted file mode 100644
index 66ab8f6..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_013.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_014.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_014.png
deleted file mode 100644
index e3424db..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_mtrl_014.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/switch_track_mtrl_alpha.9.png b/core/res/res/drawable-xxxhdpi/switch_track_mtrl_alpha.9.png
index fb07f2a..1e4a74c 100644
--- a/core/res/res/drawable-xxxhdpi/switch_track_mtrl_alpha.9.png
+++ b/core/res/res/drawable-xxxhdpi/switch_track_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable/switch_thumb_material_anim.xml b/core/res/res/drawable/switch_thumb_material_anim.xml
index 67e460a..71f6cfd 100644
--- a/core/res/res/drawable/switch_thumb_material_anim.xml
+++ b/core/res/res/drawable/switch_thumb_material_anim.xml
@@ -19,130 +19,116 @@
<item
android:state_enabled="false"
android:state_checked="true">
- <bitmap
- android:src="@drawable/btn_switch_to_on_mtrl_014"
+ <nine-patch
+ android:src="@drawable/btn_switch_to_on_mtrl_00012"
android:gravity="center"
+ android:tintMode="multiply"
android:tint="?attr/colorControlActivated"
android:alpha="?attr/disabledAlpha" />
</item>
<item android:state_enabled="false">
- <bitmap
- android:src="@drawable/btn_switch_to_on_mtrl_000"
+ <nine-patch
+ android:src="@drawable/btn_switch_to_on_mtrl_00001"
android:gravity="center"
- android:tint="?attr/colorControlNormal"
+ android:tintMode="multiply"
+ android:tint="?attr/colorButtonNormal"
android:alpha="?attr/disabledAlpha" />
</item>
<item
android:state_checked="true"
android:id="@+id/on">
- <bitmap
- android:src="@drawable/btn_switch_to_on_mtrl_014"
+ <nine-patch
+ android:src="@drawable/btn_switch_to_on_mtrl_00012"
android:gravity="center"
+ android:tintMode="multiply"
android:tint="?attr/colorControlActivated" />
</item>
<item android:id="@+id/off">
- <bitmap
- android:src="@drawable/btn_switch_to_on_mtrl_000"
+ <nine-patch
+ android:src="@drawable/btn_switch_to_on_mtrl_00001"
android:gravity="center"
- android:tint="?attr/colorControlNormal" />
+ android:tintMode="multiply"
+ android:tint="?attr/colorButtonNormal" />
</item>
<transition
android:fromId="@+id/off"
android:toId="@+id/on">
<animation-list>
<item android:duration="15">
- <bitmap android:src="@drawable/btn_switch_to_on_mtrl_000" android:gravity="center" android:tint="?attr/colorControlNormal" />
+ <nine-patch android:src="@drawable/btn_switch_to_on_mtrl_00001" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorButtonNormal" />
</item>
<item android:duration="15">
- <bitmap android:src="@drawable/btn_switch_to_on_mtrl_001" android:gravity="center" android:tint="?attr/colorControlNormal" />
+ <nine-patch android:src="@drawable/btn_switch_to_on_mtrl_00002" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorButtonNormal" />
</item>
<item android:duration="15">
- <bitmap android:src="@drawable/btn_switch_to_on_mtrl_002" android:gravity="center" android:tint="?attr/colorControlNormal" />
+ <nine-patch android:src="@drawable/btn_switch_to_on_mtrl_00003" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorButtonNormal" />
</item>
<item android:duration="15">
- <bitmap android:src="@drawable/btn_switch_to_on_mtrl_003" android:gravity="center" android:tint="?attr/colorControlNormal" />
+ <nine-patch android:src="@drawable/btn_switch_to_on_mtrl_00004" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorButtonNormal" />
</item>
<item android:duration="15">
- <bitmap android:src="@drawable/btn_switch_to_on_mtrl_004" android:gravity="center" android:tint="?attr/colorControlNormal" />
+ <nine-patch android:src="@drawable/btn_switch_to_on_mtrl_00005" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorButtonNormal" />
</item>
<item android:duration="15">
- <bitmap android:src="@drawable/btn_switch_to_on_mtrl_005" android:gravity="center" android:tint="?attr/colorControlNormal" />
+ <nine-patch android:src="@drawable/btn_switch_to_on_mtrl_00006" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorButtonNormal" />
</item>
<item android:duration="15">
- <bitmap android:src="@drawable/btn_switch_to_on_mtrl_006" android:gravity="center" android:tint="?attr/colorControlNormal" />
+ <nine-patch android:src="@drawable/btn_switch_to_on_mtrl_00007" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorControlActivated" />
</item>
<item android:duration="15">
- <bitmap android:src="@drawable/btn_switch_to_on_mtrl_007" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ <nine-patch android:src="@drawable/btn_switch_to_on_mtrl_00008" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorControlActivated" />
</item>
<item android:duration="15">
- <bitmap android:src="@drawable/btn_switch_to_on_mtrl_008" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ <nine-patch android:src="@drawable/btn_switch_to_on_mtrl_00009" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorControlActivated" />
</item>
<item android:duration="15">
- <bitmap android:src="@drawable/btn_switch_to_on_mtrl_009" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ <nine-patch android:src="@drawable/btn_switch_to_on_mtrl_00010" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorControlActivated" />
</item>
<item android:duration="15">
- <bitmap android:src="@drawable/btn_switch_to_on_mtrl_010" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ <nine-patch android:src="@drawable/btn_switch_to_on_mtrl_00011" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorControlActivated" />
</item>
<item android:duration="15">
- <bitmap android:src="@drawable/btn_switch_to_on_mtrl_011" android:gravity="center" android:tint="?attr/colorControlActivated" />
- </item>
- <item android:duration="15">
- <bitmap android:src="@drawable/btn_switch_to_on_mtrl_012" android:gravity="center" android:tint="?attr/colorControlActivated" />
- </item>
- <item android:duration="15">
- <bitmap android:src="@drawable/btn_switch_to_on_mtrl_013" android:gravity="center" android:tint="?attr/colorControlActivated" />
- </item>
- <item android:duration="15">
- <bitmap android:src="@drawable/btn_switch_to_on_mtrl_014" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ <nine-patch android:src="@drawable/btn_switch_to_on_mtrl_00012" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorControlActivated" />
</item>
</animation-list>
</transition>
<transition android:fromId="@+id/on" android:toId="@+id/off">
<animation-list>
<item android:duration="15">
- <bitmap android:src="@drawable/btn_switch_to_off_mtrl_000" android:gravity="center" android:tint="?attr/colorControlActivated" />
- </item>
- <item android:duration="15">
- <bitmap android:src="@drawable/btn_switch_to_off_mtrl_001" android:gravity="center" android:tint="?attr/colorControlActivated" />
- </item>
- <item android:duration="15">
- <bitmap android:src="@drawable/btn_switch_to_off_mtrl_002" android:gravity="center" android:tint="?attr/colorControlActivated" />
- </item>
- <item android:duration="15">
- <bitmap android:src="@drawable/btn_switch_to_off_mtrl_003" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ <nine-patch android:src="@drawable/btn_switch_to_off_mtrl_00001" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorControlActivated" />
</item>
<item android:duration="15">
- <bitmap android:src="@drawable/btn_switch_to_off_mtrl_004" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ <nine-patch android:src="@drawable/btn_switch_to_off_mtrl_00002" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorControlActivated" />
</item>
<item android:duration="15">
- <bitmap android:src="@drawable/btn_switch_to_off_mtrl_005" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ <nine-patch android:src="@drawable/btn_switch_to_off_mtrl_00003" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorControlActivated" />
</item>
<item android:duration="15">
- <bitmap android:src="@drawable/btn_switch_to_off_mtrl_006" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ <nine-patch android:src="@drawable/btn_switch_to_off_mtrl_00004" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorControlActivated" />
</item>
<item android:duration="15">
- <bitmap android:src="@drawable/btn_switch_to_off_mtrl_007" android:gravity="center" android:tint="?attr/colorControlNormal" />
+ <nine-patch android:src="@drawable/btn_switch_to_off_mtrl_00005" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorControlActivated" />
</item>
<item android:duration="15">
- <bitmap android:src="@drawable/btn_switch_to_off_mtrl_008" android:gravity="center" android:tint="?attr/colorControlNormal" />
+ <nine-patch android:src="@drawable/btn_switch_to_off_mtrl_00006" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorControlActivated" />
</item>
<item android:duration="15">
- <bitmap android:src="@drawable/btn_switch_to_off_mtrl_009" android:gravity="center" android:tint="?attr/colorControlNormal" />
+ <nine-patch android:src="@drawable/btn_switch_to_off_mtrl_00007" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorButtonNormal" />
</item>
<item android:duration="15">
- <bitmap android:src="@drawable/btn_switch_to_off_mtrl_010" android:gravity="center" android:tint="?attr/colorControlNormal" />
+ <nine-patch android:src="@drawable/btn_switch_to_off_mtrl_00008" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorButtonNormal" />
</item>
<item android:duration="15">
- <bitmap android:src="@drawable/btn_switch_to_off_mtrl_011" android:gravity="center" android:tint="?attr/colorControlNormal" />
+ <nine-patch android:src="@drawable/btn_switch_to_off_mtrl_00009" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorButtonNormal" />
</item>
<item android:duration="15">
- <bitmap android:src="@drawable/btn_switch_to_off_mtrl_012" android:gravity="center" android:tint="?attr/colorControlNormal" />
+ <nine-patch android:src="@drawable/btn_switch_to_off_mtrl_00010" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorButtonNormal" />
</item>
<item android:duration="15">
- <bitmap android:src="@drawable/btn_switch_to_off_mtrl_013" android:gravity="center" android:tint="?attr/colorControlNormal" />
+ <nine-patch android:src="@drawable/btn_switch_to_off_mtrl_00011" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorButtonNormal" />
</item>
<item android:duration="15">
- <bitmap android:src="@drawable/btn_switch_to_off_mtrl_014" android:gravity="center" android:tint="?attr/colorControlNormal" />
+ <nine-patch android:src="@drawable/btn_switch_to_off_mtrl_00012" android:gravity="center" android:tintMode="multiply" android:tint="?attr/colorButtonNormal" />
</item>
</animation-list>
</transition>
diff --git a/core/res/res/drawable/switch_track_material.xml b/core/res/res/drawable/switch_track_material.xml
index 6ca2489..b400644 100644
--- a/core/res/res/drawable/switch_track_material.xml
+++ b/core/res/res/drawable/switch_track_material.xml
@@ -18,19 +18,21 @@
<item android:state_enabled="false" android:state_checked="true">
<nine-patch android:src="@drawable/switch_track_mtrl_alpha"
android:tint="?attr/colorControlActivated"
- android:alpha="?attr/disabledAlpha" />
+ android:alpha="0.15" />
</item>
<item android:state_enabled="false">
<nine-patch android:src="@drawable/switch_track_mtrl_alpha"
- android:tint="?attr/colorControlNormal"
- android:alpha="?attr/disabledAlpha" />
+ android:tint="?attr/colorButtonNormal"
+ android:alpha="0.15" />
</item>
<item android:state_checked="true">
<nine-patch android:src="@drawable/switch_track_mtrl_alpha"
- android:tint="?attr/colorControlActivated" />
+ android:tint="?attr/colorControlActivated"
+ android:alpha="0.3" />
</item>
<item>
<nine-patch android:src="@drawable/switch_track_mtrl_alpha"
- android:tint="?attr/colorControlNormal" />
+ android:tint="?attr/colorButtonNormal"
+ android:alpha="0.3" />
</item>
</selector>
diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml
index 1af4d10..327782d 100644
--- a/core/res/res/values/arrays.xml
+++ b/core/res/res/values/arrays.xml
@@ -368,36 +368,30 @@
<item>@drawable/btn_rating_star_off_mtrl_alpha</item>
<item>@drawable/btn_rating_star_on_mtrl_alpha</item>
<item>@drawable/btn_star_mtrl_alpha</item>
- <item>@drawable/btn_switch_to_off_mtrl_000</item>
- <item>@drawable/btn_switch_to_off_mtrl_001</item>
- <item>@drawable/btn_switch_to_off_mtrl_002</item>
- <item>@drawable/btn_switch_to_off_mtrl_003</item>
- <item>@drawable/btn_switch_to_off_mtrl_004</item>
- <item>@drawable/btn_switch_to_off_mtrl_005</item>
- <item>@drawable/btn_switch_to_off_mtrl_006</item>
- <item>@drawable/btn_switch_to_off_mtrl_007</item>
- <item>@drawable/btn_switch_to_off_mtrl_008</item>
- <item>@drawable/btn_switch_to_off_mtrl_009</item>
- <item>@drawable/btn_switch_to_off_mtrl_010</item>
- <item>@drawable/btn_switch_to_off_mtrl_011</item>
- <item>@drawable/btn_switch_to_off_mtrl_012</item>
- <item>@drawable/btn_switch_to_off_mtrl_013</item>
- <item>@drawable/btn_switch_to_off_mtrl_014</item>
- <item>@drawable/btn_switch_to_on_mtrl_000</item>
- <item>@drawable/btn_switch_to_on_mtrl_001</item>
- <item>@drawable/btn_switch_to_on_mtrl_002</item>
- <item>@drawable/btn_switch_to_on_mtrl_003</item>
- <item>@drawable/btn_switch_to_on_mtrl_004</item>
- <item>@drawable/btn_switch_to_on_mtrl_005</item>
- <item>@drawable/btn_switch_to_on_mtrl_006</item>
- <item>@drawable/btn_switch_to_on_mtrl_007</item>
- <item>@drawable/btn_switch_to_on_mtrl_008</item>
- <item>@drawable/btn_switch_to_on_mtrl_009</item>
- <item>@drawable/btn_switch_to_on_mtrl_010</item>
- <item>@drawable/btn_switch_to_on_mtrl_011</item>
- <item>@drawable/btn_switch_to_on_mtrl_012</item>
- <item>@drawable/btn_switch_to_on_mtrl_013</item>
- <item>@drawable/btn_switch_to_on_mtrl_014</item>
+ <item>@drawable/btn_switch_to_off_mtrl_00001</item>
+ <item>@drawable/btn_switch_to_off_mtrl_00002</item>
+ <item>@drawable/btn_switch_to_off_mtrl_00003</item>
+ <item>@drawable/btn_switch_to_off_mtrl_00004</item>
+ <item>@drawable/btn_switch_to_off_mtrl_00005</item>
+ <item>@drawable/btn_switch_to_off_mtrl_00006</item>
+ <item>@drawable/btn_switch_to_off_mtrl_00007</item>
+ <item>@drawable/btn_switch_to_off_mtrl_00008</item>
+ <item>@drawable/btn_switch_to_off_mtrl_00009</item>
+ <item>@drawable/btn_switch_to_off_mtrl_00010</item>
+ <item>@drawable/btn_switch_to_off_mtrl_00011</item>
+ <item>@drawable/btn_switch_to_off_mtrl_00012</item>
+ <item>@drawable/btn_switch_to_on_mtrl_00001</item>
+ <item>@drawable/btn_switch_to_on_mtrl_00002</item>
+ <item>@drawable/btn_switch_to_on_mtrl_00003</item>
+ <item>@drawable/btn_switch_to_on_mtrl_00004</item>
+ <item>@drawable/btn_switch_to_on_mtrl_00005</item>
+ <item>@drawable/btn_switch_to_on_mtrl_00006</item>
+ <item>@drawable/btn_switch_to_on_mtrl_00007</item>
+ <item>@drawable/btn_switch_to_on_mtrl_00008</item>
+ <item>@drawable/btn_switch_to_on_mtrl_00009</item>
+ <item>@drawable/btn_switch_to_on_mtrl_00010</item>
+ <item>@drawable/btn_switch_to_on_mtrl_00011</item>
+ <item>@drawable/btn_switch_to_on_mtrl_00012</item>
<item>@drawable/btn_toggle_indicator_mtrl_alpha</item>
<item>@drawable/expander_close_mtrl_alpha</item>
<item>@drawable/expander_open_mtrl_alpha</item>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 5cb3068..d07d0ab 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -464,24 +464,48 @@
<attr name="windowEnterTransition" format="reference"/>
<!-- Reference to a Transition XML resource defining the desired Transition
+ used to move Views out of the scene when the Window is
+ preparing to close. Corresponds to
+ {@link android.view.Window#setReturnTransition(android.transition.Transition)}. -->
+ <attr name="windowReturnTransition" format="reference"/>
+
+ <!-- Reference to a Transition XML resource defining the desired Transition
used to move Views out of the Window's content Scene when launching a new Activity.
Corresponds to
{@link android.view.Window#setExitTransition(android.transition.Transition)}. -->
<attr name="windowExitTransition" format="reference"/>
<!-- Reference to a Transition XML resource defining the desired Transition
+ used to move Views in to the scene when returning from a previously-started Activity.
+ Corresponds to
+ {@link android.view.Window#setReenterTransition(android.transition.Transition)}. -->
+ <attr name="windowReenterTransition" format="reference"/>
+
+ <!-- Reference to a Transition XML resource defining the desired Transition
used to move shared elements transferred into the Window's initial content Scene.
Corresponds to {@link android.view.Window#setSharedElementEnterTransition(
android.transition.Transition)}. -->
<attr name="windowSharedElementEnterTransition" format="reference"/>
<!-- Reference to a Transition XML resource defining the desired Transition
+ used to move shared elements transferred back to a calling Activity.
+ Corresponds to {@link android.view.Window#setSharedElementReturnTransition(
+ android.transition.Transition)}. -->
+ <attr name="windowSharedElementReturnTransition" format="reference"/>
+
+ <!-- Reference to a Transition XML resource defining the desired Transition
used when starting a new Activity to move shared elements prior to transferring
to the called Activity.
Corresponds to {@link android.view.Window#setSharedElementExitTransition(
android.transition.Transition)}. -->
<attr name="windowSharedElementExitTransition" format="reference"/>
+ <!-- Reference to a Transition XML resource defining the desired Transition
+ used for shared elements transferred back to a calling Activity.
+ Corresponds to {@link android.view.Window#setSharedElementReenterTransition(
+ android.transition.Transition)}. -->
+ <attr name="windowSharedElementReenterTransition" format="reference"/>
+
<!-- Flag indicating whether this Window's transition should overlap with
the exiting transition of the calling Activity. Corresponds to
{@link android.view.Window#setAllowEnterTransitionOverlap(boolean)}. -->
@@ -1751,30 +1775,54 @@
or a fraction of the screen size in that dimension. -->
<attr name="windowFixedHeightMajor" format="dimension|fraction" />
<attr name="windowOutsetBottom" format="dimension" />
- <!-- Reference to a TransitionManager XML resource defining the desired Transition
+ <!-- Reference to a Transition XML resource defining the desired Transition
used to move Views into the initial Window's content Scene. Corresponds to
{@link android.view.Window#setEnterTransition(android.transition.Transition)}. -->
<attr name="windowEnterTransition"/>
- <!-- Reference to a TransitionManager XML resource defining the desired Transition
+ <!-- Reference to a Transition XML resource defining the desired Transition
+ used to move Views out of the scene when the Window is
+ preparing to close. Corresponds to
+ {@link android.view.Window#setReturnTransition(android.transition.Transition)}. -->
+ <attr name="windowReturnTransition"/>
+
+ <!-- Reference to a Transition XML resource defining the desired Transition
used to move Views out of the Window's content Scene when launching a new Activity.
Corresponds to
{@link android.view.Window#setExitTransition(android.transition.Transition)}. -->
<attr name="windowExitTransition"/>
- <!-- Reference to a TransitionManager XML resource defining the desired Transition
+ <!-- Reference to a Transition XML resource defining the desired Transition
+ used to move Views in to the scene when returning from a previously-started Activity.
+ Corresponds to
+ {@link android.view.Window#setReenterTransition(android.transition.Transition)}. -->
+ <attr name="windowReenterTransition"/>
+
+ <!-- Reference to a Transition XML resource defining the desired Transition
used to move shared elements transferred into the Window's initial content Scene.
Corresponds to {@link android.view.Window#setSharedElementEnterTransition(
android.transition.Transition)}. -->
<attr name="windowSharedElementEnterTransition"/>
- <!-- Reference to a TransitionManager XML resource defining the desired Transition
+ <!-- Reference to a Transition XML resource defining the desired Transition
+ used to move shared elements transferred back to a calling Activity.
+ Corresponds to {@link android.view.Window#setSharedElementReturnTransition(
+ android.transition.Transition)}. -->
+ <attr name="windowSharedElementReturnTransition"/>
+
+ <!-- Reference to a Transition XML resource defining the desired Transition
used when starting a new Activity to move shared elements prior to transferring
to the called Activity.
Corresponds to {@link android.view.Window#setSharedElementExitTransition(
android.transition.Transition)}. -->
<attr name="windowSharedElementExitTransition"/>
+ <!-- Reference to a Transition XML resource defining the desired Transition
+ used for shared elements transferred back to a calling Activity.
+ Corresponds to {@link android.view.Window#setSharedElementReenterTransition(
+ android.transition.Transition)}. -->
+ <attr name="windowSharedElementReenterTransition"/>
+
<!-- Flag indicating whether this Window's transition should overlap with
the exiting transition of the calling Activity. Corresponds to
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 9acd4a6..d8f9665 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2264,6 +2264,11 @@
<public type="attr" name="toolbarStyle" />
<public type="attr" name="windowClipToOutline" />
<public type="attr" name="datePickerDialogTheme" />
+ <public type="attr" name="showText" />
+ <public type="attr" name="windowReturnTransition" />
+ <public type="attr" name="windowReenterTransition" />
+ <public type="attr" name="windowSharedElementReturnTransition" />
+ <public type="attr" name="windowSharedElementReenterTransition" />
<public-padding type="dimen" name="l_resource_pad" end="0x01050010" />
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index 61dff1b..9ee377f 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -537,12 +537,9 @@ please see styles_device_defaults.xml.
<style name="Widget.Material.CompoundButton.Switch">
<item name="track">@drawable/switch_track_material</item>
<item name="thumb">@drawable/switch_thumb_material_anim</item>
- <item name="splitTrack">true</item>
<item name="switchTextAppearance">@style/TextAppearance.Material.Widget.Switch</item>
<item name="textOn">@string/capital_on</item>
<item name="textOff">@string/capital_off</item>
- <item name="switchMinWidth">4dip</item>
- <item name="switchPadding">4dip</item>
<item name="background">?attr/selectableItemBackgroundBorderless</item>
<item name="showText">false</item>
</style>
diff --git a/data/fonts/Roboto-Black.ttf b/data/fonts/Roboto-Black.ttf
index 82bc9fc..1eb7cf2 100644
--- a/data/fonts/Roboto-Black.ttf
+++ b/data/fonts/Roboto-Black.ttf
Binary files differ
diff --git a/data/fonts/Roboto-BlackItalic.ttf b/data/fonts/Roboto-BlackItalic.ttf
index 40f8bc8..8f9da76 100644
--- a/data/fonts/Roboto-BlackItalic.ttf
+++ b/data/fonts/Roboto-BlackItalic.ttf
Binary files differ
diff --git a/data/fonts/Roboto-Bold.ttf b/data/fonts/Roboto-Bold.ttf
index 2957cd8..d3a6ed9 100644
--- a/data/fonts/Roboto-Bold.ttf
+++ b/data/fonts/Roboto-Bold.ttf
Binary files differ
diff --git a/data/fonts/Roboto-BoldItalic.ttf b/data/fonts/Roboto-BoldItalic.ttf
index 85ff2e9..49bd012 100644
--- a/data/fonts/Roboto-BoldItalic.ttf
+++ b/data/fonts/Roboto-BoldItalic.ttf
Binary files differ
diff --git a/data/fonts/Roboto-Italic.ttf b/data/fonts/Roboto-Italic.ttf
index d496291..da58461 100644
--- a/data/fonts/Roboto-Italic.ttf
+++ b/data/fonts/Roboto-Italic.ttf
Binary files differ
diff --git a/data/fonts/Roboto-Light.ttf b/data/fonts/Roboto-Light.ttf
index 1489708..9ca4e92 100644
--- a/data/fonts/Roboto-Light.ttf
+++ b/data/fonts/Roboto-Light.ttf
Binary files differ
diff --git a/data/fonts/Roboto-LightItalic.ttf b/data/fonts/Roboto-LightItalic.ttf
index 2dd300e..710c14c 100644
--- a/data/fonts/Roboto-LightItalic.ttf
+++ b/data/fonts/Roboto-LightItalic.ttf
Binary files differ
diff --git a/data/fonts/Roboto-Medium.ttf b/data/fonts/Roboto-Medium.ttf
index 8a8e89d..aaa3723 100644
--- a/data/fonts/Roboto-Medium.ttf
+++ b/data/fonts/Roboto-Medium.ttf
Binary files differ
diff --git a/data/fonts/Roboto-MediumItalic.ttf b/data/fonts/Roboto-MediumItalic.ttf
index 830a471..8c2b101 100644
--- a/data/fonts/Roboto-MediumItalic.ttf
+++ b/data/fonts/Roboto-MediumItalic.ttf
Binary files differ
diff --git a/data/fonts/Roboto-Regular.ttf b/data/fonts/Roboto-Regular.ttf
index f392d64..e5b0c83 100644
--- a/data/fonts/Roboto-Regular.ttf
+++ b/data/fonts/Roboto-Regular.ttf
Binary files differ
diff --git a/data/fonts/Roboto-Thin.ttf b/data/fonts/Roboto-Thin.ttf
index 1b58ba4..781ef3d 100644
--- a/data/fonts/Roboto-Thin.ttf
+++ b/data/fonts/Roboto-Thin.ttf
Binary files differ
diff --git a/data/fonts/Roboto-ThinItalic.ttf b/data/fonts/Roboto-ThinItalic.ttf
index 316a9e9..0ed5203 100644
--- a/data/fonts/Roboto-ThinItalic.ttf
+++ b/data/fonts/Roboto-ThinItalic.ttf
Binary files differ
diff --git a/data/fonts/RobotoCondensed-Bold.ttf b/data/fonts/RobotoCondensed-Bold.ttf
index 194a710..9f34ffe 100644
--- a/data/fonts/RobotoCondensed-Bold.ttf
+++ b/data/fonts/RobotoCondensed-Bold.ttf
Binary files differ
diff --git a/data/fonts/RobotoCondensed-BoldItalic.ttf b/data/fonts/RobotoCondensed-BoldItalic.ttf
index 013640f..c8dea7a 100644
--- a/data/fonts/RobotoCondensed-BoldItalic.ttf
+++ b/data/fonts/RobotoCondensed-BoldItalic.ttf
Binary files differ
diff --git a/data/fonts/RobotoCondensed-Italic.ttf b/data/fonts/RobotoCondensed-Italic.ttf
index 42c48aa..09f4f5b 100644
--- a/data/fonts/RobotoCondensed-Italic.ttf
+++ b/data/fonts/RobotoCondensed-Italic.ttf
Binary files differ
diff --git a/data/fonts/RobotoCondensed-Light.ttf b/data/fonts/RobotoCondensed-Light.ttf
index 5ca51e8..c33a3e1 100644
--- a/data/fonts/RobotoCondensed-Light.ttf
+++ b/data/fonts/RobotoCondensed-Light.ttf
Binary files differ
diff --git a/data/fonts/RobotoCondensed-LightItalic.ttf b/data/fonts/RobotoCondensed-LightItalic.ttf
index b788bd7..adfefc4 100644
--- a/data/fonts/RobotoCondensed-LightItalic.ttf
+++ b/data/fonts/RobotoCondensed-LightItalic.ttf
Binary files differ
diff --git a/data/fonts/RobotoCondensed-Regular.ttf b/data/fonts/RobotoCondensed-Regular.ttf
index 573100b..d750454 100644
--- a/data/fonts/RobotoCondensed-Regular.ttf
+++ b/data/fonts/RobotoCondensed-Regular.ttf
Binary files differ
diff --git a/docs/html/google/google_toc.cs b/docs/html/google/google_toc.cs
index b770135..7cce86b 100644
--- a/docs/html/google/google_toc.cs
+++ b/docs/html/google/google_toc.cs
@@ -138,9 +138,6 @@
<li><a href="<?cs var:toroot?>google/play/billing/billing_admin.html">
<span class="en">Administering In-app Billing</span></a>
</li>
- <li><a href="<?cs var:toroot?>google/play/billing/gp-purchase-status-api.html">
- <span class="en">Purchase Status API</span></a>
- </li>
<li><a href="<?cs var:toroot?>google/play/billing/versions.html">
<span class="en">Version Notes</span></a>
</li>
@@ -205,7 +202,9 @@
<li><a href="<?cs var:toroot ?>google/play/filters.html">
<span class="en">Filters on Google Play</span></a>
</li>
-
+ <li><a href="<?cs var:toroot?>google/play/billing/gp-purchase-status-api.html">
+ <span class="en">Google Play Developer API</span></a>
+ </li>
<li><a href="<?cs var:toroot ?>google/play/publishing/multiple-apks.html">
<span class="en">Multiple APK Support</span></a>
</li>
diff --git a/docs/html/google/play/billing/billing_subscriptions.jd b/docs/html/google/play/billing/billing_subscriptions.jd
index d0e6dc5..3c72da1 100644
--- a/docs/html/google/play/billing/billing_subscriptions.jd
+++ b/docs/html/google/play/billing/billing_subscriptions.jd
@@ -24,6 +24,7 @@ directly from Google Play.</li>
<li><a href="#administering">Configuring Subscriptions Items</a></li>
<li><a href="#cancellation">Cancellation</a></li>
<li><a href="#payment">Payment Processing</a></li>
+ <li><a href="#strategies">Purchase Verification Strategies</a></li>
</ol>
<h2>See also</h2>
<ol>
@@ -325,6 +326,21 @@ each recurring transaction by appending an integer as follows: </p>
{@code orderId} field of the {@code INAPP_PURCHASE_DATA} JSON field (in V3)
or the {@code PURCHASE_STATE_CHANGED} intent (in V2).</p>
+<h2 id="strategies">Purchase Verification Strategies</h2>
+
+<p>In a typical scenario, your app verifies the order status for new purchases
+to ensure that they are valid before granting access to the purchased
+content.</p>
+
+<p>To verify a purchase, the app passes the purchase token and other details up
+to your backend servers, which verifies them directly with Google Play using the
+Purchase Status API. If the backend server determines that the purchase is
+valid, it notifies the app and grants access to the content.</p>
+
+<p>Keep in mind that users will want the ability to use your app at any time,
+including when there may be no network connection available. Make sure that your
+approach to purchase verification accounts for the offline use-case.</p>
+
<h2 id="play-dev-api">Google Play Android Developer API</h2>
<p>Google Play offers an HTTP-based API that lets you remotely query the
@@ -333,4 +349,4 @@ API is designed to be used from your backend servers as a way of securely
managing subscriptions, as well as extending and integrating subscriptions with
other services.</p>
-<p>For complete information, see <a href="{@docRoot}google/play/billing/gp-purchase-status-api.html">Purchase Status API</a>.</p> \ No newline at end of file
+<p>For complete information, see <a href="{@docRoot}google/play/billing/gp-purchase-status-api.html">Purchase Status API</a>.</p>
diff --git a/docs/html/google/play/billing/gp-purchase-status-api.jd b/docs/html/google/play/billing/gp-purchase-status-api.jd
index d272301..fa0c397 100644
--- a/docs/html/google/play/billing/gp-purchase-status-api.jd
+++ b/docs/html/google/play/billing/gp-purchase-status-api.jd
@@ -1,38 +1,114 @@
-page.title=Purchase Status API
-page.tags=In-app Billing,Google Play,inapp billing,in app billing,iab,billing
+page.title=Google Play Developer API
+page.tags="In-app Billing", "Google Play", "inapp billing", "in app billing", "iab", "billing", "publishing"
+
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>In this document</h2>
+ <!-- TODO: Update TOC -->
<ol>
- <li><a href="#overview">Overview</a></li>
- <li><a href="#using">Using the API</a></li>
- <li><a href="#strategies">Verification Strategies</a></li>
- <li><a href="#practices">Using the API Efficiently</a></li>
+ <li><a href="#publishing_api_overview">Publishing API</a>
+ <li><a href="#subscriptions_api_overview">Subscriptions and In-App
+ Purchases API</a></li>
+ <li><a href="#using">Using the API</a>
+ <li><a href="#edits">Staged Edits</a></li>
+ <li><a href="#practices">Using the API Efficiently</a>
+ <ol>
+ <li><a href="#quota">Quota</a></li>
+ </ol>
+ </li>
</ol>
+
<h2>See also</h2>
<ol>
- <li><a href="https://developers.google.com/android-publisher/v1_1/">Google Play Android Developer API</a></li>
+ <li><a href="https://developers.google.com/android-publisher/">Google Play
+ Developer API</a> documentation</li>
+ <li><a href="https://support.google.com/googleplay/android-developer/answer/6071616">Google
+ Help Center</a> overview of the Google Play Developer API</li>
</ol>
</div>
</div>
-<p>Google Play provides an HTTP-based Purchase Status API that lets
-you remotely query the status of a specific in-app product or subscription,
-or cancel an active subscription. The API is designed to be used from your
-backend servers as a way of securely managing in-app products and
-subscriptions, as well as extending and integrating them with other services.</p>
+<p>The Google Play Developer API is a REST-based web service that allows you to perform publishing
+and app-management tasks. You can use this API to integrate your publishing
+operations with your release-management process.</p>
+
+<p>Not all developers will need to use these APIs&mdash;in most cases you will
+continue to manage your apps directly using the Google Play Developer Console.
+However, if you have a large number of APKs to manage, or have to track user
+purchases and subscriptions, you may find this API very useful.</p>
+
+<p>Using the Google Play Developer API, you can automate a variety of
+app-management tasks, including:</p>
+
+<ul>
+<li>Uploading and releasing new versions of your app</li>
+<li>Editing your app Google Play Store listings, including localized text and
+ graphics</li>
+<li>Managing your in-app product catalog, your products purchase status and your
+ app subscriptions</li>
+</li>
+</ul>
+
-<h2 id="overview">Overview</h2>
-<p>With the Purchase Status API you can quickly retrieve the details of any
-purchase using a standard GET request. In the request you supply information
-about the purchase &mdash; app package name, purchase or subscription ID,
-and the purchase token. The server responds with a JSON object describing
-the associated purchase details, order status, developer payload, and other
-information.</p>
+<p>The Google Play Developer API lets you focus on designing and developing your
+app, while spending less time and effort managing your releases, even as you
+grow to new markets.</p>
+
+<p>The Google Play Developer API includes two components:</p>
+
+<ul>
+<li>The <a href="#publishing_api_overview">Publishing API</a> lets you upload and publish
+ apps, and perform other publishing-related tasks.</li>
+<li>The <a href="#subscriptions_api_overview">Subscriptions and In-App Purchases
+ API</a> lets you manage in-app purchases and subscriptions. (This was
+ previously known as the "Purchase Status API".)</li>
+</ul>
+
+<h2 id="publishing_api_overview">Publishing API</h2>
+
+<p>
+The Google Play Developer Publishing API allows you to automate frequent tasks
+having to do with app distribution. This provides functions
+similar to those available to a developer through the Google Play
+Developer Console, such
+as:
+</p>
+
+<ul><li>Uploading new versions of an app</li>
+<li>Releasing apps, by assigning APKs to various <em>Tracks</em> (alpha, beta,
+ staged rollout, or production)</li>
+<li>Creating and modifying Google Play Store listings, including localized text
+ and graphics and multi-device screenshots</li></ul>
+
+<p>Those tasks are performed using the
+<a href="#edits">edits</a>
+functionality, which takes a transactional approach to making changes &mdash;
+you bundle several changes into a single draft edit, then commit the changes all
+at once. (None of the changes take effect until the edit is committed.)</p>
+
+<p class="note"><strong>Note:</strong> Not all developers will need to use this
+API. All the functionality provided by the API is also available through the
+Google Play
+Developer Console. However, this API lets you integrate your app and listing
+update process with your existing tools, which will be very useful for some
+developers. In particular, if you have a large number of APKs to manage, or
+localized listings in many different locales, you may find this API invaluable.
+</p>
+
+<h2 id="subscriptions_api_overview">Subscriptions and In-App Purchases API</h2>
+
+<p>The API allows you to manage your app's catalog of in-app products and
+subscriptions. In addition, with the Subscriptions and In-App Purchases API you
+can quickly retrieve the
+details of any purchase using a standard GET request. In the request you supply
+information about the purchase &mdash; app package name, purchase or
+subscription ID, and the purchase token. The server responds with a JSON object
+describing the associated purchase details, order status, developer payload, and
+other information.</p>
<p>You can use the Purchase Status API in several ways, such as for reporting
and reconciliation of individual orders and for verifying purchases and
@@ -40,101 +116,85 @@ subscription expirations. You can also use the API to learn about cancelled
orders and confirm whether in-app products have been consumed, including
whether they were consumed before being cancelled.</p>
-<p>For subscriptions, in addition to querying for order status and expiration,
-you can use the Purchase Status API to remotely cancel a subscription. This is a
-convenient way to manage cancellations on behalf of customers, without
-requiring them to manage the cancellation themselves on their Android devices.</p>
-
-<p>If you plan to use the Purchase Status API, keep in mind that:</p>
-<ul><li>You can use the API to check the status of individual items only
-&mdash; bulk requests for order status are not supported at this time.</li>
-<li>You can query for the details of orders placed on or after 12 June 2013,
-but not for orders placed earlier.</li>
-<li>You can query purchases of any item type made with the In-app
-Billing v3 API, or purchases of managed items made with In-app Billing v1 and
-v2. You can not use the Purchase Status API to query purchases of unmanaged items
-made with In-app Billing v1 or v2.</li>
-</ul>
+<p class="note"><strong>Note:</strong> The Subscriptions and In-App
+Purchases API does not use the new, transactional "edits" functionality used by
+the <a href="#publishing_api_overview">Publishing API</a>. Methods for the
+<a href="https://developers.google.com/android-publisher/api-ref/inappproducts">Inappproducts</a>,
+<a href="https://developers.google.com/android-publisher/api-ref/purchases/products">Purchases.products</a>,
+and <a href="https://developers.google.com/android-publisher/api-ref/purchases/subscriptions">Purchases.subscriptions</a>
+resources take effect immediately. Each resource's API reference page notes
+specifically whether the methods for that resource use the "edits"
+model.</p>
<p>The Purchase Status API is part of the <a
-href="https://developers.google.com/android-publisher/v1_1/">Google Play Android
-Developer API v1.1</a>, available through the Google Developers Console. The new version
-of the API supersedes the v1 API, which is deprecated. If you are using the v1
-API, please migrate your operations to the v1.1 API as soon as possible.</p>
-
+href="https://developers.google.com/android-publisher/">Google Play Developer
+API</a> v. 2.0, available through the Google Developers Console.</p>
<h2 id="using">Using the API</h2>
-<p>To use the API, you must first register a project at the <a
-href="https://cloud.google.com/console">Google Developers Console</a> and receive
-a Client ID and shared secret that your app will present when calling the
-API. All calls are authenticated with OAuth 2.0.</p>
+<p>To start making API calls, you’ll set up and manage the Google Play Developer
+API directly from the <a href="https://play.google.com/apps/publish/">Google
+Play Developer Console</a>. The API can only be managed by the owner of your
+Google Play Developer account.</p>
-<p>Once your app is registered, you can access the API directly, using standard
-HTTP methods to retrieve and manipulate resources. The API is built on a RESTful
-design that uses HTTP and JSON. so any standard web stack can send requests and
-parse the responses. However, if you don’t want to send HTTP requests and parse
-responses manually, you can access the API using the Google APIs Client
-Libraries, which provide better language integration, improved security,
-and support for making calls that require user authorization.</p>
+<p>To access the API, you'll need to:</p>
-<p>For more information about the API and how to access it through the Google
-APIs Client Libraries, see the documentation at:</p>
-
-<p style="margin-left:1.5em;"><a
-href="https://developers.google.com/android-publisher/v1_1/">https://developers.
-google.com/android-publisher/v1_1/</a></p>
-
-<h3 id="quota">Quota</h3>
-
-<p>Applications using the Google Play Android Developer API are limited to an
-initial courtesy usage quota of <strong>200,000 requests per day</strong> (per
-application). This should provide enough access for normal
-subscription-validation needs, assuming that you follow the recommendation in
-this section.</p>
-
-<p>If you need to request a higher limit for your application, see the
-instructions in the <a
-href="https://developers.google.com/console/help/new/#trafficcontrols">Google Developers
-Console Help</a>.
-Also, please read the section below on design best practices for minimizing your
-use of the API.</p>
+<ol><li>Set up a new or existing API project</li>
+<li>Set up one or more authorized clients, which can be either:
+<ul>
+ <li><a href="https://developers.google.com/accounts/docs/OAuth2">OAuth
+ clients</a></li>
+ <li><a href="https://developers.google.com/accounts/docs/OAuth2ServiceAccount">
+ service account</a></li>
+</ul></li></ol>
-<h3 id="auth">Authorization</h3>
+<p>For full details, see the Google Play Developer API
+<a href="https://developers.google.com/android-publisher/getting_started">Getting
+Started</a> page.</p>
-<p>Calls to the Google Play Android Developer API require authorization. Google
-uses the OAuth 2.0 protocol to allow authorized applications to access user
-data. To learn more, see <a
-href="https://developers.google.com/android-publisher/authorization">Authorization</a>
-in the Google Play Android Developer API documentation.</p>
+<h2 id="edits">Staged Edits</h2>
-<h2 id="strategies">Purchase Verification Strategies</h2>
+<p>The Google Play Developer Publishing API Edits methods allow you to prepare
+and commit changes to your Google Play apps. Once your update is ready to go,
+you can deploy it with a single operation. The changes you can make include:</p>
-<p>In a typical scenario, your app verifies the order status for new purchases
-to ensure that they are valid before granting access to the purchased content.</p>
+<ul>
+ <li>Uploading one or more APKs</li>
+ <li>Assigning different APKs to different “tracks”: alpha, beta, staged
+ rollout, and production</li>
+ <li>Creating and modifying localized store listings for the app</li>
+ <li>Uploading screenshots and other images for the app’s store listings</li>
+</ul>
-<p>To verify a purchase, the app passes the purchase token and other details up
-to your backend servers, which verifies them directly with Google Play using the
-Purchase Status API. For security reasons, the app should not normally attempt to verify
-the purchase itself using the Purchase Status API.</p>
+<p>Once all the desired changes have been staged, they are all committed with a
+single operation.</p>
-<p>If the backend server determines that the purchase is valid, it notifies the
-app and grants access to the content. For improved performance, the backend servers
-should store the purchase details and order status in a local database, updated at
-intervals or as-needed.</p>
+<p>For full details on staged edits, see the Google Play Developer API
+<a href="https://developers.google.com/android-publisher/edits/">Edits</a>
+page.</p>
-<p>Keep in mind that users will want the ability to use your app at any time, including
-when there may be no network connection available. Make sure that your approach to
-purchase verification accounts for the offline use-case.</p>
+<p class="note"><strong>Note:</strong> The new, transactional "edits"
+functionality is only used by the <a href="#publishing_api_overview">Publishing
+API</a>. Methods for the <a href="#subscriptions_api_overview">Subscriptions and
+In-App Purchases API</a> take effect immediately. Each resource's API reference
+page notes specifically whether the methods for that resource use the "edits"
+model.</p>
<h2 id="practices">Using the API Efficiently</h2>
-<p>Access to the Google Play Android Developer API is regulated to help ensure a
-high-performance environment for all applications that use it. While you can
+<p>Access to the Google Play Developer API is regulated to help ensure a
+high-performance environment for all applications that use it (as described in
+<a href="#quota">Quota</a>). While you can
request a higher daily quota for your application, we highly recommend that you
-minimize your access using the techniques below. </p>
+minimize your access using these techniques: </p>
<ul>
+ <li><em>Limit the number of app updates</em> &mdash; Do not publish alpha or beta
+ updates more frequently than once a day. (Production apps should be updated
+ even less frequently than that.) Every update costs your users time and
+ possibly money. If you update too frequently, users will start ignoring
+ updates, or even uninstall the product. (Of course, if there's a major problem
+ with your app, go ahead and fix it.)</li>
<li><em>Query the Purchase Status API for new purchases only</em> &mdash; At
purchase, your app can pass the purchase token and other details to your backend
servers, which can use the Purchase Status API to verify the purchase.</li>
@@ -163,6 +223,15 @@ minimize your access using the techniques below. </p>
</ul>
<p>By following those general guidelines, your implementation will offer the
-best possible performance for users and minimize use of the <a
-href="https://developers.google.com/android-publisher/v1_1/">Google Play Android
-Developer API</a>.</p>
+best possible performance for users.</p>
+
+<h3 id="quota">Quota</h3>
+
+<p>Applications using the Google Play Developer API are limited to an
+initial courtesy usage quota of <strong>200,000 requests per day</strong> (per
+application). This should provide enough access for publishing activities and
+normal subscription-validation needs.</p>
+
+<p>If you need to request a higher limit for your application, use the "Request
+more" link on the <strong>Quotas</strong>
+pane of the Google Developers Console.</p>
diff --git a/docs/html/google/play/billing/index.jd b/docs/html/google/play/billing/index.jd
index dce20cb..18b1523 100644
--- a/docs/html/google/play/billing/index.jd
+++ b/docs/html/google/play/billing/index.jd
@@ -14,7 +14,11 @@ and features, and more. You can use In-app Billing to sell products as</p>
<div class="sidebox">
<h2><strong>New in In-App Billing</strong></h2>
<ul>
- <li><strong>Purchase Status API</strong>&mdash;The <a href="{@docRoot}google/play/billing/gp-purchase-status-api.html">Purchase Status API</a> lets you query the status of in-app product or subscription purchases. </li>
+ <li><strong>Google Play Developer API</strong>&mdash;The
+ <a href="{@docRoot}google/play/billing/gp-purchase-status-api.html">Google
+ Play Developer API</a> allows you to perform a number of publishing and
+ app-management tasks. It includes the functionality previously known as the
+ <em>Purchase Status API.</em> </li>
<li><strong>In-app Billing Version 3</strong>&mdash;The <a href="{@docRoot}google/play/billing/api.html">latest version</a> of In-app Billing features a synchronous API that is easier to implement and lets you manage in-app products and subscriptions more effectively.</li>
<li><strong>Subscriptions now supported in Version 3</strong>&mdash;You can query and launch purchase flows for subscription items using the V3 API.</li>
<li><strong>Free trials</strong>&mdash;You can now offer users a configurable <a href="/google/play/billing/v2/billing_subscriptions.html#trials">free trial period</a> for your in-app subscriptions. You can set up trials with a simple change in the Developer Console&mdash;no change to your app code is needed.</li>
diff --git a/docs/html/google/play/dist.jd b/docs/html/google/play/dist.jd
index b4efe40..f1ad834 100644
--- a/docs/html/google/play/dist.jd
+++ b/docs/html/google/play/dist.jd
@@ -49,4 +49,12 @@ page.title=Google Play Distribution
<p>Protect your revenue streams and integrate policies for usage into your app.
</p><a href="{@docRoot}google/play/licensing/index.html">Learn more &raquo;</a>
</div>
-</div> \ No newline at end of file
+ <div class="layout-content-col span-6">
+ <h4>
+ Google Play Developer API
+ </h4>
+ <p>Integrate your publishing operations with your release-management
+ process.
+ </p><a href="{@docRoot}google/play/billing/gp-purchase-status-api.html">Learn more &raquo;</a>
+ </div>
+</div>
diff --git a/docs/html/preview/preview_toc.cs b/docs/html/preview/preview_toc.cs
index a505905..819976e 100644
--- a/docs/html/preview/preview_toc.cs
+++ b/docs/html/preview/preview_toc.cs
@@ -68,6 +68,8 @@
Recommendations</a></li>
</ul>
</li>
+ <li><a href="<?cs var:toroot ?>preview/tv/tif/index.html">
+ TV Input Framework</a></li>
<li><a href="<?cs var:toroot ?>preview/tv/games/index.html">
Games on TV</a></li>
<li><a href="<?cs var:toroot ?>preview/tv/start/hardware-features.html">
diff --git a/docs/html/preview/tv/adt-1/index.jd b/docs/html/preview/tv/adt-1/index.jd
index 882f421..b37a55a 100644
--- a/docs/html/preview/tv/adt-1/index.jd
+++ b/docs/html/preview/tv/adt-1/index.jd
@@ -52,16 +52,16 @@ Android TV platform.</p>
</p>
<p>Unplug the included power cable from the back of ADT-1. The device does not have an on/off
switch. However, ADT-1 will begin sleeping (daydream) based on user settings in
- <strong>Settings &gt; Display &gt; Daydream</strong>.
+ <strong>Settings &gt; Device &gt; Display &gt; Daydream</strong>.
</p>
<p>
<strong>How do I connect to the network?</strong>
</p>
<p>ADT-1 has both wireless and Ethernet for connecting to your network. To change your wireless
- network, go to <strong>Settings -&gt; Wi-Fi</strong>. To use an Ethernet network connection,
- simply plug an Ethernet cable (that is connected to your network) into the port on the back of
- ADT-1.</p>
+ network, go to <strong>Settings &gt; Device &gt; Wi-Fi</strong>. To use an Ethernet network
+ connection, simply plug an Ethernet cable (that is connected to your network) into the port on
+ the back of ADT-1.</p>
<p>
<strong>How do I use the developer cable?</strong>
@@ -70,6 +70,35 @@ Android TV platform.</p>
power port on the back of ADT-1, a standard male USB-A connector that connects your PC, and a
small, female power connector that the included power supply plugs into.</p>
+<p class="note">
+ <strong>Note:</strong> Make sure you have enabled USB debugging in <strong>Settings &gt;
+ Preferences &gt; Developer options &gt; Debugging &gt; USB debugging</strong>, so that you can
+ use the Android Debug Bridge (adb) to connect with the ADT-1 device.
+</p>
+
+<p id="adb-tcp">
+ <strong>Can I connect without a developer cable?</strong>
+</p>
+<p>
+ Yes. The ADT-1 device is enabled for Android Debug Bridge (adb) connections over TCP/IP. To
+ connect to the ADT-1 device using this method:
+</p>
+<ol>
+ <li>Make sure that your development computer and the ADT-1 device are on the same network.</li>
+ <li>Determine the IP address of the ADT-1 device by navigating to <strong>Settings &gt;
+ Device &gt; Wi-Fi &gt; your-network-name &gt; Status info</strong>.</li>
+ <li>Connect to the ADT-1 device using the following adb command:
+<pre>
+$ adb connect &lt;ip-address-for-adt-1&gt;:4321
+</pre>
+ </li>
+</ol>
+
+<p class="note">
+ <strong>Note:</strong> Make sure you have enabled USB debugging in <strong>Settings &gt;
+ Preferences &gt; Developer options &gt; Debugging &gt; USB debugging</strong>, so that you can
+ use the Android Debug Bridge (adb) to connect with the ADT-1 device.
+</p>
<h3 id="input">User Input</h3>
@@ -179,8 +208,8 @@ Android TV platform.</p>
<strong>How do I register my ADT-1 in order to run my apps?</strong>
</p>
<ol>
- <li>Go to <strong>Settings &gt; Google Cast</strong> and turn on developer support, allowing the
- ADT-1 device to send its serial number to Google.</li>
+ <li>Go to <strong>Settings &gt; Device &gt; Google Cast</strong> and turn on developer support,
+ allowing the ADT-1 device to send its serial number to Google.</li>
<li>Register your ADT-1 device in the Google Cast Developer Console, using the 12 character
serial number engraved on the back of the ADT-1.</li>
</ol>
@@ -203,8 +232,8 @@ Android TV platform.</p>
<p>
<strong>Why doesn't the on-screen keyboard come up?</strong>
</p>
-<p>Enable the keyboard in the device Settings. Go to <strong>Settings &gt; Keyboard &gt; Current
- keyboard</strong> and choose <strong>Leanback keyboard</strong>.
+<p>Enable the keyboard in the device Settings. Go to <strong>Settings &gt; Preferences &gt;
+ Keyboard &gt; Current keyboard</strong> and choose <strong>Leanback keyboard</strong>.
<p>
<strong>How do I perform a hardware reboot?</strong>
@@ -221,8 +250,8 @@ Android TV platform.</p>
data, downloaded apps, app data, and account settings.
</p>
-<p>From the home screen, go to <strong>Settings &gt; Device &gt; Factory data reset</strong>, and
- select <strong>Reset device</strong>.
+<p>From the home screen, go to <strong>Settings &gt; Device &gt; Storage &amp; Reset</strong>, and
+ select <strong>Factory data reset</strong>.
</p>
<p>
@@ -279,4 +308,3 @@ read this information before using the device:</p>
<li><a href="regulatory.html">Regulatory Disclosures</a></li>
<li><a href="safety.html">Important Safety Information</a></li>
</ul>
-
diff --git a/docs/html/preview/tv/images/tif-overview.png b/docs/html/preview/tv/images/tif-overview.png
new file mode 100644
index 0000000..197775e
--- /dev/null
+++ b/docs/html/preview/tv/images/tif-overview.png
Binary files differ
diff --git a/docs/html/preview/tv/tif/index.jd b/docs/html/preview/tv/tif/index.jd
new file mode 100644
index 0000000..ef02def
--- /dev/null
+++ b/docs/html/preview/tv/tif/index.jd
@@ -0,0 +1,38 @@
+page.title=TV Input Framework
+page.tags=tif
+
+@jd:body
+
+<p>
+ Watching live television shows and other continuous, channel-based content is a big part of the
+ TV experience. Android supports receiving and playback of live video content through the TV Input
+ Framework. This framework provides a unified method for receiving audio and video channel content
+ from hardware sources, such as HDMI ports and built-in-tuners, and software sources, such as
+ video streamed over the internet.
+</p>
+<p>
+ The framework enables developers to define live TV input sources by implementing a TV input
+ service. This service publishes a list of channels and programs to the TV Provider. The live TV
+ app on a TV device gets the list of available channels and programs from the TV Provider and
+ displays them to a user. When a user selects a specific channel, the live TV app creates a
+ session for the associated TV input service through the TV Input Manager, and tells the TV input
+ service to tune to the requested channel and play the content to a display surface provided by
+ the TV app.
+</p>
+
+<img src="{@docRoot}preview/tv/images/tif-overview.png" id="figure1">
+<p class="img-caption">
+ <strong>Figure 1.</strong> Functional diagram of the TV Input Framework
+</p>
+
+<p>
+ The TV Input Framework is designed to provide access to a wide variety of live TV input sources
+ and bring them together in a single user interface for users to browse, view, and enjoy content.
+ Building a TV input service for your content can help make it more accessible on TV devices.
+</p>
+
+<p>
+ The APIs for the TV Input Framework are available in the L Developer Preview and you can
+ review them in the preview API reference docs. However, more changes are planned, so stay tuned
+ for additional information with the official Android platform launch.
+</p>
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 58a1bf2..ec862f8 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -51,6 +51,7 @@ public class Paint {
private float mInvCompatScaling;
private Locale mLocale;
+ private String mFontFeatureSettings;
/**
* @hide
@@ -474,6 +475,7 @@ public class Paint {
mBidiFlags = BIDI_DEFAULT_LTR;
setTextLocale(Locale.getDefault());
setElegantTextHeight(false);
+ mFontFeatureSettings = null;
}
/**
@@ -513,6 +515,7 @@ public class Paint {
mBidiFlags = paint.mBidiFlags;
mLocale = paint.mLocale;
+ mFontFeatureSettings = paint.mFontFeatureSettings;
}
/** @hide */
@@ -1283,6 +1286,34 @@ public class Paint {
}
/**
+ * Get font feature settings. Default is null.
+ *
+ * @return the paint's currently set font feature settings.
+ * @hide
+ */
+ public String getFontFeatureSettings() {
+ return mFontFeatureSettings;
+ }
+
+ /**
+ * Set font feature settings.
+ *
+ * The format is the same as the CSS font-feature-settings attribute:
+ * http://dev.w3.org/csswg/css-fonts/#propdef-font-feature-settings
+ *
+ * @param settings the font feature settings string to use, may be null.
+ * @hide
+ */
+ public void setFontFeatureSettings(String settings) {
+ if (settings != null && settings.equals(""))
+ settings = null;
+ if ((settings == null && mFontFeatureSettings == null)
+ || (settings != null && settings.equals(mFontFeatureSettings))) return;
+ mFontFeatureSettings = settings;
+ native_setFontFeatureSettings(mNativePaint, settings);
+ }
+
+ /**
* Return the distance above (negative) the baseline (ascent) based on the
* current typeface and text size.
*
@@ -2259,4 +2290,6 @@ public class Paint {
private static native float native_getLetterSpacing(long native_object);
private static native void native_setLetterSpacing(long native_object,
float letterSpacing);
+ private static native void native_setFontFeatureSettings(long native_object,
+ String settings);
}
diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
index eb313ae..3397e94 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -245,9 +245,8 @@ public class NinePatchDrawable extends Drawable {
final int restoreAlpha;
if (mNinePatchState.mBaseAlpha != 1.0f) {
- final Paint p = getPaint();
- restoreAlpha = p.getAlpha();
- p.setAlpha((int) (restoreAlpha * mNinePatchState.mBaseAlpha + 0.5f));
+ restoreAlpha = mPaint.getAlpha();
+ mPaint.setAlpha((int) (restoreAlpha * mNinePatchState.mBaseAlpha + 0.5f));
} else {
restoreAlpha = -1;
}
@@ -445,6 +444,16 @@ public class NinePatchDrawable extends Drawable {
// Hey, now might be a good time to actually load optical bounds!
bitmap.getOpticalInsets(opticalInsets);
+ // Sanity check for valid padding when we have optical insets.
+ if (padding.left < opticalInsets.left) {
+ padding.left = opticalInsets.left;
+ padding.right = opticalInsets.right;
+ }
+ if (padding.top < opticalInsets.top) {
+ padding.top = opticalInsets.top;
+ padding.bottom = opticalInsets.bottom;
+ }
+
state.mNinePatch = new NinePatch(bitmap, bitmap.getNinePatchChunk());
state.mPadding = padding;
state.mOpticalInsets = Insets.of(opticalInsets);
@@ -611,6 +620,16 @@ public class NinePatchDrawable extends Drawable {
mOpticalInsets = Insets.of(opticalInsets);
mDither = dither;
mAutoMirrored = autoMirror;
+
+ // Sanity check for valid padding when we have optical insets.
+ if (mPadding.left < mOpticalInsets.left) {
+ mPadding.left = mOpticalInsets.left;
+ mPadding.right = mOpticalInsets.right;
+ }
+ if (mPadding.top < mOpticalInsets.top) {
+ mPadding.top = mOpticalInsets.top;
+ mPadding.bottom = mOpticalInsets.bottom;
+ }
}
// Copy constructor
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index f41b11a..be02c9b 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -364,13 +364,19 @@ public class VectorDrawable extends Drawable {
/** @hide */
public static VectorDrawable create(Resources resources, int rid) {
try {
- final XmlPullParser xpp = resources.getXml(rid);
- final AttributeSet attrs = Xml.asAttributeSet(xpp);
- final XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
- factory.setNamespaceAware(true);
+ final XmlPullParser parser = resources.getXml(rid);
+ final AttributeSet attrs = Xml.asAttributeSet(parser);
+ int type;
+ while ((type=parser.next()) != XmlPullParser.START_TAG &&
+ type != XmlPullParser.END_DOCUMENT) {
+ // Empty loop
+ }
+ if (type != XmlPullParser.START_TAG) {
+ throw new XmlPullParserException("No start tag found");
+ }
final VectorDrawable drawable = new VectorDrawable();
- drawable.inflate(resources, xpp, attrs);
+ drawable.inflate(resources, parser, attrs);
return drawable;
} catch (XmlPullParserException e) {
@@ -436,10 +442,10 @@ public class VectorDrawable extends Drawable {
if (pathRenderer.mViewportWidth <= 0) {
throw new XmlPullParserException(a.getPositionDescription() +
- "<viewport> tag requires viewportWidth > 0");
+ "<vector> tag requires viewportWidth > 0");
} else if (pathRenderer.mViewportHeight <= 0) {
throw new XmlPullParserException(a.getPositionDescription() +
- "<viewport> tag requires viewportHeight > 0");
+ "<vector> tag requires viewportHeight > 0");
}
pathRenderer.mBaseWidth = a.getDimension(
@@ -449,10 +455,10 @@ public class VectorDrawable extends Drawable {
if (pathRenderer.mBaseWidth <= 0) {
throw new XmlPullParserException(a.getPositionDescription() +
- "<size> tag requires width > 0");
+ "<vector> tag requires width > 0");
} else if (pathRenderer.mBaseHeight <= 0) {
throw new XmlPullParserException(a.getPositionDescription() +
- "<size> tag requires height > 0");
+ "<vector> tag requires height > 0");
}
}
diff --git a/media/java/android/media/AudioDevicePort.java b/media/java/android/media/AudioDevicePort.java
index c088906..7975e04 100644
--- a/media/java/android/media/AudioDevicePort.java
+++ b/media/java/android/media/AudioDevicePort.java
@@ -82,4 +82,12 @@ public class AudioDevicePort extends AudioPort {
}
return super.equals(o);
}
+
+ @Override
+ public String toString() {
+ return "{" + super.toString()
+ + ", mType:" + mType
+ + ", mAddress: " + mAddress
+ + "}";
+ }
}
diff --git a/media/java/android/media/AudioHandle.java b/media/java/android/media/AudioHandle.java
index b58e7a3..6493dac 100644
--- a/media/java/android/media/AudioHandle.java
+++ b/media/java/android/media/AudioHandle.java
@@ -46,4 +46,9 @@ class AudioHandle {
public int hashCode() {
return mId;
}
+
+ @Override
+ public String toString() {
+ return Integer.toString(mId);
+ }
}
diff --git a/media/java/android/media/AudioPort.java b/media/java/android/media/AudioPort.java
index 8b74842..53212aa 100644
--- a/media/java/android/media/AudioPort.java
+++ b/media/java/android/media/AudioPort.java
@@ -173,5 +173,11 @@ public class AudioPort {
public int hashCode() {
return mHandle.hashCode();
}
-}
+ @Override
+ public String toString() {
+ return "{mHandle:" + mHandle
+ + ", mRole:" + mRole
+ + "}";
+ }
+}
diff --git a/media/java/android/media/AudioPortConfig.java b/media/java/android/media/AudioPortConfig.java
index 5dc768d..f937cc2 100644
--- a/media/java/android/media/AudioPortConfig.java
+++ b/media/java/android/media/AudioPortConfig.java
@@ -90,4 +90,14 @@ public class AudioPortConfig {
public AudioGainConfig gain() {
return mGain;
}
+
+ @Override
+ public String toString() {
+ return "{mPort:" + mPort
+ + ", mSamplingRate:" + mSamplingRate
+ + ", mChannelMask: " + mChannelMask
+ + ", mFormat:" + mFormat
+ + ", mGain:" + mGain
+ + "}";
+ }
}
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 275d9b2..4a1c0ae 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -34,6 +34,7 @@ import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ReadOnlyBufferException;
import java.util.Arrays;
+import java.util.HashMap;
import java.util.Map;
/**
@@ -531,9 +532,13 @@ final public class MediaCodec {
public native final Surface createInputSurface();
/**
- * After successfully configuring the component, call start. On return
- * you can query the component for its input/output buffers.
- * @throws IllegalStateException if not in the Configured state.
+ * After successfully configuring the component, call {@code start}.
+ * <p>
+ * Call {@code start} also if the codec is configured in asynchronous mode,
+ * and it has just been flushed, to resume requesting input buffers.
+ * @throws IllegalStateException if not in the Configured state
+ * or just after {@link #flush} for a codec that is configured
+ * in asynchronous mode.
* @throws MediaCodec.CodecException upon codec error. Note that some codec errors
* for start may be attributed to future method calls.
*/
@@ -569,6 +574,15 @@ final public class MediaCodec {
* Flush both input and output ports of the component, all indices
* previously returned in calls to {@link #dequeueInputBuffer} and
* {@link #dequeueOutputBuffer} become invalid.
+ * <p>
+ * If codec is configured in asynchronous mode, call {@link #start}
+ * after {@code flush} has returned to resume codec operations. The
+ * codec will not request input buffers until this has happened.
+ * <p>
+ * If codec is configured in synchronous mode, codec will resume
+ * automatically if an input surface was created. Otherwise, it
+ * will resume when {@link #dequeueInputBuffer} is called.
+ *
* @throws IllegalStateException if not in the Executing state.
* @throws MediaCodec.CodecException upon codec error.
*/
@@ -576,10 +590,8 @@ final public class MediaCodec {
synchronized(mBufferLock) {
invalidateByteBuffers(mCachedInputBuffers);
invalidateByteBuffers(mCachedOutputBuffers);
- invalidateByteBuffers(mDequeuedInputBuffers);
- invalidateByteBuffers(mDequeuedOutputBuffers);
- freeImages(mDequeuedInputImages);
- freeImages(mDequeuedOutputImages);
+ mDequeuedInputBuffers.clear();
+ mDequeuedOutputBuffers.clear();
}
native_flush();
}
@@ -719,7 +731,7 @@ final public class MediaCodec {
throws CryptoException {
synchronized(mBufferLock) {
invalidateByteBuffer(mCachedInputBuffers, index);
- updateDequeuedByteBuffer(mDequeuedInputBuffers, index, null);
+ mDequeuedInputBuffers.remove(index);
}
native_queueInputBuffer(
index, offset, size, presentationTimeUs, flags);
@@ -839,7 +851,7 @@ final public class MediaCodec {
int flags) throws CryptoException {
synchronized(mBufferLock) {
invalidateByteBuffer(mCachedInputBuffers, index);
- updateDequeuedByteBuffer(mDequeuedInputBuffers, index, null);
+ mDequeuedInputBuffers.remove(index);
}
native_queueSecureInputBuffer(
index, offset, info, presentationTimeUs, flags);
@@ -859,7 +871,8 @@ final public class MediaCodec {
* for the availability of an input buffer if timeoutUs &lt; 0 or wait up
* to "timeoutUs" microseconds if timeoutUs &gt; 0.
* @param timeoutUs The timeout in microseconds, a negative timeout indicates "infinite".
- * @throws IllegalStateException if not in the Executing state.
+ * @throws IllegalStateException if not in the Executing state,
+ * or codec is configured in asynchronous mode.
* @throws MediaCodec.CodecException upon codec error.
*/
public final int dequeueInputBuffer(long timeoutUs) {
@@ -907,7 +920,8 @@ final public class MediaCodec {
* decoded or one of the INFO_* constants below.
* @param info Will be filled with buffer meta data.
* @param timeoutUs The timeout in microseconds, a negative timeout indicates "infinite".
- * @throws IllegalStateException if not in the Executing state.
+ * @throws IllegalStateException if not in the Executing state,
+ * or codec is configured in asynchronous mode.
* @throws MediaCodec.CodecException upon codec error.
*/
public final int dequeueOutputBuffer(
@@ -946,7 +960,7 @@ final public class MediaCodec {
public final void releaseOutputBuffer(int index, boolean render) {
synchronized(mBufferLock) {
invalidateByteBuffer(mCachedOutputBuffers, index);
- updateDequeuedByteBuffer(mDequeuedOutputBuffers, index, null);
+ mDequeuedOutputBuffers.remove(index);
}
releaseOutputBuffer(index, render, false /* updatePTS */, 0 /* dummy */);
}
@@ -1003,7 +1017,7 @@ final public class MediaCodec {
public final void releaseOutputBuffer(int index, long renderTimestampNs) {
synchronized(mBufferLock) {
invalidateByteBuffer(mCachedOutputBuffers, index);
- updateDequeuedByteBuffer(mDequeuedOutputBuffers, index, null);
+ mDequeuedOutputBuffers.remove(index);
}
releaseOutputBuffer(
index, true /* render */, true /* updatePTS */, renderTimestampNs);
@@ -1068,17 +1082,82 @@ final public class MediaCodec {
private native final Map<String, Object> getOutputFormatNative(int index);
+ // used to track dequeued buffers
+ private static class BufferMap {
+ // various returned representations of the codec buffer
+ private static class CodecBuffer {
+ private Image mImage;
+ private ByteBuffer mByteBuffer;
+
+ public void free() {
+ if (mByteBuffer != null) {
+ // all of our ByteBuffers are direct
+ java.nio.NioUtils.freeDirectBuffer(mByteBuffer);
+ mByteBuffer = null;
+ }
+ if (mImage != null) {
+ mImage.close();
+ mImage = null;
+ }
+ }
+
+ public void setImage(Image image) {
+ free();
+ mImage = image;
+ }
+
+ public void setByteBuffer(ByteBuffer buffer) {
+ free();
+ mByteBuffer = buffer;
+ }
+ }
+
+ private final Map<Integer, CodecBuffer> mMap =
+ new HashMap<Integer, CodecBuffer>();
+
+ public void remove(int index) {
+ CodecBuffer buffer = mMap.get(index);
+ if (buffer != null) {
+ buffer.free();
+ mMap.remove(index);
+ }
+ }
+
+ public void put(int index, ByteBuffer newBuffer) {
+ CodecBuffer buffer = mMap.get(index);
+ if (buffer == null) { // likely
+ buffer = new CodecBuffer();
+ mMap.put(index, buffer);
+ }
+ buffer.setByteBuffer(newBuffer);
+ }
+
+ public void put(int index, Image newImage) {
+ CodecBuffer buffer = mMap.get(index);
+ if (buffer == null) { // likely
+ buffer = new CodecBuffer();
+ mMap.put(index, buffer);
+ }
+ buffer.setImage(newImage);
+ }
+
+ public void clear() {
+ for (CodecBuffer buffer: mMap.values()) {
+ buffer.free();
+ }
+ mMap.clear();
+ }
+ }
+
private ByteBuffer[] mCachedInputBuffers;
private ByteBuffer[] mCachedOutputBuffers;
- private ByteBuffer[] mDequeuedInputBuffers;
- private ByteBuffer[] mDequeuedOutputBuffers;
- private Image[] mDequeuedInputImages;
- private Image[] mDequeuedOutputImages;
+ private final BufferMap mDequeuedInputBuffers = new BufferMap();
+ private final BufferMap mDequeuedOutputBuffers = new BufferMap();
final private Object mBufferLock;
private final void invalidateByteBuffer(
ByteBuffer[] buffers, int index) {
- if (index >= 0 && index < buffers.length) {
+ if (buffers != null && index >= 0 && index < buffers.length) {
ByteBuffer buffer = buffers[index];
if (buffer != null) {
buffer.setAccessible(false);
@@ -1088,7 +1167,7 @@ final public class MediaCodec {
private final void validateInputByteBuffer(
ByteBuffer[] buffers, int index) {
- if (index >= 0 && index < buffers.length) {
+ if (buffers != null && index >= 0 && index < buffers.length) {
ByteBuffer buffer = buffers[index];
if (buffer != null) {
buffer.setAccessible(true);
@@ -1099,7 +1178,7 @@ final public class MediaCodec {
private final void validateOutputByteBuffer(
ByteBuffer[] buffers, int index, BufferInfo info) {
- if (index >= 0 && index < buffers.length) {
+ if (buffers != null && index >= 0 && index < buffers.length) {
ByteBuffer buffer = buffers[index];
if (buffer != null) {
buffer.setAccessible(true);
@@ -1133,46 +1212,29 @@ final public class MediaCodec {
}
}
- private final void freeImage(Image image) {
- if (image != null) {
- image.close();
- }
- }
-
- private final void freeImages(Image[] images) {
- if (images != null) {
- for (Image image: images) {
- freeImage(image);
- }
- }
- }
-
private final void freeAllTrackedBuffers() {
- freeByteBuffers(mCachedInputBuffers);
- freeByteBuffers(mCachedOutputBuffers);
- freeImages(mDequeuedInputImages);
- freeImages(mDequeuedOutputImages);
- freeByteBuffers(mDequeuedInputBuffers);
- freeByteBuffers(mDequeuedOutputBuffers);
- mCachedInputBuffers = null;
- mCachedOutputBuffers = null;
- mDequeuedInputImages = null;
- mDequeuedOutputImages = null;
- mDequeuedInputBuffers = null;
- mDequeuedOutputBuffers = null;
+ synchronized (mBufferLock) {
+ freeByteBuffers(mCachedInputBuffers);
+ freeByteBuffers(mCachedOutputBuffers);
+ mCachedInputBuffers = null;
+ mCachedOutputBuffers = null;
+ mDequeuedInputBuffers.clear();
+ mDequeuedOutputBuffers.clear();
+ }
}
private final void cacheBuffers(boolean input) {
- ByteBuffer[] buffers = getBuffers(input);
- invalidateByteBuffers(buffers);
+ ByteBuffer[] buffers = null;
+ try {
+ buffers = getBuffers(input);
+ invalidateByteBuffers(buffers);
+ } catch (IllegalStateException e) {
+ // we don't get buffers in async mode
+ }
if (input) {
mCachedInputBuffers = buffers;
- mDequeuedInputImages = new Image[buffers.length];
- mDequeuedInputBuffers = new ByteBuffer[buffers.length];
} else {
mCachedOutputBuffers = buffers;
- mDequeuedOutputImages = new Image[buffers.length];
- mDequeuedOutputBuffers = new ByteBuffer[buffers.length];
}
}
@@ -1188,7 +1250,8 @@ final public class MediaCodec {
* <b>Note:</b>As of API 21, dequeued input buffers are
* automatically {@link java.nio.Buffer#clear cleared}.
*
- * @throws IllegalStateException if not in the Executing state.
+ * @throws IllegalStateException if not in the Executing state,
+ * or codec is configured in asynchronous mode.
* @throws MediaCodec.CodecException upon codec error.
*/
public ByteBuffer[] getInputBuffers() {
@@ -1227,26 +1290,6 @@ final public class MediaCodec {
return mCachedOutputBuffers;
}
- private boolean updateDequeuedByteBuffer(
- ByteBuffer[] buffers, int index, ByteBuffer newBuffer) {
- if (index < 0 || index >= buffers.length) {
- return false;
- }
- freeByteBuffer(buffers[index]);
- buffers[index] = newBuffer;
- return newBuffer != null;
- }
-
- private boolean updateDequeuedImage(
- Image[] images, int index, Image newImage) {
- if (index < 0 || index >= images.length) {
- return false;
- }
- freeImage(images[index]);
- images[index] = newImage;
- return newImage != null;
- }
-
/**
* Returns a {@link java.nio.Buffer#clear cleared}, writable ByteBuffer
* object for a dequeued input buffer index to contain the input data.
@@ -1268,13 +1311,10 @@ final public class MediaCodec {
public ByteBuffer getInputBuffer(int index) {
ByteBuffer newBuffer = getBuffer(true /* input */, index);
synchronized(mBufferLock) {
- if (updateDequeuedByteBuffer(mDequeuedInputBuffers, index, newBuffer)) {
- updateDequeuedImage(mDequeuedInputImages, index, null);
- invalidateByteBuffer(mCachedInputBuffers, index);
- return newBuffer;
- }
+ invalidateByteBuffer(mCachedInputBuffers, index);
+ mDequeuedInputBuffers.put(index, newBuffer);
}
- return null;
+ return newBuffer;
}
/**
@@ -1298,12 +1338,11 @@ final public class MediaCodec {
*/
public Image getInputImage(int index) {
Image newImage = getImage(true /* input */, index);
- if (updateDequeuedImage(mDequeuedInputImages, index, newImage)) {
- updateDequeuedByteBuffer(mDequeuedInputBuffers, index, null);
+ synchronized(mBufferLock) {
invalidateByteBuffer(mCachedInputBuffers, index);
- return newImage;
+ mDequeuedInputBuffers.put(index, newImage);
}
- return null;
+ return newImage;
}
/**
@@ -1328,13 +1367,10 @@ final public class MediaCodec {
public ByteBuffer getOutputBuffer(int index) {
ByteBuffer newBuffer = getBuffer(false /* input */, index);
synchronized(mBufferLock) {
- if (updateDequeuedByteBuffer(mDequeuedOutputBuffers, index, newBuffer)) {
- updateDequeuedImage(mDequeuedOutputImages, index, null);
- invalidateByteBuffer(mCachedOutputBuffers, index);
- return newBuffer;
- }
+ invalidateByteBuffer(mCachedOutputBuffers, index);
+ mDequeuedOutputBuffers.put(index, newBuffer);
}
- return null;
+ return newBuffer;
}
/**
@@ -1358,13 +1394,10 @@ final public class MediaCodec {
public Image getOutputImage(int index) {
Image newImage = getImage(false /* input */, index);
synchronized(mBufferLock) {
- if (updateDequeuedImage(mDequeuedOutputImages, index, newImage)) {
- updateDequeuedByteBuffer(mDequeuedOutputBuffers, index, null);
- invalidateByteBuffer(mCachedOutputBuffers, index);
- return newImage;
- }
+ invalidateByteBuffer(mCachedOutputBuffers, index);
+ mDequeuedOutputBuffers.put(index, newImage);
}
- return null;
+ return newImage;
}
/**
@@ -1445,7 +1478,12 @@ final public class MediaCodec {
* a valid callback should be provided before {@link #configure} is called.
*
* When asynchronous callback is enabled, the client should not call
- * {@link #dequeueInputBuffer(long)} or {@link #dequeueOutputBuffer(BufferInfo, long)}
+ * {@link #getInputBuffers}, {@link #getOutputBuffers},
+ * {@link #dequeueInputBuffer(long)} or {@link #dequeueOutputBuffer(BufferInfo, long)}.
+ * <p>
+ * Also, {@link #flush} behaves differently in asynchronous mode. After calling
+ * {@code flush}, you must call {@link #start} to "resume" receiving input buffers,
+ * even if an input surface was created.
*
* @param cb The callback that will run.
*/
diff --git a/media/java/android/media/browse/MediaBrowserItem.java b/media/java/android/media/browse/MediaBrowserItem.java
index d0a0342..47ec46b 100644
--- a/media/java/android/media/browse/MediaBrowserItem.java
+++ b/media/java/android/media/browse/MediaBrowserItem.java
@@ -135,6 +135,19 @@ public final class MediaBrowserItem implements Parcelable {
}
}
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder("MediaBrowserItem{");
+ sb.append("mUri=").append(mUri);
+ sb.append(", mFlags=").append(mFlags);
+ sb.append(", mTitle=").append(mTitle);
+ sb.append(", mSummary=").append(mSummary);
+ sb.append(", mIconUri=").append(mIconUri);
+ sb.append(", mIconResourceId=").append(mIconResourceId);
+ sb.append('}');
+ return sb.toString();
+ }
+
public static final Parcelable.Creator<MediaBrowserItem> CREATOR =
new Parcelable.Creator<MediaBrowserItem>() {
@Override
diff --git a/media/java/android/media/tv/ITvInputClient.aidl b/media/java/android/media/tv/ITvInputClient.aidl
index c48ddf1..2c39afa 100644
--- a/media/java/android/media/tv/ITvInputClient.aidl
+++ b/media/java/android/media/tv/ITvInputClient.aidl
@@ -34,6 +34,7 @@ oneway interface ITvInputClient {
void onSessionEvent(in String name, in Bundle args, int seq);
void onChannelRetuned(in Uri channelUri, int seq);
void onTrackInfoChanged(in List<TvTrackInfo> tracks, int seq);
+ void onTrackSelectionChanged(in List<TvTrackInfo> selectedTracks, int seq);
void onVideoAvailable(int seq);
void onVideoUnavailable(int reason, int seq);
void onContentAllowed(int seq);
diff --git a/media/java/android/media/tv/ITvInputSessionCallback.aidl b/media/java/android/media/tv/ITvInputSessionCallback.aidl
index 4186bb5..3773987 100644
--- a/media/java/android/media/tv/ITvInputSessionCallback.aidl
+++ b/media/java/android/media/tv/ITvInputSessionCallback.aidl
@@ -31,6 +31,7 @@ oneway interface ITvInputSessionCallback {
void onSessionEvent(in String name, in Bundle args);
void onChannelRetuned(in Uri channelUri);
void onTrackInfoChanged(in List<TvTrackInfo> tracks);
+ void onTrackSelectionChanged(in List<TvTrackInfo> selectedTracks);
void onVideoAvailable();
void onVideoUnavailable(int reason);
void onContentAllowed();
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index d97aee0..49b2240 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -164,7 +164,7 @@ public final class TvInputManager {
* This is called when the channel of this session is changed by the underlying TV input
* with out any {@link TvInputManager.Session#tune(Uri)} request.
*
- * @param session A {@link TvInputManager.Session} associated with this callback
+ * @param session A {@link TvInputManager.Session} associated with this callback.
* @param channelUri The URI of a channel.
*/
public void onChannelRetuned(Session session, Uri channelUri) {
@@ -173,16 +173,25 @@ public final class TvInputManager {
/**
* This is called when the track information of the session has been changed.
*
- * @param session A {@link TvInputManager.Session} associated with this callback
+ * @param session A {@link TvInputManager.Session} associated with this callback.
* @param tracks A list which includes track information.
*/
public void onTrackInfoChanged(Session session, List<TvTrackInfo> tracks) {
}
/**
- * This is called when the video is available, so the TV input starts the playback.
+ * This is called when there is a change on the selected tracks in this session.
*
* @param session A {@link TvInputManager.Session} associated with this callback
+ * @param selectedTracks A list of selected tracks.
+ */
+ public void onTrackSelectionChanged(Session session, List<TvTrackInfo> selectedTracks) {
+ }
+
+ /**
+ * This is called when the video is available, so the TV input starts the playback.
+ *
+ * @param session A {@link TvInputManager.Session} associated with this callback.
*/
public void onVideoAvailable(Session session) {
}
@@ -277,12 +286,22 @@ public final class TvInputManager {
mHandler.post(new Runnable() {
@Override
public void run() {
- mSession.setTracks(tracks);
+ mSession.mTracks = tracks;
mSessionCallback.onTrackInfoChanged(mSession, tracks);
}
});
}
+ public void postTrackSelectionChanged(final List<TvTrackInfo> selectedTracks) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mSession.mSelectedTracks = selectedTracks;
+ mSessionCallback.onTrackSelectionChanged(mSession, selectedTracks);
+ }
+ });
+ }
+
public void postVideoAvailable() {
mHandler.post(new Runnable() {
@Override
@@ -469,6 +488,18 @@ public final class TvInputManager {
}
@Override
+ public void onTrackSelectionChanged(List<TvTrackInfo> selectedTracks, int seq) {
+ synchronized (mSessionCallbackRecordMap) {
+ SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq);
+ if (record == null) {
+ Log.e(TAG, "Callback not found for seq " + seq);
+ return;
+ }
+ record.postTrackSelectionChanged(selectedTracks);
+ }
+ }
+
+ @Override
public void onVideoAvailable(int seq) {
synchronized (mSessionCallbackRecordMap) {
SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq);
@@ -868,6 +899,7 @@ public final class TvInputManager {
private TvInputEventSender mSender;
private InputChannel mChannel;
private List<TvTrackInfo> mTracks;
+ private List<TvTrackInfo> mSelectedTracks;
private Session(IBinder token, InputChannel channel, ITvInputManager service, int userId,
int seq, SparseArray<SessionCallbackRecord> sessionCallbackRecordMap) {
@@ -1067,8 +1099,17 @@ public final class TvInputManager {
return new ArrayList<TvTrackInfo>(mTracks);
}
- private void setTracks(List<TvTrackInfo> tracks) {
- mTracks = tracks;
+ /**
+ * Returns a list of selected tracks May return {@code null} if the information is not
+ * available.
+ * @see #selectTrack(TvTrackInfo)
+ * @see #unselectTrack(TvTrackInfo)
+ */
+ public List<TvTrackInfo> getSelectedTracks() {
+ if (mSelectedTracks == null) {
+ return null;
+ }
+ return new ArrayList<TvTrackInfo>(mSelectedTracks);
}
/**
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index a321809..29a2230 100644
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -325,10 +325,6 @@ public abstract class TvInputService extends Service {
* @param tracks A list which includes track information.
*/
public void notifyTrackInfoChanged(final List<TvTrackInfo> tracks) {
- if (!TvTrackInfo.checkSanity(tracks)) {
- throw new IllegalArgumentException(
- "Two or more selected tracks for a track type.");
- }
mHandler.post(new Runnable() {
@Override
public void run() {
@@ -343,6 +339,28 @@ public abstract class TvInputService extends Service {
}
/**
+ * Sends the list of selected tracks. This is expected to be called whenever there is a
+ * change on track selection.
+ *
+ * @param selectedTracks A list of selected tracks.
+ * @see #onSelectTrack(TvTrackInfo)
+ * @see #onUnselectTrack(TvTrackInfo)
+ */
+ public void notifyTrackSelectionChanged(final List<TvTrackInfo> selectedTracks) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ if (DEBUG) Log.d(TAG, "notifyTrackSelectionChanged");
+ mSessionCallback.onTrackSelectionChanged(selectedTracks);
+ } catch (RemoteException e) {
+ Log.w(TAG, "error in notifyTrackSelectionChanged");
+ }
+ }
+ });
+ }
+
+ /**
* Informs the application that video is available and the playback of the TV stream has
* been started.
*/
@@ -572,13 +590,12 @@ public abstract class TvInputService extends Service {
* If it is called multiple times on the same type of track (ie. Video, Audio, Text), the
* track selected previously should be unselected in the implementation of this method.
* Also, if the select operation was successful, the implementation should call
- * {@link #notifyTrackInfoChanged(List)} to report the updated track information.
+ * {@link #notifyTrackSelectionChanged(List)} to report the selected track list.
* </p>
*
* @param track The track to be selected.
* @return {@code true} if the select operation was successful, {@code false} otherwise.
- * @see #notifyTrackInfoChanged
- * @see TvTrackInfo#KEY_IS_SELECTED
+ * @see #notifyTrackSelectionChanged(List)
*/
public boolean onSelectTrack(TvTrackInfo track) {
return false;
@@ -588,13 +605,12 @@ public abstract class TvInputService extends Service {
* Unselects a given track.
* <p>
* If the unselect operation was successful, the implementation should call
- * {@link #notifyTrackInfoChanged(List)} to report the updated track information.
+ * {@link #notifyTrackSelectionChanged(List)} to report the selected track list.
* </p>
*
* @param track The track to be unselected.
* @return {@code true} if the unselect operation was successful, {@code false} otherwise.
- * @see #notifyTrackInfoChanged
- * @see TvTrackInfo#KEY_IS_SELECTED
+ * @see #notifyTrackSelectionChanged(List)
*/
public boolean onUnselectTrack(TvTrackInfo track) {
return false;
diff --git a/media/java/android/media/tv/TvStreamConfig.java b/media/java/android/media/tv/TvStreamConfig.java
index 243f864..a7e7e44 100644
--- a/media/java/android/media/tv/TvStreamConfig.java
+++ b/media/java/android/media/tv/TvStreamConfig.java
@@ -88,6 +88,16 @@ public class TvStreamConfig implements Parcelable {
return mGeneration;
}
+ @Override
+ public String toString() {
+ StringBuilder b = new StringBuilder(128);
+ b.append("TvStreamConfig {");
+ b.append("mStreamId=").append(mStreamId).append(";");
+ b.append("mType=").append(mType).append(";");
+ b.append("mGeneration=").append(mGeneration).append("}");
+ return b.toString();
+ }
+
// Parcelable
@Override
public int describeContents() {
diff --git a/media/java/android/media/tv/TvTrackInfo.java b/media/java/android/media/tv/TvTrackInfo.java
index de4f4b7..3b80db4 100644
--- a/media/java/android/media/tv/TvTrackInfo.java
+++ b/media/java/android/media/tv/TvTrackInfo.java
@@ -16,171 +16,121 @@
package android.media.tv;
-import android.media.MediaFormat;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
-import java.util.List;
-
/**
* Encapsulates the format of tracks played in {@link TvInputService}.
*/
public final class TvTrackInfo implements Parcelable {
/**
- * A key describing the type of this track. The associated value is an integer and it should be
- * one of {@link #VALUE_TYPE_AUDIO}, {@link #VALUE_TYPE_VIDEO}, and {@link #VALUE_TYPE_SUBTITLE}.
- * <p>
- * This is a required key.
- * </p>
- */
- public static final String KEY_TYPE = "type";
-
- /**
- * A key describing the language of the track, using either ISO 639-1 or 639-2/T codes.
- * If the language is unknown or could not be determined, the corresponding value will be "und".
- * The associated value is a string.
- * <p>
- * This is a required key.
- * </p>
+ * The type value for audio tracks.
*/
- public static final String KEY_LANGUAGE = MediaFormat.KEY_LANGUAGE;
+ public static final int TYPE_AUDIO = 0;
/**
- * A key describing whether this track is selected for the playback.
- * The associated value is a boolean.
- * <p>
- * This is a required key.
- * </p>
+ * The type value for video tracks.
*/
- public static final String KEY_IS_SELECTED = "is-selected";
+ public static final int TYPE_VIDEO = 1;
/**
- * A key describing the sample rate of an audio track.
- * The associated value is an integer.
+ * The type value for subtitle tracks.
*/
- public static final String KEY_SAMPLE_RATE = MediaFormat.KEY_SAMPLE_RATE;
-
- /**
- * A key describing the number of channels in an audio track.
- * The associated value is an integer.
- */
- public static final String KEY_CHANNEL_COUNT = MediaFormat.KEY_CHANNEL_COUNT;
-
- /**
- * A key describing the width of the content in a video track.
- * The associated value is an integer.
- */
- public static final String KEY_WIDTH = MediaFormat.KEY_WIDTH;
-
- /**
- * A key describing the height of the content in a video track.
- * The associated value is an integer.
- */
- public static final String KEY_HEIGHT = MediaFormat.KEY_HEIGHT;
-
- /**
- * A key describing a tag associated with this track. Expected to be used as an identifier with
- * in a session. The associated value is a string.
- */
- public static final String KEY_TAG = "tag";
+ public static final int TYPE_SUBTITLE = 2;
+
+ private final int mType;
+ private final String mLanguage;
+ private final int mAudioChannelCount;
+ private final int mAudioSampleRate;
+ private final int mVideoWidth;
+ private final int mVideoHeight;
+ private final Bundle mExtra;
+
+ private TvTrackInfo(int type, String language, int audioChannelCount,
+ int audioSampleRate, int videoWidth, int videoHeight, Bundle extra) {
+ mType = type;
+ mLanguage = language;
+ mAudioChannelCount = audioChannelCount;
+ mAudioSampleRate = audioSampleRate;
+ mVideoWidth = videoWidth;
+ mVideoHeight = videoHeight;
+ mExtra = extra;
+ }
- /**
- * The type value for audio track.
- */
- public static final int VALUE_TYPE_AUDIO = 0;
+ private TvTrackInfo(Parcel in) {
+ mType = in.readInt();
+ mLanguage = in.readString();
+ mAudioChannelCount = in.readInt();
+ mAudioSampleRate = in.readInt();
+ mVideoWidth = in.readInt();
+ mVideoHeight = in.readInt();
+ mExtra = in.readBundle();
+ }
/**
- * The type value for video track.
+ * Returns the type of the track. The type should be one of the followings:
+ * {@link #TYPE_AUDIO}, {@link #TYPE_VIDEO} and {@link #TYPE_SUBTITLE}.
*/
- public static final int VALUE_TYPE_VIDEO = 1;
+ public final int getType() {
+ return mType;
+ }
/**
- * The type value for subtitle track.
+ * Returns the language information encoded by either ISO 639-1 or ISO 639-2/T. If the language
+ * is unknown or could not be determined, the corresponding value will be {@code null}.
*/
- public static final int VALUE_TYPE_SUBTITLE = 2;
-
- private final Bundle mBundle;
-
- private TvTrackInfo(Bundle bundle) {
- mBundle = new Bundle(bundle);
- }
-
- private TvTrackInfo(Parcel in) {
- mBundle = in.readBundle();
+ public final String getLanguage() {
+ return mLanguage;
}
/**
- * Checks if there is only one or zero selected track per track type.
- *
- * @param tracks a list including tracks which will be checked.
- * @return true if there is only one or zero selected track per track type, false otherwise
- * @hide
+ * Returns the audio channel count. Valid for {@link #TYPE_AUDIO} tracks only.
*/
- public static boolean checkSanity(List<TvTrackInfo> tracks) {
- int selectedAudioTracks = 0;
- int selectedVideoTracks = 0;
- int selectedSubtitleTracks = 0;
- for (TvTrackInfo track : tracks) {
- if (track.getBoolean(KEY_IS_SELECTED)) {
- int type = track.getInt(KEY_TYPE);
- if (type == VALUE_TYPE_AUDIO) {
- selectedAudioTracks++;
- } else if (type == VALUE_TYPE_VIDEO) {
- selectedVideoTracks++;
- } else if (type == VALUE_TYPE_SUBTITLE) {
- selectedSubtitleTracks++;
- }
- }
- }
- if (selectedAudioTracks > 1 || selectedVideoTracks > 1 || selectedSubtitleTracks > 1) {
- return false;
+ public final int getAudioChannelCount() {
+ if (mType != TYPE_AUDIO) {
+ throw new IllegalStateException("Not an audio track");
}
- return true;
+ return mAudioChannelCount;
}
/**
- * Returns true if the given key is contained in the metadata
- *
- * @param key A String key
- * @return true If the key exists in this metadata, false otherwise
+ * Returns the audio sample rate, in the unit of Hz. Valid for {@link #TYPE_AUDIO} tracks only.
*/
- public boolean containsKey(String key) {
- return mBundle.containsKey(key);
+ public final int getAudioSampleRate() {
+ if (mType != TYPE_AUDIO) {
+ throw new IllegalStateException("Not an audio track");
+ }
+ return mAudioSampleRate;
}
/**
- * Returns the value associated with the given key, or null if no mapping of
- * the desired type exists for the given key or a null value is explicitly
- * associated with the key.
- *
- * @param key The key the value is stored under
- * @return A String value, or null
+ * Returns the width of the video, in the unit of pixels. Valid for {@link #TYPE_VIDEO} tracks
+ * only.
*/
- public String getString(String key) {
- return mBundle.getString(key);
+ public final int getVideoWidth() {
+ if (mType != TYPE_VIDEO) {
+ throw new IllegalStateException("Not a video track");
+ }
+ return mVideoWidth;
}
/**
- * Returns the value associated with the given key, or 0L if no integer exists
- * for the given key.
- *
- * @param key The key the value is stored under
- * @return An integer value
+ * Returns the height of the video, in the unit of pixels. Valid for {@link #TYPE_VIDEO} tracks
+ * only.
*/
- public int getInt(String key) {
- return mBundle.getInt(key, 0);
+ public final int getVideoHeight() {
+ if (mType != TYPE_VIDEO) {
+ throw new IllegalStateException("Not a video track");
+ }
+ return mVideoHeight;
}
/**
- * Returns the value associated with the given key, or false if no integer exists
- * for the given key.
- *
- * @param key The key the value is stored under
- * @return A boolean value
+ * Returns the extra information about the current track.
*/
- public boolean getBoolean(String key) {
- return mBundle.getBoolean(key, false);
+ public final Bundle getExtra() {
+ return mExtra;
}
@Override
@@ -188,13 +138,25 @@ public final class TvTrackInfo implements Parcelable {
return 0;
}
+ /**
+ * Used to package this object into a {@link Parcel}.
+ *
+ * @param dest The {@link Parcel} to be written.
+ * @param flags The flags used for parceling.
+ */
@Override
public void writeToParcel(Parcel dest, int flags) {
- dest.writeBundle(mBundle);
+ dest.writeInt(mType);
+ dest.writeString(mLanguage);
+ dest.writeInt(mAudioChannelCount);
+ dest.writeInt(mAudioSampleRate);
+ dest.writeInt(mVideoWidth);
+ dest.writeInt(mVideoHeight);
+ dest.writeBundle(mExtra);
}
- public static final Parcelable.Creator<TvTrackInfo> CREATOR
- = new Parcelable.Creator<TvTrackInfo>() {
+ public static final Parcelable.Creator<TvTrackInfo> CREATOR =
+ new Parcelable.Creator<TvTrackInfo>() {
@Override
public TvTrackInfo createFromParcel(Parcel in) {
return new TvTrackInfo(in);
@@ -210,73 +172,100 @@ public final class TvTrackInfo implements Parcelable {
* A builder class for creating {@link TvTrackInfo} objects.
*/
public static final class Builder {
- private final Bundle mBundle;
+ private int mType;
+ private String mLanguage;
+ private int mAudioChannelCount;
+ private int mAudioSampleRate;
+ private int mVideoWidth;
+ private int mVideoHeight;
+ private Bundle mExtra;
/**
- * Create a {@link Builder}. Any field that should be included in the
- * {@link TvTrackInfo} must be added.
+ * Create a {@link Builder}. Any field that should be included in the {@link TvTrackInfo}
+ * must be added.
*
* @param type The type of the track.
- * @param language The language of the track, using either ISO 639-1 or 639-2/T codes.
- * "und" if the language is unknown.
- * @param isSelected Whether this track is selected for the playback or not.
*/
- public Builder(int type, String language, boolean isSelected) {
- if (type != VALUE_TYPE_AUDIO
- && type != VALUE_TYPE_VIDEO
- && type != VALUE_TYPE_SUBTITLE) {
+ public Builder(int type) {
+ if (type != TYPE_AUDIO
+ && type != TYPE_VIDEO
+ && type != TYPE_SUBTITLE) {
throw new IllegalArgumentException("Unknown type: " + type);
}
- mBundle = new Bundle();
- putInt(KEY_TYPE, type);
- putString(KEY_LANGUAGE, language);
- putBoolean(KEY_IS_SELECTED, isSelected);
+ mType = type;
}
/**
- * Create a Builder using a {@link TvTrackInfo} instance to set the
- * initial values. All fields in the source metadata will be included in
- * the new metadata. Fields can be overwritten by adding the same key.
+ * Sets the language information of the current track.
*
- * @param source The source {@link TvTrackInfo} instance
+ * @param language The language string encoded by either ISO 639-1 or ISO 639-2/T.
*/
- public Builder(TvTrackInfo source) {
- mBundle = new Bundle(source.mBundle);
+ public final Builder setLanguage(String language) {
+ mLanguage = language;
+ return this;
}
/**
- * Put a String value into the track.
+ * Sets the audio channel count. Valid for {@link #TYPE_AUDIO} tracks only.
*
- * @param key The key for referencing this value
- * @param value The String value to store
- * @return The Builder to allow chaining
+ * @param audioChannelCount The audio channel count.
*/
- public Builder putString(String key, String value) {
- mBundle.putString(key, value);
+ public final Builder setAudioChannelCount(int audioChannelCount) {
+ if (mType != TYPE_AUDIO) {
+ throw new IllegalStateException("Not an audio track");
+ }
+ mAudioChannelCount = audioChannelCount;
return this;
}
/**
- * Put an integer value into the track.
+ * Sets the audio sample rate, in the unit of Hz. Valid for {@link #TYPE_AUDIO} tracks only.
*
- * @param key The key for referencing this value
- * @param value The integer value to store
- * @return The Builder to allow chaining
+ * @param audioSampleRate The audio sample rate.
*/
- public Builder putInt(String key, int value) {
- mBundle.putInt(key, value);
+ public final Builder setAudioSampleRate(int audioSampleRate) {
+ if (mType != TYPE_AUDIO) {
+ throw new IllegalStateException("Not an audio track");
+ }
+ mAudioSampleRate = audioSampleRate;
+ return this;
+ }
+
+ /**
+ * Sets the width of the video, in the unit of pixels. Valid for {@link #TYPE_VIDEO} tracks
+ * only.
+ *
+ * @param videoWidth The width of the video.
+ */
+ public final Builder setVideoWidth(int videoWidth) {
+ if (mType != TYPE_VIDEO) {
+ throw new IllegalStateException("Not a video track");
+ }
+ mVideoWidth = videoWidth;
+ return this;
+ }
+
+ /**
+ * Sets the height of the video, in the unit of pixels. Valid for {@link #TYPE_VIDEO} tracks
+ * only.
+ *
+ * @param videoHeight The height of the video.
+ */
+ public final Builder setVideoHeight(int videoHeight) {
+ if (mType != TYPE_VIDEO) {
+ throw new IllegalStateException("Not a video track");
+ }
+ mVideoHeight = videoHeight;
return this;
}
/**
- * Put a boolean value into the track.
+ * Sets the extra information about the current track.
*
- * @param key The key for referencing this value
- * @param value The boolean value to store
- * @return The Builder to allow chaining
+ * @param extra The extra information.
*/
- public Builder putBoolean(String key, boolean value) {
- mBundle.putBoolean(key, value);
+ public final Builder setExtra(Bundle extra) {
+ mExtra = new Bundle(extra);
return this;
}
@@ -286,7 +275,8 @@ public final class TvTrackInfo implements Parcelable {
* @return The new {@link TvTrackInfo} instance
*/
public TvTrackInfo build() {
- return new TvTrackInfo(mBundle);
+ return new TvTrackInfo(mType, mLanguage, mAudioChannelCount,
+ mAudioSampleRate, mVideoWidth, mVideoHeight, mExtra);
}
}
} \ No newline at end of file
diff --git a/media/java/android/media/tv/TvView.java b/media/java/android/media/tv/TvView.java
index f6af8c8..7031f05 100644
--- a/media/java/android/media/tv/TvView.java
+++ b/media/java/android/media/tv/TvView.java
@@ -68,7 +68,7 @@ public class TvView extends ViewGroup {
private final Handler mHandler = new Handler();
private Session mSession;
- private final SurfaceView mSurfaceView;
+ private SurfaceView mSurfaceView;
private Surface mSurface;
private boolean mOverlayViewCreated;
private Rect mOverlayViewFrame;
@@ -84,6 +84,8 @@ public class TvView extends ViewGroup {
private int mSurfaceFormat;
private int mSurfaceWidth;
private int mSurfaceHeight;
+ private final AttributeSet mAttrs;
+ private final int mDefStyleAttr;
private final SurfaceHolder.Callback mSurfaceHolderCallback = new SurfaceHolder.Callback() {
@Override
@@ -143,14 +145,9 @@ public class TvView extends ViewGroup {
public TvView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
- mSurfaceView = new SurfaceView(context, attrs, defStyleAttr) {
- @Override
- protected void updateWindow(boolean force, boolean redrawNeeded) {
- super.updateWindow(force, redrawNeeded);
- relayoutSessionOverlayView();
- }};
- mSurfaceView.getHolder().addCallback(mSurfaceHolderCallback);
- addView(mSurfaceView);
+ mAttrs = attrs;
+ mDefStyleAttr = defStyleAttr;
+ resetSurfaceView();
mTvInputManager = (TvInputManager) getContext().getSystemService(Context.TV_INPUT_SERVICE);
}
@@ -228,9 +225,7 @@ public class TvView extends ViewGroup {
mSessionCallback.mChannelUri = channelUri;
}
} else {
- if (mSession != null) {
- release();
- }
+ reset();
// When createSession() is called multiple times before the callback is called,
// only the callback of the last createSession() call will be actually called back.
// The previous callbacks will be ignored. For the logic, mSessionCallback
@@ -249,6 +244,7 @@ public class TvView extends ViewGroup {
public void reset() {
if (mSession != null) {
release();
+ resetSurfaceView();
}
}
@@ -325,6 +321,17 @@ public class TvView extends ViewGroup {
}
/**
+ * Returns a list of selected tracks. May return {@code null} if the information is not
+ * available.
+ */
+ public List<TvTrackInfo> getSelectedTracks() {
+ if (mSession == null) {
+ return null;
+ }
+ return mSession.getSelectedTracks();
+ }
+
+ /**
* Call {@link TvInputService.Session#appPrivateCommand(String, Bundle)
* TvInputService.Session.appPrivateCommand()} on the current TvView.
*
@@ -495,6 +502,21 @@ public class TvView extends ViewGroup {
}
}
+ private void resetSurfaceView() {
+ if (mSurfaceView != null) {
+ mSurfaceView.getHolder().removeCallback(mSurfaceHolderCallback);
+ removeView(mSurfaceView);
+ }
+ mSurfaceView = new SurfaceView(getContext(), mAttrs, mDefStyleAttr) {
+ @Override
+ protected void updateWindow(boolean force, boolean redrawNeeded) {
+ super.updateWindow(force, redrawNeeded);
+ relayoutSessionOverlayView();
+ }};
+ mSurfaceView.getHolder().addCallback(mSurfaceHolderCallback);
+ addView(mSurfaceView);
+ }
+
private void release() {
setSessionSurface(null);
removeSessionOverlayView();
@@ -558,10 +580,9 @@ public class TvView extends ViewGroup {
private void updateVideoSize(List<TvTrackInfo> tracks) {
for (TvTrackInfo track : tracks) {
- if (track.getBoolean(TvTrackInfo.KEY_IS_SELECTED)
- && track.getInt(TvTrackInfo.KEY_TYPE) == TvTrackInfo.VALUE_TYPE_VIDEO) {
- int width = track.getInt(TvTrackInfo.KEY_WIDTH);
- int height = track.getInt(TvTrackInfo.KEY_HEIGHT);
+ if (track.getType() == TvTrackInfo.TYPE_VIDEO) {
+ int width = track.getVideoWidth();
+ int height = track.getVideoHeight();
if (width != mVideoWidth || height != mVideoHeight) {
mVideoWidth = width;
mVideoHeight = height;
@@ -619,6 +640,15 @@ public class TvView extends ViewGroup {
}
/**
+ * This is called when there is a change on the selected tracks.
+ *
+ * @param inputId The ID of the TV input bound to this view.
+ * @param selectedTracks A list which includes track information.
+ */
+ public void onTrackSelectionChanged(String inputId, List<TvTrackInfo> selectedTracks) {
+ }
+
+ /**
* This is called when the video is available, so the TV input starts the playback.
*
* @param inputId The ID of the TV input bound to this view.
@@ -768,13 +798,26 @@ public class TvView extends ViewGroup {
if (DEBUG) {
Log.d(TAG, "onTrackInfoChanged()");
}
- updateVideoSize(tracks);
if (mListener != null) {
mListener.onTrackInfoChanged(mInputId, tracks);
}
}
@Override
+ public void onTrackSelectionChanged(Session session, List<TvTrackInfo> selectedTracks) {
+ if (this != mSessionCallback) {
+ return;
+ }
+ if (DEBUG) {
+ Log.d(TAG, "onTrackInfoChanged()");
+ }
+ updateVideoSize(selectedTracks);
+ if (mListener != null) {
+ mListener.onTrackSelectionChanged(mInputId, selectedTracks);
+ }
+ }
+
+ @Override
public void onVideoAvailable(Session session) {
if (this != mSessionCallback) {
return;
diff --git a/packages/SystemUI/res/layout/keyguard_status_bar.xml b/packages/SystemUI/res/layout/keyguard_status_bar.xml
new file mode 100644
index 0000000..d4b1214
--- /dev/null
+++ b/packages/SystemUI/res/layout/keyguard_status_bar.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2014 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
+ -->
+
+<!-- Extends RelativeLayout -->
+<com.android.systemui.statusbar.phone.KeyguardStatusBarView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
+ android:id="@+id/keyguard_header"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/status_bar_header_height_keyguard"
+ android:baselineAligned="false"
+ >
+
+ <com.android.systemui.statusbar.phone.MultiUserSwitch android:id="@+id/multi_user_switch"
+ android:layout_width="@dimen/multi_user_switch_width_keyguard"
+ android:layout_height="@dimen/status_bar_header_height_keyguard"
+ android:layout_alignParentEnd="true"
+ android:background="@drawable/ripple_drawable"
+ android:layout_marginEnd="@dimen/multi_user_switch_keyguard_margin">
+ <ImageView android:id="@+id/multi_user_avatar"
+ android:layout_width="@dimen/multi_user_avatar_keyguard_size"
+ android:layout_height="@dimen/multi_user_avatar_keyguard_size"
+ android:layout_gravity="center"
+ android:scaleType="centerInside"/>
+ </com.android.systemui.statusbar.phone.MultiUserSwitch>
+
+ <LinearLayout android:id="@+id/system_icons_super_container"
+ android:layout_width="wrap_content"
+ android:layout_height="@dimen/status_bar_header_height"
+ android:layout_toStartOf="@id/multi_user_switch"
+ android:layout_alignWithParentIfMissing="true"
+ android:layout_marginStart="16dp"
+ android:paddingEnd="2dp">
+ <FrameLayout android:id="@+id/system_icons_container"
+ android:layout_width="wrap_content"
+ android:layout_height="@dimen/status_bar_height"
+ android:layout_gravity="center_vertical"
+ >
+ <include layout="@layout/system_icons" />
+ </FrameLayout>
+ <TextView android:id="@+id/battery_level"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_marginStart="@dimen/header_battery_margin_keyguard"
+ android:paddingEnd="@dimen/battery_level_padding_end"
+ android:textColor="#ffffff"
+ android:visibility="gone"
+ android:textSize="12sp"/>
+ </LinearLayout>
+
+ <com.android.keyguard.CarrierText
+ android:id="@+id/keyguard_carrier_text"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/status_bar_header_height_keyguard"
+ android:layout_marginStart="@dimen/keyguard_carrier_text_margin"
+ android:layout_toStartOf="@id/system_icons_super_container"
+ android:gravity="center_vertical"
+ android:ellipsize="marquee"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="#ffffff"
+ android:singleLine="true" />
+
+</com.android.systemui.statusbar.phone.KeyguardStatusBarView>
diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml
index 19dc36d..beb8e00 100644
--- a/packages/SystemUI/res/layout/status_bar.xml
+++ b/packages/SystemUI/res/layout/status_bar.xml
@@ -82,33 +82,9 @@
android:layout_height="match_parent"
android:orientation="horizontal"
>
- <LinearLayout android:id="@+id/system_icons"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:gravity="center_vertical"
- >
- <com.android.systemui.statusbar.AlphaOptimizedLinearLayout
- android:id="@+id/statusIcons"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:gravity="center_vertical"
- android:orientation="horizontal"/>
- <include layout="@layout/signal_cluster_view"
- android:id="@+id/signal_cluster"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginStart="2dp"
- />
- <!-- battery must be padded below to match assets -->
- <com.android.systemui.BatteryMeterView
- android:id="@+id/battery"
- android:layout_height="16dp"
- android:layout_width="10.5dp"
- android:layout_marginBottom="0.33dp"
- android:layout_marginStart="4dip"
- />
- </LinearLayout>
+ <include layout="@layout/system_icons" />
+
<com.android.systemui.statusbar.policy.Clock
android:id="@+id/clock"
android:textAppearance="@style/TextAppearance.StatusBar.Clock"
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index 9af2879..53a832a 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -50,6 +50,10 @@
android:visibility="gone"
/>
+ <include
+ layout="@layout/keyguard_status_bar"
+ android:visibility="invisible" />
+
<com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer
style="@style/NotificationsQuickSettings"
android:id="@+id/notification_container_parent"
diff --git a/packages/SystemUI/res/layout/status_bar_expanded_header.xml b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
index b260a4a..1afde69 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
@@ -68,7 +68,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
- android:layout_marginStart="@dimen/header_battery_margin_keyguard"
+ android:layout_marginStart="@dimen/header_battery_margin_expanded"
android:paddingEnd="@dimen/battery_level_padding_end"
android:textColor="#ffffff"
android:textSize="12sp"/>
@@ -139,18 +139,6 @@
android:visibility="gone"
/>
- <com.android.keyguard.CarrierText
- android:id="@+id/keyguard_carrier_text"
- android:layout_width="match_parent"
- android:layout_height="@dimen/status_bar_header_height_keyguard"
- android:layout_marginStart="@dimen/keyguard_carrier_text_margin"
- android:layout_toStartOf="@id/system_icons_super_container"
- android:gravity="center_vertical"
- android:ellipsize="marquee"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="#ffffff"
- android:singleLine="true" />
-
<include
android:id="@+id/qs_detail_header"
layout="@layout/qs_detail_header"
diff --git a/packages/SystemUI/res/layout/system_icons.xml b/packages/SystemUI/res/layout/system_icons.xml
new file mode 100644
index 0000000..69f9c14
--- /dev/null
+++ b/packages/SystemUI/res/layout/system_icons.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2014 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
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/system_icons"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:gravity="center_vertical">
+
+ <com.android.systemui.statusbar.AlphaOptimizedLinearLayout android:id="@+id/statusIcons"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:gravity="center_vertical"
+ android:orientation="horizontal"/>
+
+ <include layout="@layout/signal_cluster_view"
+ android:id="@+id/signal_cluster"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="2dp"/>
+
+ <!-- battery must be padded below to match assets -->
+ <com.android.systemui.BatteryMeterView android:id="@+id/battery"
+ android:layout_height="16dp"
+ android:layout_width="10.5dp"
+ android:layout_marginBottom="0.33dp"
+ android:layout_marginStart="4dip"/>
+</LinearLayout> \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 8eca0ae..4b037d2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -220,7 +220,7 @@ public abstract class BaseStatusBar extends SystemUI implements
setZenMode(mode);
final boolean show = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.LOCK_SCREEN_SHOW_NOTIFICATIONS, 1) != 0;
- setShowLockscreenNotifications(show);
+ mShowLockscreenNotifications = show;
}
};
@@ -1423,7 +1423,8 @@ public abstract class BaseStatusBar extends SystemUI implements
}
private boolean shouldShowOnKeyguard(StatusBarNotification sbn) {
- return sbn.getNotification().priority >= Notification.PRIORITY_LOW;
+ return mShowLockscreenNotifications &&
+ sbn.getNotification().priority >= Notification.PRIORITY_LOW;
}
protected void setZenMode(int mode) {
@@ -1432,10 +1433,6 @@ public abstract class BaseStatusBar extends SystemUI implements
updateNotifications();
}
- protected void setShowLockscreenNotifications(boolean show) {
- mShowLockscreenNotifications = show;
- }
-
protected abstract void haltTicker();
protected abstract void setAreThereNotifications();
protected abstract void updateNotifications();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
new file mode 100644
index 0000000..bf66c41
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+import com.android.systemui.R;
+import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
+import com.android.systemui.statusbar.policy.UserInfoController;
+
+/**
+ * The header group on Keyguard.
+ */
+public class KeyguardStatusBarView extends RelativeLayout
+ implements BatteryController.BatteryStateChangeCallback {
+
+ private boolean mBatteryCharging;
+ private boolean mKeyguardUserSwitcherShowing;
+ private boolean mBatteryListening;
+
+ private View mSystemIconsSuperContainer;
+ private MultiUserSwitch mMultiUserSwitch;
+ private ImageView mMultiUserAvatar;
+ private TextView mBatteryLevel;
+
+ private BatteryController mBatteryController;
+ private KeyguardUserSwitcher mKeyguardUserSwitcher;
+
+ private int mSystemIconsSwitcherHiddenExpandedMargin;
+
+ public KeyguardStatusBarView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mSystemIconsSuperContainer = findViewById(R.id.system_icons_super_container);
+ mMultiUserSwitch = (MultiUserSwitch) findViewById(R.id.multi_user_switch);
+ mMultiUserAvatar = (ImageView) findViewById(R.id.multi_user_avatar);
+ mBatteryLevel = (TextView) findViewById(R.id.battery_level);
+ loadDimens();
+ updateUserSwitcher();
+ }
+
+ private void loadDimens() {
+ mSystemIconsSwitcherHiddenExpandedMargin = getResources().getDimensionPixelSize(
+ R.dimen.system_icons_switcher_hidden_expanded_margin);
+ }
+
+ private void updateVisibilities() {
+ mMultiUserSwitch.setVisibility(!mKeyguardUserSwitcherShowing ? VISIBLE : GONE);
+ mBatteryLevel.setVisibility(mBatteryCharging ? View.VISIBLE : View.GONE);
+ }
+
+ private void updateSystemIconsLayoutParams() {
+ RelativeLayout.LayoutParams lp =
+ (LayoutParams) mSystemIconsSuperContainer.getLayoutParams();
+ int marginEnd = mKeyguardUserSwitcherShowing ? mSystemIconsSwitcherHiddenExpandedMargin : 0;
+ if (marginEnd != lp.getMarginEnd()) {
+ lp.setMarginEnd(marginEnd);
+ mSystemIconsSuperContainer.setLayoutParams(lp);
+ }
+ }
+
+ public void setListening(boolean listening) {
+ if (listening == mBatteryListening) {
+ return;
+ }
+ mBatteryListening = listening;
+ if (mBatteryListening) {
+ mBatteryController.addStateChangedCallback(this);
+ } else {
+ mBatteryController.removeStateChangedCallback(this);
+ }
+ }
+
+ private void updateUserSwitcher() {
+ boolean keyguardSwitcherAvailable = mKeyguardUserSwitcher != null;
+ mMultiUserSwitch.setClickable(keyguardSwitcherAvailable);
+ mMultiUserSwitch.setFocusable(keyguardSwitcherAvailable);
+ mMultiUserSwitch.setKeyguardMode(keyguardSwitcherAvailable);
+ }
+
+ public void setBatteryController(BatteryController batteryController) {
+ mBatteryController = batteryController;
+ }
+
+ public void setUserInfoController(UserInfoController userInfoController) {
+ userInfoController.addListener(new UserInfoController.OnUserInfoChangedListener() {
+ @Override
+ public void onUserInfoChanged(String name, Drawable picture) {
+ mMultiUserAvatar.setImageDrawable(picture);
+ }
+ });
+ }
+
+ @Override
+ public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
+ mBatteryLevel.setText(getResources().getString(R.string.battery_level_template, level));
+ boolean changed = mBatteryCharging != charging;
+ mBatteryCharging = charging;
+ if (changed) {
+ updateVisibilities();
+ }
+ }
+
+ @Override
+ public void onPowerSaveChanged() {
+ // could not care less
+ }
+
+ public void setKeyguardUserSwitcher(KeyguardUserSwitcher keyguardUserSwitcher) {
+ mKeyguardUserSwitcher = keyguardUserSwitcher;
+ mMultiUserSwitch.setKeyguardUserSwitcher(keyguardUserSwitcher);
+ updateUserSwitcher();
+ }
+
+ public void setKeyguardUserSwitcherShowing(boolean showing) {
+ mKeyguardUserSwitcherShowing = showing;
+ updateVisibilities();
+ updateSystemIconsLayoutParams();
+ }
+
+ @Override
+ public boolean hasOverlappingRendering() {
+ return false;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index cccfb7b..602b914 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -60,6 +60,7 @@ public class NotificationPanelView extends PanelView implements
private KeyguardAffordanceHelper mAfforanceHelper;
private StatusBarHeaderView mHeader;
+ private KeyguardStatusBarView mKeyguardStatusBar;
private View mQsContainer;
private QSPanel mQsPanel;
private View mKeyguardStatusView;
@@ -138,6 +139,7 @@ public class NotificationPanelView extends PanelView implements
private boolean mIsLaunchTransitionRunning;
private Runnable mLaunchAnimationEndRunnable;
private boolean mOnlyAffordanceInThisMotion;
+ private boolean mKeyguardStatusBarAnimatingIn;
public NotificationPanelView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -153,6 +155,7 @@ public class NotificationPanelView extends PanelView implements
super.onFinishInflate();
mHeader = (StatusBarHeaderView) findViewById(R.id.header);
mHeader.setOnClickListener(this);
+ mKeyguardStatusBar = (KeyguardStatusBarView) findViewById(R.id.keyguard_header);
mKeyguardStatusView = findViewById(R.id.keyguard_status_view);
mQsContainer = findViewById(R.id.quick_settings_container);
mQsPanel = (QSPanel) findViewById(R.id.quick_settings_panel);
@@ -196,11 +199,10 @@ public class NotificationPanelView extends PanelView implements
// Update Clock Pivot
mKeyguardStatusView.setPivotX(getWidth() / 2);
- mKeyguardStatusView.setPivotY(
- (FONT_HEIGHT - CAP_HEIGHT) / 2048f * mClockView.getTextSize());
+ mKeyguardStatusView.setPivotY((FONT_HEIGHT - CAP_HEIGHT) / 2048f * mClockView.getTextSize());
// Calculate quick setting heights.
- mQsMinExpansionHeight = mHeader.getCollapsedHeight() + mQsPeekHeight;
+ mQsMinExpansionHeight = mKeyguardShowing ? 0 : mHeader.getCollapsedHeight() + mQsPeekHeight;
mQsMaxExpansionHeight = mHeader.getExpandedHeight() + mQsContainer.getHeight();
if (mQsExpanded) {
if (mQsFullyExpanded) {
@@ -223,10 +225,11 @@ public class NotificationPanelView extends PanelView implements
private void positionClockAndNotifications() {
boolean animate = mNotificationStackScroller.isAddOrRemoveAnimationPending();
int stackScrollerPadding;
- if (mStatusBar.getBarState() != StatusBarState.KEYGUARD) {
+ if (mStatusBarState != StatusBarState.KEYGUARD) {
int bottom = mHeader.getCollapsedHeight();
- stackScrollerPadding = bottom + mQsPeekHeight
- + mNotificationTopPadding;
+ stackScrollerPadding = mStatusBarState == StatusBarState.SHADE
+ ? bottom + mQsPeekHeight + mNotificationTopPadding
+ : mKeyguardStatusBar.getHeight() + mNotificationTopPadding;
mTopPaddingAdjustment = 0;
} else {
mClockPositionAlgorithm.setup(
@@ -671,6 +674,8 @@ public class NotificationPanelView extends PanelView implements
public void setBarState(int statusBarState) {
boolean keyguardShowing = statusBarState == StatusBarState.KEYGUARD
|| statusBarState == StatusBarState.SHADE_LOCKED;
+ mKeyguardStatusBar.setAlpha(1f);
+ mKeyguardStatusBar.setVisibility(keyguardShowing ? View.VISIBLE : View.INVISIBLE);
if (!mKeyguardShowing && keyguardShowing) {
setQsTranslation(mQsExpansionHeight);
mHeader.setTranslationY(0f);
@@ -682,9 +687,11 @@ public class NotificationPanelView extends PanelView implements
private void updateQsState() {
boolean expandVisually = mQsExpanded || mStackScrollerOverscrolling;
- mHeader.setExpanded(expandVisually, mStackScrollerOverscrolling);
- mNotificationStackScroller.setScrollingEnabled(mStatusBarState != StatusBarState.KEYGUARD
- && (!mQsExpanded || mQsExpansionFromOverscroll));
+ mHeader.setVisibility((mQsExpanded || !mKeyguardShowing) ? View.VISIBLE : View.INVISIBLE);
+ mHeader.setExpanded(mKeyguardShowing || (mQsExpanded && !mStackScrollerOverscrolling));
+ mNotificationStackScroller.setScrollingEnabled(
+ mStatusBarState != StatusBarState.KEYGUARD && (!mQsExpanded
+ || mQsExpansionFromOverscroll));
mQsPanel.setVisibility(expandVisually ? View.VISIBLE : View.INVISIBLE);
mQsContainer.setVisibility(
mKeyguardShowing && !expandVisually ? View.INVISIBLE : View.VISIBLE);
@@ -700,10 +707,22 @@ public class NotificationPanelView extends PanelView implements
setQsExpanded(false);
}
mQsExpansionHeight = height;
- mHeader.setExpansion(getQsExpansionFraction());
+ mHeader.setExpansion(getHeaderExpansionFraction());
setQsTranslation(height);
requestScrollerTopPaddingUpdate(false /* animate */);
updateNotificationScrim(height);
+ if (mKeyguardShowing) {
+ float alpha = getQsExpansionFraction();
+ alpha *= 2;
+ alpha = Math.min(1, alpha);
+ alpha = 1 - alpha;
+ if (alpha == 0f) {
+ mKeyguardStatusBar.setVisibility(View.INVISIBLE);
+ } else {
+ mKeyguardStatusBar.setVisibility(View.VISIBLE);
+ mKeyguardStatusBar.setAlpha(alpha);
+ }
+ }
}
private void updateNotificationScrim(float height) {
@@ -713,12 +732,33 @@ public class NotificationPanelView extends PanelView implements
mNotificationStackScroller.setScrimAlpha(progress);
}
+ private float getHeaderExpansionFraction() {
+ if (!mKeyguardShowing) {
+ return getQsExpansionFraction();
+ } else {
+ return 1f;
+ }
+ }
+
private void setQsTranslation(float height) {
mQsContainer.setY(height - mQsContainer.getHeight() + getHeaderTranslation());
+ if (mKeyguardShowing) {
+ mHeader.setY(interpolate(getQsExpansionFraction(), -mHeader.getHeight(), 0));
+ }
+ }
+
+ private float calculateQsTopPadding() {
+ if (mKeyguardShowing) {
+ return interpolate(getQsExpansionFraction(),
+ mNotificationStackScroller.getIntrinsicPadding() - mNotificationTopPadding,
+ mQsMaxExpansionHeight);
+ } else {
+ return mQsExpansionHeight;
+ }
}
private void requestScrollerTopPaddingUpdate(boolean animate) {
- mNotificationStackScroller.updateTopPadding(mQsExpansionHeight,
+ mNotificationStackScroller.updateTopPadding(calculateQsTopPadding(),
mScrollView.getScrollY(),
mAnimateNextTopPaddingChange || animate);
mAnimateNextTopPaddingChange = false;
@@ -794,8 +834,9 @@ public class NotificationPanelView extends PanelView implements
if (!mQsExpansionEnabled) {
return false;
}
- boolean onHeader = x >= mHeader.getLeft() && x <= mHeader.getRight()
- && y >= mHeader.getTop() && y <= mHeader.getBottom();
+ View header = mKeyguardShowing ? mKeyguardStatusBar : mHeader;
+ boolean onHeader = x >= header.getLeft() && x <= header.getRight()
+ && y >= header.getTop() && y <= header.getBottom();
if (mQsExpanded) {
return onHeader || (mScrollView.isScrolledToBottom() && yDiff < 0);
} else {
@@ -862,12 +903,9 @@ public class NotificationPanelView extends PanelView implements
}
int maxHeight;
if (mTwoFingerQsExpand || mQsExpanded || mIsExpanding && mQsExpandedWhenExpandingStarted) {
- maxHeight = (int) calculatePanelHeightQsExpanded();
+ maxHeight = Math.max(calculatePanelHeightQsExpanded(), calculatePanelHeightShade());
} else {
- int emptyBottomMargin = mNotificationStackScroller.getEmptyBottomMargin();
- maxHeight = mNotificationStackScroller.getHeight() - emptyBottomMargin
- - mTopPaddingAdjustment;
- maxHeight += mNotificationStackScroller.getTopPaddingOverflow();
+ maxHeight = calculatePanelHeightShade();
}
maxHeight = Math.max(maxHeight, min);
return maxHeight;
@@ -912,7 +950,15 @@ public class NotificationPanelView extends PanelView implements
return qsTempMaxExpansion;
}
- private float calculatePanelHeightQsExpanded() {
+ private int calculatePanelHeightShade() {
+ int emptyBottomMargin = mNotificationStackScroller.getEmptyBottomMargin();
+ int maxHeight = mNotificationStackScroller.getHeight() - emptyBottomMargin
+ - mTopPaddingAdjustment;
+ maxHeight += mNotificationStackScroller.getTopPaddingOverflow();
+ return maxHeight;
+ }
+
+ private int calculatePanelHeightQsExpanded() {
float notificationHeight = mNotificationStackScroller.getHeight()
- mNotificationStackScroller.getEmptyBottomMargin()
- mNotificationStackScroller.getTopPadding();
@@ -925,7 +971,7 @@ public class NotificationPanelView extends PanelView implements
- getScrollViewScrollY();
totalHeight = Math.max(fullyCollapsedHeight, mNotificationStackScroller.getHeight());
}
- return totalHeight;
+ return (int) totalHeight;
}
private int getScrollViewScrollY() {
@@ -993,7 +1039,6 @@ public class NotificationPanelView extends PanelView implements
}
private void updateHeaderShade() {
- mHeader.setAlpha(1f);
mHeader.setTranslationY(getHeaderTranslation());
setQsTranslation(mQsExpansionHeight);
}
@@ -1014,7 +1059,6 @@ public class NotificationPanelView extends PanelView implements
}
private void updateHeaderKeyguard() {
- mHeader.setTranslationY(0f);
float alpha;
if (mStatusBar.getBarState() == StatusBarState.KEYGUARD) {
@@ -1032,7 +1076,9 @@ public class NotificationPanelView extends PanelView implements
}
alpha = Math.max(0, Math.min(alpha, 1));
alpha = (float) Math.pow(alpha, 0.75);
- mHeader.setAlpha(alpha);
+ if (!mQsExpanded && !mKeyguardStatusBarAnimatingIn) {
+ mKeyguardStatusBar.setAlpha(alpha);
+ }
mKeyguardBottomArea.setAlpha(alpha);
setQsTranslation(mQsExpansionHeight);
}
@@ -1062,21 +1108,24 @@ public class NotificationPanelView extends PanelView implements
mIsExpanding = false;
mScrollYOverride = -1;
if (mExpandedHeight == 0f) {
- mHeader.setListening(false);
- mQsPanel.setListening(false);
+ setListening(false);
} else {
- mHeader.setListening(true);
- mQsPanel.setListening(true);
+ setListening(true);
}
mTwoFingerQsExpand = false;
mTwoFingerQsExpandPossible = false;
}
+ private void setListening(boolean listening) {
+ mHeader.setListening(listening);
+ mKeyguardStatusBar.setListening(listening);
+ mQsPanel.setListening(listening);
+ }
+
@Override
public void instantExpand() {
super.instantExpand();
- mHeader.setListening(true);
- mQsPanel.setListening(true);
+ setListening(true);
}
@Override
@@ -1352,4 +1401,8 @@ public class NotificationPanelView extends PanelView implements
mEmptyDragAmount = amount * factor;
positionClockAndNotifications();
}
+
+ private static float interpolate(float t, float start, float end) {
+ return (1 - t) * start + t * end;
+ }
}
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 20a4092..0284036 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -252,6 +252,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
// left-hand icons
LinearLayout mStatusIcons;
+ LinearLayout mStatusIconsKeyguard;
+
// the icons themselves
IconMerger mNotificationIcons;
View mNotificationIconArea;
@@ -273,6 +275,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
// top bar
StatusBarHeaderView mHeader;
+ KeyguardStatusBarView mKeyguardStatusBar;
View mKeyguardStatusView;
KeyguardBottomAreaView mKeyguardBottomArea;
boolean mLeaveOpenOnKeyguardHide;
@@ -406,8 +409,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
private Interpolator mLinearOutSlowIn;
private Interpolator mLinearInterpolator = new LinearInterpolator();
private Interpolator mBackdropInterpolator = new AccelerateDecelerateInterpolator();
- private Interpolator mAlphaIn = new PathInterpolator(0f, 0.2f, 1f, 1f);
- private Interpolator mAlphaOut = new PathInterpolator(0f, 0f, 0.8f, 1f);
+ public static final Interpolator ALPHA_IN = new PathInterpolator(0.4f, 0f, 1f, 1f);
+ public static final Interpolator ALPHA_OUT = new PathInterpolator(0f, 0f, 0.8f, 1f);
private FrameLayout mBackdrop;
private ImageView mBackdropFront, mBackdropBack;
@@ -534,12 +537,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
};
@Override
- protected void setShowLockscreenNotifications(boolean show) {
- super.setShowLockscreenNotifications(show);
- updateStackScrollerState();
- }
-
- @Override
public void start() {
mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
.getDefaultDisplay();
@@ -695,6 +692,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mHeader = (StatusBarHeaderView) mStatusBarWindow.findViewById(R.id.header);
mHeader.setActivityStarter(this);
+ mKeyguardStatusBar = (KeyguardStatusBarView) mStatusBarWindow.findViewById(R.id.keyguard_header);
+ mStatusIconsKeyguard = (LinearLayout) mKeyguardStatusBar.findViewById(R.id.statusIcons);
mKeyguardStatusView = mStatusBarWindow.findViewById(R.id.keyguard_status_view);
mKeyguardBottomArea =
(KeyguardBottomAreaView) mStatusBarWindow.findViewById(R.id.keyguard_bottom_area);
@@ -744,10 +743,13 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mZenModeController = mVolumeComponent.getZenController();
mCastController = new CastControllerImpl(mContext);
final SignalClusterView signalCluster =
- (SignalClusterView)mStatusBarView.findViewById(R.id.signal_cluster);
-
+ (SignalClusterView) mStatusBarView.findViewById(R.id.signal_cluster);
+ final SignalClusterView signalClusterKeyguard =
+ (SignalClusterView) mKeyguardStatusBar.findViewById(R.id.signal_cluster);
mNetworkController.addSignalCluster(signalCluster);
+ mNetworkController.addSignalCluster(signalClusterKeyguard);
signalCluster.setNetworkController(mNetworkController);
+ signalClusterKeyguard.setNetworkController(mNetworkController);
final boolean isAPhone = mNetworkController.hasVoiceCallingFeature();
if (isAPhone) {
mNetworkController.addEmergencyLabelView(mHeader);
@@ -783,8 +785,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mKeyguardMonitor = new KeyguardMonitor();
mKeyguardUserSwitcher = new KeyguardUserSwitcher(mContext,
- (ViewStub) mStatusBarWindow.findViewById(R.id.keyguard_user_switcher), mHeader,
- mUserSwitcherController);
+ (ViewStub) mStatusBarWindow.findViewById(R.id.keyguard_user_switcher),
+ mKeyguardStatusBar, mUserSwitcherController);
// Set up the quick settings tile panel
@@ -808,9 +810,11 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
// User info. Trigger first load.
mHeader.setUserInfoController(mUserInfoController);
+ mKeyguardStatusBar.setUserInfoController(mUserInfoController);
mUserInfoController.reloadUserInfo();
mHeader.setBatteryController(mBatteryController);
+ mKeyguardStatusBar.setBatteryController(mBatteryController);
mHeader.setNextAlarmController(mNextAlarmController);
PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
@@ -1167,6 +1171,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
public void refreshAllStatusBarIcons() {
refreshAllIconsForLayout(mStatusIcons);
+ refreshAllIconsForLayout(mStatusIconsKeyguard);
refreshAllIconsForLayout(mNotificationIcons);
}
@@ -1186,19 +1191,26 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
StatusBarIconView view = new StatusBarIconView(mContext, slot, null);
view.set(icon);
mStatusIcons.addView(view, viewIndex, new LinearLayout.LayoutParams(mIconSize, mIconSize));
+ view = new StatusBarIconView(mContext, slot, null);
+ view.set(icon);
+ mStatusIconsKeyguard.addView(view, viewIndex,
+ new LinearLayout.LayoutParams(mIconSize, mIconSize));
}
public void updateIcon(String slot, int index, int viewIndex,
StatusBarIcon old, StatusBarIcon icon) {
if (SPEW) Log.d(TAG, "updateIcon slot=" + slot + " index=" + index + " viewIndex=" + viewIndex
+ " old=" + old + " icon=" + icon);
- StatusBarIconView view = (StatusBarIconView)mStatusIcons.getChildAt(viewIndex);
+ StatusBarIconView view = (StatusBarIconView) mStatusIcons.getChildAt(viewIndex);
+ view.set(icon);
+ view = (StatusBarIconView) mStatusIconsKeyguard.getChildAt(viewIndex);
view.set(icon);
}
public void removeIcon(String slot, int index, int viewIndex) {
if (SPEW) Log.d(TAG, "removeIcon slot=" + slot + " index=" + index + " viewIndex=" + viewIndex);
mStatusIcons.removeViewAt(viewIndex);
+ mStatusIconsKeyguard.removeViewAt(viewIndex);
}
public UserHandle getCurrentUserHandle() {
@@ -1919,7 +1931,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
.alpha(0f)
.setDuration(160)
.setStartDelay(0)
- .setInterpolator(mAlphaOut)
+ .setInterpolator(ALPHA_OUT)
.withEndAction(new Runnable() {
@Override
public void run() {
@@ -1941,7 +1953,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
v.animate()
.alpha(1f)
.setDuration(320)
- .setInterpolator(mAlphaIn)
+ .setInterpolator(ALPHA_IN)
.setStartDelay(50);
// Synchronize the motion with the Keyguard fading if necessary.
@@ -3378,11 +3390,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) {
mKeyguardBottomArea.setVisibility(View.VISIBLE);
- mHeader.setKeyguardShowing(true);
mScrimController.setKeyguardShowing(true);
} else {
mKeyguardBottomArea.setVisibility(View.GONE);
- mHeader.setKeyguardShowing(false);
mScrimController.setKeyguardShowing(false);
}
mNotificationPanel.setBarState(mState);
@@ -3398,20 +3408,18 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
private void updateDozingState() {
- final boolean bottomGone = mKeyguardBottomArea.getVisibility() == View.GONE;
+ if (mState != StatusBarState.KEYGUARD) {
+ return;
+ }
if (mDozing) {
mNotificationPanel.setBackgroundColor(0xff000000);
- mHeader.setVisibility(View.INVISIBLE);
- if (!bottomGone) {
- mKeyguardBottomArea.setVisibility(View.INVISIBLE);
- }
+ mKeyguardStatusBar.setVisibility(View.INVISIBLE);
+ mKeyguardBottomArea.setVisibility(View.INVISIBLE);
mStackScroller.setDark(true, false /*animate*/);
} else {
mNotificationPanel.setBackground(null);
- mHeader.setVisibility(View.VISIBLE);
- if (!bottomGone) {
+ mKeyguardStatusBar.setVisibility(View.VISIBLE);
mKeyguardBottomArea.setVisibility(View.VISIBLE);
- }
mStackScroller.setDark(false, false /*animate*/);
}
mScrimController.setDozing(mDozing);
@@ -3421,8 +3429,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
if (mStackScroller == null) return;
boolean onKeyguard = mState == StatusBarState.KEYGUARD;
mStackScroller.setDimmed(onKeyguard, false /* animate */);
- mStackScroller.setVisibility(!mShowLockscreenNotifications && onKeyguard
- ? View.INVISIBLE : View.VISIBLE);
mStackScroller.setExpandingEnabled(!onKeyguard);
ActivatableNotificationView activatedChild = mStackScroller.getActivatedChild();
mStackScroller.setActivatedChild(null);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
index 197bb39..b3051b4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
@@ -38,7 +38,6 @@ import com.android.systemui.R;
import com.android.systemui.qs.QSPanel;
import com.android.systemui.qs.QSTile;
import com.android.systemui.statusbar.policy.BatteryController;
-import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
import com.android.systemui.statusbar.policy.NextAlarmController;
import com.android.systemui.statusbar.policy.UserInfoController;
@@ -50,9 +49,6 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
private boolean mExpanded;
private boolean mListening;
- private boolean mOverscrolled;
- private boolean mKeyguardShowing;
- private boolean mCharging;
private ViewGroup mSystemIconsContainer;
private View mSystemIconsSuperContainer;
@@ -60,7 +56,6 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
private View mClock;
private View mTime;
private View mAmPm;
- private View mKeyguardCarrierText;
private MultiUserSwitch mMultiUserSwitch;
private ImageView mMultiUserAvatar;
private View mDateCollapsed;
@@ -77,29 +72,19 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
private TextView mAlarmStatus;
private boolean mShowEmergencyCallsOnly;
- private boolean mKeyguardUserSwitcherShowing;
private boolean mAlarmShowing;
private AlarmClockInfo mNextAlarm;
private int mCollapsedHeight;
private int mExpandedHeight;
- private int mKeyguardHeight;
- private int mKeyguardWidth = ViewGroup.LayoutParams.MATCH_PARENT;
- private int mNormalWidth;
- private int mPadding;
private int mMultiUserExpandedMargin;
private int mMultiUserCollapsedMargin;
- private int mMultiUserKeyguardMargin;
- private int mSystemIconsSwitcherHiddenExpandedMargin;
+
private int mClockMarginBottomExpanded;
private int mClockMarginBottomCollapsed;
private int mMultiUserSwitchWidthCollapsed;
private int mMultiUserSwitchWidthExpanded;
- private int mMultiUserSwitchWidthKeyguard;
- private int mBatteryPaddingEnd;
- private int mBatteryMarginExpanded;
- private int mBatteryMarginKeyguard;
/**
* In collapsed QS, the clock and avatar are scaled down a bit post-layout to allow for a nice
@@ -107,13 +92,12 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
*/
private float mClockCollapsedScaleFactor;
private float mAvatarCollapsedScaleFactor;
- private float mAvatarKeyguardScaleFactor;
private ActivityStarter mActivityStarter;
private BatteryController mBatteryController;
private NextAlarmController mNextAlarmController;
private QSPanel mQSPanel;
- private KeyguardUserSwitcher mKeyguardUserSwitcher;
+
private final Rect mClipBounds = new Rect();
@@ -139,7 +123,6 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
mClock = findViewById(R.id.clock);
mTime = findViewById(R.id.time_view);
mAmPm = findViewById(R.id.am_pm_view);
- mKeyguardCarrierText = findViewById(R.id.keyguard_carrier_text);
mMultiUserSwitch = (MultiUserSwitch) findViewById(R.id.multi_user_switch);
mMultiUserAvatar = (ImageView) findViewById(R.id.multi_user_avatar);
mDateCollapsed = findViewById(R.id.date_collapsed);
@@ -187,7 +170,7 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
if (mCaptureValues) {
- if (mExpanded && !mOverscrolled) {
+ if (mExpanded) {
captureLayoutValues(mExpandedValues);
} else {
captureLayoutValues(mCollapsedValues);
@@ -207,18 +190,11 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
mCollapsedHeight = getResources().getDimensionPixelSize(R.dimen.status_bar_header_height);
mExpandedHeight = getResources().getDimensionPixelSize(
R.dimen.status_bar_header_height_expanded);
- mKeyguardHeight = getResources().getDimensionPixelSize(
- R.dimen.status_bar_header_height_keyguard);
- mNormalWidth = getLayoutParams().width;
- mPadding = getResources().getDimensionPixelSize(R.dimen.notification_side_padding);
mMultiUserExpandedMargin =
getResources().getDimensionPixelSize(R.dimen.multi_user_switch_expanded_margin);
mMultiUserCollapsedMargin =
getResources().getDimensionPixelSize(R.dimen.multi_user_switch_collapsed_margin);
- mMultiUserKeyguardMargin =
- getResources().getDimensionPixelSize(R.dimen.multi_user_switch_keyguard_margin);
- mSystemIconsSwitcherHiddenExpandedMargin = getResources().getDimensionPixelSize(
- R.dimen.system_icons_switcher_hidden_expanded_margin);
+
mClockMarginBottomExpanded =
getResources().getDimensionPixelSize(R.dimen.clock_expanded_bottom_margin);
mClockMarginBottomCollapsed =
@@ -227,23 +203,12 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
getResources().getDimensionPixelSize(R.dimen.multi_user_switch_width_collapsed);
mMultiUserSwitchWidthExpanded =
getResources().getDimensionPixelSize(R.dimen.multi_user_switch_width_expanded);
- mMultiUserSwitchWidthKeyguard =
- getResources().getDimensionPixelSize(R.dimen.multi_user_switch_width_keyguard);
mAvatarCollapsedScaleFactor =
getResources().getDimensionPixelSize(R.dimen.multi_user_avatar_collapsed_size)
/ (float) mMultiUserAvatar.getLayoutParams().width;
- mAvatarKeyguardScaleFactor =
- getResources().getDimensionPixelSize(R.dimen.multi_user_avatar_keyguard_size)
- / (float) mMultiUserAvatar.getLayoutParams().width;
mClockCollapsedScaleFactor =
(float) getResources().getDimensionPixelSize(R.dimen.qs_time_collapsed_size)
/ (float) getResources().getDimensionPixelSize(R.dimen.qs_time_expanded_size);
- mBatteryPaddingEnd =
- getResources().getDimensionPixelSize(R.dimen.battery_level_padding_end);
- mBatteryMarginExpanded =
- getResources().getDimensionPixelSize(R.dimen.header_battery_margin_expanded);
- mBatteryMarginKeyguard =
- getResources().getDimensionPixelSize(R.dimen.header_battery_margin_keyguard);
}
public void setActivityStarter(ActivityStarter activityStarter) {
@@ -259,7 +224,7 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
}
public int getCollapsedHeight() {
- return mKeyguardShowing ? mKeyguardHeight : mCollapsedHeight;
+ return mCollapsedHeight;
}
public int getExpandedHeight() {
@@ -274,130 +239,73 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
updateListeners();
}
- public void setExpanded(boolean expanded, boolean overscrolled) {
+ public void setExpanded(boolean expanded) {
boolean changed = expanded != mExpanded;
- boolean overscrollChanged = overscrolled != mOverscrolled;
mExpanded = expanded;
- mOverscrolled = overscrolled;
- if (changed || overscrollChanged) {
+ if (changed) {
updateHeights();
updateVisibilities();
updateSystemIconsLayoutParams();
- updateZTranslation();
updateClickTargets();
- updateWidth();
- updatePadding();
updateMultiUserSwitch();
if (mQSPanel != null) {
- mQSPanel.setExpanded(expanded && !overscrolled);
+ mQSPanel.setExpanded(expanded);
}
updateClockScale();
updateAvatarScale();
updateClockLp();
- updateBatteryLevelPaddingEnd();
- updateBatteryLevelLp();
requestCaptureValues();
}
}
private void updateHeights() {
- boolean onKeyguardAndCollapsed = mKeyguardShowing && !mExpanded;
- int height;
- if (mExpanded && !mOverscrolled) {
- height = mExpandedHeight;
- } else if (onKeyguardAndCollapsed) {
- height = mKeyguardHeight;
- } else {
- height = mCollapsedHeight;
- }
+ int height = mExpanded ? mExpandedHeight : mCollapsedHeight;
ViewGroup.LayoutParams lp = getLayoutParams();
if (lp.height != height) {
lp.height = height;
setLayoutParams(lp);
}
- int systemIconsContainerHeight = onKeyguardAndCollapsed ? mKeyguardHeight : mCollapsedHeight;
- lp = mSystemIconsSuperContainer.getLayoutParams();
- if (lp.height != systemIconsContainerHeight) {
- lp.height = systemIconsContainerHeight;
- mSystemIconsSuperContainer.setLayoutParams(lp);
- }
- lp = mMultiUserSwitch.getLayoutParams();
- if (lp.height != systemIconsContainerHeight) {
- lp.height = systemIconsContainerHeight;
- mMultiUserSwitch.setLayoutParams(lp);
- }
- }
-
- private void updateWidth() {
- int width = (mKeyguardShowing && !mExpanded) ? mKeyguardWidth : mNormalWidth;
- ViewGroup.LayoutParams lp = getLayoutParams();
- if (width != lp.width) {
- lp.width = width;
- setLayoutParams(lp);
- }
}
private void updateVisibilities() {
- boolean onKeyguardAndCollapsed = mKeyguardShowing && !mExpanded;
- if (onKeyguardAndCollapsed) {
- setBackground(null);
- } else {
- setBackgroundResource(R.drawable.notification_header_bg);
- }
- mDateGroup.setVisibility(onKeyguardAndCollapsed ? View.INVISIBLE : View.VISIBLE);
- mClock.setVisibility(onKeyguardAndCollapsed ? View.INVISIBLE : View.VISIBLE);
- mKeyguardCarrierText.setVisibility(onKeyguardAndCollapsed ? View.VISIBLE : View.GONE);
- mDateCollapsed.setVisibility(mExpanded && !mOverscrolled && mAlarmShowing
- ? View.VISIBLE : View.INVISIBLE);
- mDateExpanded.setVisibility(mExpanded && !mOverscrolled && mAlarmShowing
- ? View.INVISIBLE : View.VISIBLE);
- mAlarmStatus.setVisibility(mExpanded && !mOverscrolled && mAlarmShowing
- ? View.VISIBLE : View.INVISIBLE);
- mSettingsButton.setVisibility(mExpanded && !mOverscrolled ? View.VISIBLE : View.INVISIBLE);
+ mDateCollapsed.setVisibility(mExpanded && mAlarmShowing ? View.VISIBLE : View.INVISIBLE);
+ mDateExpanded.setVisibility(mExpanded && mAlarmShowing ? View.INVISIBLE : View.VISIBLE);
+ mAlarmStatus.setVisibility(mExpanded && mAlarmShowing ? View.VISIBLE : View.INVISIBLE);
+ mSettingsButton.setVisibility(mExpanded ? View.VISIBLE : View.INVISIBLE);
mQsDetailHeader.setVisibility(mExpanded ? View.VISIBLE : View.GONE);
- if (mStatusIcons != null) {
- mStatusIcons.setVisibility(mKeyguardShowing && (!mExpanded || mOverscrolled)
- ? View.VISIBLE : View.GONE);
- }
if (mSignalCluster != null) {
updateSignalClusterDetachment();
}
- mEmergencyCallsOnly.setVisibility(mExpanded && !mOverscrolled && mShowEmergencyCallsOnly
- ? VISIBLE : GONE);
- mMultiUserSwitch.setVisibility(mExpanded || !mKeyguardUserSwitcherShowing
- ? VISIBLE : GONE);
- mBatteryLevel.setVisibility(mKeyguardShowing && mCharging || mExpanded && !mOverscrolled
- ? View.VISIBLE : View.GONE);
- if (mExpanded && !mOverscrolled && mKeyguardUserSwitcherShowing) {
- mKeyguardUserSwitcher.hide();
- }
+ mEmergencyCallsOnly.setVisibility(mExpanded && mShowEmergencyCallsOnly ? VISIBLE : GONE);
+ mBatteryLevel.setVisibility(mExpanded ? View.VISIBLE : View.GONE);
}
private void updateSignalClusterDetachment() {
- boolean detached = mExpanded && !mOverscrolled;
+ boolean detached = mExpanded;
if (detached != mSignalClusterDetached) {
if (detached) {
getOverlay().add(mSignalCluster);
} else {
- getOverlay().remove(mSignalCluster);
- mSystemIcons.addView(mSignalCluster, 1);
+ reattachSignalCluster();
}
}
mSignalClusterDetached = detached;
}
+ private void reattachSignalCluster() {
+ getOverlay().remove(mSignalCluster);
+ mSystemIcons.addView(mSignalCluster, 1);
+ }
+
private void updateSystemIconsLayoutParams() {
RelativeLayout.LayoutParams lp = (LayoutParams) mSystemIconsSuperContainer.getLayoutParams();
- lp.addRule(RelativeLayout.START_OF, mExpanded && !mOverscrolled
+ int rule = mExpanded
? mSettingsButton.getId()
- : mMultiUserSwitch.getId());
- lp.removeRule(ALIGN_PARENT_START);
- if (mMultiUserSwitch.getVisibility() == GONE) {
- lp.setMarginEnd(mSystemIconsSwitcherHiddenExpandedMargin);
- } else {
- lp.setMarginEnd(0);
+ : mMultiUserSwitch.getId();
+ if (rule != lp.getRules()[RelativeLayout.START_OF]) {
+ lp.addRule(RelativeLayout.START_OF, rule);
+ mSystemIconsSuperContainer.setLayoutParams(lp);
}
- mSystemIconsSuperContainer.setLayoutParams(lp);
}
private void updateListeners() {
@@ -411,12 +319,9 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
}
private void updateAvatarScale() {
- if (mExpanded && !mOverscrolled) {
+ if (mExpanded) {
mMultiUserAvatar.setScaleX(1f);
mMultiUserAvatar.setScaleY(1f);
- } else if (mKeyguardShowing) {
- mMultiUserAvatar.setScaleX(mAvatarKeyguardScaleFactor);
- mMultiUserAvatar.setScaleY(mAvatarKeyguardScaleFactor);
} else {
mMultiUserAvatar.setScaleX(mAvatarCollapsedScaleFactor);
mMultiUserAvatar.setScaleY(mAvatarCollapsedScaleFactor);
@@ -432,7 +337,7 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
}
private float getTimeScale() {
- return !mExpanded || mOverscrolled ? mClockCollapsedScaleFactor : 1f;
+ return !mExpanded ? mClockCollapsedScaleFactor : 1f;
}
private void updateAmPmTranslation() {
@@ -440,20 +345,9 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
mAmPm.setTranslationX((rtl ? 1 : -1) * mTime.getWidth() * (1 - mTime.getScaleX()));
}
- private void updateBatteryLevelPaddingEnd() {
- mBatteryLevel.setPaddingRelative(0, 0,
- mKeyguardShowing && !mExpanded ? 0 : mBatteryPaddingEnd, 0);
- }
-
@Override
public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
mBatteryLevel.setText(getResources().getString(R.string.battery_level_template, level));
- boolean changed = mCharging != charging;
- mCharging = charging;
- if (changed) {
- updateVisibilities();
- requestCaptureValues();
- }
}
@Override
@@ -472,37 +366,14 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
requestCaptureValues();
}
-
private void updateClickTargets() {
- setClickable(!mKeyguardShowing || mExpanded);
-
- boolean keyguardSwitcherAvailable =
- mKeyguardUserSwitcher != null && mKeyguardShowing && !mExpanded;
- mMultiUserSwitch.setClickable(mExpanded || keyguardSwitcherAvailable);
- mMultiUserSwitch.setKeyguardMode(keyguardSwitcherAvailable);
+ mMultiUserSwitch.setClickable(mExpanded);
mSystemIconsSuperContainer.setClickable(mExpanded);
mAlarmStatus.setClickable(mNextAlarm != null && mNextAlarm.getShowIntent() != null);
}
- private void updateZTranslation() {
-
- // If we are on the Keyguard, we need to set our z position to zero, so we don't get
- // shadows.
- if (mKeyguardShowing && !mExpanded) {
- setZ(0);
- } else {
- setTranslationZ(0);
- }
- }
-
- private void updatePadding() {
- boolean padded = !mKeyguardShowing || mExpanded;
- int padding = padded ? mPadding : 0;
- setPaddingRelative(padding, 0, padding, 0);
- }
-
private void updateClockLp() {
- int marginBottom = mExpanded && !mOverscrolled
+ int marginBottom = mExpanded
? mClockMarginBottomExpanded
: mClockMarginBottomCollapsed;
LayoutParams lp = (LayoutParams) mDateGroup.getLayoutParams();
@@ -515,12 +386,9 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
private void updateMultiUserSwitch() {
int marginEnd;
int width;
- if (mExpanded && !mOverscrolled) {
+ if (mExpanded) {
marginEnd = mMultiUserExpandedMargin;
width = mMultiUserSwitchWidthExpanded;
- } else if (mKeyguardShowing) {
- marginEnd = mMultiUserKeyguardMargin;
- width = mMultiUserSwitchWidthKeyguard;
} else {
marginEnd = mMultiUserCollapsedMargin;
width = mMultiUserSwitchWidthCollapsed;
@@ -533,19 +401,8 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
}
}
- private void updateBatteryLevelLp() {
- int marginStart = mExpanded && !mOverscrolled
- ? mBatteryMarginExpanded
- : mBatteryMarginKeyguard;
- MarginLayoutParams lp = (MarginLayoutParams) mBatteryLevel.getLayoutParams();
- if (marginStart != lp.getMarginStart()) {
- lp.setMarginStart(marginStart);
- mBatteryLevel.setLayoutParams(lp);
- }
- }
-
public void setExpansion(float t) {
- if (mOverscrolled) {
+ if (!mExpanded) {
t = 0f;
}
mCurrentT = t;
@@ -580,12 +437,18 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
mSignalCluster = systemIcons.findViewById(R.id.signal_cluster);
mSystemIcons = systemIcons;
updateVisibilities();
+ if (mStatusIcons != null) {
+ mStatusIcons.setVisibility(View.GONE);
+ }
}
public void onSystemIconsDetached() {
+ if (mSignalClusterDetached) {
+ reattachSignalCluster();
+ mSignalClusterDetached = false;
+ }
if (mStatusIcons != null) {
mStatusIcons.setVisibility(View.VISIBLE);
- mStatusIcons.setAlpha(1f);
}
if (mSignalCluster != null) {
mSignalCluster.setVisibility(View.VISIBLE);
@@ -598,20 +461,6 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
mSystemIcons = null;
}
- public void setKeyguardShowing(boolean keyguardShowing) {
- mKeyguardShowing = keyguardShowing;
- updateHeights();
- updateWidth();
- updateVisibilities();
- updateZTranslation();
- updatePadding();
- updateMultiUserSwitch();
- updateClickTargets();
- updateBatteryLevelPaddingEnd();
- updateAvatarScale();
- mCaptureValues = true;
- }
-
public void setUserInfoController(UserInfoController userInfoController) {
userInfoController.addListener(new UserInfoController.OnUserInfoChangedListener() {
@Override
@@ -651,11 +500,6 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
mMultiUserSwitch.setQsPanel(qsp);
}
- public void setKeyguarUserSwitcher(KeyguardUserSwitcher keyguardUserSwitcher) {
- mKeyguardUserSwitcher = keyguardUserSwitcher;
- mMultiUserSwitch.setKeyguardUserSwitcher(keyguardUserSwitcher);
- }
-
@Override
public boolean shouldDelayChildPressedState() {
return true;
@@ -665,20 +509,10 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
mShowEmergencyCallsOnly = show;
if (mExpanded) {
updateVisibilities();
+ requestCaptureValues();
}
}
- public void setKeyguardUserSwitcherShowing(boolean showing) {
- mKeyguardUserSwitcherShowing = showing;
- updateVisibilities();
- updateSystemIconsLayoutParams();
- }
-
- @Override
- public boolean hasOverlappingRendering() {
- return !mKeyguardShowing || mExpanded;
- }
-
@Override
protected void dispatchSetPressed(boolean pressed) {
// We don't want that everything lights up when we click on the header, so block the request
@@ -700,11 +534,11 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
target.batteryY = mSystemIconsSuperContainer.getTop() + mSystemIconsContainer.getTop();
target.batteryLevelAlpha = getAlphaForVisibility(mBatteryLevel);
target.settingsAlpha = getAlphaForVisibility(mSettingsButton);
- target.settingsTranslation = mExpanded && !mOverscrolled
+ target.settingsTranslation = mExpanded
? 0
: mMultiUserSwitch.getLeft() - mSettingsButton.getLeft();
target.signalClusterAlpha = mSignalClusterDetached ? 0f : 1f;
- target.settingsRotation = !mExpanded || mOverscrolled ? 90f : 0f;
+ target.settingsRotation = !mExpanded ? 90f : 0f;
}
private float getAlphaForVisibility(View v) {
@@ -735,7 +569,7 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
mMultiUserAvatar.setY(values.avatarY - mMultiUserSwitch.getTop());
mSystemIconsSuperContainer.setX(values.batteryX - mSystemIconsContainer.getRight());
mSystemIconsSuperContainer.setY(values.batteryY - mSystemIconsContainer.getTop());
- if (mSignalCluster != null && mExpanded && !mOverscrolled) {
+ if (mSignalCluster != null && mExpanded) {
mSignalCluster.setX(mSystemIconsSuperContainer.getX()
- mSignalCluster.getWidth());
mSignalCluster.setY(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java
index 2be566c..6795842 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java
@@ -16,10 +16,6 @@
package com.android.systemui.statusbar.policy;
-import com.android.systemui.R;
-import com.android.systemui.statusbar.phone.StatusBarHeaderView;
-import com.android.systemui.statusbar.phone.UserAvatarView;
-
import android.content.Context;
import android.database.DataSetObserver;
import android.provider.Settings;
@@ -29,6 +25,10 @@ import android.view.ViewGroup;
import android.view.ViewStub;
import android.widget.TextView;
+import com.android.systemui.R;
+import com.android.systemui.statusbar.phone.KeyguardStatusBarView;
+import com.android.systemui.statusbar.phone.UserAvatarView;
+
/**
* Manages the user switcher on the Keyguard.
*/
@@ -40,23 +40,23 @@ public class KeyguardUserSwitcher {
"lockscreenSimpleUserSwitcher";
private final ViewGroup mUserSwitcher;
- private final StatusBarHeaderView mHeader;
+ private final KeyguardStatusBarView mStatusBarView;
private final Adapter mAdapter;
private final boolean mSimpleUserSwitcher;
public KeyguardUserSwitcher(Context context, ViewStub userSwitcher,
- StatusBarHeaderView header, UserSwitcherController userSwitcherController) {
+ KeyguardStatusBarView statusBarView, UserSwitcherController userSwitcherController) {
if (context.getResources().getBoolean(R.bool.config_keyguardUserSwitcher) || ALWAYS_ON) {
mUserSwitcher = (ViewGroup) userSwitcher.inflate();
- mHeader = header;
- mHeader.setKeyguarUserSwitcher(this);
+ mStatusBarView = statusBarView;
+ mStatusBarView.setKeyguardUserSwitcher(this);
mAdapter = new Adapter(context, userSwitcherController);
mAdapter.registerDataSetObserver(mDataSetObserver);
mSimpleUserSwitcher = Settings.Global.getInt(context.getContentResolver(),
SIMPLE_USER_SWITCHER_GLOBAL_SETTING, 0) != 0;
} else {
mUserSwitcher = null;
- mHeader = null;
+ mStatusBarView = null;
mAdapter = null;
mSimpleUserSwitcher = false;
}
@@ -84,7 +84,7 @@ public class KeyguardUserSwitcher {
if (mUserSwitcher != null) {
// TODO: animate
mUserSwitcher.setVisibility(View.VISIBLE);
- mHeader.setKeyguardUserSwitcherShowing(true);
+ mStatusBarView.setKeyguardUserSwitcherShowing(true);
}
}
@@ -92,7 +92,7 @@ public class KeyguardUserSwitcher {
if (mUserSwitcher != null) {
// TODO: animate
mUserSwitcher.setVisibility(View.GONE);
- mHeader.setKeyguardUserSwitcherShowing(false);
+ mStatusBarView.setKeyguardUserSwitcherShowing(false);
}
}
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index fdc91a4..ff3cd9d 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -50,7 +50,6 @@ import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.media.AudioManager;
import android.media.session.MediaController;
-import android.media.session.MediaSession;
import android.media.session.MediaSessionLegacyHelper;
import android.net.Uri;
import android.os.Bundle;
@@ -63,6 +62,7 @@ import android.transition.Scene;
import android.transition.Transition;
import android.transition.TransitionInflater;
import android.transition.TransitionManager;
+import android.transition.TransitionSet;
import android.util.AndroidRuntimeException;
import android.util.DisplayMetrics;
import android.util.EventLog;
@@ -126,6 +126,8 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
(1 << FEATURE_CONTENT_TRANSITIONS) |
(1 << FEATURE_ACTION_MODE_OVERLAY);
+ private static final Transition USE_DEFAULT_TRANSITION = new TransitionSet();
+
/**
* Simple callback used by the context menu and its submenus. The options
* menu submenus do not use this (their behavior is more complex).
@@ -254,10 +256,14 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
}
};
- private Transition mEnterTransition;
- private Transition mExitTransition;
- private Transition mSharedElementEnterTransition;
- private Transition mSharedElementExitTransition;
+ private Transition mEnterTransition = null;
+ private Transition mReturnTransition = USE_DEFAULT_TRANSITION;
+ private Transition mExitTransition = null;
+ private Transition mReenterTransition = USE_DEFAULT_TRANSITION;
+ private Transition mSharedElementEnterTransition = null;
+ private Transition mSharedElementReturnTransition = USE_DEFAULT_TRANSITION;
+ private Transition mSharedElementExitTransition = null;
+ private Transition mSharedElementReenterTransition = USE_DEFAULT_TRANSITION;
private Boolean mAllowExitTransitionOverlap;
private Boolean mAllowEnterTransitionOverlap;
private long mBackgroundFadeDurationMillis = -1;
@@ -3513,40 +3519,47 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
}
}
- mEnterTransition = getTransition(mEnterTransition,
+ mEnterTransition = getTransition(mEnterTransition, null,
R.styleable.Window_windowEnterTransition);
- mExitTransition = getTransition(mExitTransition,
+ mReturnTransition = getTransition(mReturnTransition, USE_DEFAULT_TRANSITION,
+ R.styleable.Window_windowReturnTransition);
+ mExitTransition = getTransition(mExitTransition, null,
R.styleable.Window_windowExitTransition);
- mSharedElementEnterTransition = getTransition(mSharedElementEnterTransition,
+ mReenterTransition = getTransition(mReenterTransition, USE_DEFAULT_TRANSITION,
+ R.styleable.Window_windowReenterTransition);
+ mSharedElementEnterTransition = getTransition(mSharedElementEnterTransition, null,
R.styleable.Window_windowSharedElementEnterTransition);
- mSharedElementExitTransition = getTransition(mSharedElementExitTransition,
+ mSharedElementReturnTransition = getTransition(mSharedElementReturnTransition,
+ USE_DEFAULT_TRANSITION,
+ R.styleable.Window_windowSharedElementReturnTransition);
+ mSharedElementExitTransition = getTransition(mSharedElementExitTransition, null,
R.styleable.Window_windowSharedElementExitTransition);
+ mSharedElementReenterTransition = getTransition(mSharedElementReenterTransition,
+ USE_DEFAULT_TRANSITION,
+ R.styleable.Window_windowSharedElementReenterTransition);
if (mAllowEnterTransitionOverlap == null) {
mAllowEnterTransitionOverlap = getWindowStyle().getBoolean(
- R.styleable.
- Window_windowAllowEnterTransitionOverlap, true);
+ R.styleable.Window_windowAllowEnterTransitionOverlap, true);
}
if (mAllowExitTransitionOverlap == null) {
mAllowExitTransitionOverlap = getWindowStyle().getBoolean(
- R.styleable.
- Window_windowAllowExitTransitionOverlap, true);
+ R.styleable.Window_windowAllowExitTransitionOverlap, true);
}
if (mBackgroundFadeDurationMillis < 0) {
mBackgroundFadeDurationMillis = getWindowStyle().getInteger(
- R.styleable.
- Window_windowTransitionBackgroundFadeDuration,
+ R.styleable.Window_windowTransitionBackgroundFadeDuration,
DEFAULT_BACKGROUND_FADE_DURATION_MS);
}
}
}
}
- private Transition getTransition(Transition currentValue, int id) {
- if (currentValue != null) {
+ private Transition getTransition(Transition currentValue, Transition defaultValue, int id) {
+ if (currentValue != defaultValue) {
return currentValue;
}
int transitionId = getWindowStyle().getResourceId(id, -1);
- Transition transition = null;
+ Transition transition = defaultValue;
if (transitionId != -1 && transitionId != R.transition.no_transition) {
TransitionInflater inflater = TransitionInflater.from(getContext());
transition = inflater.inflateTransition(transitionId);
@@ -3899,41 +3912,85 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
}
@Override
+ public void setReturnTransition(Transition transition) {
+ mReturnTransition = transition;
+ }
+
+ @Override
public void setExitTransition(Transition exitTransition) {
mExitTransition = exitTransition;
}
@Override
+ public void setReenterTransition(Transition transition) {
+ mReenterTransition = transition;
+ }
+
+ @Override
public void setSharedElementEnterTransition(Transition sharedElementEnterTransition) {
mSharedElementEnterTransition = sharedElementEnterTransition;
}
@Override
+ public void setSharedElementReturnTransition(Transition transition) {
+ mSharedElementReturnTransition = transition;
+ }
+
+ @Override
public void setSharedElementExitTransition(Transition sharedElementExitTransition) {
mSharedElementExitTransition = sharedElementExitTransition;
}
@Override
+ public void setSharedElementReenterTransition(Transition transition) {
+ mSharedElementReenterTransition = transition;
+ }
+
+ @Override
public Transition getEnterTransition() {
return mEnterTransition;
}
@Override
+ public Transition getReturnTransition() {
+ return mReturnTransition == USE_DEFAULT_TRANSITION ? getEnterTransition()
+ : mReturnTransition;
+ }
+
+ @Override
public Transition getExitTransition() {
return mExitTransition;
}
@Override
+ public Transition getReenterTransition() {
+ return mReenterTransition == USE_DEFAULT_TRANSITION ? getExitTransition()
+ : mReenterTransition;
+ }
+
+ @Override
public Transition getSharedElementEnterTransition() {
return mSharedElementEnterTransition;
}
@Override
+ public Transition getSharedElementReturnTransition() {
+ return mSharedElementReturnTransition == USE_DEFAULT_TRANSITION
+ ? getSharedElementEnterTransition() : mSharedElementReturnTransition;
+ }
+
+ @Override
public Transition getSharedElementExitTransition() {
return mSharedElementExitTransition;
}
@Override
+ public Transition getSharedElementReenterTransition() {
+ return mSharedElementReenterTransition == USE_DEFAULT_TRANSITION
+ ? getSharedElementExitTransition() : mSharedElementReenterTransition;
+ }
+
+ @Override
public void setAllowEnterTransitionOverlap(boolean allow) {
mAllowEnterTransitionOverlap = allow;
}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 7aa69fd..5382489 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -556,6 +556,19 @@ public class ConnectivityService extends IConnectivityManager.Stub {
}
}
}
+
+ public void dump(IndentingPrintWriter pw) {
+ for (int type = 0; type < mTypeLists.length; type++) {
+ if (mTypeLists[type] == null) continue;
+ pw.print(type + " ");
+ pw.increaseIndent();
+ if (mTypeLists[type].size() == 0) pw.println("none");
+ for (NetworkAgentInfo nai : mTypeLists[type]) {
+ pw.println(nai.name());
+ }
+ pw.decreaseIndent();
+ }
+ }
}
private LegacyTypeTracker mLegacyTypeTracker = new LegacyTypeTracker();
@@ -1680,6 +1693,13 @@ public class ConnectivityService extends IConnectivityManager.Stub {
pw.println();
pw.decreaseIndent();
+ pw.println("mActiveDefaultNetwork:" + mActiveDefaultNetwork);
+ pw.println("mLegacyTypeTracker:");
+ pw.increaseIndent();
+ mLegacyTypeTracker.dump(pw);
+ pw.decreaseIndent();
+ pw.println();
+
synchronized (this) {
pw.println("NetworkTranstionWakeLock is currently " +
(mNetTransitionWakeLock.isHeld() ? "" : "not ") + "held.");
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 3a4e2ee..28a6917 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -482,33 +482,36 @@ public class LocationManagerService extends ILocationManager.Stub {
}
// bind to fused hardware provider if supported
+ // in devices without support, requesting an instance of FlpHardwareProvider will raise an
+ // exception, so make sure we only do that when supported
+ FlpHardwareProvider flpHardwareProvider;
if (FlpHardwareProvider.isSupported()) {
- FlpHardwareProvider flpHardwareProvider =
- FlpHardwareProvider.getInstance(mContext);
- FusedProxy fusedProxy = FusedProxy.createAndBind(
- mContext,
- mLocationHandler,
- flpHardwareProvider.getLocationHardware(),
- com.android.internal.R.bool.config_enableHardwareFlpOverlay,
- com.android.internal.R.string.config_hardwareFlpPackageName,
- com.android.internal.R.array.config_locationProviderPackageNames);
- if(fusedProxy == null) {
- Slog.e(TAG, "Unable to bind FusedProxy.");
- }
-
- // bind to geofence provider
- GeofenceProxy provider = GeofenceProxy.createAndBind(mContext,
- com.android.internal.R.bool.config_enableGeofenceOverlay,
- com.android.internal.R.string.config_geofenceProviderPackageName,
- com.android.internal.R.array.config_locationProviderPackageNames,
- mLocationHandler,
- gpsProvider.getGpsGeofenceProxy(),
- flpHardwareProvider.getGeofenceHardware());
- if (provider == null) {
- Slog.e(TAG, "Unable to bind FLP Geofence proxy.");
- }
+ flpHardwareProvider = FlpHardwareProvider.getInstance(mContext);
+ FusedProxy fusedProxy = FusedProxy.createAndBind(
+ mContext,
+ mLocationHandler,
+ flpHardwareProvider.getLocationHardware(),
+ com.android.internal.R.bool.config_enableHardwareFlpOverlay,
+ com.android.internal.R.string.config_hardwareFlpPackageName,
+ com.android.internal.R.array.config_locationProviderPackageNames);
+ if (fusedProxy == null) {
+ Slog.e(TAG, "Unable to bind FusedProxy.");
+ }
} else {
- Slog.e(TAG, "FLP HAL not supported.");
+ flpHardwareProvider = null;
+ Slog.e(TAG, "FLP HAL not supported");
+ }
+
+ // bind to geofence provider
+ GeofenceProxy provider = GeofenceProxy.createAndBind(
+ mContext,com.android.internal.R.bool.config_enableGeofenceOverlay,
+ com.android.internal.R.string.config_geofenceProviderPackageName,
+ com.android.internal.R.array.config_locationProviderPackageNames,
+ mLocationHandler,
+ gpsProvider.getGpsGeofenceProxy(),
+ flpHardwareProvider != null ? flpHardwareProvider.getGeofenceHardware() : null);
+ if (provider == null) {
+ Slog.e(TAG, "Unable to bind FLP Geofence proxy.");
}
// bind to the hardware activity recognition if supported
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index f59edc7..4c6b772 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -73,6 +73,7 @@ final class UiModeManagerService extends SystemService {
private boolean mTelevision;
private boolean mWatch;
private boolean mComputedNightMode;
+ private int mCarModeEnableFlags;
int mCurUiMode = 0;
private int mSetUiMode = 0;
@@ -193,7 +194,7 @@ final class UiModeManagerService extends SystemService {
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
- setCarModeLocked(true);
+ setCarModeLocked(true, flags);
if (mSystemReady) {
updateLocked(flags, 0);
}
@@ -208,7 +209,7 @@ final class UiModeManagerService extends SystemService {
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
- setCarModeLocked(false);
+ setCarModeLocked(false, 0);
if (mSystemReady) {
updateLocked(0, flags);
}
@@ -285,7 +286,8 @@ final class UiModeManagerService extends SystemService {
pw.print(" mLastBroadcastState="); pw.println(mLastBroadcastState);
pw.print(" mNightMode="); pw.print(mNightMode);
pw.print(" mCarModeEnabled="); pw.print(mCarModeEnabled);
- pw.print(" mComputedNightMode="); pw.println(mComputedNightMode);
+ pw.print(" mComputedNightMode="); pw.print(mComputedNightMode);
+ pw.print(" mCarModeEnableFlags="); pw.println(mCarModeEnableFlags);
pw.print(" mCurUiMode=0x"); pw.print(Integer.toHexString(mCurUiMode));
pw.print(" mSetUiMode=0x"); pw.println(Integer.toHexString(mSetUiMode));
pw.print(" mHoldingConfiguration="); pw.print(mHoldingConfiguration);
@@ -311,17 +313,18 @@ final class UiModeManagerService extends SystemService {
return mCarModeEnabled || mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED;
}
- void setCarModeLocked(boolean enabled) {
+ void setCarModeLocked(boolean enabled, int flags) {
if (mCarModeEnabled != enabled) {
mCarModeEnabled = enabled;
}
+ mCarModeEnableFlags = flags;
}
private void updateDockState(int newState) {
synchronized (mLock) {
if (newState != mDockState) {
mDockState = newState;
- setCarModeLocked(mDockState == Intent.EXTRA_DOCK_STATE_CAR);
+ setCarModeLocked(mDockState == Intent.EXTRA_DOCK_STATE_CAR, 0);
if (mSystemReady) {
updateLocked(UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME, 0);
}
@@ -475,7 +478,8 @@ final class UiModeManagerService extends SystemService {
// keep screen on when charging and in car mode
boolean keepScreenOn = mCharging &&
- ((mCarModeEnabled && mCarModeKeepsScreenOn) ||
+ ((mCarModeEnabled && mCarModeKeepsScreenOn &&
+ (mCarModeEnableFlags & UiModeManager.ENABLE_CAR_MODE_NO_WAKE_LOCK) == 0) ||
(mCurUiMode == Configuration.UI_MODE_TYPE_DESK && mDeskModeKeepsScreenOn));
if (keepScreenOn != mWakeLock.isHeld()) {
if (keepScreenOn) {
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 9a86136..2a66baf 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -3144,6 +3144,9 @@ public class AccountManagerService
DevicePolicyManager dpm = (DevicePolicyManager) mContext
.getSystemService(Context.DEVICE_POLICY_SERVICE);
String[] typesArray = dpm.getAccountTypesWithManagementDisabledAsUser(userId);
+ if (typesArray == null) {
+ return true;
+ }
for (String forbiddenType : typesArray) {
if (forbiddenType.equals(accountType)) {
return false;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index cfdf7cf..9a58c56 100755
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -3638,6 +3638,27 @@ public final class ActivityManagerService extends ActivityManagerNative
return ret;
}
+ //explicitly remove thd old information in mRecentTasks when removing existing user.
+ private void removeRecentTasksForUser(int userId) {
+ if(userId <= 0) {
+ Slog.i(TAG, "Can't remove recent task on user " + userId);
+ return;
+ }
+
+ for (int i = mRecentTasks.size() - 1; i >= 0; --i) {
+ TaskRecord tr = mRecentTasks.get(i);
+ if (tr.userId == userId) {
+ if(DEBUG_TASKS) Slog.i(TAG, "remove RecentTask " + tr
+ + " when finishing user" + userId);
+ tr.disposeThumbnail();
+ mRecentTasks.remove(i);
+ }
+ }
+
+ // Remove tasks from persistent storage.
+ mTaskPersister.wakeup(null, true);
+ }
+
final void addRecentTaskLocked(TaskRecord task) {
int N = mRecentTasks.size();
// Quick case: check if the top-most recent task is the same.
@@ -10966,11 +10987,17 @@ public final class ActivityManagerService extends ActivityManagerNative
int uid = r != null ? r.info.uid : Binder.getCallingUid();
if (!mController.appCrashed(name, pid,
shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
- Slog.w(TAG, "Force-killing crashed app " + name
- + " at watcher's request");
- Process.killProcess(pid);
- if (r != null) {
- Process.killProcessGroup(uid, pid);
+ if ("1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"))
+ && "Native crash".equals(crashInfo.exceptionClassName)) {
+ Slog.w(TAG, "Skip killing native crashed app " + name
+ + "(" + pid + ") during testing");
+ } else {
+ Slog.w(TAG, "Force-killing crashed app " + name
+ + " at watcher's request");
+ Process.killProcess(pid);
+ if (r != null) {
+ Process.killProcessGroup(uid, pid);
+ }
}
return;
}
@@ -17636,6 +17663,9 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
+ // Explicitly remove the old information in mRecentTasks.
+ removeRecentTasksForUser(userId);
+
for (int i=0; i<callbacks.size(); i++) {
try {
if (stopped) callbacks.get(i).userStopped(userId);
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 75df136..c5bc7d3 100755
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -1882,6 +1882,10 @@ final class ActivityStack {
boolean startIt = true;
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
task = mTaskHistory.get(taskNdx);
+ if (task.getTopActivity() == null) {
+ // All activities in task are finishing.
+ continue;
+ }
if (task == r.task) {
// Here it is! Now, if this is not yet visible to the
// user, then just add it without starting; it will
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index b9dd609..eddf414 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -684,6 +684,11 @@ public class Vpn {
if (((app.flags & ApplicationInfo.FLAG_SYSTEM) != 0) && (appId == app.uid)) {
return;
}
+ // SystemUI dialogs are also allowed to control VPN.
+ ApplicationInfo sysUiApp = pm.getApplicationInfo("com.android.systemui", 0);
+ if (((sysUiApp.flags & ApplicationInfo.FLAG_SYSTEM) != 0) && (appId == sysUiApp.uid)) {
+ return;
+ }
} catch (Exception e) {
// ignore
} finally {
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 390d121..bb9355e 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -281,7 +281,7 @@ public final class HdmiControlService extends SystemService {
// A container for [Logical Address, Local device info].
final SparseArray<HdmiCecLocalDevice> devices = new SparseArray<>();
final SparseIntArray finished = new SparseIntArray();
- mCecController.clearLogicalAddress();
+ clearLocalDevices();
for (int type : deviceTypes) {
final HdmiCecLocalDevice localDevice = HdmiCecLocalDevice.create(this, type);
localDevice.init();
@@ -1415,7 +1415,9 @@ public final class HdmiControlService extends SystemService {
devices.remove(device);
if (devices.isEmpty()) {
onStandbyCompleted();
- clearLocalDevices();
+ // We will not clear local devices here, since some OEM/SOC will keep passing
+ // the received packets until the application processor enters to the sleep
+ // actually.
}
}
});
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index a277f91..53006f3 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -50,6 +50,7 @@ import android.media.AudioManager;
import android.media.IRingtonePlayer;
import android.net.Uri;
import android.os.Binder;
+import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
@@ -1273,7 +1274,7 @@ public class NotificationManagerService extends SystemService {
final int N = mNotificationList.size();
for (int i=0; i<N; i++) {
StatusBarNotification sbn = mNotificationList.get(i).sbn;
- if (info.enabledAndUserMatches(sbn.getUserId())) {
+ if (isVisibleToListener(sbn, info)) {
list.add(sbn);
}
}
@@ -1625,7 +1626,6 @@ public class NotificationManagerService extends SystemService {
// Make sure we don't lose the foreground service state.
notification.flags |=
old.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE;
- mNotificationsByKey.remove(old.sbn.getKey());
r.isUpdate = true;
}
@@ -1643,7 +1643,8 @@ public class NotificationManagerService extends SystemService {
mRankingHelper.sort(mNotificationList);
if (notification.icon != 0) {
- mListeners.notifyPostedLocked(n);
+ StatusBarNotification oldSbn = (old != null) ? old.sbn : null;
+ mListeners.notifyPostedLocked(n, oldSbn);
} else {
Slog.e(TAG, "Not posting notification with icon==0: " + notification);
if (old != null && !old.isCanceled) {
@@ -2154,6 +2155,8 @@ public class NotificationManagerService extends SystemService {
break;
}
+ mNotificationsByKey.remove(r.sbn.getKey());
+
// Save it for users of getHistoricalNotifications()
mArchive.record(r.sbn);
}
@@ -2196,7 +2199,6 @@ public class NotificationManagerService extends SystemService {
}
mNotificationList.remove(index);
- mNotificationsByKey.remove(r.sbn.getKey());
cancelNotificationLocked(r, sendDelete, reason);
cancelGroupChildrenLocked(r, callingUid, callingPid, listenerName);
@@ -2272,7 +2274,6 @@ public class NotificationManagerService extends SystemService {
return true;
}
mNotificationList.remove(i);
- mNotificationsByKey.remove(r.sbn.getKey());
cancelNotificationLocked(r, false, reason);
}
if (doit && canceledNotifications != null) {
@@ -2312,7 +2313,6 @@ public class NotificationManagerService extends SystemService {
if ((r.getFlags() & (Notification.FLAG_ONGOING_EVENT
| Notification.FLAG_NO_CLEAR)) == 0) {
mNotificationList.remove(i);
- mNotificationsByKey.remove(r.sbn.getKey());
cancelNotificationLocked(r, true, reason);
// Make a note so we can cancel children later.
if (canceledNotifications == null) {
@@ -2333,7 +2333,7 @@ public class NotificationManagerService extends SystemService {
private void cancelGroupChildrenLocked(NotificationRecord r, int callingUid, int callingPid,
String listenerName) {
Notification n = r.getNotification();
- if (n.getGroup() == null || (n.flags & Notification.FLAG_GROUP_SUMMARY) == 0) {
+ if (!n.isGroupSummary()) {
return;
}
@@ -2356,7 +2356,6 @@ public class NotificationManagerService extends SystemService {
pkg, childSbn.getId(), childSbn.getTag(), userId, 0, 0,
REASON_GROUP_SUMMARY_CANCELED, listenerName);
mNotificationList.remove(i);
- mNotificationsByKey.remove(childR.getKey());
cancelNotificationLocked(childR, false, REASON_GROUP_SUMMARY_CANCELED);
}
}
@@ -2487,7 +2486,7 @@ public class NotificationManagerService extends SystemService {
ArrayList<String> interceptedKeys = new ArrayList<String>(N);
for (int i = 0; i < N; i++) {
NotificationRecord record = mNotificationList.get(i);
- if (!info.enabledAndUserMatches(record.sbn.getUserId())) {
+ if (!isVisibleToListener(record.sbn, info)) {
continue;
}
keys.add(record.sbn.getKey());
@@ -2504,6 +2503,17 @@ public class NotificationManagerService extends SystemService {
return new NotificationRankingUpdate(keysAr, interceptedKeysAr, speedBumpIndex);
}
+ private boolean isVisibleToListener(StatusBarNotification sbn, ManagedServiceInfo listener) {
+ if (!listener.enabledAndUserMatches(sbn.getUserId())) {
+ return false;
+ }
+ Notification n = sbn.getNotification();
+ if (listener.targetSdkVersion < Build.VERSION_CODES.L && n.isGroupChild()) {
+ return false;
+ }
+ return true;
+ }
+
public class NotificationListeners extends ManagedServices {
public NotificationListeners() {
@@ -2550,22 +2560,39 @@ public class NotificationManagerService extends SystemService {
/**
* asynchronously notify all listeners about a new notification
+ *
+ * <p>
+ * Also takes care of removing a notification that has been visible to a listener before,
+ * but isn't anymore.
*/
- public void notifyPostedLocked(StatusBarNotification sbn) {
+ public void notifyPostedLocked(StatusBarNotification sbn, StatusBarNotification oldSbn) {
// make a copy in case changes are made to the underlying Notification object
final StatusBarNotification sbnClone = sbn.clone();
for (final ManagedServiceInfo info : mServices) {
- if (!info.isEnabledForCurrentProfiles()) {
+ boolean sbnVisible = isVisibleToListener(sbn, info);
+ boolean oldSbnVisible = oldSbn != null ? isVisibleToListener(oldSbn, info) : false;
+ // This notification hasn't been and still isn't visible -> ignore.
+ if (!oldSbnVisible && !sbnVisible) {
continue;
}
final NotificationRankingUpdate update = makeRankingUpdateLocked(info);
- if (update.getOrderedKeys().length == 0) {
+
+ // This notification became invisible -> remove the old one.
+ if (oldSbnVisible && !sbnVisible) {
+ final StatusBarNotification oldSbnLightClone = oldSbn.cloneLight();
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ notifyRemoved(info, oldSbnLightClone, update);
+ }
+ });
continue;
}
+
mHandler.post(new Runnable() {
@Override
public void run() {
- notifyPostedIfUserMatch(info, sbnClone, update);
+ notifyPosted(info, sbnClone, update);
}
});
}
@@ -2580,14 +2607,14 @@ public class NotificationManagerService extends SystemService {
// notification
final StatusBarNotification sbnLight = sbn.cloneLight();
for (final ManagedServiceInfo info : mServices) {
- if (!info.isEnabledForCurrentProfiles()) {
+ if (!isVisibleToListener(sbn, info)) {
continue;
}
final NotificationRankingUpdate update = makeRankingUpdateLocked(info);
mHandler.post(new Runnable() {
@Override
public void run() {
- notifyRemovedIfUserMatch(info, sbnLight, update);
+ notifyRemoved(info, sbnLight, update);
}
});
}
@@ -2601,8 +2628,7 @@ public class NotificationManagerService extends SystemService {
if (!serviceInfo.isEnabledForCurrentProfiles()) {
continue;
}
- final NotificationRankingUpdate update =
- makeRankingUpdateLocked(serviceInfo);
+ final NotificationRankingUpdate update = makeRankingUpdateLocked(serviceInfo);
mHandler.post(new Runnable() {
@Override
public void run() {
@@ -2626,11 +2652,8 @@ public class NotificationManagerService extends SystemService {
}
}
- private void notifyPostedIfUserMatch(final ManagedServiceInfo info,
+ private void notifyPosted(final ManagedServiceInfo info,
final StatusBarNotification sbn, NotificationRankingUpdate rankingUpdate) {
- if (!info.enabledAndUserMatches(sbn.getUserId())) {
- return;
- }
final INotificationListener listener = (INotificationListener)info.service;
try {
listener.onNotificationPosted(sbn, rankingUpdate);
@@ -2639,7 +2662,7 @@ public class NotificationManagerService extends SystemService {
}
}
- private void notifyRemovedIfUserMatch(ManagedServiceInfo info, StatusBarNotification sbn,
+ private void notifyRemoved(ManagedServiceInfo info, StatusBarNotification sbn,
NotificationRankingUpdate rankingUpdate) {
if (!info.enabledAndUserMatches(sbn.getUserId())) {
return;
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 6036bcf..1650768 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -19,7 +19,22 @@ package com.android.server.pm;
import static android.content.pm.PackageManager.INSTALL_ALL_USERS;
import static android.content.pm.PackageManager.INSTALL_FROM_ADB;
import static android.content.pm.PackageManager.INSTALL_REPLACE_EXISTING;
-
+import static com.android.internal.util.XmlUtils.readBitmapAttribute;
+import static com.android.internal.util.XmlUtils.readBooleanAttribute;
+import static com.android.internal.util.XmlUtils.readIntAttribute;
+import static com.android.internal.util.XmlUtils.readLongAttribute;
+import static com.android.internal.util.XmlUtils.readStringAttribute;
+import static com.android.internal.util.XmlUtils.readUriAttribute;
+import static com.android.internal.util.XmlUtils.writeBitmapAttribute;
+import static com.android.internal.util.XmlUtils.writeBooleanAttribute;
+import static com.android.internal.util.XmlUtils.writeIntAttribute;
+import static com.android.internal.util.XmlUtils.writeLongAttribute;
+import static com.android.internal.util.XmlUtils.writeStringAttribute;
+import static com.android.internal.util.XmlUtils.writeUriAttribute;
+import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
+import static org.xmlpull.v1.XmlPullParser.START_TAG;
+
+import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.content.Context;
import android.content.pm.IPackageDeleteObserver;
@@ -29,9 +44,14 @@ import android.content.pm.IPackageInstallerSession;
import android.content.pm.InstallSessionInfo;
import android.content.pm.InstallSessionParams;
import android.content.pm.PackageManager;
+import android.graphics.Bitmap;
import android.os.Binder;
+import android.os.Environment;
import android.os.FileUtils;
+import android.os.Handler;
import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
import android.os.Process;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
@@ -40,30 +60,70 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.system.ErrnoException;
import android.system.Os;
+import android.text.format.DateUtils;
import android.util.ArraySet;
+import android.util.AtomicFile;
import android.util.ExceptionUtils;
+import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
+import android.util.Xml;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.IoThread;
+import com.android.server.pm.PackageInstallerSession.Snapshot;
import com.google.android.collect.Sets;
+import libcore.io.IoUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
+import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
+import java.util.Random;
public class PackageInstallerService extends IPackageInstaller.Stub {
private static final String TAG = "PackageInstaller";
+ private static final boolean LOGD = true;
- // TODO: destroy sessions with old timestamps
// TODO: remove outstanding sessions when installer package goes away
// TODO: notify listeners in other users when package has been installed there
+ /** XML constants used in {@link #mSessionsFile} */
+ private static final String TAG_SESSIONS = "sessions";
+ private static final String TAG_SESSION = "session";
+ private static final String ATTR_SESSION_ID = "sessionId";
+ private static final String ATTR_USER_ID = "userId";
+ private static final String ATTR_INSTALLER_PACKAGE_NAME = "installerPackageName";
+ private static final String ATTR_CREATED_MILLIS = "createdMillis";
+ private static final String ATTR_SESSION_STAGE_DIR = "sessionStageDir";
+ private static final String ATTR_SEALED = "sealed";
+ private static final String ATTR_MODE = "mode";
+ private static final String ATTR_INSTALL_FLAGS = "installFlags";
+ private static final String ATTR_INSTALL_LOCATION = "installLocation";
+ private static final String ATTR_SIZE_BYTES = "sizeBytes";
+ private static final String ATTR_APP_PACKAGE_NAME = "appPackageName";
+ private static final String ATTR_APP_ICON = "appIcon";
+ private static final String ATTR_APP_LABEL = "appLabel";
+ private static final String ATTR_ORIGINATING_URI = "originatingUri";
+ private static final String ATTR_REFERRER_URI = "referrerUri";
+ private static final String ATTR_ABI_OVERRIDE = "abiOverride";
+
+ private static final long MAX_AGE_MILLIS = 3 * DateUtils.DAY_IN_MILLIS;
+ private static final long MAX_ACTIVE_SESSIONS = 1024;
+
private final Context mContext;
private final PackageManagerService mPm;
private final AppOpsManager mAppOps;
@@ -71,10 +131,21 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
private final File mStagingDir;
private final HandlerThread mInstallThread;
- private final Callback mCallback = new Callback();
+ private final Callbacks mCallbacks;
+
+ /**
+ * File storing persisted {@link #mSessions}.
+ */
+ private final AtomicFile mSessionsFile;
+
+ private final InternalCallback mInternalCallback = new InternalCallback();
+
+ /**
+ * Used for generating session IDs. Since this is created at boot time,
+ * normal random might be predictable.
+ */
+ private final Random mRandom = new SecureRandom();
- @GuardedBy("mSessions")
- private int mNextSessionId;
@GuardedBy("mSessions")
private final SparseArray<PackageInstallerSession> mSessions = new SparseArray<>();
@@ -82,8 +153,6 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
@GuardedBy("mSessions")
private final SparseArray<PackageInstallerSession> mHistoricalSessions = new SparseArray<>();
- private RemoteCallbackList<IPackageInstallerCallback> mCallbacks = new RemoteCallbackList<>();
-
private static final FilenameFilter sStageFilter = new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
@@ -101,6 +170,11 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
mInstallThread = new HandlerThread(TAG);
mInstallThread.start();
+ mCallbacks = new Callbacks(mInstallThread.getLooper());
+
+ mSessionsFile = new AtomicFile(
+ new File(Environment.getSystemSecureDirectory(), "install_sessions.xml"));
+
synchronized (mSessions) {
readSessionsLocked();
@@ -133,13 +207,140 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
}
private void readSessionsLocked() {
- // TODO: implement persisting
+ if (LOGD) Slog.v(TAG, "readSessionsLocked()");
+
mSessions.clear();
- mNextSessionId = 1;
+
+ FileInputStream fis = null;
+ try {
+ fis = mSessionsFile.openRead();
+ final XmlPullParser in = Xml.newPullParser();
+ in.setInput(fis, null);
+
+ int type;
+ while ((type = in.next()) != END_DOCUMENT) {
+ if (type == START_TAG) {
+ final String tag = in.getName();
+ if (TAG_SESSION.equals(tag)) {
+ final PackageInstallerSession session = readSessionLocked(in);
+ final long age = System.currentTimeMillis() - session.createdMillis;
+
+ final boolean valid;
+ if (age >= MAX_AGE_MILLIS) {
+ Slog.w(TAG, "Abandoning old session first created at "
+ + session.createdMillis);
+ valid = false;
+ } else if (!session.sessionStageDir.exists()) {
+ Slog.w(TAG, "Abandoning session with missing stage "
+ + session.sessionStageDir);
+ valid = false;
+ } else {
+ valid = true;
+ }
+
+ if (valid) {
+ mSessions.put(session.sessionId, session);
+ } else {
+ // Since this is early during boot we don't send
+ // any observer events about the session, but we
+ // keep details around for dumpsys.
+ mHistoricalSessions.put(session.sessionId, session);
+ }
+ }
+ }
+ }
+ } catch (FileNotFoundException e) {
+ // Missing sessions are okay, probably first boot
+ } catch (IOException e) {
+ Log.wtf(TAG, "Failed reading install sessions", e);
+ } catch (XmlPullParserException e) {
+ Log.wtf(TAG, "Failed reading install sessions", e);
+ } finally {
+ IoUtils.closeQuietly(fis);
+ }
+ }
+
+ private PackageInstallerSession readSessionLocked(XmlPullParser in) throws IOException {
+ final int sessionId = readIntAttribute(in, ATTR_SESSION_ID);
+ final int userId = readIntAttribute(in, ATTR_USER_ID);
+ final String installerPackageName = readStringAttribute(in, ATTR_INSTALLER_PACKAGE_NAME);
+ final long createdMillis = readLongAttribute(in, ATTR_CREATED_MILLIS);
+ final File sessionStageDir = new File(readStringAttribute(in, ATTR_SESSION_STAGE_DIR));
+ final boolean sealed = readBooleanAttribute(in, ATTR_SEALED);
+
+ final InstallSessionParams params = new InstallSessionParams(
+ InstallSessionParams.MODE_INVALID);
+ params.mode = readIntAttribute(in, ATTR_MODE);
+ params.installFlags = readIntAttribute(in, ATTR_INSTALL_FLAGS);
+ params.installLocation = readIntAttribute(in, ATTR_INSTALL_LOCATION);
+ params.sizeBytes = readLongAttribute(in, ATTR_SIZE_BYTES);
+ params.appPackageName = readStringAttribute(in, ATTR_APP_PACKAGE_NAME);
+ params.appIcon = readBitmapAttribute(in, ATTR_APP_ICON);
+ params.appLabel = readStringAttribute(in, ATTR_APP_LABEL);
+ params.originatingUri = readUriAttribute(in, ATTR_ORIGINATING_URI);
+ params.referrerUri = readUriAttribute(in, ATTR_REFERRER_URI);
+ params.abiOverride = readStringAttribute(in, ATTR_ABI_OVERRIDE);
+
+ return new PackageInstallerSession(mInternalCallback, mPm, mInstallThread.getLooper(),
+ sessionId, userId, installerPackageName, params, createdMillis, sessionStageDir,
+ sealed);
}
private void writeSessionsLocked() {
- // TODO: implement persisting
+ if (LOGD) Slog.v(TAG, "writeSessionsLocked()");
+
+ FileOutputStream fos = null;
+ try {
+ fos = mSessionsFile.startWrite();
+
+ XmlSerializer out = new FastXmlSerializer();
+ out.setOutput(fos, "utf-8");
+ out.startDocument(null, true);
+ out.startTag(null, TAG_SESSIONS);
+ final int size = mSessions.size();
+ for (int i = 0; i < size; i++) {
+ final PackageInstallerSession session = mSessions.valueAt(i);
+ writeSessionLocked(out, session);
+ }
+ out.endTag(null, TAG_SESSIONS);
+ out.endDocument();
+
+ mSessionsFile.finishWrite(fos);
+ } catch (IOException e) {
+ if (fos != null) {
+ mSessionsFile.failWrite(fos);
+ }
+ }
+ }
+
+ private void writeSessionLocked(XmlSerializer out, PackageInstallerSession session)
+ throws IOException {
+ final InstallSessionParams params = session.params;
+ final Snapshot snapshot = session.snapshot();
+
+ out.startTag(null, TAG_SESSION);
+
+ writeIntAttribute(out, ATTR_SESSION_ID, session.sessionId);
+ writeIntAttribute(out, ATTR_USER_ID, session.userId);
+ writeStringAttribute(out, ATTR_INSTALLER_PACKAGE_NAME,
+ session.installerPackageName);
+ writeLongAttribute(out, ATTR_CREATED_MILLIS, session.createdMillis);
+ writeStringAttribute(out, ATTR_SESSION_STAGE_DIR,
+ session.sessionStageDir.getAbsolutePath());
+ writeBooleanAttribute(out, ATTR_SEALED, snapshot.sealed);
+
+ writeIntAttribute(out, ATTR_MODE, params.mode);
+ writeIntAttribute(out, ATTR_INSTALL_FLAGS, params.installFlags);
+ writeIntAttribute(out, ATTR_INSTALL_LOCATION, params.installLocation);
+ writeLongAttribute(out, ATTR_SIZE_BYTES, params.sizeBytes);
+ writeStringAttribute(out, ATTR_APP_PACKAGE_NAME, params.appPackageName);
+ writeBitmapAttribute(out, ATTR_APP_ICON, params.appIcon);
+ writeStringAttribute(out, ATTR_APP_LABEL, params.appLabel);
+ writeUriAttribute(out, ATTR_ORIGINATING_URI, params.originatingUri);
+ writeUriAttribute(out, ATTR_REFERRER_URI, params.referrerUri);
+ writeStringAttribute(out, ATTR_ABI_OVERRIDE, params.abiOverride);
+
+ out.endTag(null, TAG_SESSION);
}
private void writeSessionsAsync() {
@@ -163,8 +364,11 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
throw new SecurityException("User restriction prevents installing");
}
- if ((callingUid == Process.SHELL_UID) || (callingUid == 0)) {
+ if ((callingUid == Process.SHELL_UID) || (callingUid == Process.ROOT_UID)) {
+ installerPackageName = "com.android.shell";
+
params.installFlags |= INSTALL_FROM_ADB;
+
} else {
mAppOps.checkPackage(callingUid, installerPackageName);
@@ -181,6 +385,18 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
throw new IllegalArgumentException("Params must have valid mode set");
}
+ // Defensively resize giant app icons
+ if (params.appIcon != null) {
+ final ActivityManager am = (ActivityManager) mContext.getSystemService(
+ Context.ACTIVITY_SERVICE);
+ final int iconSize = am.getLauncherLargeIconSize();
+ if ((params.appIcon.getWidth() > iconSize * 2)
+ || (params.appIcon.getHeight() > iconSize * 2)) {
+ params.appIcon = Bitmap.createScaledBitmap(params.appIcon, iconSize, iconSize,
+ true);
+ }
+ }
+
// Sanity check that install could fit
if (params.sizeBytes > 0) {
try {
@@ -193,18 +409,24 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
final int sessionId;
final PackageInstallerSession session;
synchronized (mSessions) {
+ // Sanity check that installer isn't going crazy
+ final int activeCount = getSessionCountLocked(callingUid);
+ if (activeCount >= MAX_ACTIVE_SESSIONS) {
+ throw new IllegalStateException("Too many active sessions for UID " + callingUid);
+ }
+
sessionId = allocateSessionIdLocked();
final long createdMillis = System.currentTimeMillis();
final File sessionStageDir = prepareSessionStageDir(sessionId);
- session = new PackageInstallerSession(mCallback, mPm, sessionId, userId,
- installerPackageName, callingUid, params, createdMillis, sessionStageDir,
- mInstallThread.getLooper());
+ session = new PackageInstallerSession(mInternalCallback, mPm,
+ mInstallThread.getLooper(), sessionId, userId, installerPackageName, params,
+ createdMillis, sessionStageDir, false);
mSessions.put(sessionId, session);
}
- notifySessionCreated(session.generateInfo());
+ mCallbacks.notifySessionCreated(session.sessionId, session.userId);
writeSessionsAsync();
return sessionId;
}
@@ -216,25 +438,34 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
if (session == null) {
throw new IllegalStateException("Missing session " + sessionId);
}
- if (Binder.getCallingUid() != session.installerUid) {
+ if (!isCallingUidOwner(session)) {
throw new SecurityException("Caller has no access to session " + sessionId);
}
+ if (session.openCount.getAndIncrement() == 0) {
+ mCallbacks.notifySessionOpened(sessionId, session.userId);
+ }
return session;
}
}
private int allocateSessionIdLocked() {
- if (mSessions.get(mNextSessionId) != null) {
- throw new IllegalStateException("Next session already allocated");
- }
- return mNextSessionId++;
+ int n = 0;
+ int sessionId;
+ do {
+ sessionId = mRandom.nextInt(Integer.MAX_VALUE);
+ if (mSessions.get(sessionId) == null) {
+ return sessionId;
+ }
+ } while (n++ < 32);
+
+ throw new IllegalStateException("Failed to allocate session ID");
}
private File prepareSessionStageDir(int sessionId) {
final File file = new File(mStagingDir, "vmdl" + sessionId + ".tmp");
if (file.exists()) {
- throw new IllegalStateException();
+ throw new IllegalStateException("Session dir already exists: " + file);
}
try {
@@ -246,7 +477,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
}
if (!SELinux.restorecon(file)) {
- throw new IllegalStateException("Failed to prepare session dir");
+ throw new IllegalStateException("Failed to restorecon session dir");
}
return file;
@@ -256,9 +487,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
public InstallSessionInfo getSessionInfo(int sessionId) {
synchronized (mSessions) {
final PackageInstallerSession session = mSessions.get(sessionId);
- final boolean isOwner = (session != null)
- && (session.installerUid == Binder.getCallingUid());
- if (!isOwner) {
+ if (!isCallingUidOwner(session)) {
enforceCallerCanReadSessions();
}
return session != null ? session.generateInfo() : null;
@@ -323,7 +552,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "registerCallback");
enforceCallerCanReadSessions();
- mCallbacks.register(callback, new UserHandle(userId));
+ mCallbacks.register(callback, userId);
}
@Override
@@ -331,9 +560,24 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
mCallbacks.unregister(callback);
}
- private int getSessionUserId(int sessionId) {
- synchronized (mSessions) {
- return UserHandle.getUserId(mSessions.get(sessionId).installerUid);
+ private int getSessionCountLocked(int installerUid) {
+ int count = 0;
+ final int size = mSessions.size();
+ for (int i = 0; i < size; i++) {
+ final PackageInstallerSession session = mSessions.valueAt(i);
+ if (session.installerUid == installerUid) {
+ count++;
+ }
+ }
+ return count;
+ }
+
+ private boolean isCallingUidOwner(PackageInstallerSession session) {
+ final int callingUid = Binder.getCallingUid();
+ if (callingUid == Process.ROOT_UID) {
+ return true;
+ } else {
+ return (session != null) && (callingUid == session.installerUid);
}
}
@@ -352,53 +596,87 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
}
}
- private void notifySessionCreated(InstallSessionInfo info) {
- final int userId = getSessionUserId(info.sessionId);
- final int n = mCallbacks.beginBroadcast();
- for (int i = 0; i < n; i++) {
- final IPackageInstallerCallback callback = mCallbacks.getBroadcastItem(i);
- final UserHandle user = (UserHandle) mCallbacks.getBroadcastCookie(i);
- // TODO: dispatch notifications for slave profiles
- if (userId == user.getIdentifier()) {
- try {
- callback.onSessionCreated(info.sessionId);
- } catch (RemoteException ignored) {
- }
- }
+ private static class Callbacks extends Handler {
+ private static final int MSG_SESSION_CREATED = 1;
+ private static final int MSG_SESSION_OPENED = 2;
+ private static final int MSG_SESSION_PROGRESS_CHANGED = 3;
+ private static final int MSG_SESSION_CLOSED = 4;
+ private static final int MSG_SESSION_FINISHED = 5;
+
+ private final RemoteCallbackList<IPackageInstallerCallback>
+ mCallbacks = new RemoteCallbackList<>();
+
+ public Callbacks(Looper looper) {
+ super(looper);
}
- mCallbacks.finishBroadcast();
- }
- private void notifySessionProgressChanged(int sessionId, float progress) {
- final int userId = getSessionUserId(sessionId);
- final int n = mCallbacks.beginBroadcast();
- for (int i = 0; i < n; i++) {
- final IPackageInstallerCallback callback = mCallbacks.getBroadcastItem(i);
- final UserHandle user = (UserHandle) mCallbacks.getBroadcastCookie(i);
- if (userId == user.getIdentifier()) {
- try {
- callback.onSessionProgressChanged(sessionId, progress);
- } catch (RemoteException ignored) {
+ public void register(IPackageInstallerCallback callback, int userId) {
+ mCallbacks.register(callback, new UserHandle(userId));
+ }
+
+ public void unregister(IPackageInstallerCallback callback) {
+ mCallbacks.unregister(callback);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ final int userId = msg.arg2;
+ final int n = mCallbacks.beginBroadcast();
+ for (int i = 0; i < n; i++) {
+ final IPackageInstallerCallback callback = mCallbacks.getBroadcastItem(i);
+ final UserHandle user = (UserHandle) mCallbacks.getBroadcastCookie(i);
+ // TODO: dispatch notifications for slave profiles
+ if (userId == user.getIdentifier()) {
+ try {
+ invokeCallback(callback, msg);
+ } catch (RemoteException ignored) {
+ }
}
}
+ mCallbacks.finishBroadcast();
}
- mCallbacks.finishBroadcast();
- }
- private void notifySessionFinished(int sessionId, boolean success) {
- final int userId = getSessionUserId(sessionId);
- final int n = mCallbacks.beginBroadcast();
- for (int i = 0; i < n; i++) {
- final IPackageInstallerCallback callback = mCallbacks.getBroadcastItem(i);
- final UserHandle user = (UserHandle) mCallbacks.getBroadcastCookie(i);
- if (userId == user.getIdentifier()) {
- try {
- callback.onSessionFinished(sessionId, success);
- } catch (RemoteException ignored) {
- }
+ private void invokeCallback(IPackageInstallerCallback callback, Message msg)
+ throws RemoteException {
+ final int sessionId = msg.arg1;
+ switch (msg.what) {
+ case MSG_SESSION_CREATED:
+ callback.onSessionCreated(sessionId);
+ break;
+ case MSG_SESSION_OPENED:
+ callback.onSessionOpened(sessionId);
+ break;
+ case MSG_SESSION_PROGRESS_CHANGED:
+ callback.onSessionProgressChanged(sessionId, (float) msg.obj);
+ break;
+ case MSG_SESSION_CLOSED:
+ callback.onSessionClosed(sessionId);
+ break;
+ case MSG_SESSION_FINISHED:
+ callback.onSessionFinished(sessionId, (boolean) msg.obj);
+ break;
}
}
- mCallbacks.finishBroadcast();
+
+ private void notifySessionCreated(int sessionId, int userId) {
+ obtainMessage(MSG_SESSION_CREATED, sessionId, userId).sendToTarget();
+ }
+
+ private void notifySessionOpened(int sessionId, int userId) {
+ obtainMessage(MSG_SESSION_OPENED, sessionId, userId).sendToTarget();
+ }
+
+ private void notifySessionProgressChanged(int sessionId, int userId, float progress) {
+ obtainMessage(MSG_SESSION_PROGRESS_CHANGED, sessionId, userId, progress).sendToTarget();
+ }
+
+ private void notifySessionClosed(int sessionId, int userId) {
+ obtainMessage(MSG_SESSION_CLOSED, sessionId, userId).sendToTarget();
+ }
+
+ public void notifySessionFinished(int sessionId, int userId, boolean success) {
+ obtainMessage(MSG_SESSION_FINISHED, sessionId, userId, success).sendToTarget();
+ }
}
void dump(IndentingPrintWriter pw) {
@@ -427,13 +705,17 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
}
}
- class Callback {
+ class InternalCallback {
public void onSessionProgressChanged(PackageInstallerSession session, float progress) {
- notifySessionProgressChanged(session.sessionId, progress);
+ mCallbacks.notifySessionProgressChanged(session.sessionId, session.userId, progress);
+ }
+
+ public void onSessionClosed(PackageInstallerSession session) {
+ mCallbacks.notifySessionClosed(session.sessionId, session.userId);
}
public void onSessionFinished(PackageInstallerSession session, boolean success) {
- notifySessionFinished(session.sessionId, success);
+ mCallbacks.notifySessionFinished(session.sessionId, session.userId, success);
synchronized (mSessions) {
mSessions.remove(session.sessionId);
mHistoricalSessions.put(session.sessionId, session);
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 06e1d53..26019db 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -21,6 +21,7 @@ import static android.content.pm.PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_APK;
import static android.content.pm.PackageManager.INSTALL_FAILED_PACKAGE_CHANGED;
import static android.system.OsConstants.O_CREAT;
+import static android.system.OsConstants.O_RDONLY;
import static android.system.OsConstants.O_WRONLY;
import android.content.pm.ApplicationInfo;
@@ -40,7 +41,6 @@ import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.ParcelFileDescriptor;
-import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
import android.system.ErrnoException;
@@ -52,6 +52,7 @@ import android.util.ExceptionUtils;
import android.util.MathUtils;
import android.util.Slog;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
@@ -62,33 +63,64 @@ import java.io.File;
import java.io.FileDescriptor;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.concurrent.atomic.AtomicInteger;
public class PackageInstallerSession extends IPackageInstallerSession.Stub {
private static final String TAG = "PackageInstaller";
private static final boolean LOGD = true;
+ private static final int MSG_COMMIT = 0;
+
// TODO: enforce INSTALL_ALLOW_TEST
// TODO: enforce INSTALL_ALLOW_DOWNGRADE
// TODO: handle INSTALL_EXTERNAL, INSTALL_INTERNAL
// TODO: treat INHERIT_EXISTING as installExistingPackage()
- private final PackageInstallerService.Callback mCallback;
+ private final PackageInstallerService.InternalCallback mCallback;
private final PackageManagerService mPm;
private final Handler mHandler;
- public final int sessionId;
- public final int userId;
- public final String installerPackageName;
- /** UID not persisted */
- public final int installerUid;
- public final InstallSessionParams params;
- public final long createdMillis;
- public final File sessionStageDir;
+ final int sessionId;
+ final int userId;
+ final String installerPackageName;
+ final InstallSessionParams params;
+ final long createdMillis;
+ final File sessionStageDir;
- private static final int MSG_COMMIT = 0;
+ /** Note that UID is not persisted; it's always derived at runtime. */
+ final int installerUid;
+
+ AtomicInteger openCount = new AtomicInteger();
+
+ private final Object mLock = new Object();
+
+ @GuardedBy("mLock")
+ private float mClientProgress = 0;
+ @GuardedBy("mLock")
+ private float mProgress = 0;
+ @GuardedBy("mLock")
+ private float mReportedProgress = -1;
+
+ @GuardedBy("mLock")
+ private boolean mSealed = false;
+ @GuardedBy("mLock")
+ private boolean mPermissionsConfirmed = false;
+ @GuardedBy("mLock")
+ private boolean mDestroyed = false;
+
+ @GuardedBy("mLock")
+ private ArrayList<FileBridge> mBridges = new ArrayList<>();
- private Handler.Callback mHandlerCallback = new Handler.Callback() {
+ @GuardedBy("mLock")
+ private IPackageInstallObserver2 mRemoteObserver;
+
+ /** Fields derived from commit parsing */
+ private String mPackageName;
+ private int mVersionCode;
+ private Signature[] mSignatures;
+
+ private final Handler.Callback mHandlerCallback = new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
synchronized (mLock) {
@@ -114,27 +146,10 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
};
- private final Object mLock = new Object();
-
- private float mClientProgress;
- private float mProgress = 0;
-
- private String mPackageName;
- private int mVersionCode;
- private Signature[] mSignatures;
-
- private boolean mMutationsAllowed;
- private boolean mPermissionsConfirmed;
- private boolean mInvalid;
-
- private ArrayList<FileBridge> mBridges = new ArrayList<>();
-
- private IPackageInstallObserver2 mRemoteObserver;
-
- public PackageInstallerSession(PackageInstallerService.Callback callback,
- PackageManagerService pm, int sessionId, int userId, String installerPackageName,
- int installerUid, InstallSessionParams params, long createdMillis, File sessionStageDir,
- Looper looper) {
+ public PackageInstallerSession(PackageInstallerService.InternalCallback callback,
+ PackageManagerService pm, Looper looper, int sessionId, int userId,
+ String installerPackageName, InstallSessionParams params, long createdMillis,
+ File sessionStageDir, boolean sealed) {
mCallback = callback;
mPm = pm;
mHandler = new Handler(looper, mHandlerCallback);
@@ -142,24 +157,23 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
this.sessionId = sessionId;
this.userId = userId;
this.installerPackageName = installerPackageName;
- this.installerUid = installerUid;
this.params = params;
this.createdMillis = createdMillis;
this.sessionStageDir = sessionStageDir;
- // Check against any explicitly provided signatures
- mSignatures = params.signatures;
+ mSealed = sealed;
- // TODO: splice in flag when restoring persisted session
- mMutationsAllowed = true;
+ // Always derived at runtime
+ installerUid = mPm.getPackageUid(installerPackageName, userId);
- if (pm.checkPermission(android.Manifest.permission.INSTALL_PACKAGES, installerPackageName)
- == PackageManager.PERMISSION_GRANTED) {
- mPermissionsConfirmed = true;
- }
- if (installerUid == Process.SHELL_UID || installerUid == 0) {
+ if (mPm.checkPermission(android.Manifest.permission.INSTALL_PACKAGES,
+ installerPackageName) == PackageManager.PERMISSION_GRANTED) {
mPermissionsConfirmed = true;
+ } else {
+ mPermissionsConfirmed = false;
}
+
+ computeProgressLocked();
}
public InstallSessionInfo generateInfo() {
@@ -168,6 +182,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
info.sessionId = sessionId;
info.installerPackageName = installerPackageName;
info.progress = mProgress;
+ info.open = openCount.get() > 0;
info.mode = params.mode;
info.sizeBytes = params.sizeBytes;
@@ -178,16 +193,48 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
return info;
}
+ private void assertNotSealed(String cookie) {
+ synchronized (mLock) {
+ if (mSealed) {
+ throw new SecurityException(cookie + " not allowed after commit");
+ }
+ }
+ }
+
@Override
public void setClientProgress(float progress) {
- mClientProgress = progress;
- mProgress = MathUtils.constrain(mClientProgress * 0.8f, 0f, 0.8f);
- mCallback.onSessionProgressChanged(this, mProgress);
+ synchronized (mLock) {
+ mClientProgress = progress;
+ computeProgressLocked();
+ }
+ maybePublishProgress();
}
@Override
public void addClientProgress(float progress) {
- setClientProgress(mClientProgress + progress);
+ synchronized (mLock) {
+ mClientProgress += progress;
+ computeProgressLocked();
+ }
+ maybePublishProgress();
+ }
+
+ private void computeProgressLocked() {
+ mProgress = MathUtils.constrain(mClientProgress * 0.8f, 0f, 0.8f);
+ }
+
+ private void maybePublishProgress() {
+ // Only publish when meaningful change
+ if (Math.abs(mProgress - mReportedProgress) > 0.01) {
+ mReportedProgress = mProgress;
+ mCallback.onSessionProgressChanged(this, mProgress);
+ }
+ }
+
+ @Override
+ public String[] list() {
+ assertNotSealed("list");
+ return sessionStageDir.list();
}
@Override
@@ -208,9 +255,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
// will block any attempted install transitions.
final FileBridge bridge;
synchronized (mLock) {
- if (!mMutationsAllowed) {
- throw new IllegalStateException("Mutations not allowed");
- }
+ assertNotSealed("openWrite");
bridge = new FileBridge();
mBridges.add(bridge);
@@ -252,25 +297,51 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
@Override
+ public ParcelFileDescriptor openRead(String name) {
+ try {
+ return openReadInternal(name);
+ } catch (IOException e) {
+ throw ExceptionUtils.wrap(e);
+ }
+ }
+
+ private ParcelFileDescriptor openReadInternal(String name) throws IOException {
+ assertNotSealed("openRead");
+
+ try {
+ if (!FileUtils.isValidExtFilename(name)) {
+ throw new IllegalArgumentException("Invalid name: " + name);
+ }
+ final File target = new File(sessionStageDir, name);
+
+ final FileDescriptor targetFd = Libcore.os.open(target.getAbsolutePath(), O_RDONLY, 0);
+ return new ParcelFileDescriptor(targetFd);
+
+ } catch (ErrnoException e) {
+ throw e.rethrowAsIOException();
+ }
+ }
+
+ @Override
public void commit(IPackageInstallObserver2 observer) {
Preconditions.checkNotNull(observer);
mHandler.obtainMessage(MSG_COMMIT, observer).sendToTarget();
}
private void commitLocked() throws PackageManagerException {
- if (mInvalid) {
+ if (mDestroyed) {
throw new PackageManagerException(INSTALL_FAILED_ALREADY_EXISTS, "Invalid session");
}
// Verify that all writers are hands-off
- if (mMutationsAllowed) {
+ if (!mSealed) {
for (FileBridge bridge : mBridges) {
if (!bridge.isClosed()) {
throw new PackageManagerException(INSTALL_FAILED_PACKAGE_CHANGED,
"Files still open");
}
}
- mMutationsAllowed = false;
+ mSealed = true;
// TODO: persist disabled mutations before going forward, since
// beyond this point we may have hardlinks to the valid install
@@ -331,6 +402,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
private void validateInstallLocked() throws PackageManagerException {
mPackageName = null;
mVersionCode = -1;
+ mSignatures = null;
final File[] files = sessionStageDir.listFiles();
if (ArrayUtils.isEmpty(files)) {
@@ -461,7 +533,9 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
@Override
public void close() {
- // Currently ignored
+ if (openCount.decrementAndGet() == 0) {
+ mCallback.onSessionClosed(this);
+ }
}
@Override
@@ -475,7 +549,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
private void destroyInternal() {
synchronized (mLock) {
- mInvalid = true;
+ mSealed = true;
+ mDestroyed = true;
}
FileUtils.deleteContents(sessionStageDir);
sessionStageDir.delete();
@@ -496,11 +571,26 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
pw.printPair("mClientProgress", mClientProgress);
pw.printPair("mProgress", mProgress);
- pw.printPair("mMutationsAllowed", mMutationsAllowed);
+ pw.printPair("mSealed", mSealed);
pw.printPair("mPermissionsConfirmed", mPermissionsConfirmed);
+ pw.printPair("mDestroyed", mDestroyed);
pw.printPair("mBridges", mBridges.size());
pw.println();
pw.decreaseIndent();
}
+
+ Snapshot snapshot() {
+ return new Snapshot(this);
+ }
+
+ static class Snapshot {
+ final float clientProgress;
+ final boolean sealed;
+
+ public Snapshot(PackageInstallerSession session) {
+ clientProgress = session.mClientProgress;
+ sealed = session.mSealed;
+ }
+ }
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index ee6d4d0..2b55bf5 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -8257,11 +8257,11 @@ public class PackageManagerService extends IPackageManager.Stub {
// A restore should be performed at this point if (a) the install
// succeeded, (b) the operation is not an update, and (c) the new
- // package has a backupAgent defined.
+ // package has not opted out of backup participation.
final boolean update = res.removedInfo.removedPackage != null;
- boolean doRestore = (!update
- && res.pkg != null
- && res.pkg.applicationInfo.backupAgentName != null);
+ final int flags = (res.pkg == null) ? 0 : res.pkg.applicationInfo.flags;
+ boolean doRestore = !update
+ && ((flags & ApplicationInfo.FLAG_ALLOW_BACKUP) != 0);
// Set up the post-install work request bookkeeping. This will be used
// and cleaned up by the post-install event handling regardless of whether
diff --git a/services/core/java/com/android/server/tv/TvInputHal.java b/services/core/java/com/android/server/tv/TvInputHal.java
index c6213f9..e7dd82d 100644
--- a/services/core/java/com/android/server/tv/TvInputHal.java
+++ b/services/core/java/com/android/server/tv/TvInputHal.java
@@ -23,6 +23,8 @@ import android.os.HandlerThread;
import android.os.Message;
import android.view.Surface;
import android.util.Slog;
+import android.util.SparseArray;
+import android.util.SparseIntArray;
import java.util.LinkedList;
import java.util.Queue;
@@ -62,58 +64,70 @@ final class TvInputHal implements Handler.Callback {
int generation);
private static native void nativeClose(long ptr);
+ private Object mLock = new Object();
private long mPtr = 0;
private final Callback mCallback;
private final Handler mHandler;
- private int mStreamConfigGeneration = 0;
- private TvStreamConfig[] mStreamConfigs;
+ private SparseIntArray mStreamConfigGenerations = new SparseIntArray();
+ private SparseArray<TvStreamConfig[]> mStreamConfigs = new SparseArray<>();;
public TvInputHal(Callback callback) {
mCallback = callback;
mHandler = new Handler(this);
}
- public synchronized void init() {
- mPtr = nativeOpen();
+ public void init() {
+ synchronized (mLock) {
+ mPtr = nativeOpen();
+ }
}
- public synchronized int addStream(int deviceId, Surface surface, TvStreamConfig streamConfig) {
- if (mPtr == 0) {
- return ERROR_NO_INIT;
- }
- if (mStreamConfigGeneration != streamConfig.getGeneration()) {
- return ERROR_STALE_CONFIG;
- }
- if (nativeAddStream(mPtr, deviceId, streamConfig.getStreamId(), surface) == 0) {
- return SUCCESS;
- } else {
- return ERROR_UNKNOWN;
+ public int addStream(int deviceId, Surface surface, TvStreamConfig streamConfig) {
+ synchronized (mLock) {
+ if (mPtr == 0) {
+ return ERROR_NO_INIT;
+ }
+ int generation = mStreamConfigGenerations.get(deviceId, 0);
+ if (generation != streamConfig.getGeneration()) {
+ return ERROR_STALE_CONFIG;
+ }
+ if (nativeAddStream(mPtr, deviceId, streamConfig.getStreamId(), surface) == 0) {
+ return SUCCESS;
+ } else {
+ return ERROR_UNKNOWN;
+ }
}
}
- public synchronized int removeStream(int deviceId, TvStreamConfig streamConfig) {
- if (mPtr == 0) {
- return ERROR_NO_INIT;
- }
- if (mStreamConfigGeneration != streamConfig.getGeneration()) {
- return ERROR_STALE_CONFIG;
- }
- if (nativeRemoveStream(mPtr, deviceId, streamConfig.getStreamId()) == 0) {
- return SUCCESS;
- } else {
- return ERROR_UNKNOWN;
+ public int removeStream(int deviceId, TvStreamConfig streamConfig) {
+ synchronized (mLock) {
+ if (mPtr == 0) {
+ return ERROR_NO_INIT;
+ }
+ int generation = mStreamConfigGenerations.get(deviceId, 0);
+ if (generation != streamConfig.getGeneration()) {
+ return ERROR_STALE_CONFIG;
+ }
+ if (nativeRemoveStream(mPtr, deviceId, streamConfig.getStreamId()) == 0) {
+ return SUCCESS;
+ } else {
+ return ERROR_UNKNOWN;
+ }
}
}
- public synchronized void close() {
- if (mPtr != 0l) {
- nativeClose(mPtr);
+ public void close() {
+ synchronized (mLock) {
+ if (mPtr != 0l) {
+ nativeClose(mPtr);
+ }
}
}
- private synchronized void retrieveStreamConfigs(int deviceId) {
- ++mStreamConfigGeneration;
- mStreamConfigs = nativeGetStreamConfigs(mPtr, deviceId, mStreamConfigGeneration);
+ private void retrieveStreamConfigsLocked(int deviceId) {
+ int generation = mStreamConfigGenerations.get(deviceId, 0) + 1;
+ mStreamConfigs.put(deviceId, nativeGetStreamConfigs(mPtr, deviceId, generation));
+ mStreamConfigGenerations.put(deviceId, generation);
}
// Called from native
@@ -145,12 +159,16 @@ final class TvInputHal implements Handler.Callback {
public boolean handleMessage(Message msg) {
switch (msg.what) {
case EVENT_DEVICE_AVAILABLE: {
+ TvStreamConfig[] configs;
TvInputHardwareInfo info = (TvInputHardwareInfo)msg.obj;
- retrieveStreamConfigs(info.getDeviceId());
- if (DEBUG) {
- Slog.d(TAG, "EVENT_DEVICE_AVAILABLE: info = " + info);
+ synchronized (mLock) {
+ retrieveStreamConfigsLocked(info.getDeviceId());
+ if (DEBUG) {
+ Slog.d(TAG, "EVENT_DEVICE_AVAILABLE: info = " + info);
+ }
+ configs = mStreamConfigs.get(info.getDeviceId());
}
- mCallback.onDeviceAvailable(info, mStreamConfigs);
+ mCallback.onDeviceAvailable(info, configs);
break;
}
@@ -164,12 +182,16 @@ final class TvInputHal implements Handler.Callback {
}
case EVENT_STREAM_CONFIGURATION_CHANGED: {
+ TvStreamConfig[] configs;
int deviceId = msg.arg1;
- if (DEBUG) {
- Slog.d(TAG, "EVENT_STREAM_CONFIGURATION_CHANGED: deviceId = " + deviceId);
+ synchronized (mLock) {
+ if (DEBUG) {
+ Slog.d(TAG, "EVENT_STREAM_CONFIGURATION_CHANGED: deviceId = " + deviceId);
+ }
+ retrieveStreamConfigsLocked(deviceId);
+ configs = mStreamConfigs.get(deviceId);
}
- retrieveStreamConfigs(deviceId);
- mCallback.onStreamConfigurationChanged(deviceId, mStreamConfigs);
+ mCallback.onStreamConfigurationChanged(deviceId, configs);
break;
}
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index 5d34eda..16597c0 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -537,6 +537,24 @@ public final class TvInputManagerService extends SystemService {
}
@Override
+ public void onTrackSelectionChanged(List<TvTrackInfo> selectedTracks) {
+ synchronized (mLock) {
+ if (DEBUG) {
+ Slog.d(TAG, "onTrackSelectionChanged(" + selectedTracks + ")");
+ }
+ if (sessionState.mSession == null || sessionState.mClient == null) {
+ return;
+ }
+ try {
+ sessionState.mClient.onTrackSelectionChanged(selectedTracks,
+ sessionState.mSeq);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "error in onTrackSelectionChanged");
+ }
+ }
+ }
+
+ @Override
public void onVideoAvailable() {
synchronized (mLock) {
if (DEBUG) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 670ba55..80dfb91 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -19,7 +19,6 @@ package com.android.server.wm;
import static android.view.WindowManager.LayoutParams.*;
import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
-import android.app.admin.DevicePolicyManager;
import android.app.AppOpsManager;
import android.util.ArraySet;
import android.util.TimeUtils;
@@ -2455,37 +2454,24 @@ public class WindowManagerService extends IWindowManager.Stub
*/
boolean isScreenCaptureDisabledLocked(int userId) {
Boolean disabled = mScreenCaptureDisabled.get(userId);
- if (disabled != null) {
- return disabled;
- }
-
- // mScreenCaptureDisabled not set yet, try to update it.
- updateScreenCaptureDisabledLocked(userId);
- disabled = mScreenCaptureDisabled.get(userId);
if (disabled == null) {
- // Not able to update, return false by default.
return false;
- } else {
- return disabled;
}
+ return disabled;
}
/**
- * Update mScreenCaptureDisabled for specific user according to the device policy manager.
+ * Set mScreenCaptureDisabled for specific user
*/
@Override
- public void updateScreenCaptureDisabled(int userId) {
- mH.sendMessage(mH.obtainMessage(H.UPDATE_SCRN_CAP, userId, 0 /* unused argument */));
- }
+ public void setScreenCaptureDisabled(int userId, boolean disabled) {
+ int callingUid = Binder.getCallingUid();
+ if (callingUid != Process.SYSTEM_UID) {
+ throw new SecurityException("Only system can call setScreenCaptureDisabled.");
+ }
- void updateScreenCaptureDisabledLocked(int userId) {
- DevicePolicyManager dpm = (DevicePolicyManager) mContext
- .getSystemService(Context.DEVICE_POLICY_SERVICE);
- if (dpm != null) {
- boolean disabled = dpm.getScreenCaptureDisabled(null, userId);
+ synchronized(mWindowMap) {
mScreenCaptureDisabled.put(userId, disabled);
- } else {
- Slog.e(TAG, "Could not get DevicePolicyManager.");
}
}
@@ -7293,9 +7279,7 @@ public class WindowManagerService extends IWindowManager.Stub
public static final int NEW_ANIMATOR_SCALE = 34;
- public static final int UPDATE_SCRN_CAP = 35;
-
- public static final int SHOW_DISPLAY_MASK = 36;
+ public static final int SHOW_DISPLAY_MASK = 35;
@Override
public void handleMessage(Message msg) {
@@ -7776,13 +7760,6 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
break;
-
- case UPDATE_SCRN_CAP: {
- synchronized (mWindowMap) {
- updateScreenCaptureDisabledLocked(msg.arg1);
- }
- }
- break;
}
if (DEBUG_WINDOW_TRACE) {
Slog.v(TAG, "handleMessage: exit");
diff --git a/services/core/jni/com_android_server_location_FlpHardwareProvider.cpp b/services/core/jni/com_android_server_location_FlpHardwareProvider.cpp
index c2fccc1..2519ff8 100644
--- a/services/core/jni/com_android_server_location_FlpHardwareProvider.cpp
+++ b/services/core/jni/com_android_server_location_FlpHardwareProvider.cpp
@@ -364,7 +364,9 @@ static void TranslateGeofenceFromGeofenceHardwareRequestParcelable(
"()I");
options->last_transition = env->CallIntMethod(geofenceRequestObject, getLastTransition);
- // TODO: set data.sources_to_use when available
+ jmethodID getSourceTechnologies =
+ env->GetMethodID(geofenceRequestClass, "getSourceTechnologies", "()I");
+ options->sources_to_use = env->CallIntMethod(geofenceRequestObject, getSourceTechnologies);
env->DeleteLocalRef(geofenceRequestClass);
}
diff --git a/services/core/jni/com_android_server_tv_TvInputHal.cpp b/services/core/jni/com_android_server_tv_TvInputHal.cpp
index 41976ff..5eb627b 100644
--- a/services/core/jni/com_android_server_tv_TvInputHal.cpp
+++ b/services/core/jni/com_android_server_tv_TvInputHal.cpp
@@ -351,6 +351,8 @@ int JTvInputHal::addStream(int deviceId, int streamId, const sp<Surface>& surfac
ALOGE("Cannot find a config with given stream ID: %d", streamId);
return BAD_VALUE;
}
+ connection.mStreamType = configs[configIndex].type;
+
tv_stream_t stream;
stream.stream_id = configs[configIndex].stream_id;
if (connection.mStreamType == TV_STREAM_TYPE_BUFFER_PRODUCER) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 6ab504c..c6730bf 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -791,6 +791,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
policyFile.delete();
Slog.i(LOG_TAG, "Removed device policy file " + policyFile.getAbsolutePath());
}
+ updateScreenCaptureDisabledInWindowManager(userHandle, false /* default value */);
}
void loadDeviceOwner() {
@@ -1367,6 +1368,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
new SetupContentObserver(mHandler).register(mContext.getContentResolver());
// Initialize the user setup state, to handle the upgrade case.
updateUserSetupComplete();
+
+ // Update the screen capture disabled cache in the window manager
+ List<UserInfo> users = mUserManager.getUsers(true);
+ final int N = users.size();
+ for (int i = 0; i < N; i++) {
+ int userHandle = users.get(i).id;
+ updateScreenCaptureDisabledInWindowManager(userHandle,
+ getScreenCaptureDisabled(null, userHandle));
+ }
+
}
private void cleanUpOldUsers() {
@@ -3062,11 +3073,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
if (ap.disableScreenCapture != disabled) {
ap.disableScreenCapture = disabled;
saveSettingsLocked(userHandle);
- try {
- getWindowManager().updateScreenCaptureDisabled(userHandle);
- } catch (RemoteException e) {
- Log.w(LOG_TAG, "Unable to notify WindowManager.", e);
- }
+ updateScreenCaptureDisabledInWindowManager(userHandle, disabled);
}
}
}
@@ -3097,6 +3104,17 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
+ private void updateScreenCaptureDisabledInWindowManager(int userHandle, boolean disabled) {
+ long ident = Binder.clearCallingIdentity();
+ try {
+ getWindowManager().setScreenCaptureDisabled(userHandle, disabled);
+ } catch (RemoteException e) {
+ Log.w(LOG_TAG, "Unable to notify WindowManager.", e);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
/**
* The system property used to share the state of the camera. The native camera service
* is expected to read this property and act accordingly.
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java
index 15ec629..0eac1c4 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java
@@ -31,6 +31,7 @@ import android.util.Slog;
import android.util.SparseArray;
import java.util.ArrayList;
+import java.util.UUID;
/**
* Helper for {@link SoundTrigger} APIs.
@@ -63,6 +64,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
private final SparseArray<IRecognitionStatusCallback> mActiveListeners;
private int mCurrentSoundModelHandle = INVALID_SOUND_MODEL_HANDLE;
+ private UUID mCurrentSoundModelUuid = null;
SoundTriggerHelper() {
ArrayList <ModuleProperties> modules = new ArrayList<>();
@@ -109,18 +111,25 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
+ ", recognitionConfig=" + recognitionConfig);
Slog.d(TAG, "moduleProperties=" + moduleProperties);
Slog.d(TAG, "# of current listeners=" + mActiveListeners.size());
- Slog.d(TAG, "mCurrentSoundModelHandle=" + mCurrentSoundModelHandle);
+ Slog.d(TAG, "current SoundModel handle=" + mCurrentSoundModelHandle);
+ Slog.d(TAG, "current SoundModel UUID="
+ + (mCurrentSoundModelUuid == null ? null : mCurrentSoundModelUuid));
}
if (moduleProperties == null || mModule == null) {
Slog.w(TAG, "Attempting startRecognition without the capability");
return STATUS_ERROR;
}
- if (mCurrentSoundModelHandle != INVALID_SOUND_MODEL_HANDLE) {
+ if (mCurrentSoundModelHandle != INVALID_SOUND_MODEL_HANDLE
+ && !soundModel.uuid.equals(mCurrentSoundModelUuid)) {
Slog.w(TAG, "Unloading previous sound model");
- // TODO: Inspect the return codes here.
- mModule.unloadSoundModel(mCurrentSoundModelHandle);
+ int status = mModule.unloadSoundModel(mCurrentSoundModelHandle);
+ if (status != SoundTrigger.STATUS_OK) {
+ Slog.w(TAG, "unloadSoundModel call failed with " + status);
+ return status;
+ }
mCurrentSoundModelHandle = INVALID_SOUND_MODEL_HANDLE;
+ mCurrentSoundModelUuid = null;
}
// If the previous recognition was by a different listener,
@@ -136,26 +145,35 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
mActiveListeners.remove(keyphraseId);
}
- int[] handle = new int[] { INVALID_SOUND_MODEL_HANDLE };
- int status = mModule.loadSoundModel(soundModel, handle);
- if (status != SoundTrigger.STATUS_OK) {
- Slog.w(TAG, "loadSoundModel call failed with " + status);
- return STATUS_ERROR;
- }
- if (handle[0] == INVALID_SOUND_MODEL_HANDLE) {
- Slog.w(TAG, "loadSoundModel call returned invalid sound model handle");
- return STATUS_ERROR;
+ // Load the sound model if the current one is null.
+ int soundModelHandle = mCurrentSoundModelHandle;
+ if (mCurrentSoundModelHandle == INVALID_SOUND_MODEL_HANDLE
+ || mCurrentSoundModelUuid == null) {
+ int[] handle = new int[] { INVALID_SOUND_MODEL_HANDLE };
+ int status = mModule.loadSoundModel(soundModel, handle);
+ if (status != SoundTrigger.STATUS_OK) {
+ Slog.w(TAG, "loadSoundModel call failed with " + status);
+ return status;
+ }
+ if (handle[0] == INVALID_SOUND_MODEL_HANDLE) {
+ Slog.w(TAG, "loadSoundModel call returned invalid sound model handle");
+ return STATUS_ERROR;
+ }
+ soundModelHandle = handle[0];
+ } else {
+ if (DBG) Slog.d(TAG, "Reusing previously loaded sound model");
}
// Start the recognition.
- status = mModule.startRecognition(handle[0], recognitionConfig);
+ int status = mModule.startRecognition(soundModelHandle, recognitionConfig);
if (status != SoundTrigger.STATUS_OK) {
Slog.w(TAG, "startRecognition failed with " + status);
- return STATUS_ERROR;
+ return status;
}
// Everything went well!
- mCurrentSoundModelHandle = handle[0];
+ mCurrentSoundModelHandle = soundModelHandle;
+ mCurrentSoundModelUuid = soundModel.uuid;
// Register the new listener. This replaces the old one.
// There can only be a maximum of one active listener for a keyphrase
// at any given time.
@@ -194,14 +212,12 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
Slog.w(TAG, "Attempting stopRecognition without a successful startRecognition");
return STATUS_ERROR;
} else if (currentListener.asBinder() != listener.asBinder()) {
- // TODO: Figure out if this should match the listener that was passed in during
- // startRecognition, or should we allow a different listener to stop the recognition,
- // in which case we don't need to pass in a listener here.
+ // We don't allow a different listener to stop the recognition than the one
+ // that started it.
Slog.w(TAG, "Attempting stopRecognition for another recognition");
return STATUS_ERROR;
} else {
// Stop recognition if it's the current one, ignore otherwise.
- // TODO: Inspect the return codes here.
int status = mModule.stopRecognition(mCurrentSoundModelHandle);
if (status != SoundTrigger.STATUS_OK) {
Slog.w(TAG, "stopRecognition call failed with " + status);
@@ -214,6 +230,8 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
}
mCurrentSoundModelHandle = INVALID_SOUND_MODEL_HANDLE;
+ mCurrentSoundModelUuid = null;
+
mActiveListeners.remove(keyphraseId);
return STATUS_OK;
}
@@ -285,6 +303,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
Slog.w(TAG, "RemoteException in onDetectionStopped");
}
mCurrentSoundModelHandle = INVALID_SOUND_MODEL_HANDLE;
+ mCurrentSoundModelUuid = null;
// Remove all listeners.
mActiveListeners.clear();
}
diff --git a/telephony/java/android/telephony/IccOpenLogicalChannelResponse.aidl b/telephony/java/android/telephony/IccOpenLogicalChannelResponse.aidl
new file mode 100644
index 0000000..fe28c97
--- /dev/null
+++ b/telephony/java/android/telephony/IccOpenLogicalChannelResponse.aidl
@@ -0,0 +1,20 @@
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.telephony;
+
+parcelable IccOpenLogicalChannelResponse;
diff --git a/telephony/java/android/telephony/IccOpenLogicalChannelResponse.java b/telephony/java/android/telephony/IccOpenLogicalChannelResponse.java
new file mode 100644
index 0000000..bb5e277
--- /dev/null
+++ b/telephony/java/android/telephony/IccOpenLogicalChannelResponse.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+
+/**
+ * Response to the {@link TelephonyManager#iccOpenLogicalChannel} command.
+ */
+public class IccOpenLogicalChannelResponse implements Parcelable {
+ // Indicates an invalid channel.
+ public static int INVALID_CHANNEL = -1;
+
+ // Possible status values.
+ public static int NO_ERROR = 1;
+ public static int MISSING_RESOURCE = 2;
+ public static int NO_SUCH_ELEMENT = 3;
+ public static int UNKNOWN_ERROR = 4;
+
+ private final int mChannel;
+ private final int mStatus;
+ private final byte[] mSelectResponse;
+
+ /**
+ * Constructor.
+ *
+ * @hide
+ */
+ public IccOpenLogicalChannelResponse(int channel, int status, byte[] selectResponse) {
+ mChannel = channel;
+ mStatus = status;
+ mSelectResponse = selectResponse;
+ }
+
+ /**
+ * Construct a IccOpenLogicalChannelResponse from a given parcel.
+ */
+ private IccOpenLogicalChannelResponse(Parcel in) {
+ mChannel = in.readInt();
+ mStatus = in.readInt();
+ int arrayLength = in.readInt();
+ if (arrayLength > 0) {
+ mSelectResponse = new byte[arrayLength];
+ in.readByteArray(mSelectResponse);
+ } else {
+ mSelectResponse = null;
+ }
+ }
+
+ /**
+ * @return the channel id.
+ */
+ public int getChannel() {
+ return mChannel;
+ }
+
+ /**
+ * @return the status of the command.
+ */
+ public int getStatus() {
+ return mStatus;
+ }
+
+ /**
+ * @return the select response.
+ */
+ public byte[] getSelectResponse() {
+ return mSelectResponse;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(mChannel);
+ out.writeInt(mStatus);
+ if (mSelectResponse != null & mSelectResponse.length > 0) {
+ out.writeInt(mSelectResponse.length);
+ out.writeByteArray(mSelectResponse);
+ } else {
+ out.writeInt(0);
+ }
+ }
+
+ public static final Parcelable.Creator<IccOpenLogicalChannelResponse> CREATOR
+ = new Parcelable.Creator<IccOpenLogicalChannelResponse>() {
+
+ @Override
+ public IccOpenLogicalChannelResponse createFromParcel(Parcel in) {
+ return new IccOpenLogicalChannelResponse(in);
+ }
+
+ public IccOpenLogicalChannelResponse[] newArray(int size) {
+ return new IccOpenLogicalChannelResponse[size];
+ }
+ };
+
+ @Override
+ public String toString() {
+ return "Channel: " + mChannel + " Status: " + mStatus;
+ }
+}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 35568cf..0772687 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -26,6 +26,7 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemProperties;
import android.util.Log;
+import android.util.Pair;
import com.android.internal.telecomm.ITelecommService;
import com.android.internal.telephony.IPhoneSubInfo;
@@ -2348,15 +2349,15 @@ public class TelephonyManager {
* Or the calling app has carrier privileges. @see #hasCarrierPrivileges
*
* @param AID Application id. See ETSI 102.221 and 101.220.
- * @return The logical channel id which is negative on error.
+ * @return an IccOpenLogicalChannelResponse object.
*/
- public int iccOpenLogicalChannel(String AID) {
+ public IccOpenLogicalChannelResponse iccOpenLogicalChannel(String AID) {
try {
return getITelephony().iccOpenLogicalChannel(AID);
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
}
- return -1;
+ return null;
}
/**
@@ -2414,6 +2415,62 @@ public class TelephonyManager {
}
/**
+ * Transmit an APDU to the ICC card over the basic channel.
+ *
+ * Input parameters equivalent to TS 27.007 AT+CSIM command.
+ *
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
+ * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ *
+ * @param cla Class of the APDU command.
+ * @param instruction Instruction of the APDU command.
+ * @param p1 P1 value of the APDU command.
+ * @param p2 P2 value of the APDU command.
+ * @param p3 P3 value of the APDU command. If p3 is negative a 4 byte APDU
+ * is sent to the SIM.
+ * @param data Data to be sent with the APDU.
+ * @return The APDU response from the ICC card with the status appended at
+ * the end. If an error occurs, an empty string is returned.
+ */
+ public String iccTransmitApduBasicChannel(int cla,
+ int instruction, int p1, int p2, int p3, String data) {
+ try {
+ return getITelephony().iccTransmitApduBasicChannel(cla,
+ instruction, p1, p2, p3, data);
+ } catch (RemoteException ex) {
+ } catch (NullPointerException ex) {
+ }
+ return "";
+ }
+
+ /**
+ * Returns the response APDU for a command APDU sent through SIM_IO.
+ *
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
+ * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ *
+ * @param fileID
+ * @param command
+ * @param p1 P1 value of the APDU command.
+ * @param p2 P2 value of the APDU command.
+ * @param p3 P3 value of the APDU command.
+ * @param filePath
+ * @return The APDU response.
+ */
+ byte[] iccExchangeSimIO(int fileID, int command, int p1, int p2, int p3,
+ String filePath) {
+ try {
+ return getITelephony().iccExchangeSimIO(fileID, command, p1, p2,
+ p3, filePath);
+ } catch (RemoteException ex) {
+ } catch (NullPointerException ex) {
+ }
+ return null;
+ }
+
+ /**
* Send ENVELOPE to the SIM and return the response.
*
* <p>Requires Permission:
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 886de40..72b04cf 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -18,9 +18,10 @@ package com.android.internal.telephony;
import android.content.Intent;
import android.os.Bundle;
-import java.util.List;
-import android.telephony.NeighboringCellInfo;
import android.telephony.CellInfo;
+import android.telephony.IccOpenLogicalChannelResponse;
+import android.telephony.NeighboringCellInfo;
+import java.util.List;
/**
@@ -499,9 +500,9 @@ interface ITelephony {
* Input parameters equivalent to TS 27.007 AT+CCHO command.
*
* @param AID Application id. See ETSI 102.221 and 101.220.
- * @return The logical channel id which is set to -1 on error.
+ * @return an IccOpenLogicalChannelResponse object.
*/
- int iccOpenLogicalChannel(String AID);
+ IccOpenLogicalChannelResponse iccOpenLogicalChannel(String AID);
/**
* Closes a previously opened logical channel to the ICC card.
@@ -535,6 +536,38 @@ interface ITelephony {
int p1, int p2, int p3, String data);
/**
+ * Transmit an APDU to the ICC card over the basic channel.
+ *
+ * Input parameters equivalent to TS 27.007 AT+CSIM command.
+ *
+ * @param cla Class of the APDU command.
+ * @param instruction Instruction of the APDU command.
+ * @param p1 P1 value of the APDU command.
+ * @param p2 P2 value of the APDU command.
+ * @param p3 P3 value of the APDU command. If p3 is negative a 4 byte APDU
+ * is sent to the SIM.
+ * @param data Data to be sent with the APDU.
+ * @return The APDU response from the ICC card with the status appended at
+ * the end. If an error occurs, an empty string is returned.
+ */
+ String iccTransmitApduBasicChannel(int cla, int instruction,
+ int p1, int p2, int p3, String data);
+
+ /**
+ * Returns the response APDU for a command APDU sent through SIM_IO.
+ *
+ * @param fileID
+ * @param command
+ * @param p1 P1 value of the APDU command.
+ * @param p2 P2 value of the APDU command.
+ * @param p3 P3 value of the APDU command.
+ * @param filePath
+ * @return The APDU response.
+ */
+ byte[] iccExchangeSimIO(int fileID, int command, int p1, int p2, int p3,
+ String filePath);
+
+ /**
* Send ENVELOPE to the SIM and returns the response.
*
* @param contents String containing SAT/USAT response in hexadecimal
diff --git a/tests/SharedLibrary/lib/AndroidManifest.xml b/tests/SharedLibrary/lib/AndroidManifest.xml
index 31fac20..bb939dd 100644
--- a/tests/SharedLibrary/lib/AndroidManifest.xml
+++ b/tests/SharedLibrary/lib/AndroidManifest.xml
@@ -19,7 +19,8 @@
android:versionCode="2">
<application android:label="SharedLibrary">
<library android:name="com.google.android.test.shared_library" />
- <activity android:name="ActivityMain">
+ <activity android:name="ActivityMain"
+ android:icon="@drawable/size_48x48">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
diff --git a/tests/SharedLibrary/lib/res/drawable/size_48x48.jpg b/tests/SharedLibrary/lib/res/drawable/size_48x48.jpg
new file mode 100644
index 0000000..5c2291e
--- /dev/null
+++ b/tests/SharedLibrary/lib/res/drawable/size_48x48.jpg
Binary files differ
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index afeb546..755a77a 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -714,7 +714,6 @@ extern char CONSOLE_DATA[2925]; // see EOF
int doDump(Bundle* bundle)
{
status_t result = UNKNOWN_ERROR;
- Asset* asset = NULL;
if (bundle->getFileSpecCount() < 1) {
fprintf(stderr, "ERROR: no dump option specified\n");
@@ -758,12 +757,21 @@ int doDump(Bundle* bundle)
const ResTable& res = assets.getResources(false);
if (&res == NULL) {
fprintf(stderr, "ERROR: dump failed because no resource table was found\n");
- goto bail;
+ return 1;
} else if (res.getError() != NO_ERROR) {
fprintf(stderr, "ERROR: dump failed because the resource table is invalid/corrupt.\n");
- goto bail;
+ return 1;
+ }
+
+ const DynamicRefTable* dynamicRefTable = res.getDynamicRefTableForCookie(assetsCookie);
+ if (dynamicRefTable == NULL) {
+ fprintf(stderr, "ERROR: failed to find dynamic reference table for asset cookie %d\n",
+ assetsCookie);
+ return 1;
}
+ Asset* asset = NULL;
+
if (strcmp("resources", option) == 0) {
#ifndef HAVE_ANDROID_OS
res.print(bundle->getValues());
@@ -781,8 +789,8 @@ int doDump(Bundle* bundle)
for (int i=2; i<bundle->getFileSpecCount(); i++) {
const char* resname = bundle->getFileSpecEntry(i);
- ResXMLTree tree;
- asset = assets.openNonAsset(resname, Asset::ACCESS_BUFFER);
+ ResXMLTree tree(dynamicRefTable);
+ asset = assets.openNonAsset(assetsCookie, resname, Asset::ACCESS_BUFFER);
if (asset == NULL) {
fprintf(stderr, "ERROR: dump failed because resource %s found\n", resname);
goto bail;
@@ -808,13 +816,13 @@ int doDump(Bundle* bundle)
for (int i=2; i<bundle->getFileSpecCount(); i++) {
const char* resname = bundle->getFileSpecEntry(i);
- ResXMLTree tree;
- asset = assets.openNonAsset(resname, Asset::ACCESS_BUFFER);
+ asset = assets.openNonAsset(assetsCookie, resname, Asset::ACCESS_BUFFER);
if (asset == NULL) {
fprintf(stderr, "ERROR: dump failed because resource %s found\n", resname);
goto bail;
}
+ ResXMLTree tree(dynamicRefTable);
if (tree.setTo(asset->getBuffer(true),
asset->getLength()) != NO_ERROR) {
fprintf(stderr, "ERROR: Resource %s is corrupt\n", resname);
@@ -826,14 +834,13 @@ int doDump(Bundle* bundle)
}
} else {
- ResXMLTree tree;
- asset = assets.openNonAsset("AndroidManifest.xml",
- Asset::ACCESS_BUFFER);
+ asset = assets.openNonAsset(assetsCookie, "AndroidManifest.xml", Asset::ACCESS_BUFFER);
if (asset == NULL) {
fprintf(stderr, "ERROR: dump failed because no AndroidManifest.xml found\n");
goto bail;
}
+ ResXMLTree tree(dynamicRefTable);
if (tree.setTo(asset->getBuffer(true),
asset->getLength()) != NO_ERROR) {
fprintf(stderr, "ERROR: AndroidManifest.xml is corrupt\n");
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index 2ffe4a2..09b57fe 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -360,7 +360,7 @@ public class IWindowManagerImpl implements IWindowManager {
}
@Override
- public void updateScreenCaptureDisabled(int userId) {
+ public void setScreenCaptureDisabled(int userId, boolean disabled) {
// TODO Auto-generated method stub
}
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/ReplaceMethodCallsAdapter.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/ReplaceMethodCallsAdapter.java
index 0b5fb46..94d5975 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/ReplaceMethodCallsAdapter.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/ReplaceMethodCallsAdapter.java
@@ -78,7 +78,7 @@ public class ReplaceMethodCallsAdapter extends ClassVisitor {
assert isNeeded(owner, name, desc) && output.length == 3
&& opcodeOut.length == 1;
opcodeOut[0] = Opcodes.INVOKESTATIC;
- output[0] = "com.android.layoutlib.bridge.android.AndroidLocale";
+ output[0] = "com/android/layoutlib/bridge/android/AndroidLocale";
output[1] = name;
output[2] = "(Ljava/util/Locale;)Ljava/lang/String;";
}
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index 67ff868..f0a7f38 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -185,6 +185,14 @@ public class ScanResult implements Parcelable {
public static class InformationElement {
public int id;
public byte[] bytes;
+
+ public InformationElement() {
+ }
+
+ public InformationElement(InformationElement rhs) {
+ this.id = rhs.id;
+ this.bytes = rhs.bytes.clone();
+ }
}
/** information elements found in the beacon
diff --git a/wifi/java/android/net/wifi/WifiScanner.java b/wifi/java/android/net/wifi/WifiScanner.java
index 4cdbc44..c5c44b5 100644
--- a/wifi/java/android/net/wifi/WifiScanner.java
+++ b/wifi/java/android/net/wifi/WifiScanner.java
@@ -145,6 +145,8 @@ public class WifiScanner {
public int periodInMs;
/** must have a valid REPORT_EVENT value */
public int reportEvents;
+ /** defines number of bssids to cache from each scan */
+ public int numBssidsPerScan;
/** Implement the Parcelable interface {@hide} */
public int describeContents() {
@@ -267,13 +269,6 @@ public class WifiScanner {
public void onFullResult(ScanResult fullScanResult);
}
- /** @hide */
- public void scan(ScanSettings settings, ScanListener listener) {
- validateChannel();
- settings.periodInMs = 0;
- sAsyncChannel.sendMessage(CMD_SCAN, 0, putListener(listener), settings);
- }
-
/** start wifi scan in background
* @param settings specifies various parameters for the scan; for more information look at
* {@link ScanSettings}
@@ -305,7 +300,7 @@ public class WifiScanner {
}
/** specifies information about an access point of interest */
- public static class HotspotInfo {
+ public static class BssidInfo {
/** bssid of the access point; in XX:XX:XX:XX:XX:XX format */
public String bssid;
/** low signal strength threshold; more information at {@link ScanResult#level} */
@@ -324,7 +319,7 @@ public class WifiScanner {
public int unchangedSampleSize; /* samples to confirm no change */
public int minApsBreachingThreshold; /* change threshold to trigger event */
public int periodInMs; /* scan period in millisecond */
- public HotspotInfo[] hotspotInfos;
+ public BssidInfo[] bssidInfos;
/** Implement the Parcelable interface {@hide} */
public int describeContents() {
@@ -338,10 +333,10 @@ public class WifiScanner {
dest.writeInt(unchangedSampleSize);
dest.writeInt(minApsBreachingThreshold);
dest.writeInt(periodInMs);
- if (hotspotInfos != null) {
- dest.writeInt(hotspotInfos.length);
- for (int i = 0; i < hotspotInfos.length; i++) {
- HotspotInfo info = hotspotInfos[i];
+ if (bssidInfos != null) {
+ dest.writeInt(bssidInfos.length);
+ for (int i = 0; i < bssidInfos.length; i++) {
+ BssidInfo info = bssidInfos[i];
dest.writeString(info.bssid);
dest.writeInt(info.low);
dest.writeInt(info.high);
@@ -363,14 +358,14 @@ public class WifiScanner {
settings.minApsBreachingThreshold = in.readInt();
settings.periodInMs = in.readInt();
int len = in.readInt();
- settings.hotspotInfos = new HotspotInfo[len];
+ settings.bssidInfos = new BssidInfo[len];
for (int i = 0; i < len; i++) {
- HotspotInfo info = new HotspotInfo();
+ BssidInfo info = new BssidInfo();
info.bssid = in.readString();
info.low = in.readInt();
info.high = in.readInt();
info.frequencyHint = in.readInt();
- settings.hotspotInfos[i] = info;
+ settings.bssidInfos[i] = info;
}
return settings;
}
@@ -389,7 +384,7 @@ public class WifiScanner {
* @param minApsBreachingThreshold minimum number of access points that need to be
* out of range to detect WifiChange
* @param periodInMs indicates period of scan to find changes
- * @param hotspotInfos access points to watch
+ * @param bssidInfos access points to watch
*/
public void configureWifiChange(
int rssiSampleSize, /* sample size for RSSI averaging */
@@ -397,7 +392,7 @@ public class WifiScanner {
int unchangedSampleSize, /* samples to confirm no change */
int minApsBreachingThreshold, /* change threshold to trigger event */
int periodInMs, /* period of scan */
- HotspotInfo[] hotspotInfos /* signal thresholds to crosss */
+ BssidInfo[] bssidInfos /* signal thresholds to crosss */
)
{
validateChannel();
@@ -408,7 +403,7 @@ public class WifiScanner {
settings.unchangedSampleSize = unchangedSampleSize;
settings.minApsBreachingThreshold = minApsBreachingThreshold;
settings.periodInMs = periodInMs;
- settings.hotspotInfos = hotspotInfos;
+ settings.bssidInfos = bssidInfos;
configureWifiChange(settings);
}
@@ -455,7 +450,7 @@ public class WifiScanner {
}
/** interface to receive hotlist events on; use this on {@link #setHotlist} */
- public static interface HotspotListener extends ActionListener {
+ public static interface BssidListener extends ActionListener {
/** indicates that access points were found by on going scans
* @param results list of scan results, one for each access point visible currently
*/
@@ -465,7 +460,7 @@ public class WifiScanner {
/** @hide */
@SystemApi
public static class HotlistSettings implements Parcelable {
- public HotspotInfo[] hotspotInfos;
+ public BssidInfo[] bssidInfos;
public int apLostThreshold;
/** Implement the Parcelable interface {@hide} */
@@ -477,10 +472,10 @@ public class WifiScanner {
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(apLostThreshold);
- if (hotspotInfos != null) {
- dest.writeInt(hotspotInfos.length);
- for (int i = 0; i < hotspotInfos.length; i++) {
- HotspotInfo info = hotspotInfos[i];
+ if (bssidInfos != null) {
+ dest.writeInt(bssidInfos.length);
+ for (int i = 0; i < bssidInfos.length; i++) {
+ BssidInfo info = bssidInfos[i];
dest.writeString(info.bssid);
dest.writeInt(info.low);
dest.writeInt(info.high);
@@ -498,14 +493,14 @@ public class WifiScanner {
HotlistSettings settings = new HotlistSettings();
settings.apLostThreshold = in.readInt();
int n = in.readInt();
- settings.hotspotInfos = new HotspotInfo[n];
+ settings.bssidInfos = new BssidInfo[n];
for (int i = 0; i < n; i++) {
- HotspotInfo info = new HotspotInfo();
+ BssidInfo info = new BssidInfo();
info.bssid = in.readString();
info.low = in.readInt();
info.high = in.readInt();
info.frequencyHint = in.readInt();
- settings.hotspotInfos[i] = info;
+ settings.bssidInfos[i] = info;
}
return settings;
}
@@ -518,24 +513,24 @@ public class WifiScanner {
/**
* set interesting access points to find
- * @param hotspots access points of interest
+ * @param bssidInfos access points of interest
* @param apLostThreshold number of scans needed to indicate that AP is lost
* @param listener object provided to report events on; this object must be unique and must
- * also be provided on {@link #stopTrackingHotspots}
+ * also be provided on {@link #stopTrackingBssids}
*/
- public void startTrackingHotspots(HotspotInfo[] hotspots,
- int apLostThreshold, HotspotListener listener) {
+ public void startTrackingBssids(BssidInfo[] bssidInfos,
+ int apLostThreshold, BssidListener listener) {
validateChannel();
HotlistSettings settings = new HotlistSettings();
- settings.hotspotInfos = hotspots;
+ settings.bssidInfos = bssidInfos;
sAsyncChannel.sendMessage(CMD_SET_HOTLIST, 0, putListener(listener), settings);
}
/**
* remove tracking of interesting access points
- * @param listener same object provided in {@link #startTrackingHotspots}
+ * @param listener same object provided in {@link #startTrackingBssids}
*/
- public void stopTrackingHotspots(HotspotListener listener) {
+ public void stopTrackingBssids(BssidListener listener) {
validateChannel();
sAsyncChannel.sendMessage(CMD_RESET_HOTLIST, 0, removeListener(listener));
}
@@ -802,7 +797,7 @@ public class WifiScanner {
((ScanListener) listener).onPeriodChanged(msg.arg1);
return;
case CMD_AP_FOUND:
- ((HotspotListener) listener).onFound(
+ ((BssidListener) listener).onFound(
((ParcelableScanResults) msg.obj).getResults());
return;
case CMD_WIFI_CHANGE_DETECTED: