summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Android.mk1
-rw-r--r--CleanSpec.mk1
-rw-r--r--api/current.txt70
-rw-r--r--api/system-current.txt87
-rw-r--r--cmds/am/src/com/android/commands/am/Am.java58
-rw-r--r--cmds/screencap/screencap.cpp29
-rw-r--r--core/java/android/app/ApplicationPackageManager.java69
-rw-r--r--core/java/android/app/Presentation.java4
-rw-r--r--core/java/android/app/admin/DeviceInitializerStatus.java145
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java120
-rw-r--r--core/java/android/app/admin/IDevicePolicyManager.aidl3
-rw-r--r--core/java/android/content/ContentProviderOperation.java54
-rw-r--r--core/java/android/content/Context.java4
-rw-r--r--core/java/android/content/pm/IOnPermissionsChangeListener.aidl25
-rw-r--r--core/java/android/content/pm/IPackageManager.aidl4
-rw-r--r--core/java/android/content/pm/PackageManager.java40
-rw-r--r--core/java/android/hardware/SensorManager.java4
-rw-r--r--core/java/android/hardware/SystemSensorManager.java6
-rw-r--r--core/java/android/hardware/camera2/CameraCaptureSession.java25
-rw-r--r--core/java/android/hardware/camera2/impl/CameraDeviceImpl.java31
-rw-r--r--core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java4
-rw-r--r--core/java/android/hardware/camera2/utils/SurfaceUtils.java6
-rw-r--r--core/java/android/hardware/usb/IUsbManager.aidl10
-rw-r--r--core/java/android/hardware/usb/UsbManager.java40
-rw-r--r--core/java/android/net/NetworkFactory.java32
-rw-r--r--core/java/android/os/BatteryStats.java81
-rw-r--r--core/java/android/os/ParcelFileDescriptor.java3
-rw-r--r--core/java/android/os/RemoteCallbackList.java1
-rw-r--r--core/java/android/os/storage/DiskInfo.java6
-rw-r--r--core/java/android/os/storage/VolumeInfo.java17
-rw-r--r--core/java/android/preference/SeekBarDialogPreference.java19
-rw-r--r--core/java/android/preference/SeekBarVolumizer.java44
-rw-r--r--core/java/android/preference/VolumePreference.java28
-rw-r--r--core/java/android/printservice/PrintService.java13
-rw-r--r--core/java/android/provider/ContactsContract.java153
-rw-r--r--core/java/android/provider/DocumentsContract.java6
-rw-r--r--core/java/android/provider/Settings.java45
-rw-r--r--core/java/android/service/notification/NotificationListenerService.java2
-rw-r--r--core/java/android/text/Spanned.java11
-rw-r--r--core/java/android/text/TextUtils.java9
-rw-r--r--core/java/android/util/KeyValueListParser.java114
-rw-r--r--core/java/android/view/Choreographer.java32
-rw-r--r--core/java/android/view/MenuInflater.java32
-rw-r--r--core/java/android/view/MenuItem.java24
-rw-r--r--core/java/android/view/SurfaceView.java2
-rw-r--r--core/java/android/view/ViewPropertyAnimator.java15
-rw-r--r--core/java/android/view/ViewRootImpl.java7
-rw-r--r--core/java/android/widget/ActionMenuPresenter.java73
-rw-r--r--core/java/android/widget/ActionMenuView.java50
-rw-r--r--core/java/android/widget/ListPopupWindow.java5
-rw-r--r--core/java/android/widget/Toolbar.java163
-rw-r--r--core/java/com/android/internal/app/ResolverActivity.java82
-rw-r--r--core/java/com/android/internal/app/ResolverComparator.java215
-rw-r--r--core/java/com/android/internal/view/menu/ActionMenuItem.java49
-rw-r--r--core/java/com/android/internal/view/menu/MenuItemImpl.java58
-rw-r--r--core/java/com/android/internal/widget/FloatingToolbar.java39
-rw-r--r--core/jni/android/graphics/SurfaceTexture.cpp11
-rw-r--r--core/res/AndroidManifest.xml34
-rw-r--r--core/res/res/drawable-hdpi/ic_fingerprint_light_overlay.pngbin5519 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/ic_fingerprint_light_overlay.pngbin3172 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ic_fingerprint_light_overlay.pngbin8649 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/ic_fingerprint_light_overlay.pngbin16227 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/ic_fingerprint_light_overlay.pngbin14255 -> 0 bytes
-rw-r--r--core/res/res/drawable/ic_fingerprint.xml37
-rw-r--r--core/res/res/drawable/ic_fingerprint_dark.xml37
-rw-r--r--core/res/res/drawable/ic_fingerprint_light.xml28
-rw-r--r--core/res/res/layout/preference_dialog_seekbar.xml (renamed from core/res/res/layout/seekbar_dialog.xml)33
-rw-r--r--core/res/res/layout/preference_dialog_seekbar_material.xml37
-rw-r--r--core/res/res/values/attrs.xml84
-rw-r--r--core/res/res/values/attrs_manifest.xml21
-rw-r--r--core/res/res/values/public.xml22
-rw-r--r--core/res/res/values/strings.xml53
-rw-r--r--core/res/res/values/styles.xml4
-rw-r--r--core/res/res/values/styles_material.xml4
-rwxr-xr-xcore/res/res/values/symbols.xml18
-rw-r--r--core/res/res/values/themes.xml2
-rw-r--r--core/res/res/values/themes_material.xml4
-rw-r--r--data/fonts/Android.mk21
-rw-r--r--docs/html/robots.txt1
-rw-r--r--docs/html/sdk/index.jd32
-rw-r--r--docs/html/tools/revisions/studio.jd18
-rw-r--r--graphics/java/android/graphics/drawable/RippleDrawable.java26
-rw-r--r--keystore/java/android/security/KeyChain.java15
-rw-r--r--keystore/java/android/security/KeyPairGeneratorSpec.java4
-rw-r--r--keystore/java/android/security/KeyStore.java12
-rw-r--r--keystore/java/android/security/keystore/AndroidKeyStoreECPrivateKey.java40
-rw-r--r--keystore/java/android/security/keystore/AndroidKeyStoreKey.java38
-rw-r--r--keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java63
-rw-r--r--keystore/java/android/security/keystore/AndroidKeyStoreProvider.java158
-rw-r--r--keystore/java/android/security/keystore/AndroidKeyStorePublicKey.java27
-rw-r--r--keystore/java/android/security/keystore/AndroidKeyStoreRSAPrivateKey.java41
-rw-r--r--keystore/java/android/security/keystore/AndroidKeyStoreSignatureSpiBase.java2
-rw-r--r--keystore/java/android/security/keystore/AndroidKeyStoreSpi.java137
-rw-r--r--keystore/java/android/security/keystore/DelegatingX509Certificate.java212
-rw-r--r--keystore/tests/src/android/security/KeyStoreTest.java5
-rw-r--r--keystore/tests/src/android/security/keystore/AndroidKeyPairGeneratorTest.java56
-rw-r--r--keystore/tests/src/android/security/keystore/AndroidKeyStoreTest.java67
-rw-r--r--media/java/android/media/MediaCodecInfo.java2
-rw-r--r--media/java/android/media/SoundPool.java40
-rw-r--r--media/java/android/media/browse/MediaBrowser.java36
-rw-r--r--media/java/android/media/tv/TvInputInfo.java109
-rw-r--r--media/java/android/service/media/MediaBrowserService.java50
-rw-r--r--media/jni/android_media_ImageReader.cpp11
-rw-r--r--media/jni/android_media_ImageWriter.cpp3
-rw-r--r--media/jni/soundpool/android_media_SoundPool.cpp2
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CodecTest.java5
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaPlayerStressTest.java14
-rw-r--r--native/android/Android.mk1
-rw-r--r--native/android/trace.cpp30
-rw-r--r--packages/DocumentsUI/res/layout-sw720dp/activity.xml4
-rw-r--r--packages/DocumentsUI/res/layout/activity.xml4
-rw-r--r--packages/DocumentsUI/res/values/strings.xml5
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java78
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java7
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java8
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/DocumentsToolBar.java72
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/RootsCache.java6
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java2
-rw-r--r--packages/DocumentsUI/tests/src/com/android/documentsui/RootsCacheTest.java25
-rw-r--r--packages/Keyguard/res/layout/keyguard_pattern_view.xml3
-rw-r--r--packages/Keyguard/res/values/strings.xml36
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardPINView.java7
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java7
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java7
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java2
-rw-r--r--packages/SettingsLib/res/values/dimens.xml24
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/animation/AppearAnimationCreator.java (renamed from packages/Keyguard/src/com/android/keyguard/AppearAnimationCreator.java)6
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/animation/AppearAnimationUtils.java (renamed from packages/Keyguard/src/com/android/keyguard/AppearAnimationUtils.java)34
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/animation/DisappearAnimationUtils.java (renamed from packages/Keyguard/src/com/android/keyguard/DisappearAnimationUtils.java)22
-rw-r--r--packages/StatementService/src/com/android/statementservice/retriever/AbstractStatementRetriever.java2
-rw-r--r--packages/StatementService/src/com/android/statementservice/retriever/DirectStatementRetriever.java2
-rw-r--r--packages/StatementService/src/com/android/statementservice/retriever/Statement.java2
-rw-r--r--packages/StatementService/src/com/android/statementservice/retriever/URLFetcher.java43
-rw-r--r--packages/SystemUI/res/drawable/managed_profile_toast_background.xml21
-rw-r--r--packages/SystemUI/res/drawable/stat_sys_managed_profile_status.xml4
-rw-r--r--packages/SystemUI/res/layout-sw600dp/navigation_bar.xml38
-rw-r--r--packages/SystemUI/res/layout/keyguard_bottom_area.xml3
-rw-r--r--packages/SystemUI/res/layout/managed_profile_toast.xml39
-rw-r--r--packages/SystemUI/res/layout/navigation_bar.xml42
-rw-r--r--packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml1
-rw-r--r--packages/SystemUI/res/layout/status_bar_toggle_slider.xml1
-rw-r--r--packages/SystemUI/res/layout/volume_dialog_row.xml6
-rw-r--r--packages/SystemUI/res/values/colors.xml2
-rw-r--r--packages/SystemUI/res/values/config.xml2
-rw-r--r--packages/SystemUI/res/values/strings.xml7
-rw-r--r--packages/SystemUI/res/values/styles.xml5
-rw-r--r--packages/SystemUI/src/com/android/systemui/ExpandHelper.java28
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/AssistManager.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSPanel.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java93
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/DelegateViewHelper.java157
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java26
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowContainer.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/StackScrollerDecorView.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java46
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java65
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java41
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java2
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java5
-rw-r--r--services/core/java/com/android/server/DeviceIdleController.java348
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java12
-rw-r--r--services/core/java/com/android/server/am/ActivityStackSupervisor.java38
-rw-r--r--services/core/java/com/android/server/am/TaskRecord.java20
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerService.java8
-rw-r--r--services/core/java/com/android/server/display/LogicalDisplay.java2
-rw-r--r--services/core/java/com/android/server/display/OverlayDisplayAdapter.java4
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java122
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java17
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java40
-rw-r--r--services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java114
-rw-r--r--services/usb/java/com/android/server/usb/UsbDeviceManager.java40
-rw-r--r--services/usb/java/com/android/server/usb/UsbService.java12
-rw-r--r--telecomm/java/android/telecom/Connection.java24
-rw-r--r--telephony/java/android/telephony/CarrierConfigManager.java9
-rw-r--r--telephony/java/android/telephony/SignalStrength.java7
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java27
-rw-r--r--test-runner/src/android/test/mock/MockPackageManager.java12
190 files changed, 3706 insertions, 2295 deletions
diff --git a/Android.mk b/Android.mk
index 1752caf..e96a932 100644
--- a/Android.mk
+++ b/Android.mk
@@ -142,6 +142,7 @@ LOCAL_SRC_FILES += \
core/java/android/content/pm/IPackageManager.aidl \
core/java/android/content/pm/IPackageMoveObserver.aidl \
core/java/android/content/pm/IPackageStatsObserver.aidl \
+ core/java/android/content/pm/IOnPermissionsChangeListener.aidl \
core/java/android/database/IContentObserver.aidl \
core/java/android/hardware/ICameraService.aidl \
core/java/android/hardware/ICameraServiceListener.aidl \
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 667ed02..48be749 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -234,6 +234,7 @@ $(call add-clean-step, rm -rf $(PRODUCT_OUT)/symbols/system/lib/libinputflingerh
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/lib/libinputflingerhost.so $(PRODUCT_OUT)/obj_arm/lib/libinputflingerhost.so)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libinputflingerhost_intermediates $(PRODUCT_OUT)/obj_arm/SHARED_LIBRARIES/libinputflingerhost_intermediates)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/target/common/obj/framework.aidl)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates)
# ******************************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THIS BANNER
diff --git a/api/current.txt b/api/current.txt
index 049d790..cfb9398 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -222,6 +222,12 @@ package android {
ctor public R.attr();
field public static final int __reserved0 = 16844020; // 0x10104f4
field public static final int __reserved1 = 16844019; // 0x10104f3
+ field public static final int __reserved2 = 16843999; // 0x10104df
+ field public static final int __reserved3 = 16844000; // 0x10104e0
+ field public static final int __reserved4 = 16844001; // 0x10104e1
+ field public static final int __reserved5 = 16844002; // 0x10104e2
+ field public static final int __reserved6 = 16844003; // 0x10104e3
+ field public static final int __reserved7 = 16844004; // 0x10104e4
field public static final int absListViewStyle = 16842858; // 0x101006a
field public static final int accessibilityEventTypes = 16843648; // 0x1010380
field public static final int accessibilityFeedbackType = 16843650; // 0x1010382
@@ -570,7 +576,7 @@ package android {
field public static final int fillViewport = 16843130; // 0x101017a
field public static final int filter = 16843035; // 0x101011b
field public static final int filterTouchesWhenObscured = 16843460; // 0x10102c4
- field public static final int fingerprintDrawable = 16844025; // 0x10104f9
+ field public static final int fingerprintAuthDrawable = 16844025; // 0x10104f9
field public static final int finishOnCloseSystemDialogs = 16843431; // 0x10102a7
field public static final int finishOnTaskLaunch = 16842772; // 0x1010014
field public static final int firstDayOfWeek = 16843581; // 0x101033d
@@ -661,8 +667,6 @@ package android {
field public static final int hyphenationFrequency = 16844024; // 0x10104f8
field public static final int icon = 16842754; // 0x1010002
field public static final int iconPreview = 16843337; // 0x1010249
- field public static final int iconTint = 16843999; // 0x10104df
- field public static final int iconTintMode = 16844000; // 0x10104e0
field public static final int iconifiedByDefault = 16843514; // 0x10102fa
field public static final int id = 16842960; // 0x10100d0
field public static final int ignoreGravity = 16843263; // 0x10101ff
@@ -874,8 +878,6 @@ package android {
field public static final int navigationContentDescription = 16843969; // 0x10104c1
field public static final int navigationIcon = 16843968; // 0x10104c0
field public static final int navigationMode = 16843471; // 0x10102cf
- field public static final int navigationTint = 16844003; // 0x10104e3
- field public static final int navigationTintMode = 16844004; // 0x10104e4
field public static final int negativeButtonText = 16843254; // 0x10101f6
field public static final int nestedScrollingEnabled = 16843830; // 0x1010436
field public static final int nextFocusDown = 16842980; // 0x10100e4
@@ -907,8 +909,6 @@ package android {
field public static final int overScrollFooter = 16843459; // 0x10102c3
field public static final int overScrollHeader = 16843458; // 0x10102c2
field public static final int overScrollMode = 16843457; // 0x10102c1
- field public static final int overflowTint = 16844001; // 0x10104e1
- field public static final int overflowTintMode = 16844002; // 0x10104e2
field public static final int overlapAnchor = 16843874; // 0x1010462
field public static final int overridesImplicitlyEnabledSubtype = 16843682; // 0x10103a2
field public static final int packageNames = 16843649; // 0x1010381
@@ -5681,23 +5681,6 @@ package android.app.admin {
field public static final java.lang.String EXTRA_LOCK_TASK_PACKAGE = "android.app.extra.LOCK_TASK_PACKAGE";
}
- public class DeviceInitializerStatus {
- field public static final int FLAG_STATUS_CUSTOM = 33554432; // 0x2000000
- field public static final int FLAG_STATUS_ERROR = 16777216; // 0x1000000
- field public static final int FLAG_STATUS_HIGH_PRIORITY = 134217728; // 0x8000000
- field public static final int FLAG_STATUS_RESERVED = 67108864; // 0x4000000
- field public static final int STATUS_ERROR_CONNECT_WIFI = 16777237; // 0x1000015
- field public static final int STATUS_ERROR_DELETE_APPS = 16777242; // 0x100001a
- field public static final int STATUS_ERROR_DOUBLE_BUMP = 16777246; // 0x100001e
- field public static final int STATUS_ERROR_DOWNLOAD_PACKAGE = 16777239; // 0x1000017
- field public static final int STATUS_ERROR_INSTALL_PACKAGE = 16777240; // 0x1000018
- field public static final int STATUS_ERROR_RESET_PROTECTION_BLOCKING_PROVISIONING = 16777238; // 0x1000016
- field public static final int STATUS_ERROR_SET_DEVICE_POLICY = 16777241; // 0x1000019
- field public static final int STATUS_STATE_CONNECTING_BLUETOOTH_PROXY = 134217736; // 0x8000008
- field public static final int STATUS_STATE_DEVICE_PROVISIONED = 134217738; // 0x800000a
- field public static final int STATUS_STATE_DISCONNECTING_BLUETOOTH_PROXY = 134217737; // 0x8000009
- }
-
public class DevicePolicyManager {
method public void addCrossProfileIntentFilter(android.content.ComponentName, android.content.IntentFilter, int);
method public boolean addCrossProfileWidgetProvider(android.content.ComponentName, java.lang.String);
@@ -5765,7 +5748,6 @@ package android.app.admin {
method public boolean removeCrossProfileWidgetProvider(android.content.ComponentName, java.lang.String);
method public boolean removeUser(android.content.ComponentName, android.os.UserHandle);
method public boolean resetPassword(java.lang.String, int);
- method public void sendDeviceInitializerStatus(int, java.lang.String);
method public void setAccountManagementDisabled(android.content.ComponentName, java.lang.String, boolean);
method public boolean setApplicationHidden(android.content.ComponentName, java.lang.String, boolean);
method public void setApplicationRestrictions(android.content.ComponentName, java.lang.String, android.os.Bundle);
@@ -5829,10 +5811,6 @@ package android.app.admin {
field public static final java.lang.String EXTRA_DEVICE_ADMIN = "android.app.extra.DEVICE_ADMIN";
field public static final java.lang.String EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE = "android.app.extra.PROVISIONING_ACCOUNT_TO_MIGRATE";
field public static final java.lang.String EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE = "android.app.extra.PROVISIONING_ADMIN_EXTRAS_BUNDLE";
- field public static final java.lang.String EXTRA_PROVISIONING_BT_DEVICE_ID = "android.app.extra.PROVISIONING_BT_DEVICE_ID";
- field public static final java.lang.String EXTRA_PROVISIONING_BT_MAC_ADDRESS = "android.app.extra.PROVISIONING_BT_MAC_ADDRESS";
- field public static final java.lang.String EXTRA_PROVISIONING_BT_USE_PROXY = "android.app.extra.PROVISIONING_BT_USE_PROXY";
- field public static final java.lang.String EXTRA_PROVISIONING_BT_UUID = "android.app.extra.PROVISIONING_BT_UUID";
field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_CERTIFICATE_CHECKSUM = "android.app.extra.PROVISIONING_DEVICE_ADMIN_CERTIFICATE_CHECKSUM";
field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME = "android.app.extra.PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME";
field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_MINIMUM_VERSION_CODE = "android.app.extra.PROVISIONING_DEVICE_ADMIN_MINIMUM_VERSION_CODE";
@@ -7721,6 +7699,7 @@ package android.content {
method public final java.lang.String getString(int, java.lang.Object...);
method public abstract java.lang.Object getSystemService(java.lang.String);
method public final T getSystemService(java.lang.Class<T>);
+ method public abstract java.lang.String getSystemServiceName(java.lang.Class<?>);
method public final java.lang.CharSequence getText(int);
method public abstract android.content.res.Resources.Theme getTheme();
method public abstract deprecated android.graphics.drawable.Drawable getWallpaper();
@@ -17210,7 +17189,7 @@ package android.media.browse {
method public void connect();
method public void disconnect();
method public android.os.Bundle getExtras();
- method public void getMediaItem(java.lang.String, android.media.browse.MediaBrowser.MediaItemCallback);
+ method public void getItem(java.lang.String, android.media.browse.MediaBrowser.ItemCallback);
method public java.lang.String getRoot();
method public android.content.ComponentName getServiceComponent();
method public android.media.session.MediaSession.Token getSessionToken();
@@ -17226,6 +17205,12 @@ package android.media.browse {
method public void onConnectionSuspended();
}
+ public static abstract class MediaBrowser.ItemCallback {
+ ctor public MediaBrowser.ItemCallback();
+ method public void onError(java.lang.String);
+ method public void onItemLoaded(android.media.browse.MediaBrowser.MediaItem);
+ }
+
public static class MediaBrowser.MediaItem implements android.os.Parcelable {
ctor public MediaBrowser.MediaItem(android.media.MediaDescription, int);
method public int describeContents();
@@ -17240,12 +17225,6 @@ package android.media.browse {
field public static final int FLAG_PLAYABLE = 2; // 0x2
}
- public static abstract class MediaBrowser.MediaItemCallback {
- ctor public MediaBrowser.MediaItemCallback();
- method public void onError();
- method public void onMediaItemLoaded(android.media.browse.MediaBrowser.MediaItem);
- }
-
public static abstract class MediaBrowser.SubscriptionCallback {
ctor public MediaBrowser.SubscriptionCallback();
method public void onChildrenLoaded(java.lang.String, java.util.List<android.media.browse.MediaBrowser.MediaItem>);
@@ -24476,6 +24455,7 @@ package android.printservice {
method protected abstract void onPrintJobQueued(android.printservice.PrintJob);
method protected abstract void onRequestCancelPrintJob(android.printservice.PrintJob);
field public static final java.lang.String EXTRA_PRINTER_INFO = "android.intent.extra.print.EXTRA_PRINTER_INFO";
+ field public static final java.lang.String EXTRA_PRINT_DOCUMENT_INFO = "android.printservice.extra.PRINT_DOCUMENT_INFO";
field public static final java.lang.String EXTRA_PRINT_JOB_INFO = "android.intent.extra.print.PRINT_JOB_INFO";
field public static final java.lang.String SERVICE_INTERFACE = "android.printservice.PrintService";
field public static final java.lang.String SERVICE_META_DATA = "android.printservice";
@@ -26099,6 +26079,7 @@ package android.provider {
method public static boolean isDocumentUri(android.content.Context, android.net.Uri);
method public static android.net.Uri renameDocument(android.content.ContentResolver, android.net.Uri, java.lang.String);
field public static final java.lang.String EXTRA_ERROR = "error";
+ field public static final java.lang.String EXTRA_EXCLUDE_SELF = "android.provider.extra.EXCLUDE_SELF";
field public static final java.lang.String EXTRA_INFO = "info";
field public static final java.lang.String EXTRA_LOADING = "loading";
field public static final java.lang.String PROVIDER_INTERFACE = "android.content.action.DOCUMENTS_PROVIDER";
@@ -26536,6 +26517,7 @@ package android.provider {
field public static final java.lang.String ACTION_DISPLAY_SETTINGS = "android.settings.DISPLAY_SETTINGS";
field public static final java.lang.String ACTION_DREAM_SETTINGS = "android.settings.DREAM_SETTINGS";
field public static final java.lang.String ACTION_HOME_SETTINGS = "android.settings.HOME_SETTINGS";
+ field public static final java.lang.String ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS = "android.settings.IGNORE_BATTERY_OPTIMIZATION_SETTINGS";
field public static final java.lang.String ACTION_INPUT_METHOD_SETTINGS = "android.settings.INPUT_METHOD_SETTINGS";
field public static final java.lang.String ACTION_INPUT_METHOD_SUBTYPE_SETTINGS = "android.settings.INPUT_METHOD_SUBTYPE_SETTINGS";
field public static final java.lang.String ACTION_INTERNAL_STORAGE_SETTINGS = "android.settings.INTERNAL_STORAGE_SETTINGS";
@@ -28785,12 +28767,12 @@ package android.service.media {
public abstract class MediaBrowserService extends android.app.Service {
ctor public MediaBrowserService();
method public void dump(java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
- method public void getMediaItem(java.lang.String, android.service.media.MediaBrowserService.Result<android.media.browse.MediaBrowser.MediaItem>) throws java.lang.UnsupportedOperationException;
method public android.media.session.MediaSession.Token getSessionToken();
method public void notifyChildrenChanged(java.lang.String);
method public android.os.IBinder onBind(android.content.Intent);
method public abstract android.service.media.MediaBrowserService.BrowserRoot onGetRoot(java.lang.String, int, android.os.Bundle);
method public abstract void onLoadChildren(java.lang.String, android.service.media.MediaBrowserService.Result<java.util.List<android.media.browse.MediaBrowser.MediaItem>>);
+ method public void onLoadItem(java.lang.String, android.service.media.MediaBrowserService.Result<android.media.browse.MediaBrowser.MediaItem>);
method public void setSessionToken(android.media.session.MediaSession.Token);
field public static final java.lang.String SERVICE_INTERFACE = "android.media.browse.MediaBrowserService";
}
@@ -30733,7 +30715,7 @@ package android.telephony {
field public static final java.lang.String KEY_USE_HFA_FOR_PROVISIONING_BOOL = "use_hfa_for_provisioning_bool";
field public static final java.lang.String KEY_USE_OTASP_FOR_PROVISIONING_BOOL = "use_otasp_for_provisioning_bool";
field public static final java.lang.String KEY_VOICEMAIL_NOTIFICATION_PERSISTENT_BOOL = "voicemail_notification_persistent_bool";
- field public static final java.lang.String KEY_VOICE_PRIVACY_DISABLE_BOOL = "voice_privacy_disable_bool";
+ field public static final java.lang.String KEY_VOICE_PRIVACY_DISABLE_UI_BOOL = "voice_privacy_disable_ui_bool";
field public static final java.lang.String KEY_VOLTE_REPLACEMENT_RAT_INT = "volte_replacement_rat_int";
field public static final java.lang.String KEY_WORLD_PHONE_BOOL = "world_phone_bool";
}
@@ -35489,8 +35471,6 @@ package android.view {
method public abstract android.view.MenuItem setEnabled(boolean);
method public abstract android.view.MenuItem setIcon(android.graphics.drawable.Drawable);
method public abstract android.view.MenuItem setIcon(int);
- method public abstract android.view.MenuItem setIconTintList(android.content.res.ColorStateList);
- method public abstract android.view.MenuItem setIconTintMode(android.graphics.PorterDuff.Mode);
method public abstract android.view.MenuItem setIntent(android.content.Intent);
method public abstract android.view.MenuItem setNumericShortcut(char);
method public abstract android.view.MenuItem setOnActionExpandListener(android.view.MenuItem.OnActionExpandListener);
@@ -39551,14 +39531,14 @@ package android.widget {
ctor public ActionMenuView(android.content.Context, android.util.AttributeSet);
method public void dismissPopupMenus();
method public android.view.Menu getMenu();
+ method public android.graphics.drawable.Drawable getOverflowIcon();
method public int getPopupTheme();
method public boolean hideOverflowMenu();
method public boolean isOverflowMenuShowing();
method public void onConfigurationChanged(android.content.res.Configuration);
method public void onDetachedFromWindow();
method public void setOnMenuItemClickListener(android.widget.ActionMenuView.OnMenuItemClickListener);
- method public void setOverflowTintList(android.content.res.ColorStateList);
- method public void setOverflowTintMode(android.graphics.PorterDuff.Mode);
+ method public void setOverflowIcon(android.graphics.drawable.Drawable);
method public void setPopupTheme(int);
method public boolean showOverflowMenu();
}
@@ -41848,6 +41828,7 @@ package android.widget {
method public android.view.Menu getMenu();
method public java.lang.CharSequence getNavigationContentDescription();
method public android.graphics.drawable.Drawable getNavigationIcon();
+ method public android.graphics.drawable.Drawable getOverflowIcon();
method public int getPopupTheme();
method public java.lang.CharSequence getSubtitle();
method public java.lang.CharSequence getTitle();
@@ -41867,11 +41848,8 @@ package android.widget {
method public void setNavigationIcon(int);
method public void setNavigationIcon(android.graphics.drawable.Drawable);
method public void setNavigationOnClickListener(android.view.View.OnClickListener);
- method public void setNavigationTintList(android.content.res.ColorStateList);
- method public void setNavigationTintMode(android.graphics.PorterDuff.Mode);
method public void setOnMenuItemClickListener(android.widget.Toolbar.OnMenuItemClickListener);
- method public void setOverflowTintList(android.content.res.ColorStateList);
- method public void setOverflowTintMode(android.graphics.PorterDuff.Mode);
+ method public void setOverflowIcon(android.graphics.drawable.Drawable);
method public void setPopupTheme(int);
method public void setSubtitle(int);
method public void setSubtitle(java.lang.CharSequence);
diff --git a/api/system-current.txt b/api/system-current.txt
index 8b3c181..6035ef2 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -297,6 +297,12 @@ package android {
ctor public R.attr();
field public static final int __reserved0 = 16844020; // 0x10104f4
field public static final int __reserved1 = 16844019; // 0x10104f3
+ field public static final int __reserved2 = 16843999; // 0x10104df
+ field public static final int __reserved3 = 16844000; // 0x10104e0
+ field public static final int __reserved4 = 16844001; // 0x10104e1
+ field public static final int __reserved5 = 16844002; // 0x10104e2
+ field public static final int __reserved6 = 16844003; // 0x10104e3
+ field public static final int __reserved7 = 16844004; // 0x10104e4
field public static final int absListViewStyle = 16842858; // 0x101006a
field public static final int accessibilityEventTypes = 16843648; // 0x1010380
field public static final int accessibilityFeedbackType = 16843650; // 0x1010382
@@ -645,7 +651,7 @@ package android {
field public static final int fillViewport = 16843130; // 0x101017a
field public static final int filter = 16843035; // 0x101011b
field public static final int filterTouchesWhenObscured = 16843460; // 0x10102c4
- field public static final int fingerprintDrawable = 16844025; // 0x10104f9
+ field public static final int fingerprintAuthDrawable = 16844025; // 0x10104f9
field public static final int finishOnCloseSystemDialogs = 16843431; // 0x10102a7
field public static final int finishOnTaskLaunch = 16842772; // 0x1010014
field public static final int firstDayOfWeek = 16843581; // 0x101033d
@@ -736,8 +742,6 @@ package android {
field public static final int hyphenationFrequency = 16844024; // 0x10104f8
field public static final int icon = 16842754; // 0x1010002
field public static final int iconPreview = 16843337; // 0x1010249
- field public static final int iconTint = 16843999; // 0x10104df
- field public static final int iconTintMode = 16844000; // 0x10104e0
field public static final int iconifiedByDefault = 16843514; // 0x10102fa
field public static final int id = 16842960; // 0x10100d0
field public static final int ignoreGravity = 16843263; // 0x10101ff
@@ -949,8 +953,6 @@ package android {
field public static final int navigationContentDescription = 16843969; // 0x10104c1
field public static final int navigationIcon = 16843968; // 0x10104c0
field public static final int navigationMode = 16843471; // 0x10102cf
- field public static final int navigationTint = 16844003; // 0x10104e3
- field public static final int navigationTintMode = 16844004; // 0x10104e4
field public static final int negativeButtonText = 16843254; // 0x10101f6
field public static final int nestedScrollingEnabled = 16843830; // 0x1010436
field public static final int nextFocusDown = 16842980; // 0x10100e4
@@ -982,8 +984,6 @@ package android {
field public static final int overScrollFooter = 16843459; // 0x10102c3
field public static final int overScrollHeader = 16843458; // 0x10102c2
field public static final int overScrollMode = 16843457; // 0x10102c1
- field public static final int overflowTint = 16844001; // 0x10104e1
- field public static final int overflowTintMode = 16844002; // 0x10104e2
field public static final int overlapAnchor = 16843874; // 0x1010462
field public static final int overridesImplicitlyEnabledSubtype = 16843682; // 0x10103a2
field public static final int packageNames = 16843649; // 0x1010381
@@ -5781,23 +5781,6 @@ package android.app.admin {
field public static final java.lang.String EXTRA_LOCK_TASK_PACKAGE = "android.app.extra.LOCK_TASK_PACKAGE";
}
- public class DeviceInitializerStatus {
- field public static final int FLAG_STATUS_CUSTOM = 33554432; // 0x2000000
- field public static final int FLAG_STATUS_ERROR = 16777216; // 0x1000000
- field public static final int FLAG_STATUS_HIGH_PRIORITY = 134217728; // 0x8000000
- field public static final int FLAG_STATUS_RESERVED = 67108864; // 0x4000000
- field public static final int STATUS_ERROR_CONNECT_WIFI = 16777237; // 0x1000015
- field public static final int STATUS_ERROR_DELETE_APPS = 16777242; // 0x100001a
- field public static final int STATUS_ERROR_DOUBLE_BUMP = 16777246; // 0x100001e
- field public static final int STATUS_ERROR_DOWNLOAD_PACKAGE = 16777239; // 0x1000017
- field public static final int STATUS_ERROR_INSTALL_PACKAGE = 16777240; // 0x1000018
- field public static final int STATUS_ERROR_RESET_PROTECTION_BLOCKING_PROVISIONING = 16777238; // 0x1000016
- field public static final int STATUS_ERROR_SET_DEVICE_POLICY = 16777241; // 0x1000019
- field public static final int STATUS_STATE_CONNECTING_BLUETOOTH_PROXY = 134217736; // 0x8000008
- field public static final int STATUS_STATE_DEVICE_PROVISIONED = 134217738; // 0x800000a
- field public static final int STATUS_STATE_DISCONNECTING_BLUETOOTH_PROXY = 134217737; // 0x8000009
- }
-
public class DevicePolicyManager {
method public void addCrossProfileIntentFilter(android.content.ComponentName, android.content.IntentFilter, int);
method public boolean addCrossProfileWidgetProvider(android.content.ComponentName, java.lang.String);
@@ -5874,7 +5857,6 @@ package android.app.admin {
method public boolean removeCrossProfileWidgetProvider(android.content.ComponentName, java.lang.String);
method public boolean removeUser(android.content.ComponentName, android.os.UserHandle);
method public boolean resetPassword(java.lang.String, int);
- method public void sendDeviceInitializerStatus(int, java.lang.String);
method public void setAccountManagementDisabled(android.content.ComponentName, java.lang.String, boolean);
method public deprecated boolean setActiveProfileOwner(android.content.ComponentName, java.lang.String) throws java.lang.IllegalArgumentException;
method public boolean setApplicationHidden(android.content.ComponentName, java.lang.String, boolean);
@@ -5927,7 +5909,6 @@ package android.app.admin {
field public static final java.lang.String ACTION_MANAGED_PROFILE_PROVISIONED = "android.app.action.MANAGED_PROFILE_PROVISIONED";
field public static final java.lang.String ACTION_PROVISION_MANAGED_DEVICE = "android.app.action.PROVISION_MANAGED_DEVICE";
field public static final java.lang.String ACTION_PROVISION_MANAGED_PROFILE = "android.app.action.PROVISION_MANAGED_PROFILE";
- field public static final java.lang.String ACTION_SEND_DEVICE_INITIALIZER_STATUS = "android.app.action.SEND_DEVICE_INITIALIZER_STATUS";
field public static final java.lang.String ACTION_SET_NEW_PASSWORD = "android.app.action.SET_NEW_PASSWORD";
field public static final java.lang.String ACTION_SET_PROFILE_OWNER = "android.app.action.SET_PROFILE_OWNER";
field public static final java.lang.String ACTION_START_ENCRYPTION = "android.app.action.START_ENCRYPTION";
@@ -5939,15 +5920,9 @@ package android.app.admin {
field public static final int ENCRYPTION_STATUS_UNSUPPORTED = 0; // 0x0
field public static final java.lang.String EXTRA_ADD_EXPLANATION = "android.app.extra.ADD_EXPLANATION";
field public static final java.lang.String EXTRA_DEVICE_ADMIN = "android.app.extra.DEVICE_ADMIN";
- field public static final java.lang.String EXTRA_DEVICE_INITIALIZER_STATUS_CODE = "android.app.extra.DEVICE_INITIALIZER_STATUS_CODE";
- field public static final java.lang.String EXTRA_DEVICE_INITIALIZER_STATUS_DESCRIPTION = "android.app.extra.DEVICE_INITIALIZER_STATUS_DESCRIPTION";
field public static final java.lang.String EXTRA_PROFILE_OWNER_NAME = "android.app.extra.PROFILE_OWNER_NAME";
field public static final java.lang.String EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE = "android.app.extra.PROVISIONING_ACCOUNT_TO_MIGRATE";
field public static final java.lang.String EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE = "android.app.extra.PROVISIONING_ADMIN_EXTRAS_BUNDLE";
- field public static final java.lang.String EXTRA_PROVISIONING_BT_DEVICE_ID = "android.app.extra.PROVISIONING_BT_DEVICE_ID";
- field public static final java.lang.String EXTRA_PROVISIONING_BT_MAC_ADDRESS = "android.app.extra.PROVISIONING_BT_MAC_ADDRESS";
- field public static final java.lang.String EXTRA_PROVISIONING_BT_USE_PROXY = "android.app.extra.PROVISIONING_BT_USE_PROXY";
- field public static final java.lang.String EXTRA_PROVISIONING_BT_UUID = "android.app.extra.PROVISIONING_BT_UUID";
field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_CERTIFICATE_CHECKSUM = "android.app.extra.PROVISIONING_DEVICE_ADMIN_CERTIFICATE_CHECKSUM";
field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME = "android.app.extra.PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME";
field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_MINIMUM_VERSION_CODE = "android.app.extra.PROVISIONING_DEVICE_ADMIN_MINIMUM_VERSION_CODE";
@@ -7944,6 +7919,7 @@ package android.content {
method public final java.lang.String getString(int, java.lang.Object...);
method public abstract java.lang.Object getSystemService(java.lang.String);
method public final T getSystemService(java.lang.Class<T>);
+ method public abstract java.lang.String getSystemServiceName(java.lang.Class<?>);
method public final java.lang.CharSequence getText(int);
method public abstract android.content.res.Resources.Theme getTheme();
method public abstract deprecated android.graphics.drawable.Drawable getWallpaper();
@@ -9521,6 +9497,7 @@ package android.content.pm {
public abstract class PackageManager {
ctor public PackageManager();
+ method public abstract void addOnPermissionsChangeListener(android.content.pm.PackageManager.OnPermissionsChangedListener);
method public abstract deprecated void addPackageToPreferred(java.lang.String);
method public abstract boolean addPermission(android.content.pm.PermissionInfo);
method public abstract boolean addPermissionAsync(android.content.pm.PermissionInfo);
@@ -9594,6 +9571,7 @@ package android.content.pm {
method public abstract java.util.List<android.content.pm.ResolveInfo> queryIntentContentProviders(android.content.Intent, int);
method public abstract java.util.List<android.content.pm.ResolveInfo> queryIntentServices(android.content.Intent, int);
method public abstract java.util.List<android.content.pm.PermissionInfo> queryPermissionsByGroup(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
+ method public abstract void removeOnPermissionsChangeListener(android.content.pm.PackageManager.OnPermissionsChangedListener);
method public abstract deprecated void removePackageFromPreferred(java.lang.String);
method public abstract void removePermission(java.lang.String);
method public abstract android.content.pm.ResolveInfo resolveActivity(android.content.Intent, int);
@@ -9769,6 +9747,10 @@ package android.content.pm {
ctor public PackageManager.NameNotFoundException(java.lang.String);
}
+ public static abstract interface PackageManager.OnPermissionsChangedListener {
+ method public abstract void onPermissionsChanged(int);
+ }
+
public static abstract class PackageManager.PermissionFlags implements java.lang.annotation.Annotation {
}
@@ -18522,7 +18504,7 @@ package android.media.browse {
method public void connect();
method public void disconnect();
method public android.os.Bundle getExtras();
- method public void getMediaItem(java.lang.String, android.media.browse.MediaBrowser.MediaItemCallback);
+ method public void getItem(java.lang.String, android.media.browse.MediaBrowser.ItemCallback);
method public java.lang.String getRoot();
method public android.content.ComponentName getServiceComponent();
method public android.media.session.MediaSession.Token getSessionToken();
@@ -18538,6 +18520,12 @@ package android.media.browse {
method public void onConnectionSuspended();
}
+ public static abstract class MediaBrowser.ItemCallback {
+ ctor public MediaBrowser.ItemCallback();
+ method public void onError(java.lang.String);
+ method public void onItemLoaded(android.media.browse.MediaBrowser.MediaItem);
+ }
+
public static class MediaBrowser.MediaItem implements android.os.Parcelable {
ctor public MediaBrowser.MediaItem(android.media.MediaDescription, int);
method public int describeContents();
@@ -18552,12 +18540,6 @@ package android.media.browse {
field public static final int FLAG_PLAYABLE = 2; // 0x2
}
- public static abstract class MediaBrowser.MediaItemCallback {
- ctor public MediaBrowser.MediaItemCallback();
- method public void onError();
- method public void onMediaItemLoaded(android.media.browse.MediaBrowser.MediaItem);
- }
-
public static abstract class MediaBrowser.SubscriptionCallback {
ctor public MediaBrowser.SubscriptionCallback();
method public void onChildrenLoaded(java.lang.String, java.util.List<android.media.browse.MediaBrowser.MediaItem>);
@@ -19194,7 +19176,9 @@ package android.media.tv {
method public android.content.Intent createSettingsIntent();
method public android.content.Intent createSetupIntent();
method public static android.media.tv.TvInputInfo createTvInputInfo(android.content.Context, android.content.pm.ResolveInfo, android.hardware.hdmi.HdmiDeviceInfo, java.lang.String, java.lang.String, android.net.Uri) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+ method public static android.media.tv.TvInputInfo createTvInputInfo(android.content.Context, android.content.pm.ResolveInfo, android.hardware.hdmi.HdmiDeviceInfo, java.lang.String, int, android.graphics.drawable.Icon) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public static android.media.tv.TvInputInfo createTvInputInfo(android.content.Context, android.content.pm.ResolveInfo, android.media.tv.TvInputHardwareInfo, java.lang.String, android.net.Uri) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+ method public static android.media.tv.TvInputInfo createTvInputInfo(android.content.Context, android.content.pm.ResolveInfo, android.media.tv.TvInputHardwareInfo, int, android.graphics.drawable.Icon) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public int describeContents();
method public android.hardware.hdmi.HdmiDeviceInfo getHdmiDeviceInfo();
method public java.lang.String getId();
@@ -26406,6 +26390,7 @@ package android.printservice {
method protected abstract void onPrintJobQueued(android.printservice.PrintJob);
method protected abstract void onRequestCancelPrintJob(android.printservice.PrintJob);
field public static final java.lang.String EXTRA_PRINTER_INFO = "android.intent.extra.print.EXTRA_PRINTER_INFO";
+ field public static final java.lang.String EXTRA_PRINT_DOCUMENT_INFO = "android.printservice.extra.PRINT_DOCUMENT_INFO";
field public static final java.lang.String EXTRA_PRINT_JOB_INFO = "android.intent.extra.print.PRINT_JOB_INFO";
field public static final java.lang.String SERVICE_INTERFACE = "android.printservice.PrintService";
field public static final java.lang.String SERVICE_META_DATA = "android.printservice";
@@ -28029,6 +28014,7 @@ package android.provider {
method public static boolean isDocumentUri(android.content.Context, android.net.Uri);
method public static android.net.Uri renameDocument(android.content.ContentResolver, android.net.Uri, java.lang.String);
field public static final java.lang.String EXTRA_ERROR = "error";
+ field public static final java.lang.String EXTRA_EXCLUDE_SELF = "android.provider.extra.EXCLUDE_SELF";
field public static final java.lang.String EXTRA_INFO = "info";
field public static final java.lang.String EXTRA_LOADING = "loading";
field public static final java.lang.String PROVIDER_INTERFACE = "android.content.action.DOCUMENTS_PROVIDER";
@@ -28568,6 +28554,7 @@ package android.provider {
field public static final java.lang.String ACTION_DISPLAY_SETTINGS = "android.settings.DISPLAY_SETTINGS";
field public static final java.lang.String ACTION_DREAM_SETTINGS = "android.settings.DREAM_SETTINGS";
field public static final java.lang.String ACTION_HOME_SETTINGS = "android.settings.HOME_SETTINGS";
+ field public static final java.lang.String ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS = "android.settings.IGNORE_BATTERY_OPTIMIZATION_SETTINGS";
field public static final java.lang.String ACTION_INPUT_METHOD_SETTINGS = "android.settings.INPUT_METHOD_SETTINGS";
field public static final java.lang.String ACTION_INPUT_METHOD_SUBTYPE_SETTINGS = "android.settings.INPUT_METHOD_SUBTYPE_SETTINGS";
field public static final java.lang.String ACTION_INTERNAL_STORAGE_SETTINGS = "android.settings.INTERNAL_STORAGE_SETTINGS";
@@ -30818,12 +30805,12 @@ package android.service.media {
public abstract class MediaBrowserService extends android.app.Service {
ctor public MediaBrowserService();
method public void dump(java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
- method public void getMediaItem(java.lang.String, android.service.media.MediaBrowserService.Result<android.media.browse.MediaBrowser.MediaItem>) throws java.lang.UnsupportedOperationException;
method public android.media.session.MediaSession.Token getSessionToken();
method public void notifyChildrenChanged(java.lang.String);
method public android.os.IBinder onBind(android.content.Intent);
method public abstract android.service.media.MediaBrowserService.BrowserRoot onGetRoot(java.lang.String, int, android.os.Bundle);
method public abstract void onLoadChildren(java.lang.String, android.service.media.MediaBrowserService.Result<java.util.List<android.media.browse.MediaBrowser.MediaItem>>);
+ method public void onLoadItem(java.lang.String, android.service.media.MediaBrowserService.Result<android.media.browse.MediaBrowser.MediaItem>);
method public void setSessionToken(android.media.session.MediaSession.Token);
field public static final java.lang.String SERVICE_INTERFACE = "android.media.browse.MediaBrowserService";
}
@@ -32949,7 +32936,7 @@ package android.telephony {
field public static final java.lang.String KEY_USE_HFA_FOR_PROVISIONING_BOOL = "use_hfa_for_provisioning_bool";
field public static final java.lang.String KEY_USE_OTASP_FOR_PROVISIONING_BOOL = "use_otasp_for_provisioning_bool";
field public static final java.lang.String KEY_VOICEMAIL_NOTIFICATION_PERSISTENT_BOOL = "voicemail_notification_persistent_bool";
- field public static final java.lang.String KEY_VOICE_PRIVACY_DISABLE_BOOL = "voice_privacy_disable_bool";
+ field public static final java.lang.String KEY_VOICE_PRIVACY_DISABLE_UI_BOOL = "voice_privacy_disable_ui_bool";
field public static final java.lang.String KEY_VOLTE_REPLACEMENT_RAT_INT = "volte_replacement_rat_int";
field public static final java.lang.String KEY_WORLD_PHONE_BOOL = "world_phone_bool";
}
@@ -33514,6 +33501,10 @@ package android.telephony {
field public static final int CALL_STATE_IDLE = 0; // 0x0
field public static final int CALL_STATE_OFFHOOK = 2; // 0x2
field public static final int CALL_STATE_RINGING = 1; // 0x1
+ field public static final int CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES = -2; // 0xfffffffe
+ field public static final int CARRIER_PRIVILEGE_STATUS_HAS_ACCESS = 1; // 0x1
+ field public static final int CARRIER_PRIVILEGE_STATUS_NO_ACCESS = 0; // 0x0
+ field public static final int CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED = -1; // 0xffffffff
field public static final int DATA_ACTIVITY_DORMANT = 4; // 0x4
field public static final int DATA_ACTIVITY_IN = 1; // 0x1
field public static final int DATA_ACTIVITY_INOUT = 3; // 0x3
@@ -34151,6 +34142,7 @@ package android.test.mock {
public class MockPackageManager extends android.content.pm.PackageManager {
ctor public MockPackageManager();
+ method public void addOnPermissionsChangeListener(android.content.pm.PackageManager.OnPermissionsChangedListener);
method public void addPackageToPreferred(java.lang.String);
method public boolean addPermission(android.content.pm.PermissionInfo);
method public boolean addPermissionAsync(android.content.pm.PermissionInfo);
@@ -34225,6 +34217,7 @@ package android.test.mock {
method public java.util.List<android.content.pm.ResolveInfo> queryIntentContentProviders(android.content.Intent, int);
method public java.util.List<android.content.pm.ResolveInfo> queryIntentServices(android.content.Intent, int);
method public java.util.List<android.content.pm.PermissionInfo> queryPermissionsByGroup(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
+ method public void removeOnPermissionsChangeListener(android.content.pm.PackageManager.OnPermissionsChangedListener);
method public void removePackageFromPreferred(java.lang.String);
method public void removePermission(java.lang.String);
method public android.content.pm.ResolveInfo resolveActivity(android.content.Intent, int);
@@ -37755,8 +37748,6 @@ package android.view {
method public abstract android.view.MenuItem setEnabled(boolean);
method public abstract android.view.MenuItem setIcon(android.graphics.drawable.Drawable);
method public abstract android.view.MenuItem setIcon(int);
- method public abstract android.view.MenuItem setIconTintList(android.content.res.ColorStateList);
- method public abstract android.view.MenuItem setIconTintMode(android.graphics.PorterDuff.Mode);
method public abstract android.view.MenuItem setIntent(android.content.Intent);
method public abstract android.view.MenuItem setNumericShortcut(char);
method public abstract android.view.MenuItem setOnActionExpandListener(android.view.MenuItem.OnActionExpandListener);
@@ -42131,14 +42122,14 @@ package android.widget {
ctor public ActionMenuView(android.content.Context, android.util.AttributeSet);
method public void dismissPopupMenus();
method public android.view.Menu getMenu();
+ method public android.graphics.drawable.Drawable getOverflowIcon();
method public int getPopupTheme();
method public boolean hideOverflowMenu();
method public boolean isOverflowMenuShowing();
method public void onConfigurationChanged(android.content.res.Configuration);
method public void onDetachedFromWindow();
method public void setOnMenuItemClickListener(android.widget.ActionMenuView.OnMenuItemClickListener);
- method public void setOverflowTintList(android.content.res.ColorStateList);
- method public void setOverflowTintMode(android.graphics.PorterDuff.Mode);
+ method public void setOverflowIcon(android.graphics.drawable.Drawable);
method public void setPopupTheme(int);
method public boolean showOverflowMenu();
}
@@ -44428,6 +44419,7 @@ package android.widget {
method public android.view.Menu getMenu();
method public java.lang.CharSequence getNavigationContentDescription();
method public android.graphics.drawable.Drawable getNavigationIcon();
+ method public android.graphics.drawable.Drawable getOverflowIcon();
method public int getPopupTheme();
method public java.lang.CharSequence getSubtitle();
method public java.lang.CharSequence getTitle();
@@ -44447,11 +44439,8 @@ package android.widget {
method public void setNavigationIcon(int);
method public void setNavigationIcon(android.graphics.drawable.Drawable);
method public void setNavigationOnClickListener(android.view.View.OnClickListener);
- method public void setNavigationTintList(android.content.res.ColorStateList);
- method public void setNavigationTintMode(android.graphics.PorterDuff.Mode);
method public void setOnMenuItemClickListener(android.widget.Toolbar.OnMenuItemClickListener);
- method public void setOverflowTintList(android.content.res.ColorStateList);
- method public void setOverflowTintMode(android.graphics.PorterDuff.Mode);
+ method public void setOverflowIcon(android.graphics.drawable.Drawable);
method public void setPopupTheme(int);
method public void setSubtitle(int);
method public void setSubtitle(java.lang.CharSequence);
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index b0a7dc7..bf3b455 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -305,11 +305,23 @@ public class Am extends BaseCommand {
" [--eu <EXTRA_KEY> <EXTRA_URI_VALUE> ...]\n" +
" [--ecn <EXTRA_KEY> <EXTRA_COMPONENT_NAME_VALUE>]\n" +
" [--eia <EXTRA_KEY> <EXTRA_INT_VALUE>[,<EXTRA_INT_VALUE...]]\n" +
+ " (mutiple extras passed as Integer[])\n" +
+ " [--eial <EXTRA_KEY> <EXTRA_INT_VALUE>[,<EXTRA_INT_VALUE...]]\n" +
+ " (mutiple extras passed as List<Integer>)\n" +
" [--ela <EXTRA_KEY> <EXTRA_LONG_VALUE>[,<EXTRA_LONG_VALUE...]]\n" +
+ " (mutiple extras passed as Long[])\n" +
+ " [--elal <EXTRA_KEY> <EXTRA_LONG_VALUE>[,<EXTRA_LONG_VALUE...]]\n" +
+ " (mutiple extras passed as List<Long>)\n" +
" [--efa <EXTRA_KEY> <EXTRA_FLOAT_VALUE>[,<EXTRA_FLOAT_VALUE...]]\n" +
+ " (mutiple extras passed as Float[])\n" +
+ " [--efal <EXTRA_KEY> <EXTRA_FLOAT_VALUE>[,<EXTRA_FLOAT_VALUE...]]\n" +
+ " (mutiple extras passed as List<Float>)\n" +
" [--esa <EXTRA_KEY> <EXTRA_STRING_VALUE>[,<EXTRA_STRING_VALUE...]]\n" +
- " (to embed a comma into a string escape it using \"\\,\")\n" +
- " [-n <COMPONENT>] [-p <PACKAGE>] [-f <FLAGS>]\n" +
+ " (mutiple extras passed as String[]; to embed a comma into a string,\n" +
+ " escape it using \"\\,\")\n" +
+ " [--esal <EXTRA_KEY> <EXTRA_STRING_VALUE>[,<EXTRA_STRING_VALUE...]]\n" +
+ " (mutiple extras passed as List<String>; to embed a comma into a string,\n" +
+ " escape it using \"\\,\")\n" +
" [--grant-read-uri-permission] [--grant-write-uri-permission]\n" +
" [--grant-persistable-uri-permission] [--grant-prefix-uri-permission]\n" +
" [--debug-log-resolution] [--exclude-stopped-packages]\n" +
@@ -490,6 +502,15 @@ public class Am extends BaseCommand {
list[i] = Integer.decode(strings[i]);
}
intent.putExtra(key, list);
+ } else if (opt.equals("--eial")) {
+ String key = nextArgRequired();
+ String value = nextArgRequired();
+ String[] strings = value.split(",");
+ ArrayList<Integer> list = new ArrayList<>(strings.length);
+ for (int i = 0; i < strings.length; i++) {
+ list.add(Integer.decode(strings[i]));
+ }
+ intent.putExtra(key, list);
} else if (opt.equals("--el")) {
String key = nextArgRequired();
String value = nextArgRequired();
@@ -504,6 +525,16 @@ public class Am extends BaseCommand {
}
intent.putExtra(key, list);
hasIntentInfo = true;
+ } else if (opt.equals("--elal")) {
+ String key = nextArgRequired();
+ String value = nextArgRequired();
+ String[] strings = value.split(",");
+ ArrayList<Long> list = new ArrayList<>(strings.length);
+ for (int i = 0; i < strings.length; i++) {
+ list.add(Long.valueOf(strings[i]));
+ }
+ intent.putExtra(key, list);
+ hasIntentInfo = true;
} else if (opt.equals("--ef")) {
String key = nextArgRequired();
String value = nextArgRequired();
@@ -519,6 +550,16 @@ public class Am extends BaseCommand {
}
intent.putExtra(key, list);
hasIntentInfo = true;
+ } else if (opt.equals("--efal")) {
+ String key = nextArgRequired();
+ String value = nextArgRequired();
+ String[] strings = value.split(",");
+ ArrayList<Float> list = new ArrayList<>(strings.length);
+ for (int i = 0; i < strings.length; i++) {
+ list.add(Float.valueOf(strings[i]));
+ }
+ intent.putExtra(key, list);
+ hasIntentInfo = true;
} else if (opt.equals("--esa")) {
String key = nextArgRequired();
String value = nextArgRequired();
@@ -528,6 +569,19 @@ public class Am extends BaseCommand {
String[] strings = value.split("(?<!\\\\),");
intent.putExtra(key, strings);
hasIntentInfo = true;
+ } else if (opt.equals("--esal")) {
+ String key = nextArgRequired();
+ String value = nextArgRequired();
+ // Split on commas unless they are preceeded by an escape.
+ // The escape character must be escaped for the string and
+ // again for the regex, thus four escape characters become one.
+ String[] strings = value.split("(?<!\\\\),");
+ ArrayList<String> list = new ArrayList<>(strings.length);
+ for (int i = 0; i < strings.length; i++) {
+ list.add(strings[i]);
+ }
+ intent.putExtra(key, list);
+ hasIntentInfo = true;
} else if (opt.equals("--ez")) {
String key = nextArgRequired();
String value = nextArgRequired().toLowerCase();
diff --git a/cmds/screencap/screencap.cpp b/cmds/screencap/screencap.cpp
index dbc35af..c469ae4 100644
--- a/cmds/screencap/screencap.cpp
+++ b/cmds/screencap/screencap.cpp
@@ -30,6 +30,7 @@
#include <gui/SurfaceComposerClient.h>
#include <gui/ISurfaceComposer.h>
+#include <ui/DisplayInfo.h>
#include <ui/PixelFormat.h>
// TODO: Fix Skia.
@@ -159,9 +160,35 @@ int main(int argc, char** argv)
uint32_t w, s, h, f;
size_t size = 0;
+ // Maps orientations from DisplayInfo to ISurfaceComposer
+ static const uint32_t ORIENTATION_MAP[] = {
+ ISurfaceComposer::eRotateNone, // 0 == DISPLAY_ORIENTATION_0
+ ISurfaceComposer::eRotate270, // 1 == DISPLAY_ORIENTATION_90
+ ISurfaceComposer::eRotate180, // 2 == DISPLAY_ORIENTATION_180
+ ISurfaceComposer::eRotate90, // 3 == DISPLAY_ORIENTATION_270
+ };
+
ScreenshotClient screenshot;
sp<IBinder> display = SurfaceComposerClient::getBuiltInDisplay(displayId);
- if (display != NULL && screenshot.update(display, Rect(), false) == NO_ERROR) {
+ if (display == NULL) {
+ fprintf(stderr, "Unable to get handle for display %d\n", displayId);
+ return 1;
+ }
+
+ Vector<DisplayInfo> configs;
+ SurfaceComposerClient::getDisplayConfigs(display, &configs);
+ int activeConfig = SurfaceComposerClient::getActiveConfig(display);
+ if (static_cast<size_t>(activeConfig) >= configs.size()) {
+ fprintf(stderr, "Active config %d not inside configs (size %zu)\n",
+ activeConfig, configs.size());
+ return 1;
+ }
+ uint8_t displayOrientation = configs[activeConfig].orientation;
+ uint32_t captureOrientation = ORIENTATION_MAP[displayOrientation];
+
+ status_t result = screenshot.update(display, Rect(), 0, 0, 0, -1U,
+ false, captureOrientation);
+ if (result == NO_ERROR) {
base = screenshot.getPixels();
w = screenshot.getWidth();
h = screenshot.getHeight();
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 41e3db8..cb1e7aa 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -31,6 +31,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.ComponentInfo;
import android.content.pm.ContainerEncryptionParams;
import android.content.pm.FeatureInfo;
+import android.content.pm.IOnPermissionsChangeListener;
import android.content.pm.IPackageDataObserver;
import android.content.pm.IPackageDeleteObserver;
import android.content.pm.IPackageInstallObserver;
@@ -88,6 +89,7 @@ import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import java.util.Objects;
/*package*/
@@ -1048,6 +1050,38 @@ final class ApplicationPackageManager extends PackageManager {
}
}
+ @Override
+ public void addOnPermissionsChangeListener(OnPermissionsChangedListener listener) {
+ synchronized (mPermissionListeners) {
+ if (mPermissionListeners.get(listener) != null) {
+ return;
+ }
+ OnPermissionsChangeListenerDelegate delegate =
+ new OnPermissionsChangeListenerDelegate(listener, Looper.getMainLooper());
+ try {
+ mPM.addOnPermissionsChangeListener(delegate);
+ mPermissionListeners.put(listener, delegate);
+ } catch (RemoteException e) {
+ throw new RuntimeException("Package manager has died", e);
+ }
+ }
+ }
+
+ @Override
+ public void removeOnPermissionsChangeListener(OnPermissionsChangedListener listener) {
+ synchronized (mPermissionListeners) {
+ IOnPermissionsChangeListener delegate = mPermissionListeners.get(listener);
+ if (delegate != null) {
+ try {
+ mPM.removeOnPermissionsChangeListener(delegate);
+ mPermissionListeners.remove(listener);
+ } catch (RemoteException e) {
+ throw new RuntimeException("Package manager has died", e);
+ }
+ }
+ }
+ }
+
static void configurationChanged() {
synchronized (sSync) {
sIconCache.clear();
@@ -2139,4 +2173,39 @@ final class ApplicationPackageManager extends PackageManager {
= new ArrayMap<ResourceName, WeakReference<Drawable.ConstantState>>();
private static ArrayMap<ResourceName, WeakReference<CharSequence>> sStringCache
= new ArrayMap<ResourceName, WeakReference<CharSequence>>();
+
+ private final Map<OnPermissionsChangedListener, IOnPermissionsChangeListener>
+ mPermissionListeners = new ArrayMap<>();
+
+ public class OnPermissionsChangeListenerDelegate extends IOnPermissionsChangeListener.Stub
+ implements Handler.Callback{
+ private static final int MSG_PERMISSIONS_CHANGED = 1;
+
+ private final OnPermissionsChangedListener mListener;
+ private final Handler mHandler;
+
+
+ public OnPermissionsChangeListenerDelegate(OnPermissionsChangedListener listener,
+ Looper looper) {
+ mListener = listener;
+ mHandler = new Handler(looper, this);
+ }
+
+ @Override
+ public void onPermissionsChanged(int uid) {
+ mHandler.obtainMessage(MSG_PERMISSIONS_CHANGED, uid, 0).sendToTarget();
+ }
+
+ @Override
+ public boolean handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_PERMISSIONS_CHANGED: {
+ final int uid = msg.arg1;
+ mListener.onPermissionsChanged(uid);
+ return true;
+ }
+ }
+ return false;
+ }
+ }
}
diff --git a/core/java/android/app/Presentation.java b/core/java/android/app/Presentation.java
index bb45abb4..e110dcb 100644
--- a/core/java/android/app/Presentation.java
+++ b/core/java/android/app/Presentation.java
@@ -213,7 +213,7 @@ public class Presentation extends Dialog {
// dismiss the presentation immediately. This case is expected
// to be rare but surprising, so we'll write a log message about it.
if (!isConfigurationStillValid()) {
- Log.i(TAG, "Presentation is being immediately dismissed because the "
+ Log.i(TAG, "Presentation is being dismissed because the "
+ "display metrics have changed since it was created.");
mHandler.sendEmptyMessage(MSG_CANCEL);
}
@@ -274,6 +274,8 @@ public class Presentation extends Dialog {
// is invalid and the application must recreate the presentation to get
// a new context.
if (!isConfigurationStillValid()) {
+ Log.i(TAG, "Presentation is being dismissed because the "
+ + "display metrics have changed since it was created.");
cancel();
}
}
diff --git a/core/java/android/app/admin/DeviceInitializerStatus.java b/core/java/android/app/admin/DeviceInitializerStatus.java
deleted file mode 100644
index 7de518b..0000000
--- a/core/java/android/app/admin/DeviceInitializerStatus.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright (C) 2015 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.app.admin;
-
-/**
- * Defines constants designating device provisioning status used with {@link
- * android.app.admin.DevicePolicyManager#sendDeviceInitializerStatus(int,String)}.
- *
- * This class contains flag constants that define special status codes:
- * <ul>
- * <li>{@link #FLAG_STATUS_ERROR} is used to define provisioning error status codes
- * <li>{@link #FLAG_STATUS_CUSTOM} is used to define custom status codes
- * <li>{@link #FLAG_STATUS_HIGH_PRIORITY} is used to define high priority status codes
- * </ul>
- *
- * <p>Status codes used by ManagedProvisioning are also defined in this class. These status codes
- * include provisioning errors and status codes.
- * <ul>
- * <li>{@link #STATUS_ERROR_CONNECT_WIFI}
- * <li>{@link #STATUS_ERROR_RESET_PROTECTION_BLOCKING_PROVISIONING}
- * <li>{@link #STATUS_ERROR_DOWNLOAD_PACKAGE}
- * <li>{@link #STATUS_ERROR_INSTALL_PACKAGE}
- * <li>{@link #STATUS_ERROR_SET_DEVICE_POLICY}
- * <li>{@link #STATUS_ERROR_DELETE_APPS}
- * <li>{@link #STATUS_ERROR_DOUBLE_BUMP}
- * <li>{@link #STATUS_STATE_CONNECTING_BLUETOOTH_PROXY}
- * <li>{@link #STATUS_STATE_DISCONNECTING_BLUETOOTH_PROXY}
- * <li>{@link #STATUS_STATE_DEVICE_PROVISIONED}
- * </ul>
- */
-public class DeviceInitializerStatus {
- /**
- * A flag used to designate an error status.
- *
- * <p>This flag is used with {@code statusCode} values sent through
- * {@link android.app.admin.DevicePolicyManager#sendDeviceInitializerStatus(int,String)}
- * @see #isErrorStatus(int)
- */
- public static final int FLAG_STATUS_ERROR = 0x01000000;
-
- /**
- * A flag used to designate a custom status. Custom status codes will be defined by device
- * initializer agents.
- *
- * <p>This flag is used with {@code statusCode} values sent through
- * {@link android.app.admin.DevicePolicyManager#sendDeviceInitializerStatus(int,String)}
- * @see #isCustomStatus(int)
- */
- public static final int FLAG_STATUS_CUSTOM = 0x02000000;
-
- /**
- * A bit flag used to designate a reserved status. Reserved status codes will not be defined
- * in AOSP.
- *
- * <p>This flag is used with {@code statusCode} values sent through
- * {@link android.app.admin.DevicePolicyManager#sendDeviceInitializerStatus(int,String)}
- */
- public static final int FLAG_STATUS_RESERVED = 0x04000000;
-
- /**
- * A flag used to indicate that a status message is high priority.
- *
- * <p>This flag is used with {@code statusCode} values sent through
- * {@link android.app.admin.DevicePolicyManager#sendDeviceInitializerStatus(int,String)}
- * @see #isHighPriority(int)
- */
- public static final int FLAG_STATUS_HIGH_PRIORITY = 0x08000000;
-
- /**
- * Device provisioning status code that indicates that a device is connecting to establish
- * a Bluetooth network proxy.
- */
- public static final int STATUS_STATE_CONNECTING_BLUETOOTH_PROXY = FLAG_STATUS_HIGH_PRIORITY | 8;
-
- /**
- * Device provisioning status code that indicates that a connected Bluetooth network proxy
- * is being shut down.
- */
- public static final int STATUS_STATE_DISCONNECTING_BLUETOOTH_PROXY = FLAG_STATUS_HIGH_PRIORITY | 9;
-
- /**
- * Device provisioning status code that indicates that a device has been successfully
- * provisioned.
- */
- public static final int STATUS_STATE_DEVICE_PROVISIONED = FLAG_STATUS_HIGH_PRIORITY | 10;
-
- /**
- * Device provisioning error status code that indicates that a device could not connect to
- * a Wi-Fi network.
- */
- public static final int STATUS_ERROR_CONNECT_WIFI = FLAG_STATUS_ERROR | 21;
-
- /**
- * Device provisioning error status indicating that factory reset protection is enabled on
- * the provisioned device and cannot be disabled with the provided data.
- */
- public static final int STATUS_ERROR_RESET_PROTECTION_BLOCKING_PROVISIONING =
- FLAG_STATUS_ERROR | 22;
-
- /**
- * Device provisioning error status indicating that device administrator and device initializer
- * packages could not be downloaded and verified successfully.
- */
- public static final int STATUS_ERROR_DOWNLOAD_PACKAGE = FLAG_STATUS_ERROR | 23;
-
- /**
- * Device provisioning error status indicating that device owner and device initializer packages
- * could not be installed.
- */
- public static final int STATUS_ERROR_INSTALL_PACKAGE = FLAG_STATUS_ERROR | 24;
-
- /**
- * Device provisioning error status indicating that the device owner or device initializer
- * components could not be set.
- */
- public static final int STATUS_ERROR_SET_DEVICE_POLICY = FLAG_STATUS_ERROR | 25;
-
- /**
- * Device provisioning error status indicating that deleting non-required applications during
- * provisioning failed.
- */
- public static final int STATUS_ERROR_DELETE_APPS = FLAG_STATUS_ERROR | 26;
-
- /**
- * Device provisioning error status code that indicates that a provisioning attempt has failed
- * because the device has already been provisioned or that provisioning has already started.
- */
- public static final int STATUS_ERROR_DOUBLE_BUMP = FLAG_STATUS_ERROR | 30;
-
- private DeviceInitializerStatus() {}
-}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 3ab0e01..996748a 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -540,50 +540,6 @@ public class DevicePolicyManager {
= "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_CERTIFICATE_CHECKSUM";
/**
- * A String extra holding the MAC address of the Bluetooth device to connect to with status
- * updates during provisioning.
- *
- * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC_V2} that starts device owner
- * provisioning via an NFC bump.
- */
- public static final String EXTRA_PROVISIONING_BT_MAC_ADDRESS
- = "android.app.extra.PROVISIONING_BT_MAC_ADDRESS";
-
- /**
- * A String extra holding the Bluetooth service UUID on the device to connect to with status
- * updates during provisioning.
- *
- * <p>This value must be specified when {@code #EXTRA_PROVISIONING_BT_MAC_ADDRESS} is present.
- *
- * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC_V2} that starts device owner
- * provisioning via an NFC bump.
- */
- public static final String EXTRA_PROVISIONING_BT_UUID
- = "android.app.extra.PROVISIONING_BT_UUID";
-
- /**
- * A String extra holding a unique identifier used to identify the device connecting over
- * Bluetooth. This identifier will be part of every status message sent to the remote device.
- *
- * <p>This value must be specified when {@code #EXTRA_PROVISIONING_BT_MAC_ADDRESS} is present.
- *
- * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC_V2} that starts device owner
- * provisioning via an NFC bump.
- */
- public static final String EXTRA_PROVISIONING_BT_DEVICE_ID
- = "android.app.extra.PROVISIONING_BT_DEVICE_ID";
-
- /**
- * A Boolean extra that that will cause a provisioned device to temporarily proxy network
- * traffic over Bluetooth. When a Wi-Fi network is available, the network proxy will stop.
- *
- * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC_V2} that starts device owner
- * provisioning via an NFC bump.
- */
- public static final String EXTRA_PROVISIONING_BT_USE_PROXY
- = "android.app.extra.PROVISIONING_BT_USE_PROXY";
-
- /**
* A {@link android.os.Parcelable} extra of type {@link android.os.PersistableBundle} that
* holds data needed by the system to wipe factory reset protection. The data needed to wipe
* the device depend on the installed factory reset protection implementation. For example,
@@ -665,11 +621,7 @@ public class DevicePolicyManager {
* Replaces {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME}. The value of the property
* should be converted to a String via
* {@link android.content.ComponentName#flattenToString()}</li>
- * <li>{@link #EXTRA_PROVISIONING_DEVICE_ADMIN_MINIMUM_VERSION_CODE}, optional</li>
- * <li>{@link #EXTRA_PROVISIONING_BT_MAC_ADDRESS}, optional</li>
- * <li>{@link #EXTRA_PROVISIONING_BT_UUID}, optional</li>
- * <li>{@link #EXTRA_PROVISIONING_BT_DEVICE_ID}, optional</li>
- * <li>{@link #EXTRA_PROVISIONING_BT_USE_PROXY}, optional</li></ul>
+ * <li>{@link #EXTRA_PROVISIONING_DEVICE_ADMIN_MINIMUM_VERSION_CODE}, optional</li></ul>
*
* <p> When device owner provisioning has completed, an intent of the type
* {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE} is broadcasted to the
@@ -727,45 +679,6 @@ public class DevicePolicyManager {
= "android.app.action.SET_PROFILE_OWNER";
/**
- * Protected broadcast action that will be sent to managed provisioning to notify it that a
- * status update has been reported by the device initializer. The status update will be
- * reported to the remote setup device over Bluetooth.
- *
- * <p>Broadcasts with this action must supply a
- * {@linkplain DeviceInitializerStatus#FLAG_STATUS_CUSTOM custom} status code in the
- * {@link EXTRA_DEVICE_INITIALIZER_STATUS_CODE} extra.
- *
- * <p>Broadcasts may optionally contain a description in the
- * {@link EXTRA_DEVICE_INITIALIZER_STATUS_DESCRIPTION} extra.
- * @hide
- */
- @SystemApi
- public static final String ACTION_SEND_DEVICE_INITIALIZER_STATUS
- = "android.app.action.SEND_DEVICE_INITIALIZER_STATUS";
-
- /**
- * An integer extra that contains the status code that defines a status update. This extra must
- * sent as part of a broadcast with an action of {@code ACTION_SEND_DEVICE_INITIALIZER_STATUS}.
- *
- * <p>The status code sent with this extra must be a custom status code as defined by
- * {@link DeviceInitializerStatus#FLAG_STATUS_CUSTOM}.
- * @hide
- */
- @SystemApi
- public static final String EXTRA_DEVICE_INITIALIZER_STATUS_CODE
- = "android.app.extra.DEVICE_INITIALIZER_STATUS_CODE";
-
- /**
- * A {@code String} extra that contains an optional description accompanying a status update.
- * This extra my be sent as part of a broadcast with an action of
- * {@code ACTION_SEND_DEVICE_INITIALIZER_STATUS}.
- * @hide
- */
- @SystemApi
- public static final String EXTRA_DEVICE_INITIALIZER_STATUS_DESCRIPTION
- = "android.app.extra.DEVICE_INITIALIZER_STATUS_DESCRIPTION";
-
- /**
* @hide
* Name of the profile owner admin that controls the user.
*/
@@ -2275,7 +2188,7 @@ public class DevicePolicyManager {
if (mService != null) {
try {
final String alias = getCaCertAlias(certBuffer);
- mService.uninstallCaCert(admin, alias);
+ mService.uninstallCaCerts(admin, new String[] {alias});
} catch (CertificateException e) {
Log.w(TAG, "Unable to parse certificate", e);
} catch (RemoteException e) {
@@ -2322,12 +2235,11 @@ public class DevicePolicyManager {
*/
public void uninstallAllUserCaCerts(@Nullable ComponentName admin) {
if (mService != null) {
- for (String alias : new TrustedCertificateStore().userAliases()) {
- try {
- mService.uninstallCaCert(admin, alias);
- } catch (RemoteException re) {
- Log.w(TAG, "Failed talking with device policy service", re);
- }
+ try {
+ mService.uninstallCaCerts(admin, new TrustedCertificateStore().userAliases()
+ .toArray(new String[0]));
+ } catch (RemoteException re) {
+ Log.w(TAG, "Failed talking with device policy service", re);
}
}
}
@@ -3976,6 +3888,9 @@ public class DevicePolicyManager {
* <p>Any packages that shares uid with an allowed package will also be allowed
* to activate lock task.
*
+ * From {@link android.os.Build.VERSION_CODES#MNC} removing packages from the lock task
+ * package list results in locked tasks belonging to those packages to be finished.
+ *
* This function can only be called by the device owner.
* @param packages The list of packages allowed to enter lock task mode
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
@@ -4289,21 +4204,6 @@ public class DevicePolicyManager {
}
/**
- * Called by device initializer to send a provisioning status update to the remote setup device.
- *
- * @param statusCode a custom status code value as defined by
- * {@link DeviceInitializerStatus#FLAG_STATUS_CUSTOM}.
- * @param description custom description of the status code sent
- */
- public void sendDeviceInitializerStatus(int statusCode, String description) {
- try {
- mService.sendDeviceInitializerStatus(statusCode, description);
- } catch (RemoteException re) {
- Log.w(TAG, "Could not send device initializer status", re);
- }
- }
-
- /**
* Called by device owners to set a local system update policy. When a new policy is set,
* {@link #ACTION_SYSTEM_UPDATE_POLICY_CHANGED} is broadcasted.
*
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 8c7b20a..376a3d8 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -128,7 +128,7 @@ interface IDevicePolicyManager {
boolean hasUserSetupCompleted();
boolean installCaCert(in ComponentName admin, in byte[] certBuffer);
- void uninstallCaCert(in ComponentName admin, in String alias);
+ void uninstallCaCerts(in ComponentName admin, in String[] aliases);
void enforceCanManageCaCerts(in ComponentName admin);
boolean installKeyPair(in ComponentName who, in byte[] privKeyBuffer, in byte[] certBuffer, String alias);
@@ -220,7 +220,6 @@ interface IDevicePolicyManager {
void setUserIcon(in ComponentName admin, in Bitmap icon);
- void sendDeviceInitializerStatus(int statusCode, String description);
void setSystemUpdatePolicy(in ComponentName who, in SystemUpdatePolicy policy);
SystemUpdatePolicy getSystemUpdatePolicy();
diff --git a/core/java/android/content/ContentProviderOperation.java b/core/java/android/content/ContentProviderOperation.java
index 49ac062..fd1e24a 100644
--- a/core/java/android/content/ContentProviderOperation.java
+++ b/core/java/android/content/ContentProviderOperation.java
@@ -28,6 +28,11 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
+/**
+ * Represents a single operation to be performed as part of a batch of operations.
+ *
+ * @see ContentProvider#applyBatch(ArrayList)
+ */
public class ContentProviderOperation implements Parcelable {
/** @hide exposed for unit tests */
public final static int TYPE_INSERT = 1;
@@ -195,10 +200,19 @@ public class ContentProviderOperation implements Parcelable {
return new Builder(TYPE_ASSERT, uri);
}
+ /**
+ * Gets the Uri for the target of the operation.
+ */
public Uri getUri() {
return mUri;
}
+ /**
+ * Returns true if the operation allows yielding the database to other transactions
+ * if the database is contended.
+ *
+ * @see android.database.sqlite.SQLiteDatabase#yieldIfContendedSafely()
+ */
public boolean isYieldAllowed() {
return mYieldAllowed;
}
@@ -208,26 +222,58 @@ public class ContentProviderOperation implements Parcelable {
return mType;
}
+ /**
+ * Returns true if the operation represents an insertion.
+ *
+ * @see #newInsert
+ */
public boolean isInsert() {
return mType == TYPE_INSERT;
}
+ /**
+ * Returns true if the operation represents a deletion.
+ *
+ * @see #newDelete
+ */
public boolean isDelete() {
return mType == TYPE_DELETE;
}
+ /**
+ * Returns true if the operation represents an update.
+ *
+ * @see #newUpdate
+ */
public boolean isUpdate() {
return mType == TYPE_UPDATE;
}
+ /**
+ * Returns true if the operation represents an assert query.
+ *
+ * @see #newAssertQuery
+ */
public boolean isAssertQuery() {
return mType == TYPE_ASSERT;
}
+ /**
+ * Returns true if the operation represents an insertion, deletion, or update.
+ *
+ * @see #isInsert
+ * @see #isDelete
+ * @see #isUpdate
+ */
public boolean isWriteOperation() {
return mType == TYPE_DELETE || mType == TYPE_INSERT || mType == TYPE_UPDATE;
}
+ /**
+ * Returns true if the operation represents an assert query.
+ *
+ * @see #isAssertQuery
+ */
public boolean isReadOperation() {
return mType == TYPE_ASSERT;
}
@@ -617,7 +663,7 @@ public class ContentProviderOperation implements Parcelable {
}
/**
- * If set then if the number of rows affected by this operation do not match
+ * If set then if the number of rows affected by this operation does not match
* this count {@link OperationApplicationException} will be throw.
* This can only be used with builders of type update, delete, or assert.
* @return this builder, to allow for chaining.
@@ -631,6 +677,12 @@ public class ContentProviderOperation implements Parcelable {
return this;
}
+ /**
+ * If set to true then the operation allows yielding the database to other transactions
+ * if the database is contended.
+ * @return this builder, to allow for chaining.
+ * @see android.database.sqlite.SQLiteDatabase#yieldIfContendedSafely()
+ */
public Builder withYieldAllowed(boolean yieldAllowed) {
mYieldAllowed = yieldAllowed;
return this;
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index a434c7b..970623a 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1256,7 +1256,7 @@ public abstract class Context {
* @param intent The description of the activity to start.
*
* @throws ActivityNotFoundException &nbsp;
- *
+ *`
* @see #startActivity(Intent, Bundle)
* @see PackageManager#resolveActivity
*/
@@ -2443,8 +2443,6 @@ public abstract class Context {
*
* @param serviceClass The class of the desired service.
* @return The service name or null if the class is not a supported system service.
- *
- * @hide
*/
public abstract String getSystemServiceName(Class<?> serviceClass);
diff --git a/core/java/android/content/pm/IOnPermissionsChangeListener.aidl b/core/java/android/content/pm/IOnPermissionsChangeListener.aidl
new file mode 100644
index 0000000..7791b50
--- /dev/null
+++ b/core/java/android/content/pm/IOnPermissionsChangeListener.aidl
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2015 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.content.pm;
+
+/**
+ * Listener for changes in the permissions for installed packages.
+ * {@hide}
+ */
+oneway interface IOnPermissionsChangeListener {
+ void onPermissionsChanged(int uid);
+}
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 00b8c71..0c07bc3 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -31,6 +31,7 @@ import android.content.pm.IPackageDeleteObserver2;
import android.content.pm.IPackageDataObserver;
import android.content.pm.IPackageMoveObserver;
import android.content.pm.IPackageStatsObserver;
+import android.content.pm.IOnPermissionsChangeListener;
import android.content.pm.IntentFilterVerificationInfo;
import android.content.pm.InstrumentationInfo;
import android.content.pm.KeySet;
@@ -490,4 +491,7 @@ interface IPackageManager {
KeySet getSigningKeySet(String packageName);
boolean isPackageSignedByKeySet(String packageName, in KeySet ks);
boolean isPackageSignedByKeySetExactly(String packageName, in KeySet ks);
+
+ void addOnPermissionsChangeListener(in IOnPermissionsChangeListener listener);
+ void removeOnPermissionsChangeListener(in IOnPermissionsChangeListener listener);
}
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 68092c8..bd50ca0 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -16,11 +16,13 @@
package android.content.pm;
+import android.Manifest;
import android.annotation.CheckResult;
import android.annotation.DrawableRes;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.StringRes;
@@ -78,6 +80,21 @@ public abstract class PackageManager {
}
/**
+ * Listener for changes in permissions granted to a UID.
+ *
+ * @hide
+ */
+ @SystemApi
+ public interface OnPermissionsChangedListener {
+
+ /**
+ * Called when the permissions for a UID change.
+ * @param uid The UID with a change.
+ */
+ public void onPermissionsChanged(int uid);
+ }
+
+ /**
* {@link PackageInfo} flag: return information about
* activities in the package in {@link PackageInfo#activities}.
*/
@@ -2636,7 +2653,7 @@ public abstract class PackageManager {
/**
* Retrieve the official name associated with a user id. This name is
- * guaranteed to never change, though it is possibly for the underlying
+ * guaranteed to never change, though it is possible for the underlying
* user id to be changed. That is, if you are storing information about
* user ids in persistent storage, you should use the string returned
* by this function instead of the raw user-id.
@@ -4295,6 +4312,27 @@ public abstract class PackageManager {
public abstract boolean isSafeMode();
/**
+ * Adds a listener for permission changes for installed packages.
+ *
+ * @param listener The listener to add.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS)
+ public abstract void addOnPermissionsChangeListener(OnPermissionsChangedListener listener);
+
+ /**
+ * Remvoes a listener for permission changes for installed packages.
+ *
+ * @param listener The listener to remove.
+ *
+ * @hide
+ */
+ @SystemApi
+ public abstract void removeOnPermissionsChangeListener(OnPermissionsChangedListener listener);
+
+ /**
* Return the {@link KeySet} associated with the String alias for this
* application.
*
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index fda889f..d6b1142 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -1577,7 +1577,7 @@ public abstract class SensorManager {
* Significant Motion, Step Counter etc.
*
* The tests which call this API need to have {@code
- * android.permission.HARDWARE_TEST} permission which isn't
+ * android.permission.LOCATION_HADWARE} permission which isn't
* available for third party applications.
*
* @param enable True to set the HAL in DATA_INJECTION mode.
@@ -1607,7 +1607,7 @@ public abstract class SensorManager {
* the HAL is already in data injection mode.
*
* The tests which call this API need to have {@code
- * android.permission.HARDWARE_TEST} permission which isn't
+ * android.permission.LOCATION_HARDWARE} permission which isn't
* available for third party applications.
*
* @param sensor The sensor to inject.
diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java
index 22a9e9c..d7960af 100644
--- a/core/java/android/hardware/SystemSensorManager.java
+++ b/core/java/android/hardware/SystemSensorManager.java
@@ -80,7 +80,7 @@ public class SystemSensorManager extends SensorManager {
nativeClassInit();
}
mHasDataInjectionPermissions = context.checkSelfPermission(
- Manifest.permission.HARDWARE_TEST) == PackageManager.PERMISSION_GRANTED;
+ Manifest.permission.LOCATION_HARDWARE) == PackageManager.PERMISSION_GRANTED;
}
// initialize the sensor list
@@ -233,7 +233,7 @@ public class SystemSensorManager extends SensorManager {
protected boolean enableDataInjectionImpl(boolean enable) {
if (!mHasDataInjectionPermissions) {
throw new SecurityException("Permission denial. Calling enableDataInjection without "
- + Manifest.permission.HARDWARE_TEST);
+ + Manifest.permission.LOCATION_HARDWARE);
}
synchronized (mLock) {
int ret = nativeEnableDataInjection(mNativeInstance, enable);
@@ -256,7 +256,7 @@ public class SystemSensorManager extends SensorManager {
long timestamp) {
if (!mHasDataInjectionPermissions) {
throw new SecurityException("Permission denial. Calling injectSensorData without "
- + Manifest.permission.HARDWARE_TEST);
+ + Manifest.permission.LOCATION_HARDWARE);
}
synchronized (mLock) {
if (!mDataInjectionMode) {
diff --git a/core/java/android/hardware/camera2/CameraCaptureSession.java b/core/java/android/hardware/camera2/CameraCaptureSession.java
index 82d40d3..c547b06 100644
--- a/core/java/android/hardware/camera2/CameraCaptureSession.java
+++ b/core/java/android/hardware/camera2/CameraCaptureSession.java
@@ -150,9 +150,17 @@ public abstract class CameraCaptureSession implements AutoCloseable {
* {@link CaptureRequest.Builder#addTarget}) must be a subset of the surfaces provided when this
* capture session was created.</p>
*
- * <p>Multiple requests can be in progress at once. They are processed in
- * first-in, first-out order, with minimal delays between each
- * capture. Requests submitted through this method have higher priority than
+ * <p>Multiple regular and reprocess requests can be in progress at once. If there are only
+ * regular requests or reprocess requests in progress, they are processed in first-in,
+ * first-out order. If there are both regular and reprocess requests in progress, regular
+ * requests are processed in first-in, first-out order and reprocess requests are processed in
+ * first-in, first-out order, respectively. However, the processing order of a regular request
+ * and a reprocess request in progress is not specified. In other words, a regular request
+ * will always be processed before regular requets that are submitted later. A reprocess request
+ * will always be processed before reprocess requests that are submitted later. However, a
+ * regular request may not be processed before reprocess requests that are submitted later.<p>
+ *
+ * <p>Requests submitted through this method have higher priority than
* those submitted through {@link #setRepeatingRequest} or
* {@link #setRepeatingBurst}, and will be processed as soon as the current
* repeat/repeatBurst processing completes.</p>
@@ -207,10 +215,13 @@ public abstract class CameraCaptureSession implements AutoCloseable {
* not be interleaved with requests submitted by other capture or repeat
* calls.
*
- * <p>The requests will be captured in order, each capture producing one {@link CaptureResult}
- * and image buffers for one or more target {@link android.view.Surface surfaces}. The target
- * surfaces (set with {@link CaptureRequest.Builder#addTarget}) must be a subset of the surfaces
- * provided when this capture session was created.</p>
+ * <p>Regular and reprocess requests can be mixed together in a single burst. Regular requests
+ * will be captured in order and reprocess requests will be processed in order, respectively.
+ * However, the processing order between a regular request and a reprocess request is not
+ * specified. Each capture produces one {@link CaptureResult} and image buffers for one or more
+ * target {@link android.view.Surface surfaces}. The target surfaces (set with
+ * {@link CaptureRequest.Builder#addTarget}) must be a subset of the surfaces provided when
+ * this capture session was created.</p>
*
* <p>The main difference between this method and simply calling
* {@link #capture} repeatedly is that this method guarantees that no
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index c073ba5..ed167f0 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -1924,6 +1924,28 @@ public class CameraDeviceImpl extends CameraDevice {
return mCharacteristics;
}
+ /**
+ * A high speed output surface can only be preview or hardware encoder surface.
+ *
+ * @param surface The high speed output surface to be checked.
+ */
+ private void checkHighSpeedSurfaceFormat(Surface surface) {
+ // TODO: remove this override since the default format should be
+ // ImageFormat.PRIVATE. b/9487482
+ final int HAL_FORMAT_RGB_START = 1; // HAL_PIXEL_FORMAT_RGBA_8888 from graphics.h
+ final int HAL_FORMAT_RGB_END = 5; // HAL_PIXEL_FORMAT_BGRA_8888 from graphics.h
+ int surfaceFormat = SurfaceUtils.getSurfaceFormat(surface);
+ if (surfaceFormat >= HAL_FORMAT_RGB_START &&
+ surfaceFormat <= HAL_FORMAT_RGB_END) {
+ surfaceFormat = ImageFormat.PRIVATE;
+ }
+
+ if (surfaceFormat != ImageFormat.PRIVATE) {
+ throw new IllegalArgumentException("Surface format(" + surfaceFormat + ") is not"
+ + " for preview or hardware video encoding!");
+ }
+ }
+
private void checkConstrainedHighSpeedSurfaces(Collection<Surface> surfaces,
Range<Integer> fpsRange) {
if (surfaces == null || surfaces.size() == 0 || surfaces.size() > 2) {
@@ -1948,15 +1970,10 @@ public class CameraDeviceImpl extends CameraDevice {
}
for (Surface surface : surfaces) {
+ checkHighSpeedSurfaceFormat(surface);
+
// Surface size must be supported high speed sizes.
Size surfaceSize = SurfaceUtils.getSurfaceSize(surface);
- int surfaceFormat = SurfaceUtils.getSurfaceFormat(surface);
-
- if (surfaceFormat != ImageFormat.PRIVATE) {
- throw new IllegalArgumentException("Surface format is not for preview or"
- + " hardware video encoding" + surfaceFormat);
- }
-
if (!highSpeedSizes.contains(surfaceSize)) {
throw new IllegalArgumentException("Surface size " + surfaceSize.toString() + " is"
+ " not part of the high speed supported size list " +
diff --git a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
index cc9d496..a3a998e 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
@@ -565,7 +565,7 @@ public class LegacyCameraDevice implements AutoCloseable {
throw new IllegalArgumentException("Surface was abandoned", e);
}
- return previewConsumer && (surfaceFormat == ImageFormat.PRIVATE);
+ return previewConsumer;
}
public static boolean isVideoEncoderConsumer(Surface output) {
@@ -583,7 +583,7 @@ public class LegacyCameraDevice implements AutoCloseable {
throw new IllegalArgumentException("Surface was abandoned", e);
}
- return videoEncoderConsumer && (surfaceFormat == ImageFormat.PRIVATE);
+ return videoEncoderConsumer;
}
/**
diff --git a/core/java/android/hardware/camera2/utils/SurfaceUtils.java b/core/java/android/hardware/camera2/utils/SurfaceUtils.java
index 32e74e2..40005a5 100644
--- a/core/java/android/hardware/camera2/utils/SurfaceUtils.java
+++ b/core/java/android/hardware/camera2/utils/SurfaceUtils.java
@@ -16,6 +16,7 @@
package android.hardware.camera2.utils;
+import android.graphics.ImageFormat;
import android.hardware.camera2.legacy.LegacyCameraDevice;
import android.hardware.camera2.legacy.LegacyExceptionUtils.BufferQueueAbandonedException;
import android.util.Size;
@@ -27,7 +28,7 @@ import android.view.Surface;
public class SurfaceUtils {
/**
- * Check if a surface is for preview consumer.
+ * Check if a surface is for preview consumer based on consumer end point Gralloc usage flags.
*
* @param surface The surface to be checked.
* @return true if the surface is for preview consumer, false otherwise.
@@ -37,7 +38,8 @@ public class SurfaceUtils {
}
/**
- * Check if the surface is for hardware video encoder consumer.
+ * Check if the surface is for hardware video encoder consumer based on consumer end point
+ * Gralloc usage flags.
*
* @param surface The surface to be checked.
* @return true if the surface is for hardware video encoder consumer, false otherwise.
diff --git a/core/java/android/hardware/usb/IUsbManager.aidl b/core/java/android/hardware/usb/IUsbManager.aidl
index 881dc0f..31a6a96 100644
--- a/core/java/android/hardware/usb/IUsbManager.aidl
+++ b/core/java/android/hardware/usb/IUsbManager.aidl
@@ -85,6 +85,16 @@ interface IUsbManager
/* Sets the current USB function. */
void setCurrentFunction(String function);
+ /* Sets whether USB data (for example, MTP exposed pictures) should be made
+ * available on the USB connection. Unlocking data should only be done with
+ * user involvement, since exposing pictures or other data could leak sensitive
+ * user information.
+ */
+ void setUsbDataUnlocked(boolean unlock);
+
+ /* Returns true iff sensitive user data is exposed on the USB connection. */
+ boolean isUsbDataUnlocked();
+
/* Allow USB debugging from the attached host. If alwaysAllow is true, add the
* the public key to list of host keys that the user has approved.
*/
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index 000d41f..c83f466 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -142,6 +142,16 @@ public class UsbManager {
public static final String USB_CONFIGURED = "configured";
/**
+ * Boolean extra indicating whether confidential user data, such as photos, should be
+ * made available on the USB connection. This variable will only be set when the user
+ * has explicitly asked for this data to be unlocked.
+ * Used in extras for the {@link #ACTION_USB_STATE} broadcast.
+ *
+ * {@hide}
+ */
+ public static final String USB_DATA_UNLOCKED = "unlocked";
+
+ /**
* Name of the USB mass storage USB function.
* Used in extras for the {@link #ACTION_USB_STATE} broadcast
*
@@ -464,4 +474,34 @@ public class UsbManager {
Log.e(TAG, "RemoteException in setCurrentFunction", e);
}
}
+
+ /**
+ * Sets whether USB data (for example, MTP exposed pictures) should be made available
+ * on the USB connection. Unlocking usb data should only be done with user involvement,
+ * since exposing pictures or other data could leak sensitive user information.
+ *
+ * {@hide}
+ */
+ public void setUsbDataUnlocked(boolean unlocked) {
+ try {
+ mService.setUsbDataUnlocked(unlocked);
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException in setUsbDataUnlocked", e);
+ }
+ }
+
+ /**
+ * Returns {@code true} iff access to sensitive USB data is currently allowed.
+ *
+ * {@hide}
+ */
+ public boolean isUsbDataUnlocked() {
+ try {
+ return mService.isUsbDataUnlocked();
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException in isUsbDataUnlocked", e);
+ }
+ return false;
+ }
+
}
diff --git a/core/java/android/net/NetworkFactory.java b/core/java/android/net/NetworkFactory.java
index e47220b..5f46c73 100644
--- a/core/java/android/net/NetworkFactory.java
+++ b/core/java/android/net/NetworkFactory.java
@@ -24,8 +24,13 @@ import android.os.Messenger;
import android.util.Log;
import android.util.SparseArray;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Protocol;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
/**
* A NetworkFactory is an entity that creates NetworkAgent objects.
* The bearers register with ConnectivityService using {@link #register} and
@@ -157,6 +162,11 @@ public class NetworkFactory extends Handler {
this.score = score;
this.requested = false;
}
+
+ @Override
+ public String toString() {
+ return "{" + request + ", score=" + score + ", requested=" + requested + "}";
+ }
}
private void handleAddRequest(NetworkRequest request, int score) {
@@ -176,9 +186,9 @@ public class NetworkFactory extends Handler {
private void handleRemoveRequest(NetworkRequest request) {
NetworkRequestInfo n = mNetworkRequests.get(request.requestId);
- if (n != null && n.requested) {
+ if (n != null) {
mNetworkRequests.remove(request.requestId);
- releaseNetworkFor(n.request);
+ if (n.requested) releaseNetworkFor(n.request);
}
}
@@ -273,15 +283,31 @@ public class NetworkFactory extends Handler {
sendMessage(obtainMessage(CMD_SET_FILTER, new NetworkCapabilities(netCap)));
}
+ @VisibleForTesting
+ protected int getRequestCount() {
+ return mNetworkRequests.size();
+ }
+
protected void log(String s) {
Log.d(LOG_TAG, s);
}
+ public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
+ final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
+ pw.println(toString());
+ pw.increaseIndent();
+ for (int i = 0; i < mNetworkRequests.size(); i++) {
+ pw.println(mNetworkRequests.valueAt(i));
+ }
+ pw.decreaseIndent();
+ }
+
@Override
public String toString() {
StringBuilder sb = new StringBuilder("{").append(LOG_TAG).append(" - ScoreFilter=").
append(mScore).append(", Filter=").append(mCapabilityFilter).append(", requests=").
- append(mNetworkRequests.size()).append("}");
+ append(mNetworkRequests.size()).append(", refCount=").append(mRefCount).
+ append("}");
return sb.toString();
}
}
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index c9609e5..a6efc58 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -3489,57 +3489,90 @@ public abstract class BatteryStats implements Parcelable {
pw.println();
for (int i=0; i<sippers.size(); i++) {
final BatterySipper bs = sippers.get(i);
+ pw.print(prefix);
switch (bs.drainType) {
case IDLE:
- pw.print(prefix); pw.print(" Idle: "); printmAh(pw, bs.totalPowerMah);
- pw.println();
+ pw.print(" Idle: ");
break;
case CELL:
- pw.print(prefix); pw.print(" Cell standby: "); printmAh(pw, bs.totalPowerMah);
- pw.println();
+ pw.print(" Cell standby: ");
break;
case PHONE:
- pw.print(prefix); pw.print(" Phone calls: "); printmAh(pw, bs.totalPowerMah);
- pw.println();
+ pw.print(" Phone calls: ");
break;
case WIFI:
- pw.print(prefix); pw.print(" Wifi: "); printmAh(pw, bs.totalPowerMah);
- pw.println();
+ pw.print(" Wifi: ");
break;
case BLUETOOTH:
- pw.print(prefix); pw.print(" Bluetooth: "); printmAh(pw, bs.totalPowerMah);
- pw.println();
+ pw.print(" Bluetooth: ");
break;
case SCREEN:
- pw.print(prefix); pw.print(" Screen: "); printmAh(pw, bs.totalPowerMah);
- pw.println();
+ pw.print(" Screen: ");
break;
case FLASHLIGHT:
- pw.print(prefix); pw.print(" Flashlight: "); printmAh(pw, bs.totalPowerMah);
- pw.println();
+ pw.print(" Flashlight: ");
break;
case APP:
- pw.print(prefix); pw.print(" Uid ");
+ pw.print(" Uid ");
UserHandle.formatUid(pw, bs.uidObj.getUid());
- pw.print(": "); printmAh(pw, bs.totalPowerMah); pw.println();
+ pw.print(": ");
break;
case USER:
- pw.print(prefix); pw.print(" User "); pw.print(bs.userId);
- pw.print(": "); printmAh(pw, bs.totalPowerMah); pw.println();
+ pw.print(" User "); pw.print(bs.userId);
+ pw.print(": ");
break;
case UNACCOUNTED:
- pw.print(prefix); pw.print(" Unaccounted: "); printmAh(pw, bs.totalPowerMah);
- pw.println();
+ pw.print(" Unaccounted: ");
break;
case OVERCOUNTED:
- pw.print(prefix); pw.print(" Over-counted: "); printmAh(pw, bs.totalPowerMah);
- pw.println();
+ pw.print(" Over-counted: ");
break;
case CAMERA:
- pw.print(prefix); pw.print(" Camera: "); printmAh(pw, bs.totalPowerMah);
- pw.println();
+ pw.print(" Camera: ");
+ break;
+ default:
+ pw.print(" ???: ");
break;
}
+ printmAh(pw, bs.totalPowerMah);
+
+ if (bs.drainType == BatterySipper.DrainType.APP) {
+ pw.print(" (");
+ if (bs.cpuPowerMah != 0) {
+ pw.print(" cpu=");
+ printmAh(pw, bs.cpuPowerMah);
+ }
+ if (bs.wakeLockPowerMah != 0) {
+ pw.print(" wake=");
+ printmAh(pw, bs.wakeLockPowerMah);
+ }
+ if (bs.mobileRadioPowerMah != 0) {
+ pw.print(" radio=");
+ printmAh(pw, bs.mobileRadioPowerMah);
+ }
+ if (bs.wifiPowerMah != 0) {
+ pw.print(" wifi=");
+ printmAh(pw, bs.wifiPowerMah);
+ }
+ if (bs.gpsPowerMah != 0) {
+ pw.print(" gps=");
+ printmAh(pw, bs.gpsPowerMah);
+ }
+ if (bs.sensorPowerMah != 0) {
+ pw.print(" sensor=");
+ printmAh(pw, bs.sensorPowerMah);
+ }
+ if (bs.cameraPowerMah != 0) {
+ pw.print(" camera=");
+ printmAh(pw, bs.cameraPowerMah);
+ }
+ if (bs.flashlightPowerMah != 0) {
+ pw.print(" flash=");
+ printmAh(pw, bs.flashlightPowerMah);
+ }
+ pw.print(" )");
+ }
+ pw.println();
}
pw.println();
}
diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java
index 1c9c713..135f369 100644
--- a/core/java/android/os/ParcelFileDescriptor.java
+++ b/core/java/android/os/ParcelFileDescriptor.java
@@ -621,6 +621,9 @@ public class ParcelFileDescriptor implements Parcelable, Closeable {
final int fd = getFd();
Parcel.clearFileDescriptor(mFd);
writeCommStatusAndClose(Status.DETACHED, null);
+ mClosed = true;
+ mGuard.close();
+ releaseResources();
return fd;
}
}
diff --git a/core/java/android/os/RemoteCallbackList.java b/core/java/android/os/RemoteCallbackList.java
index d2a9cdc..5849350 100644
--- a/core/java/android/os/RemoteCallbackList.java
+++ b/core/java/android/os/RemoteCallbackList.java
@@ -77,7 +77,6 @@ public class RemoteCallbackList<E extends IInterface> {
public boolean register(E callback) {
return register(callback, null);
}
-
/**
* Add a new callback to the list. This callback will remain in the list
* until a corresponding call to {@link #unregister} or its hosting process
diff --git a/core/java/android/os/storage/DiskInfo.java b/core/java/android/os/storage/DiskInfo.java
index 04e54aa..5bc45d5 100644
--- a/core/java/android/os/storage/DiskInfo.java
+++ b/core/java/android/os/storage/DiskInfo.java
@@ -80,6 +80,12 @@ public class DiskInfo implements Parcelable {
if (label.toLowerCase().contains("generic")) {
return false;
}
+ if (label.toLowerCase().startsWith("usb")) {
+ return false;
+ }
+ if (label.toLowerCase().startsWith("multiple")) {
+ return false;
+ }
return true;
}
diff --git a/core/java/android/os/storage/VolumeInfo.java b/core/java/android/os/storage/VolumeInfo.java
index 2622ee0..372725f 100644
--- a/core/java/android/os/storage/VolumeInfo.java
+++ b/core/java/android/os/storage/VolumeInfo.java
@@ -32,7 +32,9 @@ import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.DebugUtils;
import android.util.SparseArray;
+import android.util.SparseIntArray;
+import com.android.internal.R;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
@@ -80,6 +82,7 @@ public class VolumeInfo implements Parcelable {
private static SparseArray<String> sStateToEnvironment = new SparseArray<>();
private static ArrayMap<String, String> sEnvironmentToBroadcast = new ArrayMap<>();
+ private static SparseIntArray sStateToDescrip = new SparseIntArray();
private static final Comparator<VolumeInfo>
sDescriptionComparator = new Comparator<VolumeInfo>() {
@@ -116,6 +119,16 @@ public class VolumeInfo implements Parcelable {
sEnvironmentToBroadcast.put(Environment.MEDIA_UNMOUNTABLE, Intent.ACTION_MEDIA_UNMOUNTABLE);
sEnvironmentToBroadcast.put(Environment.MEDIA_REMOVED, Intent.ACTION_MEDIA_REMOVED);
sEnvironmentToBroadcast.put(Environment.MEDIA_BAD_REMOVAL, Intent.ACTION_MEDIA_BAD_REMOVAL);
+
+ sStateToDescrip.put(VolumeInfo.STATE_UNMOUNTED, R.string.ext_media_status_unmounted);
+ sStateToDescrip.put(VolumeInfo.STATE_CHECKING, R.string.ext_media_status_checking);
+ sStateToDescrip.put(VolumeInfo.STATE_MOUNTED, R.string.ext_media_status_mounted);
+ sStateToDescrip.put(VolumeInfo.STATE_MOUNTED_READ_ONLY, R.string.ext_media_status_mounted_ro);
+ sStateToDescrip.put(VolumeInfo.STATE_FORMATTING, R.string.ext_media_status_formatting);
+ sStateToDescrip.put(VolumeInfo.STATE_EJECTING, R.string.ext_media_status_ejecting);
+ sStateToDescrip.put(VolumeInfo.STATE_UNMOUNTABLE, R.string.ext_media_status_unmountable);
+ sStateToDescrip.put(VolumeInfo.STATE_REMOVED, R.string.ext_media_status_removed);
+ sStateToDescrip.put(VolumeInfo.STATE_BAD_REMOVAL, R.string.ext_media_status_bad_removal);
}
/** vold state */
@@ -201,6 +214,10 @@ public class VolumeInfo implements Parcelable {
return state;
}
+ public int getStateDescription() {
+ return sStateToDescrip.get(state, 0);
+ }
+
public @Nullable String getFsUuid() {
return fsUuid;
}
diff --git a/core/java/android/preference/SeekBarDialogPreference.java b/core/java/android/preference/SeekBarDialogPreference.java
index 9a08827..eeb69a3 100644
--- a/core/java/android/preference/SeekBarDialogPreference.java
+++ b/core/java/android/preference/SeekBarDialogPreference.java
@@ -18,29 +18,28 @@ package android.preference;
import android.content.Context;
import android.graphics.drawable.Drawable;
-import android.preference.DialogPreference;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
import android.widget.SeekBar;
+import com.android.internal.R;
+
/**
* @hide
*/
public class SeekBarDialogPreference extends DialogPreference {
- private static final String TAG = "SeekBarDialogPreference";
-
- private Drawable mMyIcon;
+ private final Drawable mMyIcon;
public SeekBarDialogPreference(
Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
- setDialogLayoutResource(com.android.internal.R.layout.seekbar_dialog);
createActionButtons();
// Steal the XML dialogIcon attribute's value
mMyIcon = getDialogIcon();
+
setDialogIcon(null);
}
@@ -49,7 +48,7 @@ public class SeekBarDialogPreference extends DialogPreference {
}
public SeekBarDialogPreference(Context context, AttributeSet attrs) {
- this(context, attrs, com.android.internal.R.attr.dialogPreferenceStyle);
+ this(context, attrs, R.attr.seekBarDialogPreferenceStyle);
}
public SeekBarDialogPreference(Context context) {
@@ -58,15 +57,15 @@ public class SeekBarDialogPreference extends DialogPreference {
// Allow subclasses to override the action buttons
public void createActionButtons() {
- setPositiveButtonText(android.R.string.ok);
- setNegativeButtonText(android.R.string.cancel);
+ setPositiveButtonText(R.string.ok);
+ setNegativeButtonText(R.string.cancel);
}
@Override
protected void onBindDialogView(View view) {
super.onBindDialogView(view);
- final ImageView iconView = (ImageView) view.findViewById(android.R.id.icon);
+ final ImageView iconView = (ImageView) view.findViewById(R.id.icon);
if (mMyIcon != null) {
iconView.setImageDrawable(mMyIcon);
} else {
@@ -75,6 +74,6 @@ public class SeekBarDialogPreference extends DialogPreference {
}
protected static SeekBar getSeekBar(View dialogView) {
- return (SeekBar) dialogView.findViewById(com.android.internal.R.id.seekbar);
+ return (SeekBar) dialogView.findViewById(R.id.seekbar);
}
}
diff --git a/core/java/android/preference/SeekBarVolumizer.java b/core/java/android/preference/SeekBarVolumizer.java
index 4bd085f..979c828 100644
--- a/core/java/android/preference/SeekBarVolumizer.java
+++ b/core/java/android/preference/SeekBarVolumizer.java
@@ -16,6 +16,7 @@
package android.preference;
+import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -31,6 +32,7 @@ import android.os.HandlerThread;
import android.os.Message;
import android.preference.VolumePreference.VolumeStore;
import android.provider.Settings;
+import android.provider.Settings.Global;
import android.provider.Settings.System;
import android.util.Log;
import android.widget.SeekBar;
@@ -46,7 +48,7 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba
public interface Callback {
void onSampleStarting(SeekBarVolumizer sbv);
void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch);
- void onMuted(boolean muted);
+ void onMuted(boolean muted, boolean zenMuted);
}
private final Context mContext;
@@ -54,6 +56,7 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba
private final Callback mCallback;
private final Uri mDefaultUri;
private final AudioManager mAudioManager;
+ private final NotificationManager mNotificationManager;
private final int mStreamType;
private final int mMaxStreamVolume;
private boolean mAffectedByRingerMode;
@@ -63,12 +66,14 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba
private Handler mHandler;
private Observer mVolumeObserver;
private int mOriginalStreamVolume;
+ private int mLastAudibleStreamVolume;
private Ringtone mRingtone;
private int mLastProgress = -1;
private boolean mMuted;
private SeekBar mSeekBar;
private int mVolumeBeforeMute = -1;
private int mRingerMode;
+ private int mZenMode;
private static final int MSG_SET_STREAM_VOLUME = 0;
private static final int MSG_START_SAMPLE = 1;
@@ -78,19 +83,22 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba
public SeekBarVolumizer(Context context, int streamType, Uri defaultUri, Callback callback) {
mContext = context;
- mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+ mAudioManager = context.getSystemService(AudioManager.class);
+ mNotificationManager = context.getSystemService(NotificationManager.class);
mStreamType = streamType;
mAffectedByRingerMode = mAudioManager.isStreamAffectedByRingerMode(mStreamType);
mNotificationOrRing = isNotificationOrRing(mStreamType);
if (mNotificationOrRing) {
mRingerMode = mAudioManager.getRingerModeInternal();
}
+ mZenMode = mNotificationManager.getZenMode();
mMaxStreamVolume = mAudioManager.getStreamMaxVolume(mStreamType);
mCallback = callback;
mOriginalStreamVolume = mAudioManager.getStreamVolume(mStreamType);
+ mLastAudibleStreamVolume = mAudioManager.getLastAudibleStreamVolume(mStreamType);
mMuted = mAudioManager.isStreamMute(mStreamType);
if (mCallback != null) {
- mCallback.onMuted(mMuted);
+ mCallback.onMuted(mMuted, isZenMuted());
}
if (defaultUri == null) {
if (mStreamType == AudioManager.STREAM_RING) {
@@ -119,8 +127,17 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba
mSeekBar.setOnSeekBarChangeListener(this);
}
+ private boolean isZenMuted() {
+ return mNotificationOrRing && mZenMode == Global.ZEN_MODE_ALARMS
+ || mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS;
+ }
+
protected void updateSeekBar() {
- if (mNotificationOrRing && mRingerMode == AudioManager.RINGER_MODE_VIBRATE) {
+ final boolean zenMuted = isZenMuted();
+ mSeekBar.setEnabled(!zenMuted);
+ if (zenMuted) {
+ mSeekBar.setProgress(mLastAudibleStreamVolume);
+ } else if (mNotificationOrRing && mRingerMode == AudioManager.RINGER_MODE_VIBRATE) {
mSeekBar.setProgress(0);
} else if (mMuted) {
mSeekBar.setProgress(0);
@@ -316,11 +333,12 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba
if (msg.what == UPDATE_SLIDER) {
if (mSeekBar != null) {
mLastProgress = msg.arg1;
- final boolean muted = msg.arg2 != 0;
+ mLastAudibleStreamVolume = Math.abs(msg.arg2);
+ final boolean muted = msg.arg2 < 0;
if (muted != mMuted) {
mMuted = muted;
if (mCallback != null) {
- mCallback.onMuted(mMuted);
+ mCallback.onMuted(mMuted, isZenMuted());
}
}
updateSeekBar();
@@ -328,16 +346,18 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba
}
}
- public void postUpdateSlider(int volume, boolean mute) {
- obtainMessage(UPDATE_SLIDER, volume, mute ? 1 : 0).sendToTarget();
+ public void postUpdateSlider(int volume, int lastAudibleVolume, boolean mute) {
+ final int arg2 = lastAudibleVolume * (mute ? -1 : 1);
+ obtainMessage(UPDATE_SLIDER, volume, arg2).sendToTarget();
}
}
private void updateSlider() {
if (mSeekBar != null && mAudioManager != null) {
final int volume = mAudioManager.getStreamVolume(mStreamType);
+ final int lastAudibleVolume = mAudioManager.getLastAudibleStreamVolume(mStreamType);
final boolean mute = mAudioManager.isStreamMute(mStreamType);
- mUiHandler.postUpdateSlider(volume, mute);
+ mUiHandler.postUpdateSlider(volume, lastAudibleVolume, mute);
}
}
@@ -362,6 +382,7 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba
if (listening) {
final IntentFilter filter = new IntentFilter(AudioManager.VOLUME_CHANGED_ACTION);
filter.addAction(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION);
+ filter.addAction(NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED);
mContext.registerReceiver(this, filter);
} else {
mContext.unregisterReceiver(this);
@@ -379,7 +400,7 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba
if (mSeekBar != null && streamMatch && streamValue != -1) {
final boolean muted = mAudioManager.isStreamMute(mStreamType)
|| streamValue == 0;
- mUiHandler.postUpdateSlider(streamValue, muted);
+ mUiHandler.postUpdateSlider(streamValue, mLastAudibleStreamVolume, muted);
}
} else if (AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION.equals(action)) {
if (mNotificationOrRing) {
@@ -388,6 +409,9 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba
if (mAffectedByRingerMode) {
updateSlider();
}
+ } else if (NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED.equals(action)) {
+ mZenMode = mNotificationManager.getZenMode();
+ updateSlider();
}
}
}
diff --git a/core/java/android/preference/VolumePreference.java b/core/java/android/preference/VolumePreference.java
index a2da01b..8a66c24 100644
--- a/core/java/android/preference/VolumePreference.java
+++ b/core/java/android/preference/VolumePreference.java
@@ -26,14 +26,13 @@ import android.view.KeyEvent;
import android.view.View;
import android.widget.SeekBar;
+import com.android.internal.R;
+
/**
* @hide
*/
public class VolumePreference extends SeekBarDialogPreference implements
PreferenceManager.OnActivityStopListener, View.OnKeyListener, SeekBarVolumizer.Callback {
-
- static final String TAG = "VolumePreference";
-
private int mStreamType;
/** May be null if the dialog isn't visible. */
@@ -44,7 +43,7 @@ public class VolumePreference extends SeekBarDialogPreference implements
super(context, attrs, defStyleAttr, defStyleRes);
final TypedArray a = context.obtainStyledAttributes(attrs,
- com.android.internal.R.styleable.VolumePreference, defStyleAttr, defStyleRes);
+ R.styleable.VolumePreference, defStyleAttr, defStyleRes);
mStreamType = a.getInt(android.R.styleable.VolumePreference_streamType, 0);
a.recycle();
}
@@ -54,7 +53,11 @@ public class VolumePreference extends SeekBarDialogPreference implements
}
public VolumePreference(Context context, AttributeSet attrs) {
- this(context, attrs, com.android.internal.R.attr.dialogPreferenceStyle);
+ this(context, attrs, R.attr.seekBarDialogPreferenceStyle);
+ }
+
+ public VolumePreference(Context context) {
+ this(context, null);
}
public void setStreamType(int streamType) {
@@ -65,7 +68,7 @@ public class VolumePreference extends SeekBarDialogPreference implements
protected void onBindDialogView(View view) {
super.onBindDialogView(view);
- final SeekBar seekBar = (SeekBar) view.findViewById(com.android.internal.R.id.seekbar);
+ final SeekBar seekBar = (SeekBar) view.findViewById(R.id.seekbar);
mSeekBarVolumizer = new SeekBarVolumizer(getContext(), mStreamType, null, this);
mSeekBarVolumizer.start();
mSeekBarVolumizer.setSeekBar(seekBar);
@@ -128,14 +131,17 @@ public class VolumePreference extends SeekBarDialogPreference implements
getPreferenceManager().unregisterOnActivityStopListener(this);
if (mSeekBarVolumizer != null) {
- Dialog dialog = getDialog();
+ final Dialog dialog = getDialog();
if (dialog != null && dialog.isShowing()) {
- View view = dialog.getWindow().getDecorView()
- .findViewById(com.android.internal.R.id.seekbar);
- if (view != null) view.setOnKeyListener(null);
+ final View view = dialog.getWindow().getDecorView().findViewById(R.id.seekbar);
+ if (view != null) {
+ view.setOnKeyListener(null);
+ }
+
// Stopped while dialog was showing, revert changes
mSeekBarVolumizer.revertVolume();
}
+
mSeekBarVolumizer.stop();
mSeekBarVolumizer = null;
}
@@ -155,7 +161,7 @@ public class VolumePreference extends SeekBarDialogPreference implements
}
@Override
- public void onMuted(boolean muted) {
+ public void onMuted(boolean muted, boolean zenMuted) {
// noop
}
diff --git a/core/java/android/printservice/PrintService.java b/core/java/android/printservice/PrintService.java
index 527c8ae..6295822 100644
--- a/core/java/android/printservice/PrintService.java
+++ b/core/java/android/printservice/PrintService.java
@@ -231,6 +231,19 @@ public abstract class PrintService extends Service {
*/
public static final String EXTRA_PRINTER_INFO = "android.intent.extra.print.EXTRA_PRINTER_INFO";
+ /**
+ * If you declared an optional activity with advanced print options via the
+ * {@link android.R.attr#advancedPrintOptionsActivity advancedPrintOptionsActivity}
+ * attribute, this extra is used to pass in the meta-data for the currently printed
+ * document as a {@link android.print.PrintDocumentInfo} to your activity allowing
+ * you to inspect it.
+ *
+ * @see #EXTRA_PRINT_JOB_INFO
+ * @see #EXTRA_PRINTER_INFO
+ */
+ public static final String EXTRA_PRINT_DOCUMENT_INFO =
+ "android.printservice.extra.PRINT_DOCUMENT_INFO";
+
private Handler mHandler;
private IPrintServiceClient mClient;
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index d9c412b..aebe7f1 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -8931,157 +8931,4 @@ public final class ContactsContract {
public static final String EXTRA_DATA_SET = "android.provider.extra.DATA_SET";
}
}
-
- /**
- * @hide
- */
- protected interface MetadataSyncColumns {
-
- /**
- * The raw contact backup id.
- * A reference to the {@link ContactsContract.RawContacts#BACKUP_ID} that save the
- * persistent unique id for each raw contact within its source system.
- *
- * @hide
- */
- public static final String RAW_CONTACT_BACKUP_ID = "raw_contact_backup_id";
-
- /**
- * The account type to which the raw_contact of this item is associated. See
- * {@link RawContacts#ACCOUNT_TYPE}
- *
- * @hide
- */
- public static final String ACCOUNT_TYPE = "account_type";
-
- /**
- * The account name to which the raw_contact of this item is associated. See
- * {@link RawContacts#ACCOUNT_NAME}
- *
- * @hide
- */
- public static final String ACCOUNT_NAME = "account_name";
-
- /**
- * The data set within the account that the raw_contact of this row belongs to. This allows
- * multiple sync adapters for the same account type to distinguish between
- * each others' data.
- * {@link RawContacts#DATA_SET}
- *
- * @hide
- */
- public static final String DATA_SET = "data_set";
-
- /**
- * A text column contains the Json string got from People API. The Json string contains
- * all the metadata related to the raw contact, i.e., all the data fields and
- * aggregation exceptions.
- *
- * Here is an example of the Json string got from the actual schema.
- * <pre>
- * {
- * "unique_contact_id": {
- * "account_type": "CUSTOM_ACCOUNT",
- * "custom_account_type": "facebook",
- * "account_name": "android-test",
- * "contact_id": "1111111",
- * "data_set": "FOCUS"
- * },
- * "contact_prefs": {
- * "send_to_voicemail": true,
- * "starred": false,
- * "pinned": 2
- * },
- * "aggregation_data": [
- * {
- * "type": "TOGETHER",
- * "contact_ids": [
- * {
- * "account_type": "GOOGLE_ACCOUNT",
- * "account_name": "android-test2",
- * "contact_id": "2222222",
- * "data_set": "GOOGLE_PLUS"
- * },
- * {
- * "account_type": "GOOGLE_ACCOUNT",
- * "account_name": "android-test3",
- * "contact_id": "3333333",
- * "data_set": "CUSTOM",
- * "custom_data_set": "custom type"
- * }
- * ]
- * }
- * ],
- * "field_data": [
- * {
- * "field_data_id": "1001",
- * "field_data_prefs": {
- * "is_primary": true,
- * "is_super_primary": true
- * },
- * "usage_stats": [
- * {
- * "usage_type": "CALL",
- * "last_time_used": 10000001,
- * "usage_count": 10
- * }
- * ]
- * }
- * ]
- * }
- * </pre>
- *
- * @hide
- */
- public static final String DATA = "data";
-
- /**
- * The "deleted" flag: "0" by default, "1" if the row has been marked
- * for deletion. When {@link android.content.ContentResolver#delete} is
- * called on a raw contact, updating MetadataSync table to set the flag of the raw contact
- * as "1", then metadata sync adapter deletes the raw contact metadata on the server.
- * <P>Type: INTEGER</P>
- *
- * @hide
- */
- public static final String DELETED = "deleted";
- }
-
- /**
- * Constants for the metadata sync table. This table is used to cache the metadata_sync data
- * from server before it is merged into other CP2 tables.
- *
- * @hide
- */
- public static final class MetadataSync implements BaseColumns, MetadataSyncColumns {
-
- /** The authority for the contacts metadata */
- public static final String METADATA_AUTHORITY = "com.android.contacts.metadata";
-
- /** A content:// style uri to the authority for the contacts metadata */
- public static final Uri METADATA_AUTHORITY_URI = Uri.parse(
- "content://" + METADATA_AUTHORITY);
-
- /**
- * This utility class cannot be instantiated
- */
- private MetadataSync() {
- }
-
- /**
- * The content:// style URI for this table.
- */
- public static final Uri CONTENT_URI = Uri.withAppendedPath(METADATA_AUTHORITY_URI,
- "metadata_sync");
-
- /**
- * The MIME type of {@link #CONTENT_URI} providing a directory of contact metadata
- */
- public static final String CONTENT_TYPE = "vnd.android.cursor.dir/contact_metadata";
-
- /**
- * The MIME type of a {@link #CONTENT_URI} subdirectory of a single contact metadata.
- */
- public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contact_metadata";
- }
}
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 69338b0..30535ff 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -93,6 +93,12 @@ public final class DocumentsContract {
public static final String EXTRA_SHOW_ADVANCED = "android.content.extra.SHOW_ADVANCED";
/**
+ * Set this in a DocumentsUI intent to cause a package's own roots to be
+ * excluded from the roots list.
+ */
+ public static final String EXTRA_EXCLUDE_SELF = "android.provider.extra.EXCLUDE_SELF";
+
+ /**
* Included in {@link AssetFileDescriptor#getExtras()} when returned
* thumbnail should be rotated.
*
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 640f434..f2d3e71 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -577,6 +577,21 @@ public final class Settings {
"android.settings.APPLICATION_DETAILS_SETTINGS";
/**
+ * Activity Action: Show screen for controlling which apps can ignore battery optimizations.
+ * <p>
+ * In some cases, a matching Activity may not exist, so ensure you
+ * safeguard against this.
+ * <p>
+ * Input: The Intent's data URI specifies the application package name
+ * to be shown, with the "package" scheme. That is "package:com.my.app".
+ * <p>
+ * Output: Nothing.
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS =
+ "android.settings.IGNORE_BATTERY_OPTIMIZATION_SETTINGS";
+
+ /**
* @hide
* Activity Action: Show the "app ops" settings screen.
* <p>
@@ -7072,6 +7087,36 @@ public final class Settings {
BLUETOOTH_SAP_PRIORITY_PREFIX = "bluetooth_sap_priority_";
/**
+ * Device Idle (Doze) specific settings.
+ * This is encoded as a key=value list, separated by commas. Ex:
+ *
+ * "inactive_timeout=60000,sensing_timeout=400000"
+ *
+ * The following keys are supported:
+ *
+ * <pre>
+ * inactive_to (long)
+ * sensing_to (long)
+ * motion_inactive_to (long)
+ * idle_after_inactive_to (long)
+ * idle_pending_to (long)
+ * max_idle_pending_to (long)
+ * idle_pending_factor (float)
+ * idle_to (long)
+ * max_idle_to (long)
+ * idle_factor (float)
+ * min_time_to_alarm (long)
+ * max_temp_app_whitelist_duration (long)
+ * </pre>
+ *
+ * <p>
+ * Type: string
+ * @hide
+ * @see com.android.server.DeviceIdleController.Constants
+ */
+ public static final String DEVICE_IDLE_CONSTANTS = "device_idle_constants";
+
+ /**
* Get the key that retrieves a bluetooth headset's priority.
* @hide
*/
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index b8493d4..8c6cd09 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -646,7 +646,7 @@ public abstract class NotificationListenerService extends Service {
private void createLegacyIconExtras(Notification n) {
Icon smallIcon = n.getSmallIcon();
Icon largeIcon = n.getLargeIcon();
- if (smallIcon.getType() == Icon.TYPE_RESOURCE) {
+ if (smallIcon != null && smallIcon.getType() == Icon.TYPE_RESOURCE) {
n.extras.putInt(Notification.EXTRA_SMALL_ICON, smallIcon.getResId());
n.icon = smallIcon.getResId();
}
diff --git a/core/java/android/text/Spanned.java b/core/java/android/text/Spanned.java
index b4622e0..a785d1b 100644
--- a/core/java/android/text/Spanned.java
+++ b/core/java/android/text/Spanned.java
@@ -187,12 +187,11 @@ extends CharSequence
public int getSpanFlags(Object tag);
/**
- * Return the first offset greater than or equal to <code>start</code>
- * where a markup object of class <code>type</code> begins or ends,
- * or <code>limit</code> if there are no starts or ends greater than or
- * equal to <code>start</code> but less than <code>limit</code>. Specify
- * <code>null</code> or Object.class for the type if you want every
- * transition regardless of type.
+ * Return the first offset greater than <code>start</code> where a markup
+ * object of class <code>type</code> begins or ends, or <code>limit</code>
+ * if there are no starts or ends greater than <code>start</code> but less
+ * than <code>limit</code>. Specify <code>null</code> or Object.class for
+ * the type if you want every transition regardless of type.
*/
public int nextSpanTransition(int start, int limit, Class type);
}
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index 6c4d8fd..d51aa79 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -1790,6 +1790,15 @@ public class TextUtils {
}
}
+ /**
+ * Return localized string representing the given number of selected items.
+ *
+ * @hide
+ */
+ public static CharSequence formatSelectedCount(int count) {
+ return Resources.getSystem().getQuantityString(R.plurals.selected_count, count, count);
+ }
+
private static Object sLock = new Object();
private static char[] sTemp = null;
diff --git a/core/java/android/util/KeyValueListParser.java b/core/java/android/util/KeyValueListParser.java
new file mode 100644
index 0000000..4abdde0
--- /dev/null
+++ b/core/java/android/util/KeyValueListParser.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2015 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.util;
+
+import android.text.TextUtils;
+
+/**
+ * Parses a list of key=value pairs, separated by some delimiter, and puts the results in
+ * an internal Map. Values can be then queried by key, or if not found, a default value
+ * can be used.
+ * @hide
+ */
+public class KeyValueListParser {
+ private final ArrayMap<String, String> mValues = new ArrayMap<>();
+ private final TextUtils.StringSplitter mSplitter;
+
+ /**
+ * Constructs a new KeyValueListParser. This can be reused for different strings
+ * by calling {@link #setString(String)}.
+ * @param delim The delimiter that separates key=value pairs.
+ */
+ public KeyValueListParser(char delim) {
+ mSplitter = new TextUtils.SimpleStringSplitter(delim);
+ }
+
+ /**
+ * Resets the parser with a new string to parse. The string is expected to be in the following
+ * format:
+ * <pre>key1=value,key2=value,key3=value</pre>
+ *
+ * where the delimiter is a comma.
+ *
+ * @param str the string to parse.
+ * @throws IllegalArgumentException if the string is malformed.
+ */
+ public void setString(String str) throws IllegalArgumentException {
+ mValues.clear();
+ if (str != null) {
+ mSplitter.setString(str);
+ for (String pair : mSplitter) {
+ int sep = pair.indexOf('=');
+ if (sep < 0) {
+ mValues.clear();
+ throw new IllegalArgumentException(
+ "'" + pair + "' in '" + str + "' is not a valid key-value pair");
+ }
+ mValues.put(pair.substring(0, sep).trim(), pair.substring(sep + 1).trim());
+ }
+ }
+ }
+
+ /**
+ * Get the value for key as a long.
+ * @param key The key to lookup.
+ * @param def The value to return if the key was not found, or the value was not a long.
+ * @return the long value associated with the key.
+ */
+ public long getLong(String key, long def) {
+ String value = mValues.get(key);
+ if (value != null) {
+ try {
+ return Long.parseLong(value);
+ } catch (NumberFormatException e) {
+ // fallthrough
+ }
+ }
+ return def;
+ }
+
+ /**
+ * Get the value for key as a float.
+ * @param key The key to lookup.
+ * @param def The value to return if the key was not found, or the value was not a float.
+ * @return the float value associated with the key.
+ */
+ public float getFloat(String key, float def) {
+ String value = mValues.get(key);
+ if (value != null) {
+ try {
+ return Float.parseFloat(value);
+ } catch (NumberFormatException e) {
+ // fallthrough
+ }
+ }
+ return def;
+ }
+
+ /**
+ * Get the value for key as a string.
+ * @param key The key to lookup.
+ * @param def The value to return if the key was not found.
+ * @return the string value associated with the key.
+ */
+ public String getString(String key, String def) {
+ String value = mValues.get(key);
+ if (value != null) {
+ return value;
+ }
+ return def;
+ }
+}
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index d2b6533..a865307 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -22,6 +22,7 @@ import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;
import android.os.SystemProperties;
+import android.os.Trace;
import android.util.Log;
import android.util.TimeUtils;
@@ -160,6 +161,14 @@ public final class Choreographer {
FrameInfo mFrameInfo = new FrameInfo();
/**
+ * Must be kept in sync with CALLBACK_* ints below, used to index into this array.
+ * @hide
+ */
+ private static final String[] CALLBACK_TRACE_TITLES = {
+ "input", "animation", "traversal", "commit"
+ };
+
+ /**
* Callback type: Input callback. Runs first.
* @hide
*/
@@ -584,16 +593,22 @@ public final class Choreographer {
mLastFrameTimeNanos = frameTimeNanos;
}
- mFrameInfo.markInputHandlingStart();
- doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos);
+ try {
+ Trace.traceBegin(Trace.TRACE_TAG_VIEW, "Choreographer#doFrame");
+
+ mFrameInfo.markInputHandlingStart();
+ doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos);
- mFrameInfo.markAnimationsStart();
- doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos);
+ mFrameInfo.markAnimationsStart();
+ doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos);
- mFrameInfo.markPerformTraversalsStart();
- doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos);
+ mFrameInfo.markPerformTraversalsStart();
+ doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos);
- doCallbacks(Choreographer.CALLBACK_COMMIT, frameTimeNanos);
+ doCallbacks(Choreographer.CALLBACK_COMMIT, frameTimeNanos);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+ }
if (DEBUG_FRAMES) {
final long endNanos = System.nanoTime();
@@ -627,6 +642,7 @@ public final class Choreographer {
// safe by ensuring the commit time is always at least one frame behind.
if (callbackType == Choreographer.CALLBACK_COMMIT) {
final long jitterNanos = now - frameTimeNanos;
+ Trace.traceCounter(Trace.TRACE_TAG_VIEW, "jitterNanos", (int) jitterNanos);
if (jitterNanos >= 2 * mFrameIntervalNanos) {
final long lastFrameOffset = jitterNanos % mFrameIntervalNanos
+ mFrameIntervalNanos;
@@ -644,6 +660,7 @@ public final class Choreographer {
}
}
try {
+ Trace.traceBegin(Trace.TRACE_TAG_VIEW, CALLBACK_TRACE_TITLES[callbackType]);
for (CallbackRecord c = callbacks; c != null; c = c.next) {
if (DEBUG_FRAMES) {
Log.d(TAG, "RunCallback: type=" + callbackType
@@ -661,6 +678,7 @@ public final class Choreographer {
callbacks = next;
} while (callbacks != null);
}
+ Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
}
diff --git a/core/java/android/view/MenuInflater.java b/core/java/android/view/MenuInflater.java
index dc8cadf..1c67ba7 100644
--- a/core/java/android/view/MenuInflater.java
+++ b/core/java/android/view/MenuInflater.java
@@ -25,11 +25,8 @@ import android.annotation.MenuRes;
import android.app.Activity;
import android.content.Context;
import android.content.ContextWrapper;
-import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
-import android.graphics.PorterDuff;
-import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Xml;
@@ -337,11 +334,6 @@ public class MenuInflater {
private ActionProvider itemActionProvider;
- private ColorStateList itemIconTintList;
- private boolean itemIconTintListSet;
- private PorterDuff.Mode itemIconTintMode;
- private boolean itemIconTintModeSet;
-
private static final int defaultGroupId = NO_ID;
private static final int defaultItemId = NO_ID;
private static final int defaultItemCategory = 0;
@@ -432,23 +424,6 @@ public class MenuInflater {
itemActionProvider = null;
}
- if (a.hasValueOrEmpty(com.android.internal.R.styleable.MenuItem_iconTint)) {
- itemIconTintList = a.getColorStateList(
- com.android.internal.R.styleable.MenuItem_iconTint);
- itemIconTintListSet = true;
- } else {
- itemIconTintList = null;
- itemIconTintListSet = false;
- }
- if (a.hasValueOrEmpty(com.android.internal.R.styleable.MenuItem_iconTintMode)) {
- itemIconTintMode = Drawable.parseTintMode(
- a.getInt(com.android.internal.R.styleable.MenuItem_iconTintMode, -1), null);
- itemIconTintModeSet = true;
- } else {
- itemIconTintMode = null;
- itemIconTintModeSet = false;
- }
-
a.recycle();
itemAdded = false;
@@ -511,13 +486,6 @@ public class MenuInflater {
if (itemActionProvider != null) {
item.setActionProvider(itemActionProvider);
}
-
- if (itemIconTintListSet) {
- item.setIconTintList(itemIconTintList);
- }
- if (itemIconTintModeSet) {
- item.setIconTintMode(itemIconTintMode);
- }
}
public MenuItem addItem() {
diff --git a/core/java/android/view/MenuItem.java b/core/java/android/view/MenuItem.java
index 2948007..9e8b97e 100644
--- a/core/java/android/view/MenuItem.java
+++ b/core/java/android/view/MenuItem.java
@@ -21,8 +21,6 @@ import android.annotation.LayoutRes;
import android.annotation.StringRes;
import android.app.Activity;
import android.content.Intent;
-import android.content.res.ColorStateList;
-import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.View.OnCreateContextMenuListener;
@@ -601,26 +599,4 @@ public interface MenuItem {
* @return This menu item instance for call chaining
*/
public MenuItem setOnActionExpandListener(OnActionExpandListener listener);
-
- /**
- * Applies a tint to the icon drawable. Does not modify the current tint
- * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
- * <p>
- * Subsequent calls to {@link android.view.MenuItem#setIcon(android.graphics.drawable.Drawable)}
- * will automatically mutate the drawable and apply the specified tint and tint mode.
- *
- * @param tint the tint to apply, may be {@code null} to clear tint
- * @return This menu item instance for call chaining
- */
- public MenuItem setIconTintList(ColorStateList tint);
-
- /**
- * Specifies the blending mode used to apply the tint specified by {@link
- * #setIconTintList(ColorStateList)} to the icon drawable. The default mode is {@link
- * PorterDuff.Mode#SRC_IN}.
- *
- * @param tintMode the blending mode used to apply the tint, may be {@code null} to clear tint
- * @return This menu item instance for call chaining
- */
- public MenuItem setIconTintMode(PorterDuff.Mode tintMode);
}
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 160c662..7d48a9a 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -523,7 +523,7 @@ public class SurfaceView extends View {
mVisibleInsets, mStableInsets, mOutsets, mConfiguration,
mNewSurface);
if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
- mReportDrawNeeded = true;
+ reportDrawNeeded = true;
}
if (DEBUG) Log.i(TAG, "New surface: " + mNewSurface
diff --git a/core/java/android/view/ViewPropertyAnimator.java b/core/java/android/view/ViewPropertyAnimator.java
index f18b7ac..bd45007 100644
--- a/core/java/android/view/ViewPropertyAnimator.java
+++ b/core/java/android/view/ViewPropertyAnimator.java
@@ -80,18 +80,12 @@ public class ViewPropertyAnimator {
/**
* The interpolator of the underlying Animator object. By default, we don't set the interpolator
- * on the Animator and just use its default interpolator. If the interpolator is ever set on
- * this Animator, then we use the interpolator that it was set to.
+ * on the Animator and just use its default interpolator. If the interpolator is set to a
+ * non-null value on this Animator, then we use the interpolator that it was set to.
*/
private TimeInterpolator mInterpolator;
/**
- * A flag indicating whether the interpolator has been set on this object. If not, we don't set
- * the interpolator on the underlying Animator, but instead just use its default interpolator.
- */
- private boolean mInterpolatorSet = false;
-
- /**
* Listener for the lifecycle events of the underlying ValueAnimator object.
*/
private Animator.AnimatorListener mListener = null;
@@ -338,7 +332,6 @@ public class ViewPropertyAnimator {
* @return This object, allowing calls to methods in this class to be chained.
*/
public ViewPropertyAnimator setInterpolator(TimeInterpolator interpolator) {
- mInterpolatorSet = true;
mInterpolator = interpolator;
return this;
}
@@ -349,7 +342,7 @@ public class ViewPropertyAnimator {
* @return The timing interpolator for this animation.
*/
public TimeInterpolator getInterpolator() {
- if (mInterpolatorSet) {
+ if (mInterpolator != null) {
return mInterpolator;
} else {
// Just return the default from ValueAnimator, since that's what we'd get if
@@ -897,7 +890,7 @@ public class ViewPropertyAnimator {
if (mDurationSet) {
animator.setDuration(mDuration);
}
- if (mInterpolatorSet) {
+ if (mInterpolator != null) {
animator.setInterpolator(mInterpolator);
}
animator.start();
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index e1e0154..e2f42db 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1105,12 +1105,7 @@ public final class ViewRootImpl implements ViewParent,
Debug.startMethodTracing("ViewAncestor");
}
- Trace.traceBegin(Trace.TRACE_TAG_VIEW, "performTraversals");
- try {
- performTraversals();
- } finally {
- Trace.traceEnd(Trace.TRACE_TAG_VIEW);
- }
+ performTraversals();
if (mProfile) {
Debug.stopMethodTracing();
diff --git a/core/java/android/widget/ActionMenuPresenter.java b/core/java/android/widget/ActionMenuPresenter.java
index f08141c..a5696ee 100644
--- a/core/java/android/widget/ActionMenuPresenter.java
+++ b/core/java/android/widget/ActionMenuPresenter.java
@@ -21,10 +21,8 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.content.Context;
-import android.content.res.ColorStateList;
import android.content.res.Configuration;
import android.content.res.Resources;
-import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.os.Parcel;
import android.os.Parcelable;
@@ -64,6 +62,8 @@ public class ActionMenuPresenter extends BaseMenuPresenter
private static final boolean ACTIONBAR_ANIMATIONS_ENABLED = false;
private OverflowMenuButton mOverflowButton;
+ private Drawable mPendingOverflowIcon;
+ private boolean mPendingOverflowIconSet;
private boolean mReserveOverflow;
private boolean mReserveOverflowSet;
private int mWidthLimit;
@@ -85,8 +85,6 @@ public class ActionMenuPresenter extends BaseMenuPresenter
private OpenOverflowRunnable mPostedOpenRunnable;
private ActionMenuPopupCallback mPopupCallback;
- private TintInfo mOverflowTintInfo;
-
final PopupPresenterCallback mPopupPresenterCallback = new PopupPresenterCallback();
int mOpenSubMenuId;
@@ -154,9 +152,13 @@ public class ActionMenuPresenter extends BaseMenuPresenter
if (mReserveOverflow) {
if (mOverflowButton == null) {
mOverflowButton = new OverflowMenuButton(mSystemContext);
+ if (mPendingOverflowIconSet) {
+ mOverflowButton.setImageDrawable(mPendingOverflowIcon);
+ mPendingOverflowIcon = null;
+ mPendingOverflowIconSet = false;
+ }
final int spec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
mOverflowButton.measure(spec, spec);
- applyOverflowTint();
}
width -= mOverflowButton.getMeasuredWidth();
} else {
@@ -198,6 +200,24 @@ public class ActionMenuPresenter extends BaseMenuPresenter
mExpandedActionViewsExclusive = isExclusive;
}
+ public void setOverflowIcon(Drawable icon) {
+ if (mOverflowButton != null) {
+ mOverflowButton.setImageDrawable(icon);
+ } else {
+ mPendingOverflowIconSet = true;
+ mPendingOverflowIcon = icon;
+ }
+ }
+
+ public Drawable getOverflowIcon() {
+ if (mOverflowButton != null) {
+ return mOverflowButton.getDrawable();
+ } else if (mPendingOverflowIconSet) {
+ return mPendingOverflowIcon;
+ }
+ return null;
+ }
+
@Override
public MenuView getMenuView(ViewGroup root) {
MenuView oldMenuView = mMenuView;
@@ -449,7 +469,6 @@ public class ActionMenuPresenter extends BaseMenuPresenter
if (hasOverflow) {
if (mOverflowButton == null) {
mOverflowButton = new OverflowMenuButton(mSystemContext);
- applyOverflowTint();
}
ViewGroup parent = (ViewGroup) mOverflowButton.getParent();
if (parent != mMenuView) {
@@ -764,40 +783,6 @@ public class ActionMenuPresenter extends BaseMenuPresenter
}
}
- public void setOverflowTintList(ColorStateList tint) {
- if (mOverflowTintInfo == null) {
- mOverflowTintInfo = new TintInfo();
- }
- mOverflowTintInfo.mTintList = tint;
- mOverflowTintInfo.mHasTintList = true;
-
- applyOverflowTint();
- }
-
- public void setOverflowTintMode(PorterDuff.Mode tintMode) {
- if (mOverflowTintInfo == null) {
- mOverflowTintInfo = new TintInfo();
- }
- mOverflowTintInfo.mTintMode = tintMode;
- mOverflowTintInfo.mHasTintMode = true;
-
- applyOverflowTint();
- }
-
- private void applyOverflowTint() {
- final TintInfo tintInfo = mOverflowTintInfo;
- if (tintInfo != null && (tintInfo.mHasTintList || tintInfo.mHasTintMode)) {
- if (mOverflowButton != null) {
- if (tintInfo.mHasTintList) {
- mOverflowButton.setImageTintList(tintInfo.mTintList);
- }
- if (tintInfo.mHasTintMode) {
- mOverflowButton.setImageTintMode(tintInfo.mTintMode);
- }
- }
- }
- }
-
private static class SavedState implements Parcelable {
public int openSubMenuId;
@@ -1023,13 +1008,6 @@ public class ActionMenuPresenter extends BaseMenuPresenter
}
}
- private static class TintInfo {
- ColorStateList mTintList;
- PorterDuff.Mode mTintMode;
- boolean mHasTintMode;
- boolean mHasTintList;
- }
-
/**
* This class holds layout information for a menu item. This is used to determine
* pre- and post-layout information about menu items, which will then be used to
@@ -1077,5 +1055,4 @@ public class ActionMenuPresenter extends BaseMenuPresenter
this.animType = animType;
}
}
-
}
diff --git a/core/java/android/widget/ActionMenuView.java b/core/java/android/widget/ActionMenuView.java
index 278a8fb..1f02c3b 100644
--- a/core/java/android/widget/ActionMenuView.java
+++ b/core/java/android/widget/ActionMenuView.java
@@ -16,11 +16,11 @@
package android.widget;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.StyleRes;
import android.content.Context;
-import android.content.res.ColorStateList;
import android.content.res.Configuration;
-import android.graphics.PorterDuff;
+import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.ContextThemeWrapper;
import android.view.Gravity;
@@ -541,39 +541,35 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo
dismissPopupMenus();
}
- /** @hide */
- public boolean isOverflowReserved() {
- return mReserveOverflow;
- }
-
- /** @hide */
- public void setOverflowReserved(boolean reserveOverflow) {
- mReserveOverflow = reserveOverflow;
- }
-
/**
- * Applies a tint to the overflow drawable. Does not modify the current tint
- * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
+ * Set the icon to use for the overflow button.
*
- * @param tint the tint to apply, may be {@code null} to clear tint
+ * @param icon Drawable to set, may be null to clear the icon
*/
- public void setOverflowTintList(ColorStateList tint) {
- if (mPresenter != null) {
- mPresenter.setOverflowTintList(tint);
- }
+ public void setOverflowIcon(@Nullable Drawable icon) {
+ getMenu();
+ mPresenter.setOverflowIcon(icon);
}
/**
- * Specifies the blending mode used to apply the tint specified by {@link
- * #setOverflowTintList(ColorStateList)} to the overflow drawable.
- * The default mode is {@link PorterDuff.Mode#SRC_IN}.
+ * Return the current drawable used as the overflow icon.
*
- * @param tintMode the blending mode used to apply the tint, may be {@code null} to clear tint
+ * @return The overflow icon drawable
*/
- public void setOverflowTintMode(PorterDuff.Mode tintMode) {
- if (mPresenter != null) {
- mPresenter.setOverflowTintMode(tintMode);
- }
+ @Nullable
+ public Drawable getOverflowIcon() {
+ getMenu();
+ return mPresenter.getOverflowIcon();
+ }
+
+ /** @hide */
+ public boolean isOverflowReserved() {
+ return mReserveOverflow;
+ }
+
+ /** @hide */
+ public void setOverflowReserved(boolean reserveOverflow) {
+ mReserveOverflow = reserveOverflow;
}
@Override
diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java
index 94b9416..afc683a 100644
--- a/core/java/android/widget/ListPopupWindow.java
+++ b/core/java/android/widget/ListPopupWindow.java
@@ -618,12 +618,11 @@ public class ListPopupWindow {
heightSpec = mDropDownHeight;
}
- mPopup.setWidth(widthSpec);
- mPopup.setHeight(heightSpec);
mPopup.setOutsideTouchable(!mForceIgnoreOutsideTouch && !mDropDownAlwaysVisible);
mPopup.update(getAnchorView(), mDropDownHorizontalOffset,
- mDropDownVerticalOffset, -1, -1);
+ mDropDownVerticalOffset, (widthSpec < 0)? -1 : widthSpec,
+ (heightSpec < 0)? -1 : heightSpec);
} else {
final int widthSpec;
if (mDropDownWidth == ViewGroup.LayoutParams.MATCH_PARENT) {
diff --git a/core/java/android/widget/Toolbar.java b/core/java/android/widget/Toolbar.java
index 62d948d..8ace0f3 100644
--- a/core/java/android/widget/Toolbar.java
+++ b/core/java/android/widget/Toolbar.java
@@ -25,9 +25,8 @@ import android.annotation.StringRes;
import android.annotation.StyleRes;
import android.app.ActionBar;
import android.content.Context;
-import android.content.res.ColorStateList;
import android.content.res.TypedArray;
-import android.graphics.PorterDuff;
+import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Parcel;
import android.os.Parcelable;
@@ -110,9 +109,6 @@ public class Toolbar extends ViewGroup {
private ImageButton mNavButtonView;
private ImageView mLogoView;
- private TintInfo mOverflowTintInfo;
- private TintInfo mNavTintInfo;
-
private Drawable mCollapseIcon;
private CharSequence mCollapseDescription;
private ImageButton mCollapseButtonView;
@@ -275,21 +271,6 @@ public class Toolbar extends ViewGroup {
if (!TextUtils.isEmpty(navDesc)) {
setNavigationContentDescription(navDesc);
}
-
- if (a.hasValue(R.styleable.Toolbar_overflowTint)) {
- setOverflowTintList(a.getColorStateList(R.styleable.Toolbar_overflowTint));
- }
- if (a.hasValue(R.styleable.Toolbar_overflowTintMode)) {
- setOverflowTintMode(Drawable.parseTintMode(
- a.getInt(R.styleable.Toolbar_overflowTintMode, -1), null));
- }
- if (a.hasValue(R.styleable.Toolbar_navigationTint)) {
- setNavigationTintList(a.getColorStateList(R.styleable.Toolbar_navigationTint));
- }
- if (a.hasValue(R.styleable.Toolbar_navigationTintMode)) {
- setNavigationTintMode(Drawable.parseTintMode(
- a.getInt(R.styleable.Toolbar_navigationTintMode, -1), null));
- }
a.recycle();
}
@@ -830,101 +811,37 @@ public class Toolbar extends ViewGroup {
}
/**
- * Applies a tint to the icon drawable. Does not modify the current tint
- * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
- * <p>
- * Subsequent calls to {@link #setNavigationIcon(Drawable)} will automatically mutate
- * the drawable and apply the specified tint and tint mode.
- *
- * @param tint the tint to apply, may be {@code null} to clear tint
- *
- * @attr ref android.R.styleable#Toolbar_navigationTint
- */
- public void setNavigationTintList(ColorStateList tint) {
- if (mNavTintInfo == null) {
- mNavTintInfo = new TintInfo();
- }
- mNavTintInfo.mTintList = tint;
- mNavTintInfo.mHasTintList = true;
-
- applyNavigationTint();
- }
-
- /**
- * Specifies the blending mode used to apply the tint specified by {@link
- * #setNavigationTintList(ColorStateList)} to the navigation drawable.
- * The default mode is {@link PorterDuff.Mode#SRC_IN}.
- *
- * @param tintMode the blending mode used to apply the tint, may be {@code null} to clear tint
- *
- * @attr ref android.R.styleable#Toolbar_navigationTintMode
- */
- public void setNavigationTintMode(PorterDuff.Mode tintMode) {
- if (mNavTintInfo == null) {
- mNavTintInfo = new TintInfo();
- }
- mNavTintInfo.mTintMode = tintMode;
- mNavTintInfo.mHasTintMode = true;
-
- applyNavigationTint();
- }
-
- /**
- * Applies a tint to the overflow drawable. Does not modify the current tint
- * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
+ * Return the Menu shown in the toolbar.
*
- * @param tint the tint to apply, may be {@code null} to clear tint
+ * <p>Applications that wish to populate the toolbar's menu can do so from here. To use
+ * an XML menu resource, use {@link #inflateMenu(int)}.</p>
*
- * @attr ref android.R.styleable#Toolbar_overflowTint
+ * @return The toolbar's Menu
*/
- public void setOverflowTintList(ColorStateList tint) {
- if (mMenuView != null) {
- // If the menu view is available, directly set the tint
- mMenuView.setOverflowTintList(tint);
- } else {
- // Otherwise we will record the value
- if (mOverflowTintInfo == null) {
- mOverflowTintInfo = new TintInfo();
- }
- mOverflowTintInfo.mTintList = tint;
- mOverflowTintInfo.mHasTintList = true;
- }
+ public Menu getMenu() {
+ ensureMenu();
+ return mMenuView.getMenu();
}
/**
- * Specifies the blending mode used to apply the tint specified by {@link
- * #setOverflowTintList(ColorStateList)} to the overflow drawable.
- * The default mode is {@link PorterDuff.Mode#SRC_IN}.
- *
- * @param tintMode the blending mode used to apply the tint, may be {@code null} to clear tint
+ * Set the icon to use for the overflow button.
*
- * @attr ref android.R.styleable#Toolbar_overflowTintMode
+ * @param icon Drawable to set, may be null to clear the icon
*/
- public void setOverflowTintMode(PorterDuff.Mode tintMode) {
- if (mMenuView != null) {
- // If the menu view is available, directly set the tint mode
- mMenuView.setOverflowTintMode(tintMode);
- } else {
- // Otherwise we will record the value
- if (mOverflowTintInfo == null) {
- mOverflowTintInfo = new TintInfo();
- }
- mOverflowTintInfo.mTintMode = tintMode;
- mOverflowTintInfo.mHasTintMode = true;
- }
+ public void setOverflowIcon(@Nullable Drawable icon) {
+ ensureMenu();
+ mMenuView.setOverflowIcon(icon);
}
/**
- * Return the Menu shown in the toolbar.
- *
- * <p>Applications that wish to populate the toolbar's menu can do so from here. To use
- * an XML menu resource, use {@link #inflateMenu(int)}.</p>
+ * Return the current drawable used as the overflow icon.
*
- * @return The toolbar's Menu
+ * @return The overflow icon drawable
*/
- public Menu getMenu() {
+ @Nullable
+ public Drawable getOverflowIcon() {
ensureMenu();
- return mMenuView.getMenu();
+ return mMenuView.getOverflowIcon();
}
private void ensureMenu() {
@@ -950,17 +867,6 @@ public class Toolbar extends ViewGroup {
lp.gravity = Gravity.END | (mButtonGravity & Gravity.VERTICAL_GRAVITY_MASK);
mMenuView.setLayoutParams(lp);
addSystemView(mMenuView);
-
- if (mOverflowTintInfo != null) {
- // If we have tint info for the overflow, set it on the menu view now
- if (mOverflowTintInfo.mHasTintList) {
- mMenuView.setOverflowTintList(mOverflowTintInfo.mTintList);
- }
- if (mOverflowTintInfo.mHasTintMode) {
- mMenuView.setOverflowTintMode(mOverflowTintInfo.mTintMode);
- }
- mOverflowTintInfo = null;
- }
}
}
@@ -1114,7 +1020,6 @@ public class Toolbar extends ViewGroup {
final LayoutParams lp = generateDefaultLayoutParams();
lp.gravity = Gravity.START | (mButtonGravity & Gravity.VERTICAL_GRAVITY_MASK);
mNavButtonView.setLayoutParams(lp);
- applyNavigationTint();
}
}
@@ -1133,7 +1038,6 @@ public class Toolbar extends ViewGroup {
collapseActionView();
}
});
- applyNavigationTint();
}
}
@@ -1885,30 +1789,6 @@ public class Toolbar extends ViewGroup {
return mPopupContext;
}
- private void applyNavigationTint() {
- final TintInfo tintInfo = mNavTintInfo;
- if (tintInfo != null && (tintInfo.mHasTintList || tintInfo.mHasTintMode)) {
- if (mNavButtonView != null) {
- if (tintInfo.mHasTintList) {
- mNavButtonView.setImageTintList(tintInfo.mTintList);
- }
- if (tintInfo.mHasTintMode) {
- mNavButtonView.setImageTintMode(tintInfo.mTintMode);
- }
- }
-
- if (mCollapseButtonView != null) {
- // We will use the same tint for the collapse button
- if (tintInfo.mHasTintList) {
- mCollapseButtonView.setImageTintList(tintInfo.mTintList);
- }
- if (tintInfo.mHasTintMode) {
- mCollapseButtonView.setImageTintMode(tintInfo.mTintMode);
- }
- }
- }
- }
-
/**
* Interface responsible for receiving menu item click events if the items themselves
* do not have individual item click listeners.
@@ -2136,11 +2016,4 @@ public class Toolbar extends ViewGroup {
public void onRestoreInstanceState(Parcelable state) {
}
}
-
- private static class TintInfo {
- ColorStateList mTintList;
- PorterDuff.Mode mTintMode;
- boolean mHasTintMode;
- boolean mHasTintList;
- }
}
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index ba4af89..39c86f9 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -18,8 +18,6 @@ package com.android.internal.app;
import android.app.Activity;
import android.app.ActivityThread;
-import android.app.usage.UsageStats;
-import android.app.usage.UsageStatsManager;
import android.os.AsyncTask;
import android.provider.Settings;
import android.text.TextUtils;
@@ -64,14 +62,11 @@ import android.widget.TextView;
import android.widget.Toast;
import com.android.internal.widget.ResolverDrawerLayout;
-import java.text.Collator;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
-import java.util.Map;
import java.util.Set;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
@@ -100,10 +95,7 @@ public class ResolverActivity extends Activity {
private boolean mResolvingHome = false;
private int mProfileSwitchMessageId = -1;
private final ArrayList<Intent> mIntents = new ArrayList<>();
-
- private UsageStatsManager mUsm;
- private Map<String, UsageStats> mStats;
- private static final long USAGE_STATS_PERIOD = 1000 * 60 * 60 * 24 * 14;
+ private ResolverComparator mResolverComparator;
private boolean mRegistered;
private final PackageMonitor mPackageMonitor = new PackageMonitor() {
@@ -222,10 +214,6 @@ public class ResolverActivity extends Activity {
}
mPm = getPackageManager();
- mUsm = (UsageStatsManager) getSystemService(Context.USAGE_STATS_SERVICE);
-
- final long sinceTime = System.currentTimeMillis() - USAGE_STATS_PERIOD;
- mStats = mUsm.queryAndAggregateUsageStats(sinceTime, System.currentTimeMillis());
mPackageMonitor.register(this, getMainLooper(), false);
mRegistered = true;
@@ -236,6 +224,10 @@ public class ResolverActivity extends Activity {
// Add our initial intent as the first item, regardless of what else has already been added.
mIntents.add(0, new Intent(intent));
+ final String referrerPackage = getReferrerPackageName();
+
+ mResolverComparator = new ResolverComparator(this, getTargetIntent(), referrerPackage);
+
configureContentView(mIntents, initialIntents, rList, alwaysUseOption);
// Prevent the Resolver window from becoming the top fullscreen window and thus from taking
@@ -265,7 +257,6 @@ public class ResolverActivity extends Activity {
// Try to initialize the title icon if we have a view for it and a title to match
final ImageView titleIcon = (ImageView) findViewById(R.id.title_icon);
if (titleIcon != null) {
- final String referrerPackage = getReferrerPackageName();
ApplicationInfo ai = null;
try {
if (!TextUtils.isEmpty(referrerPackage)) {
@@ -1175,8 +1166,8 @@ public class ResolverActivity extends Activity {
}
}
if (N > 1) {
- Collections.sort(currentResolveList,
- new ResolverComparator(ResolverActivity.this, getTargetIntent()));
+ mResolverComparator.compute(currentResolveList);
+ Collections.sort(currentResolveList, mResolverComparator);
}
// First put the initial items at the top.
if (mInitialIntents != null) {
@@ -1651,63 +1642,4 @@ public class ResolverActivity extends Activity {
&& match <= IntentFilter.MATCH_CATEGORY_PATH;
}
- class ResolverComparator implements Comparator<ResolvedComponentInfo> {
- private final Collator mCollator;
- private final boolean mHttp;
-
- public ResolverComparator(Context context, Intent intent) {
- mCollator = Collator.getInstance(context.getResources().getConfiguration().locale);
- String scheme = intent.getScheme();
- mHttp = "http".equals(scheme) || "https".equals(scheme);
- }
-
- @Override
- public int compare(ResolvedComponentInfo lhsp, ResolvedComponentInfo rhsp) {
- final ResolveInfo lhs = lhsp.getResolveInfoAt(0);
- final ResolveInfo rhs = rhsp.getResolveInfoAt(0);
-
- // We want to put the one targeted to another user at the end of the dialog.
- if (lhs.targetUserId != UserHandle.USER_CURRENT) {
- return 1;
- }
-
- if (mHttp) {
- // Special case: we want filters that match URI paths/schemes to be
- // ordered before others. This is for the case when opening URIs,
- // to make native apps go above browsers.
- final boolean lhsSpecific = isSpecificUriMatch(lhs.match);
- final boolean rhsSpecific = isSpecificUriMatch(rhs.match);
- if (lhsSpecific != rhsSpecific) {
- return lhsSpecific ? -1 : 1;
- }
- }
-
- if (mStats != null) {
- final long timeDiff =
- getPackageTimeSpent(rhs.activityInfo.packageName) -
- getPackageTimeSpent(lhs.activityInfo.packageName);
-
- if (timeDiff != 0) {
- return timeDiff > 0 ? 1 : -1;
- }
- }
-
- CharSequence sa = lhs.loadLabel(mPm);
- if (sa == null) sa = lhs.activityInfo.name;
- CharSequence sb = rhs.loadLabel(mPm);
- if (sb == null) sb = rhs.activityInfo.name;
-
- return mCollator.compare(sa.toString(), sb.toString());
- }
-
- private long getPackageTimeSpent(String packageName) {
- if (mStats != null) {
- final UsageStats stats = mStats.get(packageName);
- if (stats != null) {
- return stats.getTotalTimeInForeground();
- }
- }
- return 0;
- }
- }
}
diff --git a/core/java/com/android/internal/app/ResolverComparator.java b/core/java/com/android/internal/app/ResolverComparator.java
new file mode 100644
index 0000000..585cdf1
--- /dev/null
+++ b/core/java/com/android/internal/app/ResolverComparator.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package com.android.internal.app;
+
+import android.app.usage.UsageStats;
+import android.app.usage.UsageStatsManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.ComponentInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.UserHandle;
+import android.text.TextUtils;
+import android.util.Log;
+import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
+
+import java.text.Collator;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Ranks and compares packages based on usage stats.
+ */
+class ResolverComparator implements Comparator<ResolvedComponentInfo> {
+ private static final String TAG = "ResolverComparator";
+
+ private static final boolean DEBUG = false;
+
+ // Two weeks
+ private static final long USAGE_STATS_PERIOD = 1000 * 60 * 60 * 24 * 14;
+
+ private static final long RECENCY_TIME_PERIOD = 1000 * 60 * 60 * 12;
+
+ private static final float RECENCY_MULTIPLIER = 3.f;
+
+ private final Collator mCollator;
+ private final boolean mHttp;
+ private final PackageManager mPm;
+ private final UsageStatsManager mUsm;
+ private final Map<String, UsageStats> mStats;
+ private final long mCurrentTime;
+ private final long mSinceTime;
+ private final LinkedHashMap<ComponentName, ScoredTarget> mScoredTargets = new LinkedHashMap<>();
+ private final String mReferrerPackage;
+
+ public ResolverComparator(Context context, Intent intent, String referrerPackage) {
+ mCollator = Collator.getInstance(context.getResources().getConfiguration().locale);
+ String scheme = intent.getScheme();
+ mHttp = "http".equals(scheme) || "https".equals(scheme);
+ mReferrerPackage = referrerPackage;
+
+ mPm = context.getPackageManager();
+ mUsm = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);
+
+ mCurrentTime = System.currentTimeMillis();
+ mSinceTime = mCurrentTime - USAGE_STATS_PERIOD;
+ mStats = mUsm.queryAndAggregateUsageStats(mSinceTime, mCurrentTime);
+ }
+
+ public void compute(List<ResolvedComponentInfo> targets) {
+ mScoredTargets.clear();
+
+ final long recentSinceTime = mCurrentTime - RECENCY_TIME_PERIOD;
+
+ long mostRecentlyUsedTime = recentSinceTime + 1;
+ long mostTimeSpent = 1;
+ int mostLaunched = 1;
+
+ for (ResolvedComponentInfo target : targets) {
+ final ScoredTarget scoredTarget
+ = new ScoredTarget(target.getResolveInfoAt(0).activityInfo);
+ mScoredTargets.put(target.name, scoredTarget);
+ final UsageStats pkStats = mStats.get(target.name.getPackageName());
+ if (pkStats != null) {
+ // Only count recency for apps that weren't the caller
+ // since the caller is always the most recent.
+ // Persistent processes muck this up, so omit them too.
+ if (!target.name.getPackageName().equals(mReferrerPackage)
+ && !isPersistentProcess(target)) {
+ final long lastTimeUsed = pkStats.getLastTimeUsed();
+ scoredTarget.lastTimeUsed = lastTimeUsed;
+ if (lastTimeUsed > mostRecentlyUsedTime) {
+ mostRecentlyUsedTime = lastTimeUsed;
+ }
+ }
+ final long timeSpent = pkStats.getTotalTimeInForeground();
+ scoredTarget.timeSpent = timeSpent;
+ if (timeSpent > mostTimeSpent) {
+ mostTimeSpent = timeSpent;
+ }
+ final int launched = pkStats.mLaunchCount;
+ scoredTarget.launchCount = launched;
+ if (launched > mostLaunched) {
+ mostLaunched = launched;
+ }
+ }
+ }
+
+
+ if (DEBUG) {
+ Log.d(TAG, "compute - mostRecentlyUsedTime: " + mostRecentlyUsedTime
+ + " mostTimeSpent: " + mostTimeSpent
+ + " recentSinceTime: " + recentSinceTime
+ + " mostLaunched: " + mostLaunched);
+ }
+
+ for (ScoredTarget target : mScoredTargets.values()) {
+ final float recency = (float) Math.max(target.lastTimeUsed - recentSinceTime, 0)
+ / (mostRecentlyUsedTime - recentSinceTime);
+ final float recencyScore = recency * recency * RECENCY_MULTIPLIER;
+ final float usageTimeScore = (float) target.timeSpent / mostTimeSpent;
+ final float launchCountScore = (float) target.launchCount / mostLaunched;
+
+ target.score = recencyScore + usageTimeScore + launchCountScore;
+ if (DEBUG) {
+ Log.d(TAG, "Scores: recencyScore: " + recencyScore
+ + " usageTimeScore: " + usageTimeScore
+ + " launchCountScore: " + launchCountScore
+ + " - " + target);
+ }
+ }
+ }
+
+ static boolean isPersistentProcess(ResolvedComponentInfo rci) {
+ if (rci != null && rci.getCount() > 0) {
+ return (rci.getResolveInfoAt(0).activityInfo.applicationInfo.flags &
+ ApplicationInfo.FLAG_PERSISTENT) != 0;
+ }
+ return false;
+ }
+
+ @Override
+ public int compare(ResolvedComponentInfo lhsp, ResolvedComponentInfo rhsp) {
+ final ResolveInfo lhs = lhsp.getResolveInfoAt(0);
+ final ResolveInfo rhs = rhsp.getResolveInfoAt(0);
+
+ // We want to put the one targeted to another user at the end of the dialog.
+ if (lhs.targetUserId != UserHandle.USER_CURRENT) {
+ return 1;
+ }
+
+ if (mHttp) {
+ // Special case: we want filters that match URI paths/schemes to be
+ // ordered before others. This is for the case when opening URIs,
+ // to make native apps go above browsers.
+ final boolean lhsSpecific = ResolverActivity.isSpecificUriMatch(lhs.match);
+ final boolean rhsSpecific = ResolverActivity.isSpecificUriMatch(rhs.match);
+ if (lhsSpecific != rhsSpecific) {
+ return lhsSpecific ? -1 : 1;
+ }
+ }
+
+ if (mStats != null) {
+ final ScoredTarget lhsTarget = mScoredTargets.get(new ComponentName(
+ lhs.activityInfo.packageName, lhs.activityInfo.name));
+ final ScoredTarget rhsTarget = mScoredTargets.get(new ComponentName(
+ rhs.activityInfo.packageName, rhs.activityInfo.name));
+ final float diff = rhsTarget.score - lhsTarget.score;
+
+ if (diff != 0) {
+ return diff > 0 ? 1 : -1;
+ }
+ }
+
+ CharSequence sa = lhs.loadLabel(mPm);
+ if (sa == null) sa = lhs.activityInfo.name;
+ CharSequence sb = rhs.loadLabel(mPm);
+ if (sb == null) sb = rhs.activityInfo.name;
+
+ return mCollator.compare(sa.toString().trim(), sb.toString().trim());
+ }
+
+ static class ScoredTarget {
+ public final ComponentInfo componentInfo;
+ public float score;
+ public long lastTimeUsed;
+ public long timeSpent;
+ public long launchCount;
+
+ public ScoredTarget(ComponentInfo ci) {
+ componentInfo = ci;
+ }
+
+ @Override
+ public String toString() {
+ return "ScoredTarget{" + componentInfo
+ + " score: " + score
+ + " lastTimeUsed: " + lastTimeUsed
+ + " timeSpent: " + timeSpent
+ + " launchCount: " + launchCount
+ + "}";
+ }
+ }
+}
diff --git a/core/java/com/android/internal/view/menu/ActionMenuItem.java b/core/java/com/android/internal/view/menu/ActionMenuItem.java
index 00af401..ed676bb 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuItem.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuItem.java
@@ -18,8 +18,6 @@ package com.android.internal.view.menu;
import android.content.Context;
import android.content.Intent;
-import android.content.res.ColorStateList;
-import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.view.ActionProvider;
import android.view.ContextMenu.ContextMenuInfo;
@@ -44,7 +42,6 @@ public class ActionMenuItem implements MenuItem {
private Drawable mIconDrawable;
private int mIconResId = NO_ICON;
- private TintInfo mIconTintInfo;
private Context mContext;
@@ -161,14 +158,12 @@ public class ActionMenuItem implements MenuItem {
public MenuItem setIcon(Drawable icon) {
mIconDrawable = icon;
mIconResId = NO_ICON;
- applyIconTint();
return this;
}
public MenuItem setIcon(int iconRes) {
mIconResId = iconRes;
mIconDrawable = mContext.getDrawable(iconRes);
- applyIconTint();
return this;
}
@@ -279,48 +274,4 @@ public class ActionMenuItem implements MenuItem {
// No need to save the listener; ActionMenuItem does not support collapsing items.
return this;
}
-
- @Override
- public MenuItem setIconTintList(ColorStateList tintList) {
- if (mIconTintInfo == null) {
- mIconTintInfo = new TintInfo();
- }
- mIconTintInfo.mTintList = tintList;
- mIconTintInfo.mHasTintList = true;
- applyIconTint();
- return this;
- }
-
- @Override
- public MenuItem setIconTintMode(PorterDuff.Mode tintMode) {
- if (mIconTintInfo == null) {
- mIconTintInfo = new TintInfo();
- }
- mIconTintInfo.mTintMode = tintMode;
- mIconTintInfo.mHasTintMode = true;
- applyIconTint();
- return this;
- }
-
- private void applyIconTint() {
- final TintInfo tintInfo = mIconTintInfo;
- if (mIconDrawable != null && tintInfo != null) {
- if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
- mIconDrawable = mIconDrawable.mutate();
- if (tintInfo.mHasTintList) {
- mIconDrawable.setTintList(tintInfo.mTintList);
- }
- if (tintInfo.mHasTintMode) {
- mIconDrawable.setTintMode(tintInfo.mTintMode);
- }
- }
- }
- }
-
- private static class TintInfo {
- ColorStateList mTintList;
- PorterDuff.Mode mTintMode;
- boolean mHasTintMode;
- boolean mHasTintList;
- }
}
diff --git a/core/java/com/android/internal/view/menu/MenuItemImpl.java b/core/java/com/android/internal/view/menu/MenuItemImpl.java
index ef4e546..3b1f20d 100644
--- a/core/java/com/android/internal/view/menu/MenuItemImpl.java
+++ b/core/java/com/android/internal/view/menu/MenuItemImpl.java
@@ -21,8 +21,6 @@ import com.android.internal.view.menu.MenuView.ItemView;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
-import android.content.res.ColorStateList;
-import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.util.Log;
import android.view.ActionProvider;
@@ -62,11 +60,6 @@ public final class MenuItemImpl implements MenuItem {
* needed).
*/
private int mIconResId = NO_ICON;
-
- /**
- * Tint info for the icon
- */
- private TintInfo mIconTintInfo;
/** The menu to which this item belongs */
private MenuBuilder mMenu;
@@ -392,10 +385,10 @@ public final class MenuItemImpl implements MenuItem {
}
if (mIconResId != NO_ICON) {
- mIconDrawable = mMenu.getContext().getDrawable(mIconResId);
+ Drawable icon = mMenu.getContext().getDrawable(mIconResId);
mIconResId = NO_ICON;
- applyIconTint();
- return mIconDrawable;
+ mIconDrawable = icon;
+ return icon;
}
return null;
@@ -404,7 +397,6 @@ public final class MenuItemImpl implements MenuItem {
public MenuItem setIcon(Drawable icon) {
mIconResId = NO_ICON;
mIconDrawable = icon;
- applyIconTint();
mMenu.onItemsChanged(false);
return this;
@@ -678,48 +670,4 @@ public final class MenuItemImpl implements MenuItem {
public boolean isActionViewExpanded() {
return mIsActionViewExpanded;
}
-
- @Override
- public MenuItem setIconTintList(ColorStateList tintList) {
- if (mIconTintInfo == null) {
- mIconTintInfo = new TintInfo();
- }
- mIconTintInfo.mTintList = tintList;
- mIconTintInfo.mHasTintList = true;
- applyIconTint();
- return this;
- }
-
- @Override
- public MenuItem setIconTintMode(PorterDuff.Mode tintMode) {
- if (mIconTintInfo == null) {
- mIconTintInfo = new TintInfo();
- }
- mIconTintInfo.mTintMode = tintMode;
- mIconTintInfo.mHasTintMode = true;
- applyIconTint();
- return this;
- }
-
- private void applyIconTint() {
- final TintInfo tintInfo = mIconTintInfo;
- if (mIconDrawable != null && tintInfo != null) {
- if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
- mIconDrawable = mIconDrawable.mutate();
- if (tintInfo.mHasTintList) {
- mIconDrawable.setTintList(tintInfo.mTintList);
- }
- if (tintInfo.mHasTintMode) {
- mIconDrawable.setTintMode(tintInfo.mTintMode);
- }
- }
- }
- }
-
- private static class TintInfo {
- ColorStateList mTintList;
- PorterDuff.Mode mTintMode;
- boolean mHasTintMode;
- boolean mHasTintList;
- }
}
diff --git a/core/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java
index c77d614..2d0989f 100644
--- a/core/java/com/android/internal/widget/FloatingToolbar.java
+++ b/core/java/com/android/internal/widget/FloatingToolbar.java
@@ -361,7 +361,7 @@ public final class FloatingToolbar {
mParent = Preconditions.checkNotNull(parent);
mContentContainer = createContentContainer(parent.getContext());
mPopupWindow = createPopupWindow(mContentContainer);
- mDismissAnimation = createShrinkFadeOutFromBottomAnimation(
+ mDismissAnimation = createExitAnimation(
mContentContainer,
150, // startDelay
new AnimatorListenerAdapter() {
@@ -371,7 +371,7 @@ public final class FloatingToolbar {
mContentContainer.removeAllViews();
}
});
- mHideAnimation = createShrinkFadeOutFromBottomAnimation(
+ mHideAnimation = createExitAnimation(
mContentContainer,
0, // startDelay
new AnimatorListenerAdapter() {
@@ -561,7 +561,7 @@ public final class FloatingToolbar {
* Performs the "show" animation on the floating popup.
*/
private void runShowAnimation() {
- createGrowFadeInFromBottom(mContentContainer).start();
+ createEnterAnimation(mContentContainer).start();
}
/**
@@ -1369,38 +1369,35 @@ public final class FloatingToolbar {
}
/**
- * Creates a "grow and fade in from the bottom" animation for the specified view.
+ * Creates an "appear" animation for the specified view.
*
* @param view The view to animate
*/
- private static AnimatorSet createGrowFadeInFromBottom(View view) {
- AnimatorSet growFadeInFromBottomAnimation = new AnimatorSet();
- growFadeInFromBottomAnimation.playTogether(
- ObjectAnimator.ofFloat(view, View.SCALE_X, 0.5f, 1).setDuration(125),
- ObjectAnimator.ofFloat(view, View.SCALE_Y, 0.5f, 1).setDuration(125),
- ObjectAnimator.ofFloat(view, View.ALPHA, 0, 1).setDuration(75),
+ private static AnimatorSet createEnterAnimation(View view) {
+ AnimatorSet animation = new AnimatorSet();
+ animation.playTogether(
+ ObjectAnimator.ofFloat(view, View.ALPHA, 0, 1).setDuration(200),
// Make sure that view.x is always fixed throughout the duration of this animation.
ObjectAnimator.ofFloat(view, View.X, view.getX(), view.getX()));
- growFadeInFromBottomAnimation.setStartDelay(50);
- return growFadeInFromBottomAnimation;
+ animation.setStartDelay(50);
+ return animation;
}
/**
- * Creates a "shrink and fade out from bottom" animation for the specified view.
+ * Creates a "disappear" animation for the specified view.
*
* @param view The view to animate
* @param startDelay The start delay of the animation
* @param listener The animation listener
*/
- private static AnimatorSet createShrinkFadeOutFromBottomAnimation(
+ private static AnimatorSet createExitAnimation(
View view, int startDelay, Animator.AnimatorListener listener) {
- AnimatorSet shrinkFadeOutFromBottomAnimation = new AnimatorSet();
- shrinkFadeOutFromBottomAnimation.playTogether(
- ObjectAnimator.ofFloat(view, View.SCALE_Y, 1, 0.5f).setDuration(125),
- ObjectAnimator.ofFloat(view, View.ALPHA, 1, 0).setDuration(75));
- shrinkFadeOutFromBottomAnimation.setStartDelay(startDelay);
- shrinkFadeOutFromBottomAnimation.addListener(listener);
- return shrinkFadeOutFromBottomAnimation;
+ AnimatorSet animation = new AnimatorSet();
+ animation.playTogether(
+ ObjectAnimator.ofFloat(view, View.ALPHA, 1, 0).setDuration(200));
+ animation.setStartDelay(startDelay);
+ animation.addListener(listener);
+ return animation;
}
private static int getEstimatedToolbarHeight(Context context) {
diff --git a/core/jni/android/graphics/SurfaceTexture.cpp b/core/jni/android/graphics/SurfaceTexture.cpp
index 08d61d5..b9e48a0 100644
--- a/core/jni/android/graphics/SurfaceTexture.cpp
+++ b/core/jni/android/graphics/SurfaceTexture.cpp
@@ -49,6 +49,12 @@ struct fields_t {
};
static fields_t fields;
+// Get an ID that's unique within this process.
+static int32_t createProcessUniqueId() {
+ static volatile int32_t globalCounter = 0;
+ return android_atomic_inc(&globalCounter);
+}
+
// ----------------------------------------------------------------------------
static void SurfaceTexture_setSurfaceTexture(JNIEnv* env, jobject thiz,
@@ -253,6 +259,11 @@ static void SurfaceTexture_init(JNIEnv* env, jobject thiz, jboolean isDetached,
"Unable to create native SurfaceTexture");
return;
}
+ surfaceTexture->setName(String8::format("SurfaceTexture-%d-%d-%d",
+ (isDetached ? 0 : texName),
+ getpid(),
+ createProcessUniqueId()));
+
SurfaceTexture_setSurfaceTexture(env, thiz, surfaceTexture);
SurfaceTexture_setProducer(env, thiz, producer);
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 709de9e..6d0a902 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -90,7 +90,6 @@
<protected-broadcast android:name="android.app.action.ENTER_DESK_MODE" />
<protected-broadcast android:name="android.app.action.EXIT_DESK_MODE" />
<protected-broadcast android:name="android.app.action.NEXT_ALARM_CLOCK_CHANGED" />
- <protected-broadcast android:name="android.app.action.SEND_DEVICE_INITIALIZER_STATUS" />
<protected-broadcast android:name="android.appwidget.action.APPWIDGET_UPDATE_OPTIONS" />
<protected-broadcast android:name="android.appwidget.action.APPWIDGET_DELETED" />
@@ -1205,12 +1204,16 @@
<permission android:name="android.permission.BIND_TELECOM_CONNECTION_SERVICE"
android:protectionLevel="system|signature" />
-
<!-- @SystemApi Allows an application to control the in-call experience.
@hide -->
<permission android:name="android.permission.CONTROL_INCALL_EXPERIENCE"
android:protectionLevel="system|signature" />
+ <!-- Allows an application to receive STK related commands.
+ @hide -->
+ <permission android:name="android.permission.RECEIVE_STK_COMMANDS"
+ android:protectionLevel="system|signature" />
+
<!-- ================================== -->
<!-- Permissions for sdcard interaction -->
<!-- ================================== -->
@@ -1603,24 +1606,6 @@
<permission android:name="android.permission.WRITE_APN_SETTINGS"
android:protectionLevel="signature|system" />
- <!-- Allows an application to allow access the subscribed feeds ContentProvider.
- @hide
- @removed
- -->
- <permission android:name="android.permission.SUBSCRIBED_FEEDS_READ"
- android:label="@string/permlab_subscribedFeedsRead"
- android:description="@string/permdesc_subscribedFeedsRead"
- android:protectionLevel="normal" />
-
- <!--
- @hide
- @removed
- -->
- <permission android:name="android.permission.SUBSCRIBED_FEEDS_WRITE"
- android:label="@string/permlab_subscribedFeedsWrite"
- android:description="@string/permdesc_subscribedFeedsWrite"
- android:protectionLevel="dangerous" />
-
<!-- Allows applications to change network connectivity state -->
<permission android:name="android.permission.CHANGE_NETWORK_STATE"
android:description="@string/permdesc_changeNetworkState"
@@ -1979,6 +1964,10 @@
<permission android:name="android.permission.GRANT_REVOKE_PERMISSIONS"
android:protectionLevel="signature" />
+ <!-- @hide Allows an application to observe permission changes. -->
+ <permission android:name="android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS"
+ android:protectionLevel="signatureOrSystem" />
+
<!-- Allows an application to use SurfaceFlinger's low level features.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.ACCESS_SURFACE_FLINGER"
@@ -2446,11 +2435,6 @@
<permission android:name="android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS"
android:protectionLevel="signature" />
- <!-- Allows receiving status updates from a device initializer.
- @hide Not for use by third-party applications. -->
- <permission android:name="android.permission.RECEIVE_DEVICE_INITIALIZER_STATUS"
- android:protectionLevel="signature" />
-
<!-- The system process that is allowed to bind to services in carrier apps will
have this permission. Carrier apps should use this permission to protect
their services that only the system is allowed to bind to. -->
diff --git a/core/res/res/drawable-hdpi/ic_fingerprint_light_overlay.png b/core/res/res/drawable-hdpi/ic_fingerprint_light_overlay.png
deleted file mode 100644
index 0253c77..0000000
--- a/core/res/res/drawable-hdpi/ic_fingerprint_light_overlay.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_fingerprint_light_overlay.png b/core/res/res/drawable-mdpi/ic_fingerprint_light_overlay.png
deleted file mode 100644
index 5a1c61e..0000000
--- a/core/res/res/drawable-mdpi/ic_fingerprint_light_overlay.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_fingerprint_light_overlay.png b/core/res/res/drawable-xhdpi/ic_fingerprint_light_overlay.png
deleted file mode 100644
index 5f0c362..0000000
--- a/core/res/res/drawable-xhdpi/ic_fingerprint_light_overlay.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_fingerprint_light_overlay.png b/core/res/res/drawable-xxhdpi/ic_fingerprint_light_overlay.png
deleted file mode 100644
index f4cf906..0000000
--- a/core/res/res/drawable-xxhdpi/ic_fingerprint_light_overlay.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/ic_fingerprint_light_overlay.png b/core/res/res/drawable-xxxhdpi/ic_fingerprint_light_overlay.png
deleted file mode 100644
index dcdbed9..0000000
--- a/core/res/res/drawable-xxxhdpi/ic_fingerprint_light_overlay.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable/ic_fingerprint.xml b/core/res/res/drawable/ic_fingerprint.xml
new file mode 100644
index 0000000..c19f00f
--- /dev/null
+++ b/core/res/res/drawable/ic_fingerprint.xml
@@ -0,0 +1,37 @@
+<!--
+ ~ Copyright (C) 2015 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
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24.0dp"
+ android:height="24.0dp"
+ android:tint="?attr/colorControlNormal"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#ffffff"
+ android:pathData="M17.5,4.47c-0.08,0.0 -0.16,-0.02 -0.24,-0.06C15.45,3.42 13.88,3.0 12.01,3.0c-1.87,0.0 -3.64,0.47 -5.25,1.4C6.52,4.54 6.22,4.46 6.08,4.22C5.94,3.98 6.02,3.67 6.26,3.54C8.03,2.52 9.96,2.0 12.01,2.0c2.02,0.0 3.79,0.47 5.73,1.53c0.24,0.13 0.33,0.44 0.2,0.68C17.85,4.38 17.68,4.47 17.5,4.47z"/>
+ <path
+ android:fillColor="#ffffff"
+ android:pathData="M3.95,9.72c-0.1,0.0 -0.19,-0.03 -0.28,-0.08C3.44,9.48 3.38,9.17 3.54,8.94c0.94,-1.4 2.14,-2.5 3.56,-3.28c2.99,-1.63 6.82,-1.63 9.81,-0.01c1.42,0.77 2.61,1.87 3.56,3.26c0.15,0.23 0.09,0.54 -0.13,0.69c-0.23,0.16 -0.54,0.09 -0.69,-0.13c-0.85,-1.26 -1.93,-2.24 -3.2,-2.94c-2.7,-1.47 -6.16,-1.46 -8.86,0.01C6.3,7.24 5.22,8.23 4.37,9.5C4.27,9.64 4.11,9.72 3.95,9.72z"/>
+ <path
+ android:fillColor="#ffffff"
+ android:pathData="M9.86,21.79c-0.13,0.0 -0.27,-0.05 -0.36,-0.16c-0.82,-0.87 -1.26,-1.43 -1.9,-2.63c-0.65,-1.23 -1.0,-2.73 -1.0,-4.33c0.0,-2.97 2.42,-5.39 5.39,-5.39s5.39,2.42 5.39,5.39c0.0,0.28 -0.22,0.5 -0.5,0.5s-0.5,-0.22 -0.5,-0.5c0.0,-2.42 -1.97,-4.39 -4.39,-4.39S7.6,12.24 7.6,14.66c0.0,1.44 0.3,2.78 0.88,3.86c0.61,1.15 1.02,1.64 1.75,2.42c0.19,0.2 0.18,0.52 -0.02,0.71C10.11,21.74 9.98,21.79 9.86,21.79z"/>
+ <path
+ android:fillColor="#ffffff"
+ android:pathData="M16.7,19.94c-1.14,0.0 -2.13,-0.3 -2.96,-0.89c-1.41,-1.01 -2.25,-2.65 -2.25,-4.38c0.0,-0.28 0.22,-0.5 0.5,-0.5s0.5,0.22 0.5,0.5c0.0,1.41 0.69,2.75 1.83,3.57c0.66,0.48 1.44,0.71 2.38,0.71c0.23,0.0 0.6,-0.02 0.98,-0.1c0.27,-0.05 0.53,0.13 0.58,0.4c0.05,0.27 -0.13,0.53 -0.4,0.58C17.3,19.93 16.83,19.94 16.7,19.94z"/>
+ <path
+ android:fillColor="#ffffff"
+ android:pathData="M14.76,22.0c-0.05,0.0 -0.09,-0.01 -0.14,-0.02c-1.51,-0.44 -2.51,-1.03 -3.53,-2.11c-1.32,-1.39 -2.05,-3.24 -2.05,-5.21c0.0,-1.62 1.32,-2.94 2.94,-2.94c1.62,0.0 2.94,1.32 2.94,2.94c0.0,1.07 0.87,1.94 1.94,1.94s1.94,-0.87 1.94,-1.94c0.0,-3.77 -3.07,-6.83 -6.83,-6.83c-2.68,0.0 -5.12,1.58 -6.23,4.02c-0.37,0.81 -0.56,1.76 -0.56,2.81c0.0,0.78 0.07,2.01 0.63,3.61c0.09,0.26 -0.04,0.55 -0.3,0.64c-0.26,0.09 -0.55,-0.04 -0.64,-0.3c-0.46,-1.31 -0.69,-2.6 -0.69,-3.95c0.0,-1.2 0.22,-2.28 0.65,-3.23c1.27,-2.8 4.07,-4.61 7.14,-4.61c4.32,0.0 7.83,3.51 7.83,7.83c0.0,1.62 -1.32,2.94 -2.94,2.94c-1.62,0.0 -2.94,-1.32 -2.94,-2.94c0.0,-1.07 -0.87,-1.94 -1.94,-1.94s-1.94,0.87 -1.94,1.94c0.0,1.71 0.63,3.32 1.77,4.52c0.9,0.95 1.74,1.45 3.08,1.84c0.27,0.08 0.42,0.35 0.34,0.62C15.18,21.86 14.98,22.0 14.76,22.0z"/>
+</vector>
diff --git a/core/res/res/drawable/ic_fingerprint_dark.xml b/core/res/res/drawable/ic_fingerprint_dark.xml
deleted file mode 100644
index 6eb6ada..0000000
--- a/core/res/res/drawable/ic_fingerprint_dark.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<!--
- ~ Copyright (C) 2015 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
- -->
-
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="32.0dp"
- android:height="32.0dp"
- android:viewportWidth="32.0"
- android:viewportHeight="32.0">
- <path
- android:fillColor="?attr/colorControlNormal"
- android:pathData="M23.7,5.9c-0.1,0.0 -0.2,0.0 -0.3,-0.1C21.0,4.5 18.6,3.9 16.0,3.9c-2.5,0.0 -4.6,0.6 -6.9,1.9C8.8,6.0 8.3,5.9 8.1,5.5C7.9,5.2 8.0,4.7 8.4,4.5c2.5,-1.4 4.9,-2.1 7.7,-2.1c2.8,0.0 5.4,0.7 8.0,2.1c0.4,0.2 0.5,0.6 0.3,1.0C24.2,5.7 24.0,5.9 23.7,5.9z"/>
- <path
- android:fillColor="?attr/colorControlNormal"
- android:pathData="M5.3,13.2c-0.1,0.0 -0.3,0.0 -0.4,-0.1c-0.3,-0.2 -0.4,-0.7 -0.2,-1.0c1.3,-1.9 2.9,-3.4 4.9,-4.5c4.1,-2.2 9.3,-2.2 13.4,0.0c1.9,1.1 3.6,2.5 4.9,4.4c0.2,0.3 0.1,0.8 -0.2,1.0c-0.3,0.2 -0.8,0.1 -1.0,-0.2c-1.2,-1.7 -2.6,-3.0 -4.3,-4.0c-3.7,-2.0 -8.3,-2.0 -12.0,0.0c-1.7,0.9 -3.2,2.3 -4.3,4.0C5.7,13.1 5.5,13.2 5.3,13.2z"/>
- <path
- android:fillColor="?attr/colorControlNormal"
- android:pathData="M13.3,29.6c-0.2,0.0 -0.4,-0.1 -0.5,-0.2c-1.1,-1.2 -1.7,-2.0 -2.6,-3.6c-0.9,-1.7 -1.4,-3.7 -1.4,-5.9c0.0,-4.1 3.3,-7.4 7.4,-7.4c4.1,0.0 7.4,3.3 7.4,7.4c0.0,0.4 -0.3,0.7 -0.7,0.7s-0.7,-0.3 -0.7,-0.7c0.0,-3.3 -2.7,-5.9 -5.9,-5.9c-3.3,0.0 -5.9,2.7 -5.9,5.9c0.0,2.0 0.4,3.8 1.2,5.2c0.8,1.6 1.4,2.2 2.4,3.3c0.3,0.3 0.3,0.8 0.0,1.0C13.7,29.5 13.5,29.6 13.3,29.6z"/>
- <path
- android:fillColor="?attr/colorControlNormal"
- android:pathData="M22.6,27.1c-1.6,0.0 -2.9,-0.4 -4.1,-1.2c-1.9,-1.4 -3.1,-3.6 -3.1,-6.0c0.0,-0.4 0.3,-0.7 0.7,-0.7s0.7,0.3 0.7,0.7c0.0,1.9 0.9,3.7 2.5,4.8c0.9,0.6 1.9,1.0 3.2,1.0c0.3,0.0 0.8,0.0 1.3,-0.1c0.4,-0.1 0.8,0.2 0.8,0.6c0.1,0.4 -0.2,0.8 -0.6,0.8C23.4,27.1 22.8,27.1 22.6,27.1z"/>
- <path
- android:fillColor="?attr/colorControlNormal"
- android:pathData="M20.0,29.9c-0.1,0.0 -0.1,0.0 -0.2,0.0c-2.1,-0.6 -3.4,-1.4 -4.8,-2.9c-1.8,-1.9 -2.8,-4.4 -2.8,-7.1c0.0,-2.2 1.8,-4.1 4.1,-4.1c2.2,0.0 4.1,1.8 4.1,4.1c0.0,1.4 1.2,2.6 2.6,2.6c1.4,0.0 2.6,-1.2 2.6,-2.6c0.0,-5.1 -4.2,-9.3 -9.3,-9.3c-3.6,0.0 -6.9,2.1 -8.4,5.4C7.3,17.1 7.0,18.4 7.0,19.8c0.0,1.1 0.1,2.7 0.9,4.9c0.1,0.4 -0.1,0.8 -0.4,0.9c-0.4,0.1 -0.8,-0.1 -0.9,-0.4c-0.6,-1.8 -0.9,-3.6 -0.9,-5.4c0.0,-1.6 0.3,-3.1 0.9,-4.4c1.7,-3.8 5.6,-6.3 9.8,-6.3c5.9,0.0 10.7,4.8 10.7,10.7c0.0,2.2 -1.8,4.1 -4.1,4.1s-4.0,-1.8 -4.0,-4.1c0.0,-1.4 -1.2,-2.6 -2.6,-2.6c-1.4,0.0 -2.6,1.2 -2.6,2.6c0.0,2.3 0.9,4.5 2.4,6.1c1.2,1.3 2.4,2.0 4.2,2.5c0.4,0.1 0.6,0.5 0.5,0.9C20.6,29.7 20.3,29.9 20.0,29.9z"/>
-</vector>
diff --git a/core/res/res/drawable/ic_fingerprint_light.xml b/core/res/res/drawable/ic_fingerprint_light.xml
deleted file mode 100644
index 223d16b..0000000
--- a/core/res/res/drawable/ic_fingerprint_light.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
- Copyright (C) 2015 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.
--->
-<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
- <item>
- <shape android:shape="oval">
- <solid android:color="?attr/colorAccent"/>
- <size
- android:width="40dp"
- android:height="40dp"/>
- </shape>
- </item>
- <item>
- <bitmap android:src="@drawable/ic_fingerprint_light_overlay"/>
- </item>
-</layer-list>
diff --git a/core/res/res/layout/seekbar_dialog.xml b/core/res/res/layout/preference_dialog_seekbar.xml
index 84352a5..4e366c4 100644
--- a/core/res/res/layout/seekbar_dialog.xml
+++ b/core/res/res/layout/preference_dialog_seekbar.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
+<!-- Copyright (C) 2015 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.
@@ -15,20 +15,21 @@
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="center_horizontal"
+ android:orientation="vertical">
+
+ <ImageView
+ android:id="@+id/icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingTop="20dp" />
+
+ <SeekBar
+ android:id="@+id/seekbar"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:gravity="center_horizontal">
-
- <ImageView android:id="@+id/icon"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:paddingTop="20dip" />
-
- <SeekBar android:id="@+id/seekbar"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:padding="20dip" />
-
+ android:layout_height="wrap_content"
+ android:padding="20dp" />
+
</LinearLayout>
-
diff --git a/core/res/res/layout/preference_dialog_seekbar_material.xml b/core/res/res/layout/preference_dialog_seekbar_material.xml
new file mode 100644
index 0000000..a98a995
--- /dev/null
+++ b/core/res/res/layout/preference_dialog_seekbar_material.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 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:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="center_horizontal"
+ android:orientation="vertical">
+
+ <ImageView
+ android:id="@+id/icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingTop="?attr/dialogPreferredPadding" />
+
+ <SeekBar
+ android:id="@+id/seekbar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="?attr/dialogPreferredPadding"
+ android:paddingStart="?attr/dialogPreferredPadding"
+ android:paddingEnd="?attr/dialogPreferredPadding" />
+
+</LinearLayout>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index a13f494..52e2cf0 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -561,15 +561,18 @@
<!-- Image elements -->
<!-- ============== -->
<eat-comment />
-
+i
<!-- Background that can be used behind parts of a UI that provide
details on data the user is selecting. For example, this is
the background element of PreferenceActivity's embedded
preference fragment. -->
<attr name="detailsElementBackground" format="reference" />
- <!-- Drawable that should be used to indicate that an app is waiting for a fingerprint scan. -->
- <attr name="fingerprintDrawable" format="reference" />
+ <!-- Icon that should be used to indicate that an app is waiting for a fingerprint scan.
+ This should be used whenever an app is requesting the user to place a finger on the
+ fingerprint sensor. It can be combined with other drawables such as colored circles, so
+ the appearance matches the branding of the app requesting the fingerprint scan.-->
+ <attr name="fingerprintAuthDrawable" format="reference" />
<!-- ============ -->
<!-- Panel styles -->
@@ -868,6 +871,8 @@
<attr name="dialogPreferenceStyle" format="reference" />
<!-- Default style for EditTextPreference. -->
<attr name="editTextPreferenceStyle" format="reference" />
+ <!-- @hide Default style for SeekBarDialogPreference. -->
+ <attr name="seekBarDialogPreferenceStyle" format="reference" />
<!-- Default style for RingtonePreference. -->
<attr name="ringtonePreferenceStyle" format="reference" />
<!-- The preference layout that has the child/tabbed effect. -->
@@ -6646,33 +6651,6 @@
for more info. -->
<attr name="actionProviderClass" format="string" />
- <!-- An optional tint for the item's icon.
- See {@link android.view.MenuItem#setIconTintList(android.content.res.ColorStateList)}
- for more info. -->
- <attr name="iconTint" format="color" />
-
- <!-- The blending mode used for tinting the item's icon
- See {@link android.view.MenuItem#setIconTintMode(android.graphics.PorterDuff.Mode)}
- for more info. -->
- <attr name="iconTintMode">
- <!-- The tint is drawn on top of the drawable.
- [Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc] -->
- <enum name="src_over" value="3" />
- <!-- The tint is masked by the alpha channel of the drawable. The drawable’s
- color channels are thrown out. [Sa * Da, Sc * Da] -->
- <enum name="src_in" value="5" />
- <!-- The tint is drawn above the drawable, but with the drawable’s alpha
- channel masking the result. [Da, Sc * Da + (1 - Sa) * Dc] -->
- <enum name="src_atop" value="9" />
- <!-- Multiplies the color and alpha channels of the drawable with those of
- the tint. [Sa * Da, Sc * Dc] -->
- <enum name="multiply" value="14" />
- <!-- [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] -->
- <enum name="screen" value="15" />
- <!-- Combines the tint and drawable color and alpha channels, clamping the
- result to valid color values. Saturate(S + D) -->
- <enum name="add" value="16" />
- </attr>
</declare-styleable>
<!-- Attrbitutes for a ActvityChooserView. -->
@@ -7786,52 +7764,6 @@
<!-- Text to set as the content description for the navigation button
located at the start of the toolbar. -->
<attr name="navigationContentDescription" format="string" />
-
- <!-- Tint used for the navigation button -->
- <attr name="navigationTint" format="color" />
- <!-- The blending mode used for tinting the navigation button -->
- <attr name="navigationTintMode">
- <!-- The tint is drawn on top of the drawable.
- [Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc] -->
- <enum name="src_over" value="3" />
- <!-- The tint is masked by the alpha channel of the drawable. The drawable’s
- color channels are thrown out. [Sa * Da, Sc * Da] -->
- <enum name="src_in" value="5" />
- <!-- The tint is drawn above the drawable, but with the drawable’s alpha
- channel masking the result. [Da, Sc * Da + (1 - Sa) * Dc] -->
- <enum name="src_atop" value="9" />
- <!-- Multiplies the color and alpha channels of the drawable with those of
- the tint. [Sa * Da, Sc * Dc] -->
- <enum name="multiply" value="14" />
- <!-- [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] -->
- <enum name="screen" value="15" />
- <!-- Combines the tint and drawable color and alpha channels, clamping the
- result to valid color values. Saturate(S + D). Only works on APIv 11+ -->
- <enum name="add" value="16" />
- </attr>
-
- <!-- Tint used for the overflow button -->
- <attr name="overflowTint" format="color" />
- <!-- The blending mode used for tinting the overflow button -->
- <attr name="overflowTintMode">
- <!-- The tint is drawn on top of the drawable.
- [Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc] -->
- <enum name="src_over" value="3" />
- <!-- The tint is masked by the alpha channel of the drawable. The drawable’s
- color channels are thrown out. [Sa * Da, Sc * Da] -->
- <enum name="src_in" value="5" />
- <!-- The tint is drawn above the drawable, but with the drawable’s alpha
- channel masking the result. [Da, Sc * Da + (1 - Sa) * Dc] -->
- <enum name="src_atop" value="9" />
- <!-- Multiplies the color and alpha channels of the drawable with those of
- the tint. [Sa * Da, Sc * Dc] -->
- <enum name="multiply" value="14" />
- <!-- [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] -->
- <enum name="screen" value="15" />
- <!-- Combines the tint and drawable color and alpha channels, clamping the
- result to valid color values. Saturate(S + D). Only works on APIv 11+ -->
- <enum name="add" value="16" />
- </attr>
</declare-styleable>
<declare-styleable name="Toolbar_LayoutParams">
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 470e345..f31c1d6 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1058,18 +1058,20 @@
lockTask mode is disabled.
<p>While in lockTask mode with multiple permitted tasks running, each launched task is
permitted to finish, transitioning to the previous locked task, until there is only one
- task remaining. At that point the last task running is not permitted to finish. -->
+ task remaining. At that point the last task running is not permitted to finish, unless it
+ uses the value always. -->
<attr name="lockTaskMode">
<!-- This is the default value. Tasks will not launch into lockTask mode but can be
placed there by calling {@link android.app.Activity#startLockTask}. If a task with
this mode has been whitelisted using {@link
- android.app.admin.DevicePolicyManager#setLockTaskPackages} then calling startLockTask
- will enter lockTask mode immediately, otherwise the user will be presented with a
- dialog to approve entering lockTask mode.
+ android.app.admin.DevicePolicyManager#setLockTaskPackages} then calling
+ {@link android.app.Activity#startLockTask} will enter lockTask mode immediately,
+ otherwise the user will be presented with a dialog to approve entering pinned mode.
<p>If the system is already in lockTask mode when a new task rooted at this activity
is launched that task will or will not start depending on whether the package of this
activity has been whitelisted.
- <p>Tasks rooted at this activity can only exit lockTask mode using stopLockTask(). -->
+ <p>Tasks rooted at this activity can only exit lockTask mode using
+ {@link android.app.Activity#stopLockTask}. -->
<enum name="normal" value="0"/>
<!-- Tasks will not launch into lockTask mode and cannot be placed there using
{@link android.app.Activity#startLockTask} or be pinned from the Overview screen.
@@ -1082,16 +1084,17 @@
<!-- Tasks rooted at this activity will always launch into lockTask mode. If the system is
already in lockTask mode when this task is launched then the new task will be launched
on top of the current task. Tasks launched in this mode are capable of exiting
- lockTask mode using finish(), whereas tasks entering lockTask mode using
- startLockTask() must use stopLockTask() to exit.
+ lockTask mode using {@link android.app.Activity#finish()}.
<p>Note: This mode is only available to system and privileged applications.
Non-privileged apps with this value will be treated as normal.
-->
<enum name="always" value="2"/>
<!-- If the DevicePolicyManager (DPM) authorizes this package ({@link
android.app.admin.DevicePolicyManager#setLockTaskPackages}) then this mode is
- identical to always. If the DPM does not authorize this package then this
- mode is identical to normal. -->
+ identical to always, except that the activity needs to call
+ {@link android.app.Activity#stopLockTask} before being able to finish if it is the last
+ locked task.
+ If the DPM does not authorize this package then this mode is identical to normal. -->
<enum name="if_whitelisted" value="3"/>
</attr>
<!-- When set installer will extract native libraries. If set to false
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index bbf4005..bbe27a4 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2614,12 +2614,20 @@
<public type="attr" name="end" />
<public type="attr" name="windowLightStatusBar" />
<public type="attr" name="numbersInnerTextColor" />
- <public type="attr" name="iconTint" />
- <public type="attr" name="iconTintMode" />
- <public type="attr" name="overflowTint" />
- <public type="attr" name="overflowTintMode" />
- <public type="attr" name="navigationTint" />
- <public type="attr" name="navigationTintMode" />
+
+ <attr name="__reserved2" format="boolean" />
+ <public type="attr" name="__reserved2" />
+ <attr name="__reserved3" format="boolean" />
+ <public type="attr" name="__reserved3" />
+ <attr name="__reserved4" format="boolean" />
+ <public type="attr" name="__reserved4" />
+ <attr name="__reserved5" format="boolean" />
+ <public type="attr" name="__reserved5" />
+ <attr name="__reserved6" format="boolean" />
+ <public type="attr" name="__reserved6" />
+ <attr name="__reserved7" format="boolean" />
+ <public type="attr" name="__reserved7" />
+
<public type="attr" name="fullBackupContent" />
<public type="style" name="Widget.Material.Button.Colored" />
@@ -2690,5 +2698,5 @@
<public type="attr" name="supportsLaunchVoiceAssistFromKeyguard" />
<public type="attr" name="scrollIndicators" />
<public type="attr" name="hyphenationFrequency" />
- <public type="attr" name="fingerprintDrawable" />
+ <public type="attr" name="fingerprintAuthDrawable" />
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 2326968..675d3e2 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1302,12 +1302,6 @@
<string name="permdesc_readSyncStats">Allows an app to read the sync stats for an account, including the history of sync events and how much data is synced. </string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_subscribedFeedsWrite">write subscribed feeds</string>
- <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permdesc_subscribedFeedsWrite">Allows the app to modify
- your currently synced feeds. Malicious apps may change your synced feeds.</string>
-
- <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_readDictionary">read terms you added to the dictionary</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_readDictionary">Allows the app to read all words,
@@ -1519,10 +1513,10 @@
<string name="policylab_disableCamera">Disable cameras</string>
<!-- Description of policy access to disable all device cameras [CHAR LIMIT=110]-->
<string name="policydesc_disableCamera">Prevent use of all device cameras.</string>
- <!-- Title of policy access to disable all device cameras [CHAR LIMIT=30]-->
- <string name="policylab_disableKeyguardFeatures">Disable features of screen lock</string>
- <!-- Description of policy access to disable all device cameras [CHAR LIMIT=110]-->
- <string name="policydesc_disableKeyguardFeatures">Prevent use of some features of screen lock.</string>
+ <!-- Title of policy access to disable keyguard features [CHAR LIMIT=30]-->
+ <string name="policylab_disableKeyguardFeatures">Disable some screen lock features</string>
+ <!-- Description of policy access to disable keyguard features. [CHAR LIMIT=110]-->
+ <string name="policydesc_disableKeyguardFeatures">Prevent use of some screen lock features.</string>
<!-- The order of these is important, don't reorder without changing Contacts.java --> <skip />
<!-- Phone number types from android.provider.Contacts. This could be used when adding a new phone number for a contact, for example. -->
@@ -3028,9 +3022,14 @@
<string name="ext_media_ready_notification_message">For transferring photos and media</string>
<!-- Notification title when external media is unmountable (corrupt) [CHAR LIMIT=30] -->
- <string name="ext_media_unmountable_notification_title">Damaged <xliff:g id="name" example="SD card">%s</xliff:g></string>
+ <string name="ext_media_unmountable_notification_title">Corrupted <xliff:g id="name" example="SD card">%s</xliff:g></string>
<!-- Notification body when external media is unmountable (corrupt) [CHAR LIMIT=NONE] -->
- <string name="ext_media_unmountable_notification_message"><xliff:g id="name" example="SD card">%s</xliff:g> is damaged; try reformatting it</string>
+ <string name="ext_media_unmountable_notification_message"><xliff:g id="name" example="SD card">%s</xliff:g> is corrupt. Touch to fix.</string>
+
+ <!-- Notification title when external media is unsupported [CHAR LIMIT=30] -->
+ <string name="ext_media_unsupported_notification_title">Unsupported <xliff:g id="name" example="SD card">%s</xliff:g></string>
+ <!-- Notification body when external media is unsupported [CHAR LIMIT=NONE] -->
+ <string name="ext_media_unsupported_notification_message">This device doesn\u2019t support this <xliff:g id="name" example="SD card">%s</xliff:g>. Touch to set up in a supported format.</string>
<!-- Notification title when external media is unsafely removed [CHAR LIMIT=30] -->
<string name="ext_media_badremoval_notification_title"><xliff:g id="name" example="SD card">%s</xliff:g> unexpectedly removed</string>
@@ -3048,7 +3047,7 @@
<string name="ext_media_unmounting_notification_message">Don\'t remove</string>
<!-- Notification action to setup external media [CHAR LIMIT=20] -->
- <string name="ext_media_init_action">Setup</string>
+ <string name="ext_media_init_action">Set up</string>
<!-- Notification action to unmount external media [CHAR LIMIT=20] -->
<string name="ext_media_unmount_action">Eject</string>
<!-- Notification action to browse external media [CHAR LIMIT=20] -->
@@ -3074,6 +3073,29 @@
<!-- Notification title when moving data to external storage failed [CHAR LIMIT=64] -->
<string name="ext_media_move_failure_message">Data left at original location</string>
+ <!-- Short summary of storage media status when removed [CHAR LIMIT=32] -->
+ <string name="ext_media_status_removed">Removed</string>
+ <!-- Short summary of storage media status when unmounted [CHAR LIMIT=32] -->
+ <string name="ext_media_status_unmounted">Ejected</string>
+ <!-- Short summary of storage media status when checking [CHAR LIMIT=32] -->
+ <string name="ext_media_status_checking">Checking\u2026</string>
+ <!-- Short summary of storage media status when mounted [CHAR LIMIT=32] -->
+ <string name="ext_media_status_mounted">Ready</string>
+ <!-- Short summary of storage media status when mounted read-only [CHAR LIMIT=32] -->
+ <string name="ext_media_status_mounted_ro">Read-only</string>
+ <!-- Short summary of storage media status when removed unsafely [CHAR LIMIT=32] -->
+ <string name="ext_media_status_bad_removal">Removed unsafely</string>
+ <!-- Short summary of storage media status when unmountable [CHAR LIMIT=32] -->
+ <string name="ext_media_status_unmountable">Corrupted</string>
+ <!-- Short summary of storage media status when unsupported [CHAR LIMIT=32] -->
+ <string name="ext_media_status_unsupported">Unsupported</string>
+ <!-- Short summary of storage media status when ejecting [CHAR LIMIT=32] -->
+ <string name="ext_media_status_ejecting">Ejecting\u2026</string>
+ <!-- Short summary of storage media status when formatting [CHAR LIMIT=32] -->
+ <string name="ext_media_status_formatting">Formatting\u2026</string>
+ <!-- Short summary of storage media status when missing [CHAR LIMIT=32] -->
+ <string name="ext_media_status_missing">Not inserted</string>
+
<!-- Shown in LauncherActivity when the requested target Intent didn't return any matching Activities, leaving the list empty. -->
<string name="activity_list_empty">No matching activities found.</string>
@@ -4179,4 +4201,9 @@
notification_template_material_inbox.xml.
DO NOT TRANSLATE -->
<string name="notification_inbox_ellipsis">\u2026</string>
+
+ <!-- Label describing the number of selected items [CHAR LIMIT=48] -->
+ <plurals name="selected_count">
+ <item quantity="other"><xliff:g id="count" example="3">%1$d</xliff:g> selected</item>
+ </plurals>
</resources>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 4eba117..4bad16d 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -1017,6 +1017,10 @@ please see styles_device_defaults.xml.
<item name="negativeButtonText">@string/no</item>
</style>
+ <style name="Preference.DialogPreference.SeekBarPreference">
+ <item name="dialogLayout">@layout/preference_dialog_seekbar</item>
+ </style>
+
<style name="Preference.DialogPreference.EditTextPreference">
<item name="dialogLayout">@layout/preference_dialog_edittext</item>
</style>
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index df4106e..70f9c02 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -87,6 +87,10 @@ please see styles_device_defaults.xml.
<item name="negativeButtonText">@string/no</item>
</style>
+ <style name="Preference.Material.DialogPreference.SeekBarPreference">
+ <item name="dialogLayout">@layout/preference_dialog_seekbar_material</item>
+ </style>
+
<style name="Preference.Material.DialogPreference.EditTextPreference">
<item name="dialogLayout">@layout/preference_dialog_edittext_material</item>
</style>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 15b253d..b019adb 100755
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1341,7 +1341,6 @@
<java-symbol type="layout" name="preference_widget_seekbar" />
<java-symbol type="layout" name="progress_dialog" />
<java-symbol type="layout" name="resolve_list_item" />
- <java-symbol type="layout" name="seekbar_dialog" />
<java-symbol type="layout" name="select_dialog_singlechoice_holo" />
<java-symbol type="layout" name="ssl_certificate" />
<java-symbol type="layout" name="tab_content" />
@@ -2292,4 +2291,21 @@
<java-symbol type="string" name="config_radio_access_family" />
<java-symbol type="string" name="notification_inbox_ellipsis" />
<java-symbol type="bool" name="config_mainBuiltInDisplayIsRound" />
+
+ <java-symbol type="attr" name="seekBarDialogPreferenceStyle" />
+ <java-symbol type="string" name="ext_media_status_removed" />
+ <java-symbol type="string" name="ext_media_status_unmounted" />
+ <java-symbol type="string" name="ext_media_status_checking" />
+ <java-symbol type="string" name="ext_media_status_mounted" />
+ <java-symbol type="string" name="ext_media_status_mounted_ro" />
+ <java-symbol type="string" name="ext_media_status_bad_removal" />
+ <java-symbol type="string" name="ext_media_status_unmountable" />
+ <java-symbol type="string" name="ext_media_status_unsupported" />
+ <java-symbol type="string" name="ext_media_status_ejecting" />
+ <java-symbol type="string" name="ext_media_status_formatting" />
+ <java-symbol type="string" name="ext_media_status_missing" />
+ <java-symbol type="string" name="ext_media_unsupported_notification_message" />
+ <java-symbol type="string" name="ext_media_unsupported_notification_title" />
+ <java-symbol type="plurals" name="selected_count" />
+
</resources>
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 9e87b4d..ecf00f0 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -331,6 +331,7 @@ please see themes_device_defaults.xml.
<item name="seekBarPreferenceStyle">@style/Preference.SeekBarPreference</item>
<item name="yesNoPreferenceStyle">@style/Preference.DialogPreference.YesNoPreference</item>
<item name="dialogPreferenceStyle">@style/Preference.DialogPreference</item>
+ <item name="seekBarDialogPreferenceStyle">@style/Preference.DialogPreference.SeekBarPreference</item>
<item name="editTextPreferenceStyle">@style/Preference.DialogPreference.EditTextPreference</item>
<item name="ringtonePreferenceStyle">@style/Preference.RingtonePreference</item>
<item name="preferenceLayoutChild">@layout/preference_child</item>
@@ -386,6 +387,7 @@ please see themes_device_defaults.xml.
<item name="buttonBarNegativeButtonStyle">?attr/buttonBarButtonStyle</item>
<item name="buttonBarNeutralButtonStyle">?attr/buttonBarButtonStyle</item>
<item name="segmentedButtonStyle">@style/SegmentedButton</item>
+ <item name="fingerprintAuthDrawable">@drawable/ic_fingerprint</item>
<!-- SearchView attributes -->
<item name="searchViewStyle">@style/Widget.Holo.SearchView</item>
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index 9f3668d..295b453 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -295,6 +295,7 @@ please see themes_device_defaults.xml.
<item name="seekBarPreferenceStyle">@style/Preference.Material.SeekBarPreference</item>
<item name="yesNoPreferenceStyle">@style/Preference.Material.DialogPreference.YesNoPreference</item>
<item name="dialogPreferenceStyle">@style/Preference.Material.DialogPreference</item>
+ <item name="seekBarDialogPreferenceStyle">@style/Preference.Material.DialogPreference.SeekBarPreference</item>
<item name="editTextPreferenceStyle">@style/Preference.Material.DialogPreference.EditTextPreference</item>
<item name="ringtonePreferenceStyle">@style/Preference.Material.RingtonePreference</item>
<item name="preferenceLayoutChild">@layout/preference_child_material</item>
@@ -304,7 +305,6 @@ please see themes_device_defaults.xml.
<item name="preferenceFragmentListStyle">@style/PreferenceFragmentList.Material</item>
<item name="preferenceFragmentPaddingSide">@dimen/preference_fragment_padding_side_material</item>
<item name="detailsElementBackground">?attr/colorBackground</item>
- <item name="fingerprintDrawable">@drawable/ic_fingerprint_dark</item>
<!-- PreferenceFrameLayout attributes -->
<item name="preferenceFrameLayoutStyle">@style/Widget.Material.PreferenceFrameLayout</item>
@@ -651,6 +651,7 @@ please see themes_device_defaults.xml.
<item name="seekBarPreferenceStyle">@style/Preference.Material.SeekBarPreference</item>
<item name="yesNoPreferenceStyle">@style/Preference.Material.DialogPreference.YesNoPreference</item>
<item name="dialogPreferenceStyle">@style/Preference.Material.DialogPreference</item>
+ <item name="seekBarDialogPreferenceStyle">@style/Preference.Material.DialogPreference.SeekBarPreference</item>
<item name="editTextPreferenceStyle">@style/Preference.Material.DialogPreference.EditTextPreference</item>
<item name="ringtonePreferenceStyle">@style/Preference.Material.RingtonePreference</item>
<item name="preferenceLayoutChild">@layout/preference_child_material</item>
@@ -660,7 +661,6 @@ please see themes_device_defaults.xml.
<item name="preferenceFragmentListStyle">@style/PreferenceFragmentList.Material</item>
<item name="preferenceFragmentPaddingSide">@dimen/preference_fragment_padding_side_material</item>
<item name="detailsElementBackground">?attr/colorBackground</item>
- <item name="fingerprintDrawable">@drawable/ic_fingerprint_light</item>
<!-- PreferenceFrameLayout attributes -->
<item name="preferenceFrameLayoutStyle">@style/Widget.Material.PreferenceFrameLayout</item>
diff --git a/data/fonts/Android.mk b/data/fonts/Android.mk
index 6d8d81f..3181017 100644
--- a/data/fonts/Android.mk
+++ b/data/fonts/Android.mk
@@ -17,8 +17,8 @@
LOCAL_PATH := $(call my-dir)
-# Use full Noto Sans Japanese font on extended footprint
-ifeq ($(EXTENDED_FONT_FOOTPRINT),true)
+# Use full Noto Sans Japanese font on non-smaller footprints
+ifneq ($(SMALLER_FONT_FOOTPRINT),true)
FONT_NOTOSANS_JP_FULL := true
endif
@@ -38,7 +38,7 @@ ALL_MODULES.$(1).INSTALLED := \
endef
##########################################
-# The following fonts are distributed as symlink only.
+# The following fonts are just symlinks, for backward compatibility.
##########################################
$(eval $(call create-font-symlink,DroidSans.ttf,Roboto-Regular.ttf))
$(eval $(call create-font-symlink,DroidSans-Bold.ttf,Roboto-Bold.ttf))
@@ -54,7 +54,7 @@ extra_font_files := \
################################
# Do not include Motoya on space-constrained devices
ifneq ($(SMALLER_FONT_FOOTPRINT),true)
-# Do not include Motoya if we are including full NotoSans
+# Do not include Motoya if we are including Noto Sans Japanese
ifneq ($(FONT_NOTOSANS_JP_FULL),true)
include $(CLEAR_VARS)
@@ -82,26 +82,19 @@ include $(BUILD_PREBUILT)
extra_font_files :=
################################
-# Include DroidSansFallback only on non-EXTENDED_FONT_FOOTPRINT builds
-ifneq ($(EXTENDED_FONT_FOOTPRINT),true)
-
-# Include a subset of DroidSansFallback on SMALLER_FONT_FOOTPRINT build
+# Include the DroidSansFallback subset on SMALLER_FONT_FOOTPRINT build
ifeq ($(SMALLER_FONT_FOOTPRINT),true)
-droidsans_fallback_src := DroidSansFallback.ttf
-else # !SMALLER_FONT_FOOTPRINT
-droidsans_fallback_src := DroidSansFallbackFull.ttf
-endif # SMALLER_FONT_FOOTPRINT
include $(CLEAR_VARS)
LOCAL_MODULE := DroidSansFallback.ttf
-LOCAL_SRC_FILES := $(droidsans_fallback_src)
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
LOCAL_MODULE_CLASS := ETC
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_PATH := $(TARGET_OUT)/fonts
include $(BUILD_PREBUILT)
droidsans_fallback_src :=
-endif # !EXTENDED_FONT_FOOTPRINT
+endif # SMALLER_FONT_FOOTPRINT
################################
# Build the rest of font files as prebuilt.
diff --git a/docs/html/robots.txt b/docs/html/robots.txt
index ab379bb..f522220 100644
--- a/docs/html/robots.txt
+++ b/docs/html/robots.txt
@@ -15,5 +15,4 @@ Disallow: /shareables/
Disallow: /guide/tutorials/
Disallow: /guide/samples/
Disallow: /community/
-Disallow: /preview/
Sitemap: http://developer.android.com/sitemap.txt
diff --git a/docs/html/sdk/index.jd b/docs/html/sdk/index.jd
index bdc60a2..fed3f47 100644
--- a/docs/html/sdk/index.jd
+++ b/docs/html/sdk/index.jd
@@ -5,28 +5,28 @@ page.image=images/cards/android-studio_2x.png
header.hide=1
page.metaDescription=Download the official Android IDE and developer tools to build apps for Android phones, tablets, wearables, TVs, and more.
-studio.version=1.2.1.1
+studio.version=1.2.2.0
-studio.linux_bundle_download=android-studio-ide-141.1903250-linux.zip
-studio.linux_bundle_bytes=258634089
-studio.linux_bundle_checksum=61f576a24ac9aa00d498bb62942c028ef4a8905b
+studio.linux_bundle_download=android-studio-ide-141.1980579-linux.zip
+studio.linux_bundle_bytes=258628239
+studio.linux_bundle_checksum=1fcb226bcf71760296b07dc0db74216563ce83f7
-studio.mac_bundle_download=android-studio-ide-141.1903250-mac.dmg
-studio.mac_bundle_bytes=260877150
-studio.mac_bundle_checksum=a5a6ba50e3590de0973230a238d17726a1d9395c
+studio.mac_bundle_download=android-studio-ide-141.1980579-mac.dmg
+studio.mac_bundle_bytes=260363204
+studio.mac_bundle_checksum=811a868958f8799a1c86a3acfab0fc5dc8de2f41
-studio.win_bundle_download=android-studio-ide-141.1903250-windows.zip
-studio.win_bundle_bytes=261042465
-studio.win_bundle_checksum=ce924e0e4cff4b7f24df3f7ce0c1ce2379347d72
+studio.win_bundle_download=android-studio-ide-141.1980579-windows.zip
+studio.win_bundle_bytes=261036618
+studio.win_bundle_checksum=e61c9c27a92eff943f6bfdcdec3827199dd0c63d
-studio.win_bundle_exe_download=android-studio-bundle-141.1903250-windows.exe
-studio.win_bundle_exe_bytes=930462136
-studio.win_bundle_exe_checksum=680668b6b4a51c519efda814b96c2b61541a50f2
+studio.win_bundle_exe_download=android-studio-bundle-141.1980579-windows.exe
+studio.win_bundle_exe_bytes=930456592
+studio.win_bundle_exe_checksum=964959e5165e90aaf693e868d5d1c2f7b38e8754
-studio.win_notools_exe_download=android-studio-ide-141.1903250-windows.exe
-studio.win_notools_exe_bytes=243747312
-studio.win_notools_exe_checksum=d89917dd044e0559c87d6a05d49780ab110269f7
+studio.win_notools_exe_download=android-studio-ide-141.1980579-windows.exe
+studio.win_notools_exe_bytes=243741776
+studio.win_notools_exe_checksum=ae09797db2537afb572a00b7eacc292bb66d539e
diff --git a/docs/html/tools/revisions/studio.jd b/docs/html/tools/revisions/studio.jd
index 7138efe..b727d96 100644
--- a/docs/html/tools/revisions/studio.jd
+++ b/docs/html/tools/revisions/studio.jd
@@ -43,10 +43,24 @@ Android Studio, as denoted by revision number. </p>
<div class="toggle-content opened">
<p><a href="#" onclick="return toggleContent(this)">
<img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
+ alt=""/>Android Studio v1.2.2</a> <em>(June 2015)</em>
+ </p>
+ <div class="toggle-content-toggleme">
+ <p>Fixes and enhancements:</p>
+ <ul>
+ <li>Fixed build issues that were blocking builds from completing. </li>
+ </ul>
+ </div>
+</div>
+
+
+<div class="toggle-content closed">
+ <p><a href="#" onclick="return toggleContent(this)">
+ <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
alt=""/>Android Studio v1.2.1</a> <em>(May 2015)</em>
</p>
<div class="toggle-content-toggleme">
- <p>Various fixes and enhancements:</p>
+ <p>Fixes and enhancements:</p>
<ul>
<li>Fixed minor performance and feature issues. </li>
</ul>
@@ -62,7 +76,7 @@ Android Studio, as denoted by revision number. </p>
</p>
<div class="toggle-content-toggleme">
- <p>Various fixes and enhancements:</p>
+ <p>Fixes and enhancements:</p>
<ul>
<li>Updated the Android runtime window to include the
<a href="{@docRoot}tools/studio/index.html#mem-cpu">Memory Monitor</a> tool
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index 1af48ca..134451b 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -333,17 +333,29 @@ public class RippleDrawable extends LayerDrawable {
*/
@Override
public boolean isProjected() {
- // If the maximum radius is contained entirely within the bounds, we
- // don't need to project this ripple.
+ // If the layer is bounded, then we don't need to project.
+ if (isBounded()) {
+ return false;
+ }
+
+ // Otherwise, if the maximum radius is contained entirely within the
+ // bounds then we don't need to project. This is sort of a hack to
+ // prevent check box ripples from being projected across the edges of
+ // scroll views. It does not impact rendering performance, and it can
+ // be removed once we have better handling of projection in scrollable
+ // views.
final int radius = mState.mMaxRadius;
- final Rect bounds = getBounds();
- if (radius != RADIUS_AUTO && radius <= bounds.width() / 2
- && radius <= bounds.height() / 2) {
+ final Rect drawableBounds = getBounds();
+ final Rect hotspotBounds = mHotspotBounds;
+ if (radius != RADIUS_AUTO
+ && radius <= hotspotBounds.width() / 2
+ && radius <= hotspotBounds.height() / 2
+ && (drawableBounds.equals(hotspotBounds)
+ || drawableBounds.contains(hotspotBounds))) {
return false;
}
- // Otherwise, if the layer is bounded then we don't need to project.
- return !isBounded();
+ return true;
}
private boolean isBounded() {
diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java
index 059d8e6..f482bf0 100644
--- a/keystore/java/android/security/KeyChain.java
+++ b/keystore/java/android/security/KeyChain.java
@@ -29,15 +29,14 @@ import android.os.Looper;
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
-import android.security.keystore.KeyInfo;
+import android.security.keystore.AndroidKeyStoreProvider;
import android.security.keystore.KeyProperties;
import java.io.ByteArrayInputStream;
import java.io.Closeable;
-import java.security.InvalidKeyException;
-import java.security.KeyFactory;
import java.security.Principal;
import java.security.PrivateKey;
+import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
@@ -47,7 +46,6 @@ import java.util.Locale;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
-import com.android.org.conscrypt.OpenSSLEngine;
import com.android.org.conscrypt.TrustedCertificateStore;
/**
@@ -90,8 +88,6 @@ import com.android.org.conscrypt.TrustedCertificateStore;
// TODO reference intent for credential installation when public
public final class KeyChain {
- private static final String TAG = "KeyChain";
-
/**
* @hide Also used by KeyChainService implementation
*/
@@ -372,15 +368,14 @@ public final class KeyChain {
if (keyId == null) {
throw new KeyChainException("keystore had a problem");
}
-
- final OpenSSLEngine engine = OpenSSLEngine.getInstance("keystore");
- return engine.getPrivateKeyById(keyId);
+ return AndroidKeyStoreProvider.loadAndroidKeyStorePrivateKeyFromKeystore(
+ KeyStore.getInstance(), keyId);
} catch (RemoteException e) {
throw new KeyChainException(e);
} catch (RuntimeException e) {
// only certain RuntimeExceptions can be propagated across the IKeyChainService call
throw new KeyChainException(e);
- } catch (InvalidKeyException e) {
+ } catch (UnrecoverableKeyException e) {
throw new KeyChainException(e);
} finally {
keyChainConnection.close();
diff --git a/keystore/java/android/security/KeyPairGeneratorSpec.java b/keystore/java/android/security/KeyPairGeneratorSpec.java
index efbce41..d849317 100644
--- a/keystore/java/android/security/KeyPairGeneratorSpec.java
+++ b/keystore/java/android/security/KeyPairGeneratorSpec.java
@@ -331,7 +331,9 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec {
if (keyType == null) {
throw new NullPointerException("keyType == null");
} else {
- if (KeyStore.getKeyTypeForAlgorithm(keyType) == -1) {
+ try {
+ KeyProperties.KeyAlgorithm.toKeymasterAsymmetricKeyAlgorithm(keyType);
+ } catch (IllegalArgumentException e) {
throw new NoSuchAlgorithmException("Unsupported key type: " + keyType);
}
}
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index 893771a..35fcda6 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -19,7 +19,6 @@ package android.security;
import android.app.ActivityThread;
import android.app.Application;
import android.app.KeyguardManager;
-import com.android.org.conscrypt.NativeConstants;
import android.content.Context;
import android.hardware.fingerprint.FingerprintManager;
@@ -38,7 +37,6 @@ import android.security.keymaster.OperationResult;
import android.security.keystore.KeyExpiredException;
import android.security.keystore.KeyNotYetValidException;
import android.security.keystore.KeyPermanentlyInvalidatedException;
-import android.security.keystore.KeyProperties;
import android.security.keystore.UserNotAuthenticatedException;
import android.util.Log;
@@ -136,16 +134,6 @@ public class KeyStore {
return mToken;
}
- public static int getKeyTypeForAlgorithm(@KeyProperties.KeyAlgorithmEnum String keyType) {
- if (KeyProperties.KEY_ALGORITHM_RSA.equalsIgnoreCase(keyType)) {
- return NativeConstants.EVP_PKEY_RSA;
- } else if (KeyProperties.KEY_ALGORITHM_EC.equalsIgnoreCase(keyType)) {
- return NativeConstants.EVP_PKEY_EC;
- } else {
- return -1;
- }
- }
-
public State state(int userId) {
final int ret;
try {
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreECPrivateKey.java b/keystore/java/android/security/keystore/AndroidKeyStoreECPrivateKey.java
new file mode 100644
index 0000000..5dbcd68
--- /dev/null
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreECPrivateKey.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2015 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.security.keystore;
+
+import java.security.PrivateKey;
+import java.security.interfaces.ECKey;
+import java.security.spec.ECParameterSpec;
+
+/**
+ * EC private key (instance of {@link PrivateKey} and {@link ECKey}) backed by keystore.
+ *
+ * @hide
+ */
+public class AndroidKeyStoreECPrivateKey extends AndroidKeyStorePrivateKey implements ECKey {
+ private final ECParameterSpec mParams;
+
+ public AndroidKeyStoreECPrivateKey(String alias, ECParameterSpec params) {
+ super(alias, KeyProperties.KEY_ALGORITHM_EC);
+ mParams = params;
+ }
+
+ @Override
+ public ECParameterSpec getParams() {
+ return mParams;
+ }
+}
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKey.java b/keystore/java/android/security/keystore/AndroidKeyStoreKey.java
index 1751aa5..e76802f 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreKey.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreKey.java
@@ -52,4 +52,42 @@ public class AndroidKeyStoreKey implements Key {
// This key does not export its key material
return null;
}
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((mAlgorithm == null) ? 0 : mAlgorithm.hashCode());
+ result = prime * result + ((mAlias == null) ? 0 : mAlias.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ AndroidKeyStoreKey other = (AndroidKeyStoreKey) obj;
+ if (mAlgorithm == null) {
+ if (other.mAlgorithm != null) {
+ return false;
+ }
+ } else if (!mAlgorithm.equals(other.mAlgorithm)) {
+ return false;
+ }
+ if (mAlias == null) {
+ if (other.mAlias != null) {
+ return false;
+ }
+ } else if (!mAlias.equals(other.mAlias)) {
+ return false;
+ }
+ return true;
+ }
}
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
index 69155a8..35af34f 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
@@ -20,7 +20,6 @@ import android.annotation.Nullable;
import android.security.Credentials;
import android.security.KeyPairGeneratorSpec;
import android.security.KeyStore;
-import android.security.keymaster.ExportResult;
import android.security.keymaster.KeyCharacteristics;
import android.security.keymaster.KeymasterArguments;
import android.security.keymaster.KeymasterDefs;
@@ -44,29 +43,24 @@ import com.android.org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
import com.android.org.bouncycastle.jce.X509Principal;
import com.android.org.bouncycastle.jce.provider.X509CertificateObject;
import com.android.org.bouncycastle.x509.X509V3CertificateGenerator;
-import com.android.org.conscrypt.OpenSSLEngine;
import libcore.util.EmptyArray;
import java.math.BigInteger;
import java.security.InvalidAlgorithmParameterException;
-import java.security.InvalidKeyException;
-import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyPairGeneratorSpi;
-import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.ProviderException;
import java.security.PublicKey;
import java.security.SecureRandom;
+import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.ECGenParameterSpec;
-import java.security.spec.InvalidKeySpecException;
import java.security.spec.RSAKeyGenParameterSpec;
-import java.security.spec.X509EncodedKeySpec;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
@@ -147,6 +141,7 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
SUPPORTED_EC_NIST_CURVE_NAMES.addAll(SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.keySet());
Collections.sort(SUPPORTED_EC_NIST_CURVE_NAMES);
}
+
private final int mOriginalKeymasterAlgorithm;
private KeyStore mKeyStore;
@@ -431,24 +426,6 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
args.addInts(KeymasterDefs.KM_TAG_PADDING, mKeymasterSignaturePaddings);
args.addInts(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigests);
- // TODO: Remove the digest and padding NONE workaround below once Android Keystore returns
- // keys which are backed by AndroidKeyStoreBCWorkaround provider instead of Conscrypt. The
- // workaround is needed because Conscrypt (via keystore-engine) uses old KeyStore API which
- // translates into digest NONE and padding NONE in the new API. keystore-engine cannot be
- // updated to pass in the correct padding and digest values because it uses
- // OpenSSL/BoringSSL engine which performs digesting and padding prior before invoking
- // KeyStore API.
- if (!com.android.internal.util.ArrayUtils.contains(
- mKeymasterDigests, KeymasterDefs.KM_DIGEST_NONE)) {
- args.addInt(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_NONE);
- }
- if ((!com.android.internal.util.ArrayUtils.contains(
- mKeymasterSignaturePaddings, KeymasterDefs.KM_PAD_NONE))
- && (!com.android.internal.util.ArrayUtils.contains(
- mKeymasterEncryptionPaddings, KeymasterDefs.KM_PAD_NONE))) {
- args.addInt(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_NONE);
- }
-
KeymasterUtils.addUserAuthArgs(args,
mSpec.isUserAuthenticationRequired(),
mSpec.getUserAuthenticationValidityDurationSeconds());
@@ -483,40 +460,23 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
"Failed to generate key pair", KeyStore.getKeyStoreException(errorCode));
}
- final PrivateKey privKey;
- final OpenSSLEngine engine = OpenSSLEngine.getInstance("keystore");
+ KeyPair result;
try {
- privKey = engine.getPrivateKeyById(privateKeyAlias);
- } catch (InvalidKeyException e) {
- throw new ProviderException("Failed to obtain generated private key", e);
+ result = AndroidKeyStoreProvider.loadAndroidKeyStoreKeyPairFromKeystore(
+ mKeyStore, privateKeyAlias);
+ } catch (UnrecoverableKeyException e) {
+ throw new ProviderException("Failed to load generated key pair from keystore", e);
}
- ExportResult exportResult =
- mKeyStore.exportKey(
- privateKeyAlias, KeymasterDefs.KM_KEY_FORMAT_X509, null, null);
- if (exportResult == null) {
- throw new KeyStoreConnectException();
- } else if (exportResult.resultCode != KeyStore.NO_ERROR) {
- throw new ProviderException(
- "Failed to obtain X.509 form of generated public key",
- KeyStore.getKeyStoreException(exportResult.resultCode));
- }
- final byte[] pubKeyBytes = exportResult.exportData;
-
- final PublicKey pubKey;
- try {
- final KeyFactory keyFact = KeyFactory.getInstance(mJcaKeyAlgorithm);
- pubKey = keyFact.generatePublic(new X509EncodedKeySpec(pubKeyBytes));
- } catch (NoSuchAlgorithmException e) {
+ if (!mJcaKeyAlgorithm.equalsIgnoreCase(result.getPrivate().getAlgorithm())) {
throw new ProviderException(
- "Failed to obtain " + mJcaKeyAlgorithm + " KeyFactory", e);
- } catch (InvalidKeySpecException e) {
- throw new ProviderException("Invalid X.509 encoding of generated public key", e);
+ "Generated key pair algorithm does not match requested algorithm: "
+ + result.getPrivate().getAlgorithm() + " vs " + mJcaKeyAlgorithm);
}
final X509Certificate cert;
try {
- cert = generateSelfSignedCertificate(privKey, pubKey);
+ cert = generateSelfSignedCertificate(result.getPrivate(), result.getPublic());
} catch (Exception e) {
throw new ProviderException("Failed to generate self-signed certificate", e);
}
@@ -539,7 +499,6 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
KeyStore.getKeyStoreException(insertErrorCode));
}
- KeyPair result = new KeyPair(pubKey, privKey);
success = true;
return result;
} finally {
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java b/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java
index cb270bb..967319a 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java
@@ -16,11 +16,28 @@
package android.security.keystore;
+import android.annotation.NonNull;
import android.security.KeyStore;
+import android.security.keymaster.ExportResult;
+import android.security.keymaster.KeyCharacteristics;
+import android.security.keymaster.KeymasterDefs;
+import java.security.KeyFactory;
+import java.security.KeyPair;
+import java.security.NoSuchAlgorithmException;
import java.security.Provider;
+import java.security.ProviderException;
+import java.security.PublicKey;
import java.security.Security;
import java.security.Signature;
+import java.security.UnrecoverableKeyException;
+import java.security.interfaces.ECKey;
+import java.security.interfaces.ECPublicKey;
+import java.security.interfaces.RSAKey;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.X509EncodedKeySpec;
+import java.util.List;
import javax.crypto.Cipher;
import javax.crypto.Mac;
@@ -146,4 +163,145 @@ public class AndroidKeyStoreProvider extends Provider {
}
return ((KeyStoreCryptoOperation) spi).getOperationHandle();
}
+
+ @NonNull
+ public static AndroidKeyStorePublicKey getAndroidKeyStorePublicKey(
+ @NonNull String alias,
+ @NonNull @KeyProperties.KeyAlgorithmEnum String keyAlgorithm,
+ @NonNull byte[] x509EncodedForm) {
+ PublicKey publicKey;
+ try {
+ KeyFactory keyFactory = KeyFactory.getInstance(keyAlgorithm);
+ publicKey = keyFactory.generatePublic(new X509EncodedKeySpec(x509EncodedForm));
+ } catch (NoSuchAlgorithmException e) {
+ throw new ProviderException(
+ "Failed to obtain " + keyAlgorithm + " KeyFactory", e);
+ } catch (InvalidKeySpecException e) {
+ throw new ProviderException("Invalid X.509 encoding of public key", e);
+ }
+ if (KeyProperties.KEY_ALGORITHM_EC.equalsIgnoreCase(keyAlgorithm)) {
+ return new AndroidKeyStoreECPublicKey(alias, (ECPublicKey) publicKey);
+ } else if (KeyProperties.KEY_ALGORITHM_RSA.equalsIgnoreCase(keyAlgorithm)) {
+ return new AndroidKeyStoreRSAPublicKey(alias, (RSAPublicKey) publicKey);
+ } else {
+ throw new ProviderException("Unsupported Android Keystore public key algorithm: "
+ + keyAlgorithm);
+ }
+ }
+
+ @NonNull
+ public static AndroidKeyStorePrivateKey getAndroidKeyStorePrivateKey(
+ @NonNull AndroidKeyStorePublicKey publicKey) {
+ String keyAlgorithm = publicKey.getAlgorithm();
+ if (KeyProperties.KEY_ALGORITHM_EC.equalsIgnoreCase(keyAlgorithm)) {
+ return new AndroidKeyStoreECPrivateKey(
+ publicKey.getAlias(), ((ECKey) publicKey).getParams());
+ } else if (KeyProperties.KEY_ALGORITHM_RSA.equalsIgnoreCase(keyAlgorithm)) {
+ return new AndroidKeyStoreRSAPrivateKey(
+ publicKey.getAlias(), ((RSAKey) publicKey).getModulus());
+ } else {
+ throw new ProviderException("Unsupported Android Keystore public key algorithm: "
+ + keyAlgorithm);
+ }
+ }
+
+ @NonNull
+ public static AndroidKeyStorePublicKey loadAndroidKeyStorePublicKeyFromKeystore(
+ @NonNull KeyStore keyStore, @NonNull String privateKeyAlias)
+ throws UnrecoverableKeyException {
+ KeyCharacteristics keyCharacteristics = new KeyCharacteristics();
+ int errorCode = keyStore.getKeyCharacteristics(
+ privateKeyAlias, null, null, keyCharacteristics);
+ if (errorCode != KeyStore.NO_ERROR) {
+ throw (UnrecoverableKeyException)
+ new UnrecoverableKeyException("Failed to obtain information about private key")
+ .initCause(KeyStore.getKeyStoreException(errorCode));
+ }
+ ExportResult exportResult = keyStore.exportKey(
+ privateKeyAlias, KeymasterDefs.KM_KEY_FORMAT_X509, null, null);
+ if (exportResult.resultCode != KeyStore.NO_ERROR) {
+ throw (UnrecoverableKeyException)
+ new UnrecoverableKeyException("Failed to obtain X.509 form of public key")
+ .initCause(KeyStore.getKeyStoreException(errorCode));
+ }
+ final byte[] x509EncodedPublicKey = exportResult.exportData;
+
+ int keymasterAlgorithm = keyCharacteristics.getInt(KeymasterDefs.KM_TAG_ALGORITHM, -1);
+ if (keymasterAlgorithm == -1) {
+ throw new UnrecoverableKeyException("Key algorithm unknown");
+ }
+
+ String jcaKeyAlgorithm;
+ try {
+ jcaKeyAlgorithm = KeyProperties.KeyAlgorithm.fromKeymasterAsymmetricKeyAlgorithm(
+ keymasterAlgorithm);
+ } catch (IllegalArgumentException e) {
+ throw (UnrecoverableKeyException)
+ new UnrecoverableKeyException("Failed to load private key")
+ .initCause(e);
+ }
+
+ return AndroidKeyStoreProvider.getAndroidKeyStorePublicKey(
+ privateKeyAlias, jcaKeyAlgorithm, x509EncodedPublicKey);
+ }
+
+ @NonNull
+ public static KeyPair loadAndroidKeyStoreKeyPairFromKeystore(
+ @NonNull KeyStore keyStore, @NonNull String privateKeyAlias)
+ throws UnrecoverableKeyException {
+ AndroidKeyStorePublicKey publicKey =
+ loadAndroidKeyStorePublicKeyFromKeystore(keyStore, privateKeyAlias);
+ AndroidKeyStorePrivateKey privateKey =
+ AndroidKeyStoreProvider.getAndroidKeyStorePrivateKey(publicKey);
+ return new KeyPair(publicKey, privateKey);
+ }
+
+ @NonNull
+ public static AndroidKeyStorePrivateKey loadAndroidKeyStorePrivateKeyFromKeystore(
+ @NonNull KeyStore keyStore, @NonNull String privateKeyAlias)
+ throws UnrecoverableKeyException {
+ KeyPair keyPair = loadAndroidKeyStoreKeyPairFromKeystore(keyStore, privateKeyAlias);
+ return (AndroidKeyStorePrivateKey) keyPair.getPrivate();
+ }
+
+ @NonNull
+ public static AndroidKeyStoreSecretKey loadAndroidKeyStoreSecretKeyFromKeystore(
+ @NonNull KeyStore keyStore, @NonNull String secretKeyAlias)
+ throws UnrecoverableKeyException {
+ KeyCharacteristics keyCharacteristics = new KeyCharacteristics();
+ int errorCode = keyStore.getKeyCharacteristics(
+ secretKeyAlias, null, null, keyCharacteristics);
+ if (errorCode != KeyStore.NO_ERROR) {
+ throw (UnrecoverableKeyException)
+ new UnrecoverableKeyException("Failed to obtain information about key")
+ .initCause(KeyStore.getKeyStoreException(errorCode));
+ }
+
+ int keymasterAlgorithm = keyCharacteristics.getInt(KeymasterDefs.KM_TAG_ALGORITHM, -1);
+ if (keymasterAlgorithm == -1) {
+ throw new UnrecoverableKeyException("Key algorithm unknown");
+ }
+
+ List<Integer> keymasterDigests =
+ keyCharacteristics.getInts(KeymasterDefs.KM_TAG_DIGEST);
+ int keymasterDigest;
+ if (keymasterDigests.isEmpty()) {
+ keymasterDigest = -1;
+ } else {
+ // More than one digest can be permitted for this key. Use the first one to form the
+ // JCA key algorithm name.
+ keymasterDigest = keymasterDigests.get(0);
+ }
+
+ @KeyProperties.KeyAlgorithmEnum String keyAlgorithmString;
+ try {
+ keyAlgorithmString = KeyProperties.KeyAlgorithm.fromKeymasterSecretKeyAlgorithm(
+ keymasterAlgorithm, keymasterDigest);
+ } catch (IllegalArgumentException e) {
+ throw (UnrecoverableKeyException)
+ new UnrecoverableKeyException("Unsupported secret key type").initCause(e);
+ }
+
+ return new AndroidKeyStoreSecretKey(secretKeyAlias, keyAlgorithmString);
+ }
}
diff --git a/keystore/java/android/security/keystore/AndroidKeyStorePublicKey.java b/keystore/java/android/security/keystore/AndroidKeyStorePublicKey.java
index 8133d46..9fea30d 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStorePublicKey.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStorePublicKey.java
@@ -17,6 +17,7 @@
package android.security.keystore;
import java.security.PublicKey;
+import java.util.Arrays;
/**
* {@link PublicKey} backed by Android Keystore.
@@ -41,4 +42,30 @@ public class AndroidKeyStorePublicKey extends AndroidKeyStoreKey implements Publ
public byte[] getEncoded() {
return ArrayUtils.cloneIfNotEmpty(mEncoded);
}
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + Arrays.hashCode(mEncoded);
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!super.equals(obj)) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ AndroidKeyStorePublicKey other = (AndroidKeyStorePublicKey) obj;
+ if (!Arrays.equals(mEncoded, other.mEncoded)) {
+ return false;
+ }
+ return true;
+ }
}
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreRSAPrivateKey.java b/keystore/java/android/security/keystore/AndroidKeyStoreRSAPrivateKey.java
new file mode 100644
index 0000000..179ffd8
--- /dev/null
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreRSAPrivateKey.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2015 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.security.keystore;
+
+import java.math.BigInteger;
+import java.security.PrivateKey;
+import java.security.interfaces.RSAKey;
+
+/**
+ * RSA private key (instance of {@link PrivateKey} and {@link RSAKey}) backed by keystore.
+ *
+ * @hide
+ */
+public class AndroidKeyStoreRSAPrivateKey extends AndroidKeyStorePrivateKey implements RSAKey {
+
+ private final BigInteger mModulus;
+
+ public AndroidKeyStoreRSAPrivateKey(String alias, BigInteger modulus) {
+ super(alias, KeyProperties.KEY_ALGORITHM_RSA);
+ mModulus = modulus;
+ }
+
+ @Override
+ public BigInteger getModulus() {
+ return mModulus;
+ }
+}
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSignatureSpiBase.java b/keystore/java/android/security/keystore/AndroidKeyStoreSignatureSpiBase.java
index 4c4062f..f072ae7 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreSignatureSpiBase.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreSignatureSpiBase.java
@@ -25,7 +25,7 @@ import android.security.keymaster.KeymasterArguments;
import android.security.keymaster.KeymasterDefs;
import android.security.keymaster.OperationResult;
-import com.android.org.conscrypt.util.EmptyArray;
+import libcore.util.EmptyArray;
import java.nio.ByteBuffer;
import java.security.InvalidKeyException;
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
index c03be63..831a106 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
@@ -16,9 +16,6 @@
package android.security.keystore;
-import com.android.org.conscrypt.OpenSSLEngine;
-import com.android.org.conscrypt.OpenSSLKeyHolder;
-
import libcore.util.EmptyArray;
import android.security.Credentials;
@@ -35,7 +32,6 @@ import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyStore.Entry;
import java.security.KeyStore.PrivateKeyEntry;
@@ -45,6 +41,7 @@ import java.security.KeyStoreException;
import java.security.KeyStoreSpi;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
+import java.security.PublicKey;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
@@ -59,7 +56,6 @@ import java.util.Date;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
-import java.util.List;
import java.util.Set;
import javax.crypto.SecretKey;
@@ -92,59 +88,17 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
public Key engineGetKey(String alias, char[] password) throws NoSuchAlgorithmException,
UnrecoverableKeyException {
if (isPrivateKeyEntry(alias)) {
- final OpenSSLEngine engine = OpenSSLEngine.getInstance("keystore");
- try {
- return engine.getPrivateKeyById(Credentials.USER_PRIVATE_KEY + alias);
- } catch (InvalidKeyException e) {
- UnrecoverableKeyException t = new UnrecoverableKeyException("Can't get key");
- t.initCause(e);
- throw t;
- }
+ String privateKeyAlias = Credentials.USER_PRIVATE_KEY + alias;
+ return AndroidKeyStoreProvider.loadAndroidKeyStorePrivateKeyFromKeystore(
+ mKeyStore, privateKeyAlias);
} else if (isSecretKeyEntry(alias)) {
- KeyCharacteristics keyCharacteristics = new KeyCharacteristics();
- String keyAliasInKeystore = Credentials.USER_SECRET_KEY + alias;
- int errorCode = mKeyStore.getKeyCharacteristics(
- keyAliasInKeystore, null, null, keyCharacteristics);
- if (errorCode != KeyStore.NO_ERROR) {
- throw (UnrecoverableKeyException)
- new UnrecoverableKeyException("Failed to load information about key")
- .initCause(mKeyStore.getInvalidKeyException(alias, errorCode));
- }
-
- int keymasterAlgorithm =
- keyCharacteristics.hwEnforced.getInt(KeymasterDefs.KM_TAG_ALGORITHM, -1);
- if (keymasterAlgorithm == -1) {
- keymasterAlgorithm =
- keyCharacteristics.swEnforced.getInt(KeymasterDefs.KM_TAG_ALGORITHM, -1);
- }
- if (keymasterAlgorithm == -1) {
- throw new UnrecoverableKeyException("Key algorithm unknown");
- }
-
- List<Integer> keymasterDigests =
- keyCharacteristics.getInts(KeymasterDefs.KM_TAG_DIGEST);
- int keymasterDigest;
- if (keymasterDigests.isEmpty()) {
- keymasterDigest = -1;
- } else {
- // More than one digest can be permitted for this key. Use the first one to form the
- // JCA key algorithm name.
- keymasterDigest = keymasterDigests.get(0);
- }
-
- @KeyProperties.KeyAlgorithmEnum String keyAlgorithmString;
- try {
- keyAlgorithmString = KeyProperties.KeyAlgorithm.fromKeymasterSecretKeyAlgorithm(
- keymasterAlgorithm, keymasterDigest);
- } catch (IllegalArgumentException e) {
- throw (UnrecoverableKeyException)
- new UnrecoverableKeyException("Unsupported secret key type").initCause(e);
- }
-
- return new AndroidKeyStoreSecretKey(keyAliasInKeystore, keyAlgorithmString);
+ String secretKeyAlias = Credentials.USER_SECRET_KEY + alias;
+ return AndroidKeyStoreProvider.loadAndroidKeyStoreSecretKeyFromKeystore(
+ mKeyStore, secretKeyAlias);
+ } else {
+ // Key not found
+ return null;
}
-
- return null;
}
@Override
@@ -188,22 +142,36 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
byte[] certificate = mKeyStore.get(Credentials.USER_CERTIFICATE + alias);
if (certificate != null) {
- return toCertificate(certificate);
+ return wrapIntoKeyStoreCertificate(
+ Credentials.USER_PRIVATE_KEY + alias, toCertificate(certificate));
}
certificate = mKeyStore.get(Credentials.CA_CERTIFICATE + alias);
if (certificate != null) {
- return toCertificate(certificate);
+ return wrapIntoKeyStoreCertificate(
+ Credentials.USER_PRIVATE_KEY + alias, toCertificate(certificate));
}
return null;
}
+ /**
+ * Wraps the provided cerificate into {@link KeyStoreX509Certificate} so that the public key
+ * returned by the certificate contains information about the alias of the private key in
+ * keystore. This is needed so that Android Keystore crypto operations using public keys can
+ * find out which key alias to use. These operations cannot work without an alias.
+ */
+ private static KeyStoreX509Certificate wrapIntoKeyStoreCertificate(
+ String privateKeyAlias, X509Certificate certificate) {
+ return (certificate != null)
+ ? new KeyStoreX509Certificate(privateKeyAlias, certificate) : null;
+ }
+
private static X509Certificate toCertificate(byte[] bytes) {
try {
final CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
- return (X509Certificate) certFactory
- .generateCertificate(new ByteArrayInputStream(bytes));
+ return (X509Certificate) certFactory.generateCertificate(
+ new ByteArrayInputStream(bytes));
} catch (CertificateException e) {
Log.w(NAME, "Couldn't parse certificate in keystore", e);
return null;
@@ -214,8 +182,8 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
private static Collection<X509Certificate> toCertificates(byte[] bytes) {
try {
final CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
- return (Collection<X509Certificate>) certFactory
- .generateCertificates(new ByteArrayInputStream(bytes));
+ return (Collection<X509Certificate>) certFactory.generateCertificates(
+ new ByteArrayInputStream(bytes));
} catch (CertificateException e) {
Log.w(NAME, "Couldn't parse certificates in keystore", e);
return new ArrayList<X509Certificate>();
@@ -406,9 +374,7 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
}
final String pkeyAlias;
- if (key instanceof OpenSSLKeyHolder) {
- pkeyAlias = ((OpenSSLKeyHolder) key).getOpenSSLKey().getAlias();
- } else if (key instanceof AndroidKeyStorePrivateKey) {
+ if (key instanceof AndroidKeyStorePrivateKey) {
pkeyAlias = ((AndroidKeyStoreKey) key).getAlias();
} else {
pkeyAlias = null;
@@ -851,6 +817,19 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
if (cert == null) {
return null;
}
+ if (!"X.509".equalsIgnoreCase(cert.getType())) {
+ // Only X.509 certificates supported
+ return null;
+ }
+ byte[] targetCertBytes;
+ try {
+ targetCertBytes = cert.getEncoded();
+ } catch (CertificateEncodingException e) {
+ return null;
+ }
+ if (targetCertBytes == null) {
+ return null;
+ }
final Set<String> nonCaEntries = new HashSet<String>();
@@ -868,10 +847,9 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
continue;
}
- final Certificate c = toCertificate(certBytes);
nonCaEntries.add(alias);
- if (cert.equals(c)) {
+ if (Arrays.equals(certBytes, targetCertBytes)) {
return alias;
}
}
@@ -893,9 +871,7 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
continue;
}
- final Certificate c =
- toCertificate(mKeyStore.get(Credentials.CA_CERTIFICATE + alias));
- if (cert.equals(c)) {
+ if (Arrays.equals(certBytes, targetCertBytes)) {
return alias;
}
}
@@ -954,4 +930,25 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
}
}
+ /**
+ * {@link X509Certificate} which returns {@link AndroidKeyStorePublicKey} from
+ * {@link #getPublicKey()}. This is so that crypto operations on these public keys contain
+ * can find out which keystore private key entry to use. This is needed so that Android Keystore
+ * crypto operations using public keys can find out which key alias to use. These operations
+ * require an alias.
+ */
+ static class KeyStoreX509Certificate extends DelegatingX509Certificate {
+ private final String mPrivateKeyAlias;
+ KeyStoreX509Certificate(String privateKeyAlias, X509Certificate delegate) {
+ super(delegate);
+ mPrivateKeyAlias = privateKeyAlias;
+ }
+
+ @Override
+ public PublicKey getPublicKey() {
+ PublicKey original = super.getPublicKey();
+ return AndroidKeyStoreProvider.getAndroidKeyStorePublicKey(
+ mPrivateKeyAlias, original.getAlgorithm(), original.getEncoded());
+ }
+ }
}
diff --git a/keystore/java/android/security/keystore/DelegatingX509Certificate.java b/keystore/java/android/security/keystore/DelegatingX509Certificate.java
new file mode 100644
index 0000000..03d202f
--- /dev/null
+++ b/keystore/java/android/security/keystore/DelegatingX509Certificate.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2015 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.security.keystore;
+
+import java.math.BigInteger;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.Principal;
+import java.security.PublicKey;
+import java.security.SignatureException;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateExpiredException;
+import java.security.cert.CertificateNotYetValidException;
+import java.security.cert.CertificateParsingException;
+import java.security.cert.X509Certificate;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+
+import javax.security.auth.x500.X500Principal;
+
+class DelegatingX509Certificate extends X509Certificate {
+ private final X509Certificate mDelegate;
+
+ DelegatingX509Certificate(X509Certificate delegate) {
+ mDelegate = delegate;
+ }
+
+ @Override
+ public Set<String> getCriticalExtensionOIDs() {
+ return mDelegate.getCriticalExtensionOIDs();
+ }
+
+ @Override
+ public byte[] getExtensionValue(String oid) {
+ return mDelegate.getExtensionValue(oid);
+ }
+
+ @Override
+ public Set<String> getNonCriticalExtensionOIDs() {
+ return mDelegate.getNonCriticalExtensionOIDs();
+ }
+
+ @Override
+ public boolean hasUnsupportedCriticalExtension() {
+ return mDelegate.hasUnsupportedCriticalExtension();
+ }
+
+ @Override
+ public void checkValidity() throws CertificateExpiredException,
+ CertificateNotYetValidException {
+ mDelegate.checkValidity();
+ }
+
+ @Override
+ public void checkValidity(Date date) throws CertificateExpiredException,
+ CertificateNotYetValidException {
+ mDelegate.checkValidity(date);
+ }
+
+ @Override
+ public int getBasicConstraints() {
+ return mDelegate.getBasicConstraints();
+ }
+
+ @Override
+ public Principal getIssuerDN() {
+ return mDelegate.getIssuerDN();
+ }
+
+ @Override
+ public boolean[] getIssuerUniqueID() {
+ return mDelegate.getIssuerUniqueID();
+ }
+
+ @Override
+ public boolean[] getKeyUsage() {
+ return mDelegate.getKeyUsage();
+ }
+
+ @Override
+ public Date getNotAfter() {
+ return mDelegate.getNotAfter();
+ }
+
+ @Override
+ public Date getNotBefore() {
+ return mDelegate.getNotBefore();
+ }
+
+ @Override
+ public BigInteger getSerialNumber() {
+ return mDelegate.getSerialNumber();
+ }
+
+ @Override
+ public String getSigAlgName() {
+ return mDelegate.getSigAlgName();
+ }
+
+ @Override
+ public String getSigAlgOID() {
+ return mDelegate.getSigAlgOID();
+ }
+
+ @Override
+ public byte[] getSigAlgParams() {
+ return mDelegate.getSigAlgParams();
+ }
+
+ @Override
+ public byte[] getSignature() {
+ return mDelegate.getSignature();
+ }
+
+ @Override
+ public Principal getSubjectDN() {
+ return mDelegate.getSubjectDN();
+ }
+
+ @Override
+ public boolean[] getSubjectUniqueID() {
+ return mDelegate.getSubjectUniqueID();
+ }
+
+ @Override
+ public byte[] getTBSCertificate() throws CertificateEncodingException {
+ return mDelegate.getTBSCertificate();
+ }
+
+ @Override
+ public int getVersion() {
+ return mDelegate.getVersion();
+ }
+
+ @Override
+ public byte[] getEncoded() throws CertificateEncodingException {
+ return mDelegate.getEncoded();
+ }
+
+ @Override
+ public PublicKey getPublicKey() {
+ return mDelegate.getPublicKey();
+ }
+
+ @Override
+ public String toString() {
+ return mDelegate.toString();
+ }
+
+ @Override
+ public void verify(PublicKey key)
+ throws CertificateException,
+ NoSuchAlgorithmException,
+ InvalidKeyException,
+ NoSuchProviderException,
+ SignatureException {
+ mDelegate.verify(key);
+ }
+
+ @Override
+ public void verify(PublicKey key, String sigProvider)
+ throws CertificateException,
+ NoSuchAlgorithmException,
+ InvalidKeyException,
+ NoSuchProviderException,
+ SignatureException {
+ mDelegate.verify(key, sigProvider);
+ }
+
+ @Override
+ public List<String> getExtendedKeyUsage() throws CertificateParsingException {
+ return mDelegate.getExtendedKeyUsage();
+ }
+
+ @Override
+ public Collection<List<?>> getIssuerAlternativeNames() throws CertificateParsingException {
+ return mDelegate.getIssuerAlternativeNames();
+ }
+
+ @Override
+ public X500Principal getIssuerX500Principal() {
+ return mDelegate.getIssuerX500Principal();
+ }
+
+ @Override
+ public Collection<List<?>> getSubjectAlternativeNames() throws CertificateParsingException {
+ return mDelegate.getSubjectAlternativeNames();
+ }
+
+ @Override
+ public X500Principal getSubjectX500Principal() {
+ return mDelegate.getSubjectX500Principal();
+ }
+}
diff --git a/keystore/tests/src/android/security/KeyStoreTest.java b/keystore/tests/src/android/security/KeyStoreTest.java
index 44fb826..0b60c62 100644
--- a/keystore/tests/src/android/security/KeyStoreTest.java
+++ b/keystore/tests/src/android/security/KeyStoreTest.java
@@ -20,7 +20,6 @@ import android.app.Activity;
import android.os.Binder;
import android.os.IBinder;
import android.os.Process;
-import android.os.ServiceManager;
import android.security.keymaster.ExportResult;
import android.security.keymaster.KeyCharacteristics;
import android.security.keymaster.KeymasterArguments;
@@ -34,13 +33,9 @@ import android.test.suitebuilder.annotation.MediumTest;
import com.android.org.conscrypt.NativeConstants;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
-import java.util.Date;
import java.util.HashSet;
import java.security.spec.RSAKeyGenParameterSpec;
-import android.util.Log;
-import android.util.Base64;
-
/**
* Junit / Instrumentation test case for KeyStore class
*
diff --git a/keystore/tests/src/android/security/keystore/AndroidKeyPairGeneratorTest.java b/keystore/tests/src/android/security/keystore/AndroidKeyPairGeneratorTest.java
index 8488acd..e5c15c5 100644
--- a/keystore/tests/src/android/security/keystore/AndroidKeyPairGeneratorTest.java
+++ b/keystore/tests/src/android/security/keystore/AndroidKeyPairGeneratorTest.java
@@ -26,17 +26,21 @@ import android.test.AndroidTestCase;
import java.io.ByteArrayInputStream;
import java.math.BigInteger;
import java.security.KeyPair;
+import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
+import java.security.interfaces.ECKey;
import java.security.interfaces.ECPublicKey;
+import java.security.interfaces.RSAKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.RSAKeyGenParameterSpec;
import java.text.SimpleDateFormat;
+import java.util.Arrays;
import java.util.Date;
import javax.security.auth.x500.X500Principal;
@@ -158,6 +162,26 @@ public class AndroidKeyPairGeneratorTest extends AndroidTestCase {
}
public void testKeyPairGenerator_GenerateKeyPair_EC_Unencrypted_Success() throws Exception {
+ KeyPairGenerator generator = KeyPairGenerator.getInstance("EC", "AndroidKeyStore");
+ generator.initialize(new KeyGenParameterSpec.Builder(
+ TEST_ALIAS_1,
+ KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY)
+ .setCertificateSubject(TEST_DN_1)
+ .setCertificateSerialNumber(TEST_SERIAL_1)
+ .setCertificateNotBefore(NOW)
+ .setCertificateNotAfter(NOW_PLUS_10_YEARS)
+ .setDigests(KeyProperties.DIGEST_SHA256)
+ .build());
+
+ final KeyPair pair = generator.generateKeyPair();
+ assertNotNull("The KeyPair returned should not be null", pair);
+
+ assertKeyPairCorrect(pair, TEST_ALIAS_1, "EC", 256, null, TEST_DN_1, TEST_SERIAL_1, NOW,
+ NOW_PLUS_10_YEARS);
+ }
+
+ public void testKeyPairGenerator_Legacy_GenerateKeyPair_EC_Unencrypted_Success()
+ throws Exception {
mGenerator.initialize(new KeyPairGeneratorSpec.Builder(getContext())
.setAlias(TEST_ALIAS_1)
.setKeyType("EC")
@@ -328,19 +352,40 @@ public class AndroidKeyPairGeneratorTest extends AndroidTestCase {
assertNotNull("The PrivateKey for the KeyPair should be not null", privKey);
assertEquals(keyType, privKey.getAlgorithm());
+ if ("EC".equalsIgnoreCase(keyType)) {
+ assertTrue("EC private key must be instanceof ECKey: " + privKey.getClass().getName(),
+ privKey instanceof ECKey);
+ assertEquals("Private and public key must have the same EC parameters",
+ ((ECKey) pubKey).getParams(), ((ECKey) privKey).getParams());
+ } else if ("RSA".equalsIgnoreCase(keyType)) {
+ assertTrue("RSA private key must be instance of RSAKey: "
+ + privKey.getClass().getName(),
+ privKey instanceof RSAKey);
+ assertEquals("Private and public key must have the same RSA modulus",
+ ((RSAKey) pubKey).getModulus(), ((RSAKey) privKey).getModulus());
+ }
+
final byte[] userCertBytes = mAndroidKeyStore.get(Credentials.USER_CERTIFICATE + alias);
assertNotNull("The user certificate should exist for the generated entry", userCertBytes);
final CertificateFactory cf = CertificateFactory.getInstance("X.509");
- final Certificate userCert = cf
- .generateCertificate(new ByteArrayInputStream(userCertBytes));
+ final Certificate userCert =
+ cf.generateCertificate(new ByteArrayInputStream(userCertBytes));
assertTrue("Certificate should be in X.509 format", userCert instanceof X509Certificate);
final X509Certificate x509userCert = (X509Certificate) userCert;
+ assertEquals(
+ "Public key used to sign certificate should have the same algorithm as in KeyPair",
+ pubKey.getAlgorithm(), x509userCert.getPublicKey().getAlgorithm());
+
assertEquals("PublicKey used to sign certificate should match one returned in KeyPair",
- pubKey, x509userCert.getPublicKey());
+ pubKey,
+ AndroidKeyStoreProvider.getAndroidKeyStorePublicKey(
+ Credentials.USER_PRIVATE_KEY + alias,
+ x509userCert.getPublicKey().getAlgorithm(),
+ x509userCert.getPublicKey().getEncoded()));
assertEquals("The Subject DN should be the one passed into the params", dn,
x509userCert.getSubjectDN());
@@ -357,7 +402,10 @@ public class AndroidKeyPairGeneratorTest extends AndroidTestCase {
assertDateEquals("The notAfter date should be the one passed into the params", end,
x509userCert.getNotAfter());
+ // Assert that the cert's signature verifies using the public key from generated KeyPair
x509userCert.verify(pubKey);
+ // Assert that the cert's signature verifies using the public key from the cert itself.
+ x509userCert.verify(x509userCert.getPublicKey());
final byte[] caCerts = mAndroidKeyStore.get(Credentials.CA_CERTIFICATE + alias);
assertNull("A list of CA certificates should not exist for the generated entry", caCerts);
@@ -368,6 +416,8 @@ public class AndroidKeyPairGeneratorTest extends AndroidTestCase {
final byte[] pubKeyBytes = exportResult.exportData;
assertNotNull("The keystore should return the public key for the generated key",
pubKeyBytes);
+ assertTrue("Public key X.509 format should be as expected",
+ Arrays.equals(pubKey.getEncoded(), pubKeyBytes));
}
private static void assertDateEquals(String message, Date date1, Date date2) throws Exception {
diff --git a/keystore/tests/src/android/security/keystore/AndroidKeyStoreTest.java b/keystore/tests/src/android/security/keystore/AndroidKeyStoreTest.java
index 336fa40..c3b731b 100644
--- a/keystore/tests/src/android/security/keystore/AndroidKeyStoreTest.java
+++ b/keystore/tests/src/android/security/keystore/AndroidKeyStoreTest.java
@@ -19,38 +19,31 @@ package android.security.keystore;
import com.android.org.bouncycastle.x509.X509V3CertificateGenerator;
import com.android.org.conscrypt.NativeConstants;
-import com.android.org.conscrypt.OpenSSLEngine;
import android.security.Credentials;
import android.security.KeyStore;
import android.security.KeyStoreParameter;
-import android.security.keymaster.ExportResult;
-import android.security.keymaster.KeymasterDefs;
import android.test.AndroidTestCase;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.math.BigInteger;
-import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyFactory;
+import java.security.KeyPair;
import java.security.KeyStore.Entry;
import java.security.KeyStore.PrivateKeyEntry;
import java.security.KeyStore.TrustedCertificateEntry;
import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
-import java.security.interfaces.ECPrivateKey;
-import java.security.interfaces.ECPublicKey;
-import java.security.interfaces.RSAPrivateKey;
-import java.security.spec.InvalidKeySpecException;
+import java.security.interfaces.ECKey;
+import java.security.interfaces.RSAKey;
import java.security.spec.PKCS8EncodedKeySpec;
-import java.security.spec.X509EncodedKeySpec;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
@@ -1203,14 +1196,14 @@ public class AndroidKeyStoreTest extends AndroidTestCase {
private void assertPrivateKeyEntryEquals(PrivateKeyEntry keyEntry, PrivateKey expectedKey,
Certificate expectedCert, Collection<Certificate> expectedChain) throws Exception {
- if (expectedKey instanceof ECPrivateKey) {
+ if (expectedKey instanceof ECKey) {
assertEquals("Returned PrivateKey should be what we inserted",
- ((ECPrivateKey) expectedKey).getParams().getCurve(),
- ((ECPublicKey) keyEntry.getCertificate().getPublicKey()).getParams().getCurve());
- } else if (expectedKey instanceof RSAPrivateKey) {
+ ((ECKey) expectedKey).getParams().getCurve(),
+ ((ECKey) keyEntry.getCertificate().getPublicKey()).getParams().getCurve());
+ } else if (expectedKey instanceof RSAKey) {
assertEquals("Returned PrivateKey should be what we inserted",
- ((RSAPrivateKey) expectedKey).getModulus(),
- ((RSAPrivateKey) keyEntry.getPrivateKey()).getModulus());
+ ((RSAKey) expectedKey).getModulus(),
+ ((RSAKey) keyEntry.getPrivateKey()).getModulus());
}
assertEquals("Returned Certificate should be what we inserted", expectedCert,
@@ -1263,15 +1256,14 @@ public class AndroidKeyStoreTest extends AndroidTestCase {
Key key = mKeyStore.getKey(TEST_ALIAS_1, null);
assertNotNull("Key should exist", key);
- assertTrue("Should be a RSAPrivateKey", key instanceof RSAPrivateKey);
-
- RSAPrivateKey actualKey = (RSAPrivateKey) key;
+ assertTrue("Should be a PrivateKey", key instanceof PrivateKey);
+ assertTrue("Should be a RSAKey", key instanceof RSAKey);
KeyFactory keyFact = KeyFactory.getInstance("RSA");
PrivateKey expectedKey = keyFact.generatePrivate(new PKCS8EncodedKeySpec(FAKE_RSA_KEY_1));
assertEquals("Inserted key should be same as retrieved key",
- ((RSAPrivateKey) expectedKey).getModulus(), actualKey.getModulus());
+ ((RSAKey) expectedKey).getModulus(), ((RSAKey) key).getModulus());
}
public void testKeyStore_GetKey_NoPassword_Unencrypted_Success() throws Exception {
@@ -1287,15 +1279,14 @@ public class AndroidKeyStoreTest extends AndroidTestCase {
Key key = mKeyStore.getKey(TEST_ALIAS_1, null);
assertNotNull("Key should exist", key);
- assertTrue("Should be a RSAPrivateKey", key instanceof RSAPrivateKey);
-
- RSAPrivateKey actualKey = (RSAPrivateKey) key;
+ assertTrue("Should be a PrivateKey", key instanceof PrivateKey);
+ assertTrue("Should be a RSAKey", key instanceof RSAKey);
KeyFactory keyFact = KeyFactory.getInstance("RSA");
PrivateKey expectedKey = keyFact.generatePrivate(new PKCS8EncodedKeySpec(FAKE_RSA_KEY_1));
assertEquals("Inserted key should be same as retrieved key",
- ((RSAPrivateKey) expectedKey).getModulus(), actualKey.getModulus());
+ ((RSAKey) expectedKey).getModulus(), ((RSAKey) key).getModulus());
}
public void testKeyStore_GetKey_Certificate_Encrypted_Failure() throws Exception {
@@ -1926,31 +1917,11 @@ public class AndroidKeyStoreTest extends AndroidTestCase {
Date notAfter) throws Exception {
final String privateKeyAlias = Credentials.USER_PRIVATE_KEY + alias;
- final PrivateKey privKey;
- final OpenSSLEngine engine = OpenSSLEngine.getInstance("keystore");
- try {
- privKey = engine.getPrivateKeyById(privateKeyAlias);
- } catch (InvalidKeyException e) {
- throw new RuntimeException("Can't get key", e);
- }
-
- ExportResult exportResult =
- keyStore.exportKey(privateKeyAlias, KeymasterDefs.KM_KEY_FORMAT_X509, null, null);
- assertEquals(KeyStore.NO_ERROR, exportResult.resultCode);
- final byte[] pubKeyBytes = exportResult.exportData;
-
- final PublicKey pubKey;
- try {
- final KeyFactory keyFact = KeyFactory.getInstance("RSA");
- pubKey = keyFact.generatePublic(new X509EncodedKeySpec(pubKeyBytes));
- } catch (NoSuchAlgorithmException e) {
- throw new IllegalStateException("Can't instantiate RSA key generator", e);
- } catch (InvalidKeySpecException e) {
- throw new IllegalStateException("keystore returned invalid key encoding", e);
- }
+ KeyPair keyPair = AndroidKeyStoreProvider.loadAndroidKeyStoreKeyPairFromKeystore(
+ keyStore, privateKeyAlias);
final X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
- certGen.setPublicKey(pubKey);
+ certGen.setPublicKey(keyPair.getPublic());
certGen.setSerialNumber(serialNumber);
certGen.setSubjectDN(subjectDN);
certGen.setIssuerDN(subjectDN);
@@ -1958,7 +1929,7 @@ public class AndroidKeyStoreTest extends AndroidTestCase {
certGen.setNotAfter(notAfter);
certGen.setSignatureAlgorithm("sha1WithRSA");
- final X509Certificate cert = certGen.generate(privKey);
+ final X509Certificate cert = certGen.generate(keyPair.getPrivate());
return cert;
}
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 89d419a..6c26220 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -1382,7 +1382,7 @@ public final class MediaCodecInfo {
// upper limit.
// for now we are keeping the profile specific "width/height
// in macroblocks" limits.
- if (Integer.valueOf(1).equals(map.get("feature-can-swap-width-height"))) {
+ if (map.containsKey("feature-can-swap-width-height")) {
if (widths != null) {
mSmallerDimensionUpperLimit =
Math.min(widths.getUpper(), heights.getUpper());
diff --git a/media/java/android/media/SoundPool.java b/media/java/android/media/SoundPool.java
index 64863c2..1355635 100644
--- a/media/java/android/media/SoundPool.java
+++ b/media/java/android/media/SoundPool.java
@@ -35,6 +35,7 @@ import android.os.ServiceManager;
import android.util.AndroidRuntimeException;
import android.util.Log;
+import com.android.internal.app.IAppOpsCallback;
import com.android.internal.app.IAppOpsService;
@@ -125,10 +126,12 @@ public class SoundPool {
private EventHandler mEventHandler;
private SoundPool.OnLoadCompleteListener mOnLoadCompleteListener;
+ private boolean mHasAppOpsPlayAudio;
private final Object mLock;
private final AudioAttributes mAttributes;
private final IAppOpsService mAppOps;
+ private final IAppOpsCallback mAppOpsCallback;
/**
* Constructor. Constructs a SoundPool object with the following
@@ -159,6 +162,24 @@ public class SoundPool {
mAttributes = attributes;
IBinder b = ServiceManager.getService(Context.APP_OPS_SERVICE);
mAppOps = IAppOpsService.Stub.asInterface(b);
+ // initialize mHasAppOpsPlayAudio
+ updateAppOpsPlayAudio();
+ // register a callback to monitor whether the OP_PLAY_AUDIO is still allowed
+ mAppOpsCallback = new IAppOpsCallback.Stub() {
+ public void opChanged(int op, String packageName) {
+ synchronized (mLock) {
+ if (op == AppOpsManager.OP_PLAY_AUDIO) {
+ updateAppOpsPlayAudio();
+ }
+ }
+ }
+ };
+ try {
+ mAppOps.startWatchingMode(AppOpsManager.OP_PLAY_AUDIO,
+ ActivityThread.currentPackageName(), mAppOpsCallback);
+ } catch (RemoteException e) {
+ mHasAppOpsPlayAudio = false;
+ }
}
/**
@@ -168,7 +189,16 @@ public class SoundPool {
* object. The SoundPool can no longer be used and the reference
* should be set to null.
*/
- public native final void release();
+ public final void release() {
+ try {
+ mAppOps.stopWatchingMode(mAppOpsCallback);
+ } catch (RemoteException e) {
+ // nothing to do here, the SoundPool is being released anyway
+ }
+ native_release();
+ }
+
+ private native final void native_release();
protected void finalize() { release(); }
@@ -466,13 +496,17 @@ public class SoundPool {
if ((mAttributes.getAllFlags() & AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY) != 0) {
return false;
}
+ return !mHasAppOpsPlayAudio;
+ }
+
+ private void updateAppOpsPlayAudio() {
try {
final int mode = mAppOps.checkAudioOperation(AppOpsManager.OP_PLAY_AUDIO,
mAttributes.getUsage(),
Process.myUid(), ActivityThread.currentPackageName());
- return mode != AppOpsManager.MODE_ALLOWED;
+ mHasAppOpsPlayAudio = (mode == AppOpsManager.MODE_ALLOWED);
} catch (RemoteException e) {
- return false;
+ mHasAppOpsPlayAudio = false;
}
}
diff --git a/media/java/android/media/browse/MediaBrowser.java b/media/java/android/media/browse/MediaBrowser.java
index ef8d169..ba867e1 100644
--- a/media/java/android/media/browse/MediaBrowser.java
+++ b/media/java/android/media/browse/MediaBrowser.java
@@ -375,7 +375,7 @@ public final class MediaBrowser {
* @param mediaId The id of the item to retrieve.
* @param cb The callback to receive the result on.
*/
- public void getMediaItem(@NonNull String mediaId, @NonNull final MediaItemCallback cb) {
+ public void getItem(final @NonNull String mediaId, @NonNull final ItemCallback cb) {
if (TextUtils.isEmpty(mediaId)) {
throw new IllegalArgumentException("mediaId is empty.");
}
@@ -387,7 +387,7 @@ public final class MediaBrowser {
mHandler.post(new Runnable() {
@Override
public void run() {
- cb.onError();
+ cb.onError(mediaId);
}
});
return;
@@ -397,15 +397,15 @@ public final class MediaBrowser {
protected void onReceiveResult(int resultCode, Bundle resultData) {
if (resultCode != 0 || resultData == null
|| !resultData.containsKey(MediaBrowserService.KEY_MEDIA_ITEM)) {
- cb.onError();
+ cb.onError(mediaId);
return;
}
Parcelable item = resultData.getParcelable(MediaBrowserService.KEY_MEDIA_ITEM);
if (!(item instanceof MediaItem)) {
- cb.onError();
+ cb.onError(mediaId);
+ return;
}
- cb.onMediaItemLoaded((MediaItem) resultData.getParcelable(
- MediaBrowserService.KEY_MEDIA_ITEM));
+ cb.onItemLoaded((MediaItem)item);
}
};
try {
@@ -415,7 +415,7 @@ public final class MediaBrowser {
mHandler.post(new Runnable() {
@Override
public void run() {
- cb.onError();
+ cb.onError(mediaId);
}
});
}
@@ -728,6 +728,9 @@ public final class MediaBrowser {
public static abstract class SubscriptionCallback {
/**
* Called when the list of children is loaded or updated.
+ *
+ * @param parentId The media id of the parent media item.
+ * @param children The children which were loaded.
*/
public void onChildrenLoaded(@NonNull String parentId,
@NonNull List<MediaItem> children) {
@@ -739,29 +742,32 @@ public final class MediaBrowser {
* If this is called, the subscription remains until {@link MediaBrowser#unsubscribe}
* called, because some errors may heal themselves.
* </p>
+ *
+ * @param parentId The media id of the parent media item whose children could
+ * not be loaded.
*/
- public void onError(@NonNull String id) {
+ public void onError(@NonNull String parentId) {
}
}
/**
- * Callback for receiving the result of {@link #getMediaItem}.
+ * Callback for receiving the result of {@link #getItem}.
*/
- public static abstract class MediaItemCallback {
-
+ public static abstract class ItemCallback {
/**
* Called when the item has been returned by the browser service.
*
* @param item The item that was returned or null if it doesn't exist.
*/
- public void onMediaItemLoaded(MediaItem item) {
+ public void onItemLoaded(MediaItem item) {
}
/**
- * Called when the id doesn't exist or there was an error retrieving the
- * item.
+ * Called when the item doesn't exist or there was an error retrieving it.
+ *
+ * @param itemId The media id of the media item which could not be loaded.
*/
- public void onError() {
+ public void onError(@NonNull String itemId) {
}
}
diff --git a/media/java/android/media/tv/TvInputInfo.java b/media/java/android/media/tv/TvInputInfo.java
index c537dd6..5d1aa14 100644
--- a/media/java/android/media/tv/TvInputInfo.java
+++ b/media/java/android/media/tv/TvInputInfo.java
@@ -29,6 +29,7 @@ import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
import android.hardware.hdmi.HdmiDeviceInfo;
import android.net.Uri;
import android.os.Parcel;
@@ -125,7 +126,9 @@ public final class TvInputInfo implements Parcelable {
private String mSettingsActivity;
private HdmiDeviceInfo mHdmiDeviceInfo;
+ private int mLabelRes;
private String mLabel;
+ private Icon mIcon;
private Uri mIconUri;
private boolean mIsConnectedToHdmiSwitch;
@@ -155,7 +158,7 @@ public final class TvInputInfo implements Parcelable {
throws XmlPullParserException, IOException {
return createTvInputInfo(context, service, generateInputIdForComponentName(
new ComponentName(service.serviceInfo.packageName, service.serviceInfo.name)),
- null, TYPE_TUNER, false, null, null, false);
+ null, TYPE_TUNER, false, 0, null, null, null, false);
}
/**
@@ -165,11 +168,11 @@ public final class TvInputInfo implements Parcelable {
* @param service The ResolveInfo returned from the package manager about this TV input service.
* @param hdmiDeviceInfo The HdmiDeviceInfo for a HDMI CEC logical device.
* @param parentId The ID of this TV input's parent input. {@code null} if none exists.
+ * @param label The label of this TvInputInfo. If it is {@code null} or empty, {@code service}
+ * label will be loaded.
* @param iconUri The {@link android.net.Uri} to load the icon image. See
* {@link android.content.ContentResolver#openInputStream}. If it is {@code null},
* the application icon of {@code service} will be loaded.
- * @param label The label of this TvInputInfo. If it is {@code null} or empty, {@code service}
- * label will be loaded.
* @hide
*/
@SystemApi
@@ -179,7 +182,34 @@ public final class TvInputInfo implements Parcelable {
boolean isConnectedToHdmiSwitch = (hdmiDeviceInfo.getPhysicalAddress() & 0x0FFF) != 0;
TvInputInfo input = createTvInputInfo(context, service, generateInputIdForHdmiDevice(
new ComponentName(service.serviceInfo.packageName, service.serviceInfo.name),
- hdmiDeviceInfo), parentId, TYPE_HDMI, true, label, iconUri, isConnectedToHdmiSwitch);
+ hdmiDeviceInfo), parentId, TYPE_HDMI, true, 0, label, null, iconUri,
+ isConnectedToHdmiSwitch);
+ input.mHdmiDeviceInfo = hdmiDeviceInfo;
+ return input;
+ }
+
+ /**
+ * Create a new instance of the TvInputInfo class, instantiating it from the given Context,
+ * ResolveInfo, and HdmiDeviceInfo.
+ *
+ * @param service The ResolveInfo returned from the package manager about this TV input service.
+ * @param hdmiDeviceInfo The HdmiDeviceInfo for a HDMI CEC logical device.
+ * @param parentId The ID of this TV input's parent input. {@code null} if none exists.
+ * @param labelRes The label resource ID of this TvInputInfo. If it is {@code 0},
+ * {@code service} label will be loaded.
+ * @param icon The {@link android.graphics.drawable.Icon} to load the icon image. If it is
+ * {@code null}, the application icon of {@code service} will be loaded.
+ * @hide
+ */
+ @SystemApi
+ public static TvInputInfo createTvInputInfo(Context context, ResolveInfo service,
+ HdmiDeviceInfo hdmiDeviceInfo, String parentId, int labelRes, Icon icon)
+ throws XmlPullParserException, IOException {
+ boolean isConnectedToHdmiSwitch = (hdmiDeviceInfo.getPhysicalAddress() & 0x0FFF) != 0;
+ TvInputInfo input = createTvInputInfo(context, service, generateInputIdForHdmiDevice(
+ new ComponentName(service.serviceInfo.packageName, service.serviceInfo.name),
+ hdmiDeviceInfo), parentId, TYPE_HDMI, true, labelRes, null, icon, null,
+ isConnectedToHdmiSwitch);
input.mHdmiDeviceInfo = hdmiDeviceInfo;
return input;
}
@@ -190,11 +220,11 @@ public final class TvInputInfo implements Parcelable {
*
* @param service The ResolveInfo returned from the package manager about this TV input service.
* @param hardwareInfo The TvInputHardwareInfo for a TV input hardware device.
+ * @param label The label of this TvInputInfo. If it is {@code null} or empty, {@code service}
+ * label will be loaded.
* @param iconUri The {@link android.net.Uri} to load the icon image. See
* {@link android.content.ContentResolver#openInputStream}. If it is {@code null},
* the application icon of {@code service} will be loaded.
- * @param label The label of this TvInputInfo. If it is {@code null} or empty, {@code service}
- * label will be loaded.
* @hide
*/
@SystemApi
@@ -204,12 +234,34 @@ public final class TvInputInfo implements Parcelable {
int inputType = sHardwareTypeToTvInputType.get(hardwareInfo.getType(), TYPE_TUNER);
return createTvInputInfo(context, service, generateInputIdForHardware(
new ComponentName(service.serviceInfo.packageName, service.serviceInfo.name),
- hardwareInfo), null, inputType, true, label, iconUri, false);
+ hardwareInfo), null, inputType, true, 0, label, null, iconUri, false);
+ }
+
+ /**
+ * Create a new instance of the TvInputInfo class, instantiating it from the given Context,
+ * ResolveInfo, and TvInputHardwareInfo.
+ *
+ * @param service The ResolveInfo returned from the package manager about this TV input service.
+ * @param hardwareInfo The TvInputHardwareInfo for a TV input hardware device.
+ * @param labelRes The label resource ID of this TvInputInfo. If it is {@code 0},
+ * {@code service} label will be loaded.
+ * @param icon The {@link android.graphics.drawable.Icon} to load the icon image. If it is
+ * {@code null}, the application icon of {@code service} will be loaded.
+ * @hide
+ */
+ @SystemApi
+ public static TvInputInfo createTvInputInfo(Context context, ResolveInfo service,
+ TvInputHardwareInfo hardwareInfo, int labelRes, Icon icon)
+ throws XmlPullParserException, IOException {
+ int inputType = sHardwareTypeToTvInputType.get(hardwareInfo.getType(), TYPE_TUNER);
+ return createTvInputInfo(context, service, generateInputIdForHardware(
+ new ComponentName(service.serviceInfo.packageName, service.serviceInfo.name),
+ hardwareInfo), null, inputType, true, labelRes, null, icon, null, false);
}
- private static TvInputInfo createTvInputInfo(Context context, ResolveInfo service,
- String id, String parentId, int inputType, boolean isHardwareInput, String label,
- Uri iconUri, boolean isConnectedToHdmiSwitch)
+ private static TvInputInfo createTvInputInfo(Context context, ResolveInfo service, String id,
+ String parentId, int inputType, boolean isHardwareInput, int labelRes, String label,
+ Icon icon, Uri iconUri, boolean isConnectedToHdmiSwitch)
throws XmlPullParserException, IOException {
ServiceInfo si = service.serviceInfo;
PackageManager pm = context.getPackageManager();
@@ -254,7 +306,9 @@ public final class TvInputInfo implements Parcelable {
}
sa.recycle();
+ input.mLabelRes = labelRes;
input.mLabel = label;
+ input.mIcon = icon;
input.mIconUri = iconUri;
input.mIsConnectedToHdmiSwitch = isConnectedToHdmiSwitch;
return input;
@@ -426,11 +480,13 @@ public final class TvInputInfo implements Parcelable {
* a label, its name is returned.
*/
public CharSequence loadLabel(@NonNull Context context) {
- if (TextUtils.isEmpty(mLabel)) {
- return mService.loadLabel(context.getPackageManager());
- } else {
+ if (mLabelRes != 0) {
+ return context.getPackageManager().getText(mService.serviceInfo.packageName, mLabelRes,
+ null);
+ } else if (!TextUtils.isEmpty(mLabel)) {
return mLabel;
}
+ return mService.loadLabel(context.getPackageManager());
}
/**
@@ -454,19 +510,20 @@ public final class TvInputInfo implements Parcelable {
* application's icon is returned. If it's unavailable too, {@code null} is returned.
*/
public Drawable loadIcon(@NonNull Context context) {
- if (mIconUri == null) {
- return loadServiceIcon(context);
- }
- try (InputStream is = context.getContentResolver().openInputStream(mIconUri)) {
- Drawable drawable = Drawable.createFromStream(is, null);
- if (drawable == null) {
- return loadServiceIcon(context);
+ if (mIcon != null) {
+ return mIcon.loadDrawable(context);
+ } else if (mIconUri != null) {
+ try (InputStream is = context.getContentResolver().openInputStream(mIconUri)) {
+ Drawable drawable = Drawable.createFromStream(is, null);
+ if (drawable != null) {
+ return drawable;
+ }
+ } catch (IOException e) {
+ Log.w(TAG, "Loading the default icon due to a failure on loading " + mIconUri, e);
+ // Falls back.
}
- return drawable;
- } catch (IOException e) {
- Log.w(TAG, "Loading the default icon due to a failure on loading " + mIconUri, e);
- return loadServiceIcon(context);
}
+ return loadServiceIcon(context);
}
@Override
@@ -516,7 +573,9 @@ public final class TvInputInfo implements Parcelable {
dest.writeInt(mType);
dest.writeByte(mIsHardwareInput ? (byte) 1 : 0);
dest.writeParcelable(mHdmiDeviceInfo, flags);
+ dest.writeParcelable(mIcon, flags);
dest.writeParcelable(mIconUri, flags);
+ dest.writeInt(mLabelRes);
dest.writeString(mLabel);
dest.writeByte(mIsConnectedToHdmiSwitch ? (byte) 1 : 0);
}
@@ -591,7 +650,9 @@ public final class TvInputInfo implements Parcelable {
mType = in.readInt();
mIsHardwareInput = in.readByte() == 1 ? true : false;
mHdmiDeviceInfo = in.readParcelable(null);
+ mIcon = in.readParcelable(null);
mIconUri = in.readParcelable(null);
+ mLabelRes = in.readInt();
mLabel = in.readString();
mIsConnectedToHdmiSwitch = in.readByte() == 1 ? true : false;
}
diff --git a/media/java/android/service/media/MediaBrowserService.java b/media/java/android/service/media/MediaBrowserService.java
index 41156cb..1bb99ff 100644
--- a/media/java/android/service/media/MediaBrowserService.java
+++ b/media/java/android/service/media/MediaBrowserService.java
@@ -76,7 +76,7 @@ public abstract class MediaBrowserService extends Service {
public static final String SERVICE_INTERFACE = "android.media.browse.MediaBrowserService";
/**
- * A key for passing the MediaItem to the ResultReceiver in getMediaItem.
+ * A key for passing the MediaItem to the ResultReceiver in getItem.
*
* @hide
*/
@@ -109,6 +109,7 @@ public abstract class MediaBrowserService extends Service {
* be thrown.
*
* @see MediaBrowserService#onLoadChildren
+ * @see MediaBrowserService#onGetMediaItem
*/
public class Result<T> {
private Object mDebug;
@@ -279,20 +280,7 @@ public abstract class MediaBrowserService extends Service {
mHandler.post(new Runnable() {
@Override
public void run() {
- final Result<MediaBrowser.MediaItem> result
- = new Result<MediaBrowser.MediaItem>(mediaId) {
- @Override
- void onResultSent(MediaBrowser.MediaItem item) {
- Bundle bundle = new Bundle();
- bundle.putParcelable(KEY_MEDIA_ITEM, item);
- receiver.send(0, bundle);
- }
- };
- try {
- MediaBrowserService.this.getMediaItem(mediaId, result);
- } catch (UnsupportedOperationException e) {
- receiver.send(-1, null);
- }
+ performLoadItem(mediaId, receiver);
}
});
}
@@ -357,8 +345,7 @@ public abstract class MediaBrowserService extends Service {
@NonNull Result<List<MediaBrowser.MediaItem>> result);
/**
- * Called to get a specific media item. The mediaId should be the same id
- * that would be returned for this item when it is in a list of child items.
+ * Called to get information about a specific media item.
* <p>
* Implementations must call {@link Result#sendResult result.sendResult}. If
* loading the item will be an expensive operation {@link Result#detach
@@ -366,17 +353,15 @@ public abstract class MediaBrowserService extends Service {
* then {@link Result#sendResult result.sendResult} called when the item has
* been loaded.
* <p>
- * The default implementation throws an exception.
+ * The default implementation sends a null result.
*
- * @param mediaId The id for the specific
+ * @param itemId The id for the specific
* {@link android.media.browse.MediaBrowser.MediaItem}.
* @param result The Result to send the item to, or null if the id is
* invalid.
- * @throws UnsupportedOperationException
*/
- public void getMediaItem(String mediaId, Result<MediaBrowser.MediaItem> result)
- throws UnsupportedOperationException {
- throw new UnsupportedOperationException("getMediaItem is not supported.");
+ public void onLoadItem(String itemId, Result<MediaBrowser.MediaItem> result) {
+ result.sendResult(null);
}
/**
@@ -515,6 +500,25 @@ public abstract class MediaBrowserService extends Service {
}
}
+ private void performLoadItem(String itemId, final ResultReceiver receiver) {
+ final Result<MediaBrowser.MediaItem> result =
+ new Result<MediaBrowser.MediaItem>(itemId) {
+ @Override
+ void onResultSent(MediaBrowser.MediaItem item) {
+ Bundle bundle = new Bundle();
+ bundle.putParcelable(KEY_MEDIA_ITEM, item);
+ receiver.send(0, bundle);
+ }
+ };
+
+ MediaBrowserService.this.onLoadItem(itemId, result);
+
+ if (!result.isDone()) {
+ throw new IllegalStateException("onLoadItem must call detach() or sendResult()"
+ + " before returning for id=" + itemId);
+ }
+ }
+
/**
* Contains information that the browser service needs to send to the client
* when first connected.
diff --git a/media/jni/android_media_ImageReader.cpp b/media/jni/android_media_ImageReader.cpp
index 49614bd..635fa11 100644
--- a/media/jni/android_media_ImageReader.cpp
+++ b/media/jni/android_media_ImageReader.cpp
@@ -72,6 +72,12 @@ static struct {
jmethodID ctor;
} gSurfacePlaneClassInfo;
+// Get an ID that's unique within this process.
+static int32_t createProcessUniqueId() {
+ static volatile int32_t globalCounter = 0;
+ return android_atomic_inc(&globalCounter);
+}
+
// ----------------------------------------------------------------------------
class JNIImageReaderContext : public ConsumerBase::FrameAvailableListener
@@ -808,6 +814,9 @@ static void ImageReader_init(JNIEnv* env, jobject thiz, jobject weakThiz,
sp<ConsumerBase> consumer;
sp<CpuConsumer> cpuConsumer;
sp<BufferItemConsumer> opaqueConsumer;
+ String8 consumerName = String8::format("ImageReader-%dx%df%xm%d-%d-%d",
+ width, height, format, maxImages, getpid(),
+ createProcessUniqueId());
if (isFormatOpaque(nativeFormat)) {
// Use the SW_READ_NEVER usage to tell producer that this format is not for preview or video
// encoding. The only possibility will be ZSL output.
@@ -819,6 +828,7 @@ static void ImageReader_init(JNIEnv* env, jobject thiz, jobject weakThiz,
return;
}
ctx->setOpaqueConsumer(opaqueConsumer);
+ opaqueConsumer->setName(consumerName);
consumer = opaqueConsumer;
} else {
cpuConsumer = new CpuConsumer(gbConsumer, maxImages, /*controlledByApp*/true);
@@ -828,6 +838,7 @@ static void ImageReader_init(JNIEnv* env, jobject thiz, jobject weakThiz,
return;
}
ctx->setCpuConsumer(cpuConsumer);
+ cpuConsumer->setName(consumerName);
consumer = cpuConsumer;
}
diff --git a/media/jni/android_media_ImageWriter.cpp b/media/jni/android_media_ImageWriter.cpp
index 294cd84..634ba64 100644
--- a/media/jni/android_media_ImageWriter.cpp
+++ b/media/jni/android_media_ImageWriter.cpp
@@ -293,7 +293,8 @@ static jlong ImageWriter_init(JNIEnv* env, jobject thiz, jobject weakThiz, jobje
res = native_window_set_usage(anw.get(), GRALLOC_USAGE_SW_WRITE_OFTEN);
if (res != OK) {
ALOGE("%s: Configure usage %08x for format %08x failed: %s (%d)",
- __FUNCTION__, GRALLOC_USAGE_SW_WRITE_OFTEN, format, strerror(-res), res);
+ __FUNCTION__, static_cast<unsigned int>(GRALLOC_USAGE_SW_WRITE_OFTEN),
+ format, strerror(-res), res);
jniThrowRuntimeException(env, "Failed to SW_WRITE_OFTEN configure usage");
return 0;
}
diff --git a/media/jni/soundpool/android_media_SoundPool.cpp b/media/jni/soundpool/android_media_SoundPool.cpp
index fc4cf05..ab3e340 100644
--- a/media/jni/soundpool/android_media_SoundPool.cpp
+++ b/media/jni/soundpool/android_media_SoundPool.cpp
@@ -286,7 +286,7 @@ static JNINativeMethod gMethods[] = {
"(Ljava/lang/Object;ILjava/lang/Object;)I",
(void*)android_media_SoundPool_native_setup
},
- { "release",
+ { "native_release",
"()V",
(void*)android_media_SoundPool_release
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CodecTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CodecTest.java
index bcfcbf3..8f7d6ac 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CodecTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CodecTest.java
@@ -60,6 +60,7 @@ public class CodecTest {
private static boolean onPrepareSuccess = false;
public static boolean onCompleteSuccess = false;
public static boolean mPlaybackError = false;
+ public static boolean mFailedToCompleteWithNoError = true;
public static int mMediaInfoUnknownCount = 0;
public static int mMediaInfoVideoTrackLaggingCount = 0;
public static int mMediaInfoBadInterleavingCount = 0;
@@ -801,6 +802,7 @@ public class CodecTest {
mMediaInfoNotSeekableCount = 0;
mMediaInfoMetdataUpdateCount = 0;
mPlaybackError = false;
+ mFailedToCompleteWithNoError = true;
String testResult;
initializeMessageLooper();
@@ -843,6 +845,9 @@ public class CodecTest {
} catch (Exception e) {
Log.v(TAG, "playMediaSamples:" + e.getMessage());
}
+ // Check if playback state is unknown (neither completed nor erroneous) unless
+ // it's not interrupted in the middle. If true, that is an exceptional case to investigate.
+ mFailedToCompleteWithNoError = !(onCompleteSuccess || mPlaybackError);
return onCompleteSuccess;
}
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaPlayerStressTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaPlayerStressTest.java
index e289812..4221f1b 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaPlayerStressTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaPlayerStressTest.java
@@ -65,6 +65,7 @@ public class MediaPlayerStressTest extends ActivityInstrumentationTestCase2<Medi
private int mTotalBadInterleaving = 0;
private int mTotalNotSeekable = 0;
private int mTotalMetaDataUpdate = 0;
+ private int mTotalFailedToCompleteWithNoError = 0;
//Test result output file
private static final String PLAYBACK_RESULT = "PlaybackTestResult.txt";
@@ -78,6 +79,8 @@ public class MediaPlayerStressTest extends ActivityInstrumentationTestCase2<Medi
output.write(" Bad Interleaving: " + CodecTest.mMediaInfoBadInterleavingCount);
output.write(" Not Seekable: " + CodecTest.mMediaInfoNotSeekableCount);
output.write(" Info Meta data update: " + CodecTest.mMediaInfoMetdataUpdateCount);
+ output.write(" Failed To Complete With No Error: " +
+ CodecTest.mFailedToCompleteWithNoError);
output.write("\n");
}
@@ -90,16 +93,21 @@ public class MediaPlayerStressTest extends ActivityInstrumentationTestCase2<Medi
output.write("Total Bad Interleaving: " + mTotalBadInterleaving + "\n");
output.write("Total Not Seekable: " + mTotalNotSeekable + "\n");
output.write("Total Info Meta data update: " + mTotalMetaDataUpdate + "\n");
+ output.write("Total Failed To Complete With No Error: " +
+ mTotalFailedToCompleteWithNoError);
output.write("\n");
}
private void updateTestResult(){
- if (CodecTest.onCompleteSuccess){
+ if (CodecTest.onCompleteSuccess) {
mTotalComplete++;
}
- else if (CodecTest.mPlaybackError){
+ else if (CodecTest.mPlaybackError) {
mTotalPlaybackError++;
}
+ else if (CodecTest.mFailedToCompleteWithNoError) {
+ mTotalFailedToCompleteWithNoError++;
+ }
mTotalInfoUnknown += CodecTest.mMediaInfoUnknownCount;
mTotalVideoTrackLagging += CodecTest.mMediaInfoVideoTrackLaggingCount;
mTotalBadInterleaving += CodecTest.mMediaInfoBadInterleavingCount;
@@ -149,4 +157,4 @@ public class MediaPlayerStressTest extends ActivityInstrumentationTestCase2<Medi
assertTrue("testMediaSamples", testResult);
}
}
-} \ No newline at end of file
+}
diff --git a/native/android/Android.mk b/native/android/Android.mk
index 12fdf71..1742bee 100644
--- a/native/android/Android.mk
+++ b/native/android/Android.mk
@@ -16,6 +16,7 @@ LOCAL_SRC_FILES:= \
obb.cpp \
sensor.cpp \
storage_manager.cpp \
+ trace.cpp \
LOCAL_SHARED_LIBRARIES := \
liblog \
diff --git a/native/android/trace.cpp b/native/android/trace.cpp
new file mode 100644
index 0000000..db52220
--- /dev/null
+++ b/native/android/trace.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#include <android/trace.h>
+#include <cutils/trace.h>
+
+bool ATrace_isEnabled() {
+ return atrace_is_tag_enabled(ATRACE_TAG_APP);
+}
+
+void ATrace_beginSection(const char* sectionName) {
+ atrace_begin(ATRACE_TAG_APP, sectionName);
+}
+
+void ATrace_endSection() {
+ atrace_end(ATRACE_TAG_APP);
+}
diff --git a/packages/DocumentsUI/res/layout-sw720dp/activity.xml b/packages/DocumentsUI/res/layout-sw720dp/activity.xml
index a9f1b3c..2a273f4 100644
--- a/packages/DocumentsUI/res/layout-sw720dp/activity.xml
+++ b/packages/DocumentsUI/res/layout-sw720dp/activity.xml
@@ -19,7 +19,7 @@
android:layout_height="match_parent"
android:orientation="vertical">
- <Toolbar
+ <com.android.documentsui.DocumentsToolBar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?android:attr/actionBarSize"
@@ -34,7 +34,7 @@
android:layout_marginStart="4dp"
android:overlapAnchor="true" />
- </Toolbar>
+ </com.android.documentsui.DocumentsToolBar>
<LinearLayout
android:layout_width="match_parent"
diff --git a/packages/DocumentsUI/res/layout/activity.xml b/packages/DocumentsUI/res/layout/activity.xml
index b549cd3..43fdaf2 100644
--- a/packages/DocumentsUI/res/layout/activity.xml
+++ b/packages/DocumentsUI/res/layout/activity.xml
@@ -24,7 +24,7 @@
android:layout_height="match_parent"
android:orientation="vertical">
- <Toolbar
+ <com.android.documentsui.DocumentsToolBar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?android:attr/actionBarSize"
@@ -39,7 +39,7 @@
android:layout_marginStart="4dp"
android:overlapAnchor="true" />
- </Toolbar>
+ </com.android.documentsui.DocumentsToolBar>
<com.android.documentsui.DirectoryContainerView
android:id="@+id/container_directory"
diff --git a/packages/DocumentsUI/res/values/strings.xml b/packages/DocumentsUI/res/values/strings.xml
index 9794273..a4e6ce7 100644
--- a/packages/DocumentsUI/res/values/strings.xml
+++ b/packages/DocumentsUI/res/values/strings.xml
@@ -45,7 +45,7 @@
<!-- Menu item title that deletes the selected documents [CHAR LIMIT=24] -->
<string name="menu_delete">Delete</string>
<!-- Menu item title that selects all documents in the current directory [CHAR LIMIT=24] -->
- <string name="menu_select_all">Select All</string>
+ <string name="menu_select_all">Select all</string>
<!-- Menu item title that copies the selected documents [CHAR LIMIT=24] -->
<string name="menu_copy">Copy to\u2026</string>
@@ -68,9 +68,6 @@
<!-- Button label that copies files to the current directory [CHAR LIMIT=24] -->
<string name="button_copy">Copy</string>
- <!-- Action mode title summarizing the number of documents selected [CHAR LIMIT=32] -->
- <string name="mode_selected_count"><xliff:g id="count" example="3">%1$d</xliff:g> selected</string>
-
<!-- Mode that sorts documents by their display name alphabetically [CHAR LIMIT=24] -->
<string name="sort_name">By name</string>
<!-- Mode that sorts documents by their last modified time in descending order; most recent first [CHAR LIMIT=24] -->
diff --git a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
index cb21131..bba33be 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
@@ -25,6 +25,7 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.concurrent.Executor;
@@ -32,6 +33,10 @@ import libcore.io.IoUtils;
import android.app.Activity;
import android.app.Fragment;
import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ProviderInfo;
import android.database.Cursor;
import android.net.Uri;
import android.os.AsyncTask;
@@ -96,7 +101,7 @@ abstract class BaseActivity extends Activity {
boolean showMenu = super.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.menu.activity, menu);
- mSearchManager.install(menu.findItem(R.id.menu_search));
+ mSearchManager.install((DocumentsToolBar) findViewById(R.id.toolbar));
return showMenu;
}
@@ -232,9 +237,38 @@ abstract class BaseActivity extends Activity {
invalidateOptionsMenu();
}
+ final List<String> getExcludedAuthorities() {
+ List<String> authorities = new ArrayList<>();
+ if (getIntent().getBooleanExtra(DocumentsContract.EXTRA_EXCLUDE_SELF, false)) {
+ // Exclude roots provided by the calling package.
+ String packageName = getCallingPackageMaybeExtra();
+ try {
+ PackageInfo pkgInfo = getPackageManager().getPackageInfo(packageName,
+ PackageManager.GET_PROVIDERS);
+ for (ProviderInfo provider: pkgInfo.providers) {
+ authorities.add(provider.authority);
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(mTag, "Calling package name does not resolve: " + packageName);
+ }
+ }
+ return authorities;
+ }
+
final String getCallingPackageMaybeExtra() {
- final String extra = getIntent().getStringExtra(DocumentsContract.EXTRA_PACKAGE_NAME);
- return (extra != null) ? extra : getCallingPackage();
+ String callingPackage = getCallingPackage();
+ // System apps can set the calling package name using an extra.
+ try {
+ ApplicationInfo info = getPackageManager().getApplicationInfo(callingPackage, 0);
+ if (info.isSystemApp() || info.isUpdatedSystemApp()) {
+ final String extra = getIntent().getStringExtra(DocumentsContract.EXTRA_PACKAGE_NAME);
+ if (extra != null) {
+ callingPackage = extra;
+ }
+ }
+ } finally {
+ return callingPackage;
+ }
}
public static BaseActivity get(Fragment fragment) {
@@ -287,6 +321,9 @@ abstract class BaseActivity extends Activity {
/** Currently copying file */
public List<DocumentInfo> selectedDocumentsForCopy = new ArrayList<DocumentInfo>();
+ /** Name of the package that started DocsUI */
+ public List<String> excludedAuthorities = new ArrayList<>();
+
public static final int ACTION_OPEN = 1;
public static final int ACTION_CREATE = 2;
public static final int ACTION_GET_CONTENT = 3;
@@ -327,6 +364,7 @@ abstract class BaseActivity extends Activity {
out.writeString(currentSearch);
out.writeMap(dirState);
out.writeList(selectedDocumentsForCopy);
+ out.writeList(excludedAuthorities);
}
public static final Creator<State> CREATOR = new Creator<State>() {
@@ -348,6 +386,7 @@ abstract class BaseActivity extends Activity {
state.currentSearch = in.readString();
in.readMap(state.dirState, null);
in.readList(state.selectedDocumentsForCopy, null);
+ in.readList(state.excludedAuthorities, null);
return state;
}
@@ -627,20 +666,24 @@ abstract class BaseActivity extends Activity {
* Facade over the various search parts in the menu.
*/
final class SearchManager implements
- SearchView.OnCloseListener, OnActionExpandListener, OnQueryTextListener {
+ SearchView.OnCloseListener, OnActionExpandListener, OnQueryTextListener,
+ DocumentsToolBar.OnActionViewCollapsedListener {
private boolean mSearchExpanded;
private boolean mIgnoreNextClose;
private boolean mIgnoreNextCollapse;
+ private DocumentsToolBar mActionBar;
private MenuItem mMenu;
private SearchView mView;
- public void install(MenuItem menu) {
- assert(mMenu == null);
- mMenu = menu;
- mView = (SearchView) menu.getActionView();
+ public void install(DocumentsToolBar actionBar) {
+ assert(mActionBar == null);
+ mActionBar = actionBar;
+ mMenu = actionBar.getSearchMenu();
+ mView = (SearchView) mMenu.getActionView();
+ mActionBar.setOnActionViewCollapsedListener(this);
mMenu.setOnActionExpandListener(this);
mView.setOnQueryTextListener(this);
mView.setOnCloseListener(this);
@@ -691,6 +734,19 @@ abstract class BaseActivity extends Activity {
}
}
+ /**
+ * Cancels current search operation.
+ * @return True if it cancels search. False if it does not operate
+ * search currently.
+ */
+ boolean cancelSearch() {
+ if (mActionBar.hasExpandedActionView()) {
+ mActionBar.collapseActionView();
+ return true;
+ }
+ return false;
+ }
+
boolean isSearching() {
return getDisplayState().currentSearch != null;
}
@@ -726,7 +782,6 @@ abstract class BaseActivity extends Activity {
mIgnoreNextCollapse = false;
return true;
}
-
getDisplayState().currentSearch = null;
onCurrentDirectoryChanged(ANIM_NONE);
return true;
@@ -745,5 +800,10 @@ abstract class BaseActivity extends Activity {
public boolean onQueryTextChange(String newText) {
return false;
}
+
+ @Override
+ public void onActionViewCollapsed() {
+ updateActionBar();
+ }
}
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
index a789da8..f4be9c5 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
@@ -54,6 +54,7 @@ import android.os.OperationCanceledException;
import android.os.Parcelable;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Document;
+import android.text.TextUtils;
import android.text.format.DateUtils;
import android.text.format.Formatter;
import android.text.format.Time;
@@ -474,8 +475,7 @@ public class DirectoryFragment extends Fragment {
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
mode.getMenuInflater().inflate(R.menu.mode_directory, menu);
- mode.setTitle(getResources()
- .getString(R.string.mode_selected_count, mCurrentView.getCheckedItemCount()));
+ mode.setTitle(TextUtils.formatSelectedCount(mCurrentView.getCheckedItemCount()));
return true;
}
@@ -571,8 +571,7 @@ public class DirectoryFragment extends Fragment {
}
}
- mode.setTitle(getResources()
- .getString(R.string.mode_selected_count, mCurrentView.getCheckedItemCount()));
+ mode.setTitle(TextUtils.formatSelectedCount(mCurrentView.getCheckedItemCount()));
}
};
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
index da59d0e..90ccf91 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
@@ -31,6 +31,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import android.app.ActionBar;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
@@ -256,6 +257,8 @@ public class DocumentsActivity extends BaseActivity {
BaseActivity.DocumentsIntent.EXTRA_DIRECTORY_COPY, false);
}
+ state.excludedAuthorities = getExcludedAuthorities();
+
return state;
}
@@ -506,6 +509,11 @@ public class DocumentsActivity extends BaseActivity {
@Override
public void onBackPressed() {
+ // While action bar is expanded, the state stack UI is hidden.
+ if (mSearchManager.cancelSearch()) {
+ return;
+ }
+
if (!mState.stackTouched) {
super.onBackPressed();
return;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsToolBar.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsToolBar.java
new file mode 100644
index 0000000..36b7646
--- /dev/null
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsToolBar.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2015 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.documentsui;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.MenuItem;
+import android.widget.Toolbar;
+
+/**
+ * ToolBar of Documents UI.
+ */
+public class DocumentsToolBar extends Toolbar {
+ interface OnActionViewCollapsedListener {
+ void onActionViewCollapsed();
+ }
+
+ private OnActionViewCollapsedListener mOnActionViewCollapsedListener;
+
+ public DocumentsToolBar(Context context, AttributeSet attrs,
+ int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ }
+
+ public DocumentsToolBar(Context context, AttributeSet attrs,
+ int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ public DocumentsToolBar(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public DocumentsToolBar(Context context) {
+ super(context);
+ }
+
+ @Override
+ public void collapseActionView() {
+ super.collapseActionView();
+ if (mOnActionViewCollapsedListener != null) {
+ mOnActionViewCollapsedListener.onActionViewCollapsed();
+ }
+ }
+
+ /**
+ * Adds a listener that is invoked after collapsing the action view.
+ * @param listener
+ */
+ public void setOnActionViewCollapsedListener(
+ OnActionViewCollapsedListener listener) {
+ mOnActionViewCollapsedListener = listener;
+ }
+
+ public MenuItem getSearchMenu() {
+ return getMenu().findItem(R.id.menu_search);
+ }
+}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
index 27e8f20..fbcb938 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
@@ -383,6 +383,12 @@ public class RootsCache {
continue;
}
+ // Exclude roots from the calling package.
+ if (state.excludedAuthorities.contains(root.authority)) {
+ if (LOGD) Log.d(TAG, "Excluding root " + root.authority + " from calling package.");
+ continue;
+ }
+
matching.add(root);
}
return matching;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java b/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
index 97d8ed0..ecf4d6c 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
@@ -55,7 +55,6 @@ public class RootInfo implements Durable, Parcelable {
public String mimeTypes;
/** Derived fields that aren't persisted */
- public String derivedPackageName;
public String[] derivedMimeTypes;
public int derivedIcon;
@@ -75,7 +74,6 @@ public class RootInfo implements Durable, Parcelable {
availableBytes = -1;
mimeTypes = null;
- derivedPackageName = null;
derivedMimeTypes = null;
derivedIcon = 0;
}
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/RootsCacheTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/RootsCacheTest.java
index 7faa3ce..8c5bac1 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/RootsCacheTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/RootsCacheTest.java
@@ -114,6 +114,31 @@ public class RootsCacheTest extends AndroidTestCase {
RootsCache.getMatchingRoots(mRoots, mState));
}
+ public void testExcludedAuthorities() throws Exception {
+ final List<RootInfo> roots = Lists.newArrayList();
+
+ // Set up some roots
+ for (int i = 0; i < 5; ++i) {
+ RootInfo root = new RootInfo();
+ root.authority = "authority" + i;
+ roots.add(root);
+ }
+ // Make some allowed authorities
+ List<RootInfo> allowedRoots = Lists.newArrayList(
+ roots.get(0), roots.get(2), roots.get(4));
+ // Set up the excluded authority list
+ for (RootInfo root: roots) {
+ if (!allowedRoots.contains(root)) {
+ mState.excludedAuthorities.add(root.authority);
+ }
+ }
+ mState.acceptMimes = new String[] { "*/*" };
+
+ assertContainsExactly(
+ allowedRoots,
+ RootsCache.getMatchingRoots(roots, mState));
+ }
+
private static void assertContainsExactly(List<?> expected, List<?> actual) {
assertEquals(expected.size(), actual.size());
for (Object o : expected) {
diff --git a/packages/Keyguard/res/layout/keyguard_pattern_view.xml b/packages/Keyguard/res/layout/keyguard_pattern_view.xml
index 0f5431e..09c01de 100644
--- a/packages/Keyguard/res/layout/keyguard_pattern_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_pattern_view.xml
@@ -31,8 +31,7 @@
android:clipToPadding="false"
androidprv:layout_maxWidth="@dimen/keyguard_security_width"
androidprv:layout_maxHeight="@dimen/keyguard_security_height"
- android:gravity="center_horizontal"
- android:contentDescription="@string/keyguard_accessibility_pattern_unlock">
+ android:gravity="center_horizontal">
<FrameLayout
android:layout_width="match_parent"
diff --git a/packages/Keyguard/res/values/strings.xml b/packages/Keyguard/res/values/strings.xml
index 49ce427..748129c 100644
--- a/packages/Keyguard/res/values/strings.xml
+++ b/packages/Keyguard/res/values/strings.xml
@@ -299,6 +299,42 @@
<!-- Description of airplane mode -->
<string name="airplane_mode">Airplane mode</string>
+ <!-- An explanation text that the pattern needs to be solved since the device has just been restarted. [CHAR LIMIT=80] -->
+ <string name="kg_prompt_reason_restart_pattern">Pattern required when you restart device.</string>
+
+ <!-- An explanation text that the pin needs to be entered since the device has just been restarted. [CHAR LIMIT=80] -->
+ <string name="kg_prompt_reason_restart_pin">PIN required when you restart device.</string>
+
+ <!-- An explanation text that the password needs to be entered since the device has just been restarted. [CHAR LIMIT=80] -->
+ <string name="kg_prompt_reason_restart_password">Password required when you restart device.</string>
+
+ <!-- An explanation text that the pattern needs to be solved since profiles have just been switched. [CHAR LIMIT=80] -->
+ <string name="kg_prompt_reason_switch_profiles_pattern">Pattern required when you switch profiles.</string>
+
+ <!-- An explanation text that the pin needs to be entered since profiles have just been switched. [CHAR LIMIT=80] -->
+ <string name="kg_prompt_reason_switch_profiles_pin">PIN required when you switch profiles.</string>
+
+ <!-- An explanation text that the password needs to be entered since profiles have just been switched. [CHAR LIMIT=80] -->
+ <string name="kg_prompt_reason_switch_profiles_password">Password required when you switch profiles.</string>
+
+ <!-- An explanation text that the pattern needs to be solved since it hasn't been solved in a while. [CHAR LIMIT=80]-->
+ <plurals name="kg_prompt_reason_time_pattern">
+ <item quantity="one">Device hasn\'t been unlocked for <xliff:g id="number">%d</xliff:g> hour. Confirm pattern.</item>
+ <item quantity="other">Device hasn\'t been unlocked for <xliff:g id="number">%d</xliff:g> hours. Confirm pattern.</item>
+ </plurals>
+
+ <!-- An explanation text that the pin needs to be entered since it hasn't been entered in a while. [CHAR LIMIT=80]-->
+ <plurals name="kg_prompt_reason_time_pin">
+ <item quantity="one">Device hasn\'t been unlocked for <xliff:g id="number">%d</xliff:g> hour. Confirm PIN.</item>
+ <item quantity="other">Device hasn\'t been unlocked for <xliff:g id="number">%d</xliff:g> hours. Confirm PIN.</item>
+ </plurals>
+
+ <!-- An explanation text that the password needs to be entered since it hasn't been entered in a while. [CHAR LIMIT=80]-->
+ <plurals name="kg_prompt_reason_time_password">
+ <item quantity="one">Device hasn\'t been unlocked for <xliff:g id="number">%d</xliff:g> hour. Confirm password.</item>
+ <item quantity="other">Device hasn\'t been unlocked for <xliff:g id="number">%d</xliff:g> hours. Confirm password.</item>
+ </plurals>
+
<!-- Fingerprint hint message when finger was not recognized.-->
<string name="fingerprint_not_recognized">Not recognized</string>
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPINView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPINView.java
index d0be855..ac9dc85 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPINView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPINView.java
@@ -22,6 +22,9 @@ import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AnimationUtils;
+import com.android.settingslib.animation.AppearAnimationUtils;
+import com.android.settingslib.animation.DisappearAnimationUtils;
+
/**
* Displays a PIN pad for unlocking.
*/
@@ -115,7 +118,7 @@ public class KeyguardPINView extends KeyguardPinBasedInputView {
.setDuration(500)
.setInterpolator(mAppearAnimationUtils.getInterpolator())
.translationY(0);
- mAppearAnimationUtils.startAnimation(mViews,
+ mAppearAnimationUtils.startAnimation2d(mViews,
new Runnable() {
@Override
public void run() {
@@ -132,7 +135,7 @@ public class KeyguardPINView extends KeyguardPinBasedInputView {
.setDuration(280)
.setInterpolator(mDisappearAnimationUtils.getInterpolator())
.translationY(mDisappearYTranslation);
- mDisappearAnimationUtils.startAnimation(mViews,
+ mDisappearAnimationUtils.startAnimation2d(mViews,
new Runnable() {
@Override
public void run() {
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
index a9b2978..1bd0bb4 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
@@ -36,6 +36,9 @@ import android.widget.LinearLayout;
import com.android.internal.widget.LockPatternChecker;
import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.LockPatternView;
+import com.android.settingslib.animation.AppearAnimationCreator;
+import com.android.settingslib.animation.AppearAnimationUtils;
+import com.android.settingslib.animation.DisappearAnimationUtils;
import java.util.List;
@@ -325,7 +328,7 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit
.setDuration(500)
.setInterpolator(mAppearAnimationUtils.getInterpolator())
.translationY(0);
- mAppearAnimationUtils.startAnimation(
+ mAppearAnimationUtils.startAnimation2d(
mLockPatternView.getCellStates(),
new Runnable() {
@Override
@@ -353,7 +356,7 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit
.setDuration(300)
.setInterpolator(mDisappearAnimationUtils.getInterpolator())
.translationY(-mDisappearAnimationUtils.getStartTranslation());
- mDisappearAnimationUtils.startAnimation(mLockPatternView.getCellStates(),
+ mDisappearAnimationUtils.startAnimation2d(mLockPatternView.getCellStates(),
new Runnable() {
@Override
public void run() {
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java
index ed0d4af..23834a3 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java
@@ -150,13 +150,6 @@ public abstract class KeyguardPinBasedInputView extends KeyguardAbsKeyInputView
// Set selected property on so the view can send accessibility events.
mPasswordEntry.setSelected(true);
- // Poke the wakelock any time the text is selected or modified
- mPasswordEntry.setOnClickListener(new OnClickListener() {
- public void onClick(View v) {
- onUserInput();
- }
- });
-
mPasswordEntry.setUserActivityListener(new PasswordTextView.UserActivityListener() {
@Override
public void onUserActivity() {
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
index 4ba04e5..3c5dae3 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
@@ -679,6 +679,8 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
if (resolvedActivities.get(0).activityInfo.exported) {
intent.putExtra(PrintService.EXTRA_PRINT_JOB_INFO, mPrintJob);
intent.putExtra(PrintService.EXTRA_PRINTER_INFO, printer);
+ intent.putExtra(PrintService.EXTRA_PRINT_JOB_INFO,
+ mPrintedDocument.getDocumentInfo().info);
// This is external activity and may not be there.
try {
diff --git a/packages/SettingsLib/res/values/dimens.xml b/packages/SettingsLib/res/values/dimens.xml
new file mode 100644
index 0000000..1c4b05f
--- /dev/null
+++ b/packages/SettingsLib/res/values/dimens.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2015 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<resources>
+
+ <!-- The y translation to apply at the start in appear animations. -->
+ <dimen name="appear_y_translation_start">32dp</dimen>
+
+ <!-- The translation for disappearing security views after having solved them. -->
+ <dimen name="disappear_y_translation">-32dp</dimen>
+</resources> \ No newline at end of file
diff --git a/packages/Keyguard/src/com/android/keyguard/AppearAnimationCreator.java b/packages/SettingsLib/src/com/android/settingslib/animation/AppearAnimationCreator.java
index e4706b6..8a61e4e 100644
--- a/packages/Keyguard/src/com/android/keyguard/AppearAnimationCreator.java
+++ b/packages/SettingsLib/src/com/android/settingslib/animation/AppearAnimationCreator.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2015 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.
@@ -14,13 +14,13 @@
* limitations under the License
*/
-package com.android.keyguard;
+package com.android.settingslib.animation;
import android.view.animation.Interpolator;
/**
* An interface which can create animations when starting an appear animation with
- * {@link com.android.keyguard.AppearAnimationUtils}
+ * {@link AppearAnimationUtils}
*/
public interface AppearAnimationCreator<T> {
void createAnimation(T animatedObject, long delay, long duration,
diff --git a/packages/Keyguard/src/com/android/keyguard/AppearAnimationUtils.java b/packages/SettingsLib/src/com/android/settingslib/animation/AppearAnimationUtils.java
index 9045fe3..441474d 100644
--- a/packages/Keyguard/src/com/android/keyguard/AppearAnimationUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/animation/AppearAnimationUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2015 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.
@@ -14,13 +14,15 @@
* limitations under the License
*/
-package com.android.keyguard;
+package com.android.settingslib.animation;
import android.content.Context;
import android.view.View;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
+import com.android.settingslib.R;
+
/**
* A class to make nice appear transitions for views in a tabular layout.
*/
@@ -33,7 +35,7 @@ public class AppearAnimationUtils implements AppearAnimationCreator<View> {
private final AppearAnimationProperties mProperties = new AppearAnimationProperties();
protected final float mDelayScale;
private final long mDuration;
- protected boolean mScaleTranslationWithRow;
+ protected RowTranslationScaler mRowTranslationScaler;
protected boolean mAppearing;
public AppearAnimationUtils(Context ctx) {
@@ -49,19 +51,18 @@ public class AppearAnimationUtils implements AppearAnimationCreator<View> {
R.dimen.appear_y_translation_start) * translationScaleFactor;
mDelayScale = delayScaleFactor;
mDuration = duration;
- mScaleTranslationWithRow = false;
mAppearing = true;
}
- public void startAnimation(View[][] objects, final Runnable finishListener) {
- startAnimation(objects, finishListener, this);
+ public void startAnimation2d(View[][] objects, final Runnable finishListener) {
+ startAnimation2d(objects, finishListener, this);
}
public void startAnimation(View[] objects, final Runnable finishListener) {
startAnimation(objects, finishListener, this);
}
- public <T> void startAnimation(T[][] objects, final Runnable finishListener,
+ public <T> void startAnimation2d(T[][] objects, final Runnable finishListener,
AppearAnimationCreator<T> creator) {
AppearAnimationProperties properties = getDelays(objects);
startAnimations(properties, objects, finishListener, creator);
@@ -86,8 +87,13 @@ public class AppearAnimationUtils implements AppearAnimationCreator<View> {
if (properties.maxDelayRowIndex == row && properties.maxDelayColIndex == 0) {
endRunnable = finishListener;
}
+ float translationScale = mRowTranslationScaler != null
+ ? mRowTranslationScaler.getRowTranslationScale(row, properties.delays.length)
+ : 1f;
+ float translation = translationScale * mStartTranslation;
creator.createAnimation(objects[row], delay, mDuration,
- mStartTranslation, true /* appearing */, mInterpolator, endRunnable);
+ mAppearing ? translation : -translation,
+ mAppearing, mInterpolator, endRunnable);
}
}
@@ -99,10 +105,10 @@ public class AppearAnimationUtils implements AppearAnimationCreator<View> {
}
for (int row = 0; row < properties.delays.length; row++) {
long[] columns = properties.delays[row];
- float translation = mScaleTranslationWithRow
- ? (float) (Math.pow((properties.delays.length - row), 2)
- / properties.delays.length * mStartTranslation)
- : mStartTranslation;
+ float translationScale = mRowTranslationScaler != null
+ ? mRowTranslationScaler.getRowTranslationScale(row, properties.delays.length)
+ : 1f;
+ float translation = translationScale * mStartTranslation;
for (int col = 0; col < columns.length; col++) {
long delay = columns[col];
Runnable endRunnable = null;
@@ -193,4 +199,8 @@ public class AppearAnimationUtils implements AppearAnimationCreator<View> {
public int maxDelayRowIndex;
public int maxDelayColIndex;
}
+
+ public interface RowTranslationScaler {
+ float getRowTranslationScale(int row, int numRows);
+ }
}
diff --git a/packages/Keyguard/src/com/android/keyguard/DisappearAnimationUtils.java b/packages/SettingsLib/src/com/android/settingslib/animation/DisappearAnimationUtils.java
index 517d96a..a444ff0 100644
--- a/packages/Keyguard/src/com/android/keyguard/DisappearAnimationUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/animation/DisappearAnimationUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2015 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.
@@ -14,7 +14,7 @@
* limitations under the License
*/
-package com.android.keyguard;
+package com.android.settingslib.animation;
import android.content.Context;
import android.view.animation.AnimationUtils;
@@ -28,17 +28,31 @@ public class DisappearAnimationUtils extends AppearAnimationUtils {
public DisappearAnimationUtils(Context ctx) {
this(ctx, DEFAULT_APPEAR_DURATION,
1.0f, 1.0f,
- AnimationUtils.loadInterpolator(ctx, android.R.interpolator.linear_out_slow_in));
+ AnimationUtils.loadInterpolator(ctx, android.R.interpolator.fast_out_linear_in));
}
public DisappearAnimationUtils(Context ctx, long duration, float translationScaleFactor,
float delayScaleFactor, Interpolator interpolator) {
+ this(ctx, duration, translationScaleFactor, delayScaleFactor, interpolator,
+ ROW_TRANSLATION_SCALER);
+ }
+
+ public DisappearAnimationUtils(Context ctx, long duration, float translationScaleFactor,
+ float delayScaleFactor, Interpolator interpolator, RowTranslationScaler rowScaler) {
super(ctx, duration, translationScaleFactor, delayScaleFactor, interpolator);
- mScaleTranslationWithRow = true;
+ mRowTranslationScaler = rowScaler;
mAppearing = false;
}
protected long calculateDelay(int row, int col) {
return (long) ((row * 60 + col * (Math.pow(row, 0.4) + 0.4) * 10) * mDelayScale);
}
+
+ private static final RowTranslationScaler ROW_TRANSLATION_SCALER = new RowTranslationScaler() {
+
+ @Override
+ public float getRowTranslationScale(int row, int numRows) {
+ return (float) (Math.pow((numRows - row), 2) / numRows);
+ }
+ };
}
diff --git a/packages/StatementService/src/com/android/statementservice/retriever/AbstractStatementRetriever.java b/packages/StatementService/src/com/android/statementservice/retriever/AbstractStatementRetriever.java
index 3b59fd6..fe9b99a 100644
--- a/packages/StatementService/src/com/android/statementservice/retriever/AbstractStatementRetriever.java
+++ b/packages/StatementService/src/com/android/statementservice/retriever/AbstractStatementRetriever.java
@@ -90,7 +90,7 @@ public abstract class AbstractStatementRetriever {
* Creates a new StatementRetriever that directly retrieves statements from the asset.
*
* <p> For web assets, {@link AbstractStatementRetriever} will try to retrieve the statement
- * file from URL: {@code [webAsset.site]/.well-known/statements.json"} where {@code
+ * file from URL: {@code [webAsset.site]/.well-known/assetlinks.json"} where {@code
* [webAsset.site]} is in the form {@code http{s}://[hostname]:[optional_port]}. The file
* should contain one JSON array of statements.
*
diff --git a/packages/StatementService/src/com/android/statementservice/retriever/DirectStatementRetriever.java b/packages/StatementService/src/com/android/statementservice/retriever/DirectStatementRetriever.java
index 2ca85e9..e4feb90 100644
--- a/packages/StatementService/src/com/android/statementservice/retriever/DirectStatementRetriever.java
+++ b/packages/StatementService/src/com/android/statementservice/retriever/DirectStatementRetriever.java
@@ -38,7 +38,7 @@ import java.util.List;
private static final int HTTP_CONNECTION_TIMEOUT_MILLIS = 5000;
private static final long HTTP_CONTENT_SIZE_LIMIT_IN_BYTES = 1024 * 1024;
private static final int MAX_INCLUDE_LEVEL = 1;
- private static final String WELL_KNOWN_STATEMENT_PATH = "/.well-known/statements.json";
+ private static final String WELL_KNOWN_STATEMENT_PATH = "/.well-known/assetlinks.json";
private final URLFetcher mUrlFetcher;
private final AndroidPackageInfoFetcher mAndroidFetcher;
diff --git a/packages/StatementService/src/com/android/statementservice/retriever/Statement.java b/packages/StatementService/src/com/android/statementservice/retriever/Statement.java
index da3c355..0f40a62 100644
--- a/packages/StatementService/src/com/android/statementservice/retriever/Statement.java
+++ b/packages/StatementService/src/com/android/statementservice/retriever/Statement.java
@@ -21,7 +21,7 @@ import android.annotation.NonNull;
/**
* An immutable value type representing a statement, consisting of a source, target, and relation.
* This reflects an assertion that the relation holds for the source, target pair. For example, if a
- * web site has the following in its statements.json file:
+ * web site has the following in its assetlinks.json file:
*
* <pre>
* {
diff --git a/packages/StatementService/src/com/android/statementservice/retriever/URLFetcher.java b/packages/StatementService/src/com/android/statementservice/retriever/URLFetcher.java
index 969aa88..225e26c 100644
--- a/packages/StatementService/src/com/android/statementservice/retriever/URLFetcher.java
+++ b/packages/StatementService/src/com/android/statementservice/retriever/URLFetcher.java
@@ -60,33 +60,36 @@ public class URLFetcher {
throw new IllegalArgumentException("The url protocol should be on http or https.");
}
- HttpURLConnection connection;
- connection = (HttpURLConnection) url.openConnection();
- connection.setInstanceFollowRedirects(true);
- connection.setConnectTimeout(connectionTimeoutMillis);
- connection.setReadTimeout(connectionTimeoutMillis);
- connection.setUseCaches(true);
- connection.setInstanceFollowRedirects(false);
- connection.addRequestProperty("Cache-Control", "max-stale=60");
-
- if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
- Log.e(TAG, "The responses code is not 200 but " + connection.getResponseCode());
- return new WebContent("", DO_NOT_CACHE_RESULT);
- }
+ HttpURLConnection connection = null;
+ try {
+ connection = (HttpURLConnection) url.openConnection();
+ connection.setInstanceFollowRedirects(true);
+ connection.setConnectTimeout(connectionTimeoutMillis);
+ connection.setReadTimeout(connectionTimeoutMillis);
+ connection.setUseCaches(true);
+ connection.setInstanceFollowRedirects(false);
+ connection.addRequestProperty("Cache-Control", "max-stale=60");
+
+ if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
+ Log.e(TAG, "The responses code is not 200 but " + connection.getResponseCode());
+ return new WebContent("", DO_NOT_CACHE_RESULT);
+ }
- if (connection.getContentLength() > fileSizeLimit) {
- Log.e(TAG, "The content size of the url is larger than " + fileSizeLimit);
- return new WebContent("", DO_NOT_CACHE_RESULT);
- }
+ if (connection.getContentLength() > fileSizeLimit) {
+ Log.e(TAG, "The content size of the url is larger than " + fileSizeLimit);
+ return new WebContent("", DO_NOT_CACHE_RESULT);
+ }
- Long expireTimeMillis = getExpirationTimeMillisFromHTTPHeader(connection.getHeaderFields());
+ Long expireTimeMillis = getExpirationTimeMillisFromHTTPHeader(
+ connection.getHeaderFields());
- try {
return new WebContent(inputStreamToString(
connection.getInputStream(), connection.getContentLength(), fileSizeLimit),
expireTimeMillis);
} finally {
- connection.disconnect();
+ if (connection != null) {
+ connection.disconnect();
+ }
}
}
diff --git a/packages/SystemUI/res/drawable/managed_profile_toast_background.xml b/packages/SystemUI/res/drawable/managed_profile_toast_background.xml
new file mode 100644
index 0000000..5c77b9a
--- /dev/null
+++ b/packages/SystemUI/res/drawable/managed_profile_toast_background.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (C) 2015 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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <corners android:radius="2dp" />
+ <solid android:color="@color/managed_profile_toast_background" />
+</shape>
diff --git a/packages/SystemUI/res/drawable/stat_sys_managed_profile_status.xml b/packages/SystemUI/res/drawable/stat_sys_managed_profile_status.xml
index 3c4c646..2bfa39d 100644
--- a/packages/SystemUI/res/drawable/stat_sys_managed_profile_status.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_managed_profile_status.xml
@@ -20,10 +20,10 @@ Copyright (C) 2015 The Android Open Source Project
android:viewportHeight="17.0">
<group android:translateX="2.0">
<path
- android:fillColor="#FF000000"
+ android:fillColor="@android:color/white"
android:pathData="M9.9,11.6H7v-1.1H2.1v2.8c0,0.8,0.6,1.4,1.4,1.4h9.9c0.8,0,1.4,-0.6,1.4,-1.4v-2.8H9.9V11.6z"/>
<path
- android:fillColor="#FF000000"
+ android:fillColor="@android:color/white"
android:pathData="M14.1,4.2h-2.5V3.2l-1.1,-1.1H6.3L5.3,3.2v1H2.8C2,4.2,1.4,4.9,1.4,5.6v2.8c0,0.8,0.6,1.4,1.4,1.4H7V8.8h2.8v1.1h4.2 c0.8,0,1.4,-0.6,1.4,-1.4V5.6C15.5,4.9,14.8,4.2,14.1,4.2z M10.6,4.2H6.3V3.2h4.2V4.2z"/>
</group>
</vector>
diff --git a/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml b/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml
index 456d2f9..9912343 100644
--- a/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml
+++ b/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml
@@ -3,16 +3,16 @@
**
** Copyright 2012, The Android Open Source Project
**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
+** 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
+** 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
+** 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.
-->
@@ -48,7 +48,7 @@
android:layout_marginStart="2dp"
android:visibility="invisible"
/>
- <Space
+ <Space
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
@@ -80,7 +80,7 @@
android:layout_weight="0"
android:contentDescription="@string/accessibility_recent"
/>
- <Space
+ <Space
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
@@ -120,7 +120,7 @@
android:id="@+id/lights_out"
android:visibility="gone"
>
- <Space
+ <Space
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
@@ -132,6 +132,7 @@
android:src="@drawable/ic_sysbar_lights_out_dot_small"
android:scaleType="center"
android:layout_weight="0"
+ android:contentDescription="@string/accessibility_back"
/>
<ImageView
android:layout_width="128dp" android:paddingStart="25dp" android:paddingEnd="25dp"
@@ -139,6 +140,7 @@
android:src="@drawable/ic_sysbar_lights_out_dot_large"
android:scaleType="center"
android:layout_weight="0"
+ android:contentDescription="@string/accessibility_home"
/>
<ImageView
android:layout_width="128dp" android:paddingStart="25dp" android:paddingEnd="25dp"
@@ -147,8 +149,9 @@
android:src="@drawable/ic_sysbar_lights_out_dot_small"
android:scaleType="center"
android:layout_weight="0"
+ android:contentDescription="@string/accessibility_recent"
/>
- <Space
+ <Space
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
@@ -193,7 +196,7 @@
android:layout_marginStart="2dp"
android:visibility="invisible"
/>
- <Space
+ <Space
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
@@ -225,7 +228,7 @@
android:layout_weight="0"
android:contentDescription="@string/accessibility_recent"
/>
- <Space
+ <Space
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
@@ -264,7 +267,7 @@
android:id="@+id/lights_out"
android:visibility="gone"
>
- <Space
+ <Space
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
@@ -276,6 +279,7 @@
android:src="@drawable/ic_sysbar_lights_out_dot_small"
android:scaleType="center"
android:layout_weight="0"
+ android:contentDescription="@string/accessibility_back"
/>
<ImageView
android:layout_width="162dp" android:paddingStart="42dp" android:paddingEnd="42dp"
@@ -283,6 +287,7 @@
android:src="@drawable/ic_sysbar_lights_out_dot_large"
android:scaleType="center"
android:layout_weight="0"
+ android:contentDescription="@string/accessibility_home"
/>
<ImageView
android:layout_width="162dp" android:paddingStart="42dp" android:paddingEnd="42dp"
@@ -291,8 +296,9 @@
android:src="@drawable/ic_sysbar_lights_out_dot_small"
android:scaleType="center"
android:layout_weight="0"
+ android:contentDescription="@string/accessibility_recent"
/>
- <Space
+ <Space
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
index 5d0367e..48af565 100644
--- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml
+++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
@@ -33,7 +33,8 @@
android:gravity="center_horizontal"
android:textStyle="italic"
android:textColor="#ffffff"
- android:textAppearance="?android:attr/textAppearanceSmall" />
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:accessibilityLiveRegion="polite" />
<FrameLayout
android:id="@+id/preview_container"
diff --git a/packages/SystemUI/res/layout/managed_profile_toast.xml b/packages/SystemUI/res/layout/managed_profile_toast.xml
new file mode 100644
index 0000000..5a01ca7
--- /dev/null
+++ b/packages/SystemUI/res/layout/managed_profile_toast.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 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:orientation="vertical"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:paddingTop="16dp"
+ android:paddingBottom="16dp"
+ android:paddingLeft="32dp"
+ android:paddingRight="32dp"
+ android:background="@drawable/managed_profile_toast_background">
+ <ImageView
+ android:layout_width="32dp"
+ android:layout_height="32dp"
+ android:layout_gravity="center_horizontal"
+ android:layout_marginBottom="16dp"
+ android:src="@drawable/stat_sys_managed_profile_status"/>
+ <TextView android:text="@string/managed_profile_foreground_toast"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textColor="@android:color/white"
+ android:textSize="14sp"
+ android:layout_gravity="center_horizontal" />
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/navigation_bar.xml b/packages/SystemUI/res/layout/navigation_bar.xml
index 898389d..c92ba45 100644
--- a/packages/SystemUI/res/layout/navigation_bar.xml
+++ b/packages/SystemUI/res/layout/navigation_bar.xml
@@ -4,16 +4,16 @@
**
** Copyright 2011, The Android Open Source Project
**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
+** 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
+** 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
+** 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.
*/
-->
@@ -57,7 +57,7 @@
android:scaleType="center"
android:contentDescription="@string/accessibility_back"
/>
- <View
+ <View
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
@@ -73,7 +73,7 @@
android:scaleType="center"
android:contentDescription="@string/accessibility_home"
/>
- <View
+ <View
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
@@ -130,8 +130,9 @@
android:src="@drawable/ic_sysbar_lights_out_dot_small"
android:scaleType="center"
android:layout_weight="0"
+ android:contentDescription="@string/accessibility_back"
/>
- <View
+ <View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
@@ -143,8 +144,9 @@
android:src="@drawable/ic_sysbar_lights_out_dot_large"
android:scaleType="center"
android:layout_weight="0"
+ android:contentDescription="@string/accessibility_home"
/>
- <View
+ <View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
@@ -157,6 +159,7 @@
android:src="@drawable/ic_sysbar_lights_out_dot_small"
android:scaleType="center"
android:layout_weight="0"
+ android:contentDescription="@string/accessibility_recent"
/>
</LinearLayout>
@@ -180,7 +183,7 @@
android:paddingTop="0dp"
>
- <LinearLayout
+ <LinearLayout
android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="vertical"
@@ -225,7 +228,7 @@
android:layout_weight="0"
android:contentDescription="@string/accessibility_recent"
/>
- <View
+ <View
android:layout_height="match_parent"
android:layout_width="match_parent"
android:layout_weight="1"
@@ -241,7 +244,7 @@
android:layout_weight="0"
android:contentDescription="@string/accessibility_home"
/>
- <View
+ <View
android:layout_height="match_parent"
android:layout_width="match_parent"
android:layout_weight="1"
@@ -265,7 +268,7 @@
</LinearLayout>
<!-- lights out layout to match exactly -->
- <LinearLayout
+ <LinearLayout
android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="vertical"
@@ -279,8 +282,9 @@
android:src="@drawable/ic_sysbar_lights_out_dot_small"
android:scaleType="center"
android:layout_weight="0"
+ android:contentDescription="@string/accessibility_recent"
/>
- <View
+ <View
android:layout_height="match_parent"
android:layout_width="match_parent"
android:layout_weight="1"
@@ -292,8 +296,9 @@
android:src="@drawable/ic_sysbar_lights_out_dot_large"
android:scaleType="center"
android:layout_weight="0"
+ android:contentDescription="@string/accessibility_home"
/>
- <View
+ <View
android:layout_height="match_parent"
android:layout_width="match_parent"
android:layout_weight="1"
@@ -306,6 +311,7 @@
android:src="@drawable/ic_sysbar_lights_out_dot_small"
android:scaleType="center"
android:layout_weight="0"
+ android:contentDescription="@string/accessibility_back"
/>
</LinearLayout>
diff --git a/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml b/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
index a996260..38ea6e1 100644
--- a/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
+++ b/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
@@ -35,6 +35,7 @@
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
+ android:contentDescription="@string/accessibility_brightness"
systemui:text="@string/status_bar_settings_auto_brightness_label" />
</LinearLayout>
diff --git a/packages/SystemUI/res/layout/status_bar_toggle_slider.xml b/packages/SystemUI/res/layout/status_bar_toggle_slider.xml
index a5bf68e..062e6cb 100644
--- a/packages/SystemUI/res/layout/status_bar_toggle_slider.xml
+++ b/packages/SystemUI/res/layout/status_bar_toggle_slider.xml
@@ -45,7 +45,6 @@
android:paddingBottom="16dp"
android:thumb="@drawable/ic_brightness_thumb"
android:splitTrack="false"
- android:contentDescription="@string/accessibility_brightness"
/>
<TextView
android:id="@+id/label"
diff --git a/packages/SystemUI/res/layout/volume_dialog_row.xml b/packages/SystemUI/res/layout/volume_dialog_row.xml
index d12bf5d..c6aa588 100644
--- a/packages/SystemUI/res/layout/volume_dialog_row.xml
+++ b/packages/SystemUI/res/layout/volume_dialog_row.xml
@@ -22,15 +22,15 @@
<TextView
android:id="@+id/volume_row_header"
- style="?android:attr/textAppearanceButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
+ android:textAppearance="@style/TextAppearance.Volume.Header"
android:paddingBottom="0dp"
android:paddingEnd="12dp"
- android:paddingStart="13dp"
- android:paddingTop="8dp" />
+ android:paddingStart="12dp"
+ android:paddingTop="4dp" />
<com.android.keyguard.AlphaOptimizedImageButton
android:id="@+id/volume_row_icon"
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 0dcbe88..9a96939 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -143,4 +143,6 @@
<color name="volume_icon_color">#ffffffff</color>
<color name="volume_settings_icon_color">#7fffffff</color>
<color name="volume_slider_inactive">#FFB0BEC5</color><!-- blue grey 200 -->
+
+ <color name="managed_profile_toast_background">#E5000000</color><!-- 90% black -->
</resources>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index de5639b..260d81b 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -135,8 +135,6 @@
<!-- The maximum number of items to be displayed in quick settings -->
<integer name="quick_settings_detail_max_item_count">7</integer>
- <integer name="blinds_pop_duration_ms">10</integer>
-
<!-- Should "4G" be shown instead of "LTE" when the network is NETWORK_TYPE_LTE? -->
<bool name="config_show4GForLTE">true</bool>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 0e0584f..a0b70f0 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -772,6 +772,9 @@
<!-- Shows when people have clicked on the camera icon [CHAR LIMIT=60] -->
<string name="camera_hint">Swipe from icon for camera</string>
+ <!-- Accessibility content description for Interruption level: None. [CHAR LIMIT=NONE] -->
+ <string name="interruption_level_none_with_warning">Total silence. This will also silence screen readers.</string>
+
<!-- Interruption level: None. [CHAR LIMIT=40] -->
<string name="interruption_level_none">Total silence</string>
@@ -847,7 +850,7 @@
<string name="guest_notification_title">Guest user</string>
<!-- Text of the notification shown to a new guest user [CHAR LIMIT=60] -->
- <string name="guest_notification_text">Remove guest to delete apps and data</string>
+ <string name="guest_notification_text">To delete apps and data, remove guest user</string>
<!-- Remove action in the notification shown to a new guest user [CHAR LIMIT=30] -->
<string name="guest_notification_remove_action">REMOVE GUEST</string>
@@ -1009,7 +1012,7 @@
<string name="volumeui_notification_text">Touch to restore the original.</string>
<!-- Toast shown when user unlocks screen and managed profile activity is in the foreground -->
- <string name="managed_profile_foreground_toast">You are in the work profile</string>
+ <string name="managed_profile_foreground_toast">You\'re using your work profile</string>
<string-array name="volume_stream_titles" translatable="false">
<item>Voice calls</item> <!-- STREAM_VOICE_CALL -->
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index bda39b1..67d3312 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -275,6 +275,11 @@
<item name="android:fontFamily">sans-serif</item>
</style>
+ <style name="TextAppearance.Volume.Header">
+ <item name="android:textSize">12sp</item>
+ <item name="android:textColor">@color/volume_slider_inactive</item>
+ </style>
+
<style name="TextAppearance.Volume.ZenSummary">
<item name="android:textSize">14sp</item>
<item name="android:fontFamily">sans-serif-medium</item>
diff --git a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
index fece07f..b0e2afa 100644
--- a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
@@ -25,6 +25,7 @@ import android.media.AudioAttributes;
import android.os.Vibrator;
import android.util.Log;
import android.view.Gravity;
+import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.ScaleGestureDetector.OnScaleGestureListener;
@@ -64,15 +65,6 @@ public class ExpandHelper implements Gefingerpoken {
// 2f: maximum brightness is stretching a 1U to 3U, or a 4U to 6U
private static final float STRETCH_INTERVAL = 2f;
- // level of glow for a touch, without overstretch
- // overstretch fills the range (GLOW_BASE, 1.0]
- private static final float GLOW_BASE = 0.5f;
-
- private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder()
- .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
- .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
- .build();
-
@SuppressWarnings("unused")
private Context mContext;
@@ -94,13 +86,11 @@ public class ExpandHelper implements Gefingerpoken {
private float mLastSpanY;
private int mTouchSlop;
private float mLastMotionY;
- private int mPopDuration;
private float mPullGestureMinXSpan;
private Callback mCallback;
private ScaleGestureDetector mSGD;
private ViewScaler mScaler;
private ObjectAnimator mScaleAnimation;
- private Vibrator mVibrator;
private boolean mEnabled = true;
private ExpandableView mResizedView;
private float mCurrentHeight;
@@ -174,7 +164,6 @@ public class ExpandHelper implements Gefingerpoken {
mScaler = new ViewScaler();
mGravity = Gravity.TOP;
mScaleAnimation = ObjectAnimator.ofFloat(mScaler, "height", 0f);
- mPopDuration = mContext.getResources().getInteger(R.integer.blinds_pop_duration_ms);
mPullGestureMinXSpan = mContext.getResources().getDimension(R.dimen.pull_span_min);
final ViewConfiguration configuration = ViewConfiguration.get(mContext);
@@ -452,7 +441,9 @@ public class ExpandHelper implements Gefingerpoken {
}
if (!mHasPopped) {
- vibrate(mPopDuration);
+ if (mEventSource != null) {
+ mEventSource.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
+ }
mHasPopped = true;
}
@@ -600,16 +591,5 @@ public class ExpandHelper implements Gefingerpoken {
public void onlyObserveMovements(boolean onlyMovements) {
mOnlyMovements = onlyMovements;
}
-
- /**
- * Triggers haptic feedback.
- */
- private synchronized void vibrate(long duration) {
- if (mVibrator == null) {
- mVibrator = (android.os.Vibrator)
- mContext.getSystemService(Context.VIBRATOR_SERVICE);
- }
- mVibrator.vibrate(duration, VIBRATION_ATTRIBUTES);
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
index 3e122da..1e7ee98 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
@@ -116,7 +116,6 @@ public class AssistManager {
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
WindowManager.LayoutParams lp = getLayoutParams();
mWindowManager.addView(mView, lp);
- mBar.getNavigationBarView().setDelegateView(mView);
if (visible) {
mView.show(true /* show */, false /* animate */);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 25e3d10..c8212c2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -360,7 +360,7 @@ public class QSPanel extends ViewGroup {
}
private void handleShowDetailTile(TileRecord r, boolean show) {
- if ((mDetailRecord != null) == show) return;
+ if ((mDetailRecord != null) == show && mDetailRecord == r) return;
if (show) {
r.detailAdapter = r.tile.getDetailAdapter();
@@ -373,7 +373,8 @@ public class QSPanel extends ViewGroup {
}
private void handleShowDetailImpl(Record r, boolean show, int x, int y) {
- if ((mDetailRecord != null) == show) return; // already in right state
+ boolean visibleDiff = (mDetailRecord != null) != show;
+ if (!visibleDiff && mDetailRecord == r) return; // already in right state
DetailAdapter detailAdapter = null;
AnimatorListener listener = null;
if (show) {
@@ -399,11 +400,13 @@ public class QSPanel extends ViewGroup {
mContext.getString(detailAdapter.getTitle())));
setDetailRecord(r);
listener = mHideGridContentWhenDone;
- if (r instanceof TileRecord) {
+ if (r instanceof TileRecord && visibleDiff) {
((TileRecord) r).openingDetail = true;
}
} else {
- MetricsLogger.hidden(mContext, mDetailRecord.detailAdapter.getMetricsCategory());
+ if (mDetailRecord != null) {
+ MetricsLogger.hidden(mContext, mDetailRecord.detailAdapter.getMetricsCategory());
+ }
mClosingDetail = true;
setGridContentVisibility(true);
listener = mTeardownDetailWhenDone;
@@ -411,7 +414,9 @@ public class QSPanel extends ViewGroup {
}
sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
fireShowingDetail(show ? detailAdapter : null);
- mClipper.animateCircularClip(x, y, show, listener);
+ if (visibleDiff) {
+ mClipper.animateCircularClip(x, y, show, listener);
+ }
}
private void setGridContentVisibility(boolean visible) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
index 7c378f0..915867b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
@@ -73,6 +73,10 @@ public class RotationLockTile extends QSTile<QSTile.BooleanState> {
: mController.isRotationLocked();
final boolean userInitiated = arg != null ? ((UserBoolean) arg).userInitiated : false;
state.visible = mController.isRotationLockAffordanceVisible();
+ if (state.value == rotationLocked) {
+ // No change, no need to update all the values.
+ return;
+ }
state.value = rotationLocked;
final boolean portrait = mContext.getResources().getConfiguration().orientation
!= Configuration.ORIENTATION_LANDSCAPE;
diff --git a/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java b/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java
index 8abfe03..cdb8e69 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java
@@ -74,6 +74,8 @@ public class ToggleSlider extends RelativeLayout {
mLabel = (TextView) findViewById(R.id.label);
mLabel.setText(a.getString(R.styleable.ToggleSlider_text));
+ setLabelFor(R.id.slider); // use our a11y text to annotate, not replace, the slider's
+
a.recycle();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
index c0b3a9b..7cde44c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
@@ -21,15 +21,8 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.BitmapShader;
import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffColorFilter;
import android.graphics.RectF;
-import android.graphics.Shader;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
@@ -100,7 +93,6 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
private boolean mDark;
private int mBgTint = 0;
- private final int mRoundedRectCornerRadius;
/**
* Flag to indicate that the notification has been touched once and the second touch will
@@ -126,10 +118,8 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
private NotificationBackgroundView mBackgroundDimmed;
private ObjectAnimator mBackgroundAnimator;
private RectF mAppearAnimationRect = new RectF();
- private PorterDuffColorFilter mAppearAnimationFilter;
private float mAnimationTranslationY;
private boolean mDrawingAppearAnimation;
- private Paint mAppearPaint = new Paint();
private ValueAnimator mAppearAnimator;
private float mAppearAnimationFraction = -1.0f;
private float mAppearAnimationTranslation;
@@ -151,9 +141,6 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
mLinearInterpolator = new LinearInterpolator();
setClipChildren(false);
setClipToPadding(false);
- mAppearAnimationFilter = new PorterDuffColorFilter(0, PorterDuff.Mode.SRC_ATOP);
- mRoundedRectCornerRadius = getResources().getDimensionPixelSize(
- R.dimen.notification_material_rounded_rect_radius);
mLegacyColor = context.getColor(R.color.notification_legacy_background_color);
mNormalColor = context.getColor(R.color.notification_material_background_color);
mLowPriorityColor = context.getColor(
@@ -540,9 +527,7 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
private void startAppearAnimation(boolean isAppearing, float translationDirection, long delay,
long duration, final Runnable onFinishedRunnable) {
- if (mAppearAnimator != null) {
- mAppearAnimator.cancel();
- }
+ cancelAppearAnimation();
mAnimationTranslationY = translationDirection * getActualHeight();
if (mAppearAnimationFraction == -1.0f) {
// not initialized yet, we start anew
@@ -613,6 +598,17 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
mAppearAnimator.start();
}
+ private void cancelAppearAnimation() {
+ if (mAppearAnimator != null) {
+ mAppearAnimator.cancel();
+ }
+ }
+
+ public void cancelAppearDrawing() {
+ cancelAppearAnimation();
+ enableAppearDrawing(false);
+ }
+
private void updateAppearRect() {
float inverseFraction = (1.0f - mAppearAnimationFraction);
float translationFraction = mCurrentAppearInterpolator.getInterpolation(inverseFraction);
@@ -652,20 +648,26 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
}
private void updateAppearAnimationAlpha() {
- int backgroundColor = getBgColor();
- if (backgroundColor != -1) {
- float contentAlphaProgress = mAppearAnimationFraction;
- contentAlphaProgress = contentAlphaProgress / (1.0f - ALPHA_ANIMATION_END);
- contentAlphaProgress = Math.min(1.0f, contentAlphaProgress);
- contentAlphaProgress = mCurrentAlphaInterpolator.getInterpolation(contentAlphaProgress);
- int sourceColor = Color.argb((int) (255 * (1.0f - contentAlphaProgress)),
- Color.red(backgroundColor), Color.green(backgroundColor),
- Color.blue(backgroundColor));
- mAppearAnimationFilter.setColor(sourceColor);
- mAppearPaint.setColorFilter(mAppearAnimationFilter);
+ float contentAlphaProgress = mAppearAnimationFraction;
+ contentAlphaProgress = contentAlphaProgress / (1.0f - ALPHA_ANIMATION_END);
+ contentAlphaProgress = Math.min(1.0f, contentAlphaProgress);
+ contentAlphaProgress = mCurrentAlphaInterpolator.getInterpolation(contentAlphaProgress);
+ setContentAlpha(contentAlphaProgress);
+ }
+
+ private void setContentAlpha(float contentAlpha) {
+ int layerType = contentAlpha == 0.0f || contentAlpha == 1.0f ? LAYER_TYPE_NONE
+ : LAYER_TYPE_HARDWARE;
+ View contentView = getContentView();
+ int currentLayerType = contentView.getLayerType();
+ if (currentLayerType != layerType) {
+ contentView.setLayerType(layerType, null);
}
+ contentView.setAlpha(contentAlpha);
}
+ protected abstract View getContentView();
+
private int getBgColor() {
if (mBgTint != 0) {
return mBgTint;
@@ -699,41 +701,24 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
*/
private void enableAppearDrawing(boolean enable) {
if (enable != mDrawingAppearAnimation) {
- if (enable) {
- if (getWidth() == 0 || getActualHeight() == 0) {
- // TODO: This should not happen, but it can during expansion. Needs
- // investigation
- return;
- }
- Bitmap bitmap = Bitmap.createBitmap(getWidth(), getActualHeight(),
- Bitmap.Config.ARGB_8888);
- Canvas canvas = new Canvas(bitmap);
- draw(canvas);
- mAppearPaint.setShader(new BitmapShader(bitmap, Shader.TileMode.CLAMP,
- Shader.TileMode.CLAMP));
- } else {
- mAppearPaint.setShader(null);
- }
mDrawingAppearAnimation = enable;
+ if (!enable) {
+ setContentAlpha(1.0f);
+ }
invalidate();
}
}
@Override
protected void dispatchDraw(Canvas canvas) {
- if (!mDrawingAppearAnimation) {
- super.dispatchDraw(canvas);
- } else {
- drawAppearRect(canvas);
+ if (mDrawingAppearAnimation) {
+ canvas.save();
+ canvas.translate(0, mAppearAnimationTranslation);
+ }
+ super.dispatchDraw(canvas);
+ if (mDrawingAppearAnimation) {
+ canvas.restore();
}
- }
-
- private void drawAppearRect(Canvas canvas) {
- canvas.save();
- canvas.translate(0, mAppearAnimationTranslation);
- canvas.drawRoundRect(mAppearAnimationRect, mRoundedRectCornerRadius,
- mRoundedRectCornerRadius, mAppearPaint);
- canvas.restore();
}
public void setOnActivatedListener(OnActivatedListener onActivatedListener) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 4cce1a4..85b4a64 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -65,6 +65,7 @@ import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.view.Display;
+import android.view.Gravity;
import android.view.IWindowManager;
import android.view.LayoutInflater;
import android.view.MotionEvent;
@@ -395,8 +396,14 @@ public abstract class BaseStatusBar extends SystemUI implements
if (recentTask != null && recentTask.size() > 0) {
UserInfo user = mUserManager.getUserInfo(recentTask.get(0).userId);
if (user != null && user.isManagedProfile()) {
- Toast.makeText(mContext, R.string.managed_profile_foreground_toast,
- Toast.LENGTH_SHORT).show();
+ LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
+ Context.LAYOUT_INFLATER_SERVICE);
+ View layout = inflater.inflate(R.layout.managed_profile_toast, null);
+ Toast toast = new Toast(mContext);
+ toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
+ toast.setDuration(Toast.LENGTH_SHORT);
+ toast.setView(layout);
+ toast.show();
}
}
} else if (BANNER_ACTION_CANCEL.equals(action) || BANNER_ACTION_SETUP.equals(action)) {
@@ -1848,11 +1855,8 @@ public abstract class BaseStatusBar extends SystemUI implements
}
}
- if (onKeyguard && mKeyguardIconOverflowContainer.getIconsView().getChildCount() > 0) {
- mKeyguardIconOverflowContainer.setVisibility(View.VISIBLE);
- } else {
- mKeyguardIconOverflowContainer.setVisibility(View.GONE);
- }
+ mStackScroller.updateOverflowContainerVisibility(onKeyguard
+ && mKeyguardIconOverflowContainer.getIconsView().getChildCount() > 0);
mStackScroller.changeViewPosition(mDismissView, mStackScroller.getChildCount() - 1);
mStackScroller.changeViewPosition(mEmptyShadeView, mStackScroller.getChildCount() - 2);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DelegateViewHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/DelegateViewHelper.java
deleted file mode 100644
index 2dc521e..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/DelegateViewHelper.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar;
-
-import android.app.StatusBarManager;
-import android.content.res.Resources;
-import android.graphics.RectF;
-import android.view.MotionEvent;
-import android.view.View;
-import com.android.systemui.R;
-import com.android.systemui.statusbar.phone.PhoneStatusBar;
-
-public class DelegateViewHelper {
- private View mDelegateView;
- private View mSourceView;
- private PhoneStatusBar mBar;
- private int[] mTempPoint = new int[2];
- private float[] mDownPoint = new float[2];
- private float mTriggerThreshhold;
- private boolean mPanelShowing;
-
- RectF mInitialTouch = new RectF();
- private boolean mStarted;
- private boolean mSwapXY = false;
- private boolean mDisabled;
-
- public DelegateViewHelper(View sourceView) {
- setSourceView(sourceView);
- }
-
- public void setDelegateView(View view) {
- mDelegateView = view;
- }
-
- public void setBar(PhoneStatusBar phoneStatusBar) {
- mBar = phoneStatusBar;
- }
-
- public boolean onInterceptTouchEvent(MotionEvent event) {
- if (mSourceView == null || mDelegateView == null || mBar.shouldDisableNavbarGestures()) {
- return false;
- }
-
- mSourceView.getLocationOnScreen(mTempPoint);
- final float sourceX = mTempPoint[0];
- final float sourceY = mTempPoint[1];
-
- final int action = event.getAction();
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- mPanelShowing = mDelegateView.getVisibility() == View.VISIBLE;
- mDownPoint[0] = event.getX();
- mDownPoint[1] = event.getY();
- mStarted = mInitialTouch.contains(mDownPoint[0] + sourceX, mDownPoint[1] + sourceY);
- break;
- }
-
- if (!mStarted) {
- return false;
- }
-
- if (!mDisabled && !mPanelShowing && action == MotionEvent.ACTION_MOVE) {
- final int historySize = event.getHistorySize();
- for (int k = 0; k < historySize + 1; k++) {
- float x = k < historySize ? event.getHistoricalX(k) : event.getX();
- float y = k < historySize ? event.getHistoricalY(k) : event.getY();
- final float distance = mSwapXY ? (mDownPoint[0] - x) : (mDownPoint[1] - y);
- if (distance > mTriggerThreshhold) {
- mBar.invokeAssistGesture(false /* vibrate */);
- mPanelShowing = true;
- break;
- }
- }
- }
-
- if (action == MotionEvent.ACTION_DOWN) {
- mBar.setInteracting(StatusBarManager.WINDOW_NAVIGATION_BAR, true);
- } else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
- mBar.setInteracting(StatusBarManager.WINDOW_NAVIGATION_BAR, false);
- }
-
- mDelegateView.getLocationOnScreen(mTempPoint);
- final float delegateX = mTempPoint[0];
- final float delegateY = mTempPoint[1];
-
- float deltaX = sourceX - delegateX;
- float deltaY = sourceY - delegateY;
- event.offsetLocation(deltaX, deltaY);
- mDelegateView.dispatchTouchEvent(event);
- event.offsetLocation(-deltaX, -deltaY);
- return mPanelShowing;
- }
-
- public void abortCurrentGesture() {
- if (mStarted) {
- mStarted = false;
- mBar.setInteracting(StatusBarManager.WINDOW_NAVIGATION_BAR, false);
- }
- }
-
- public void setSourceView(View view) {
- mSourceView = view;
- if (mSourceView != null) {
- Resources r = mSourceView.getContext().getResources();
- mTriggerThreshhold = r.getDimensionPixelSize(R.dimen.navigation_bar_min_swipe_distance);
- }
- }
-
- /**
- * Selects the initial touch region based on a list of views. This is meant to be called by
- * a container widget on children over which the initial touch should be detected. Note this
- * will compute a minimum bound that contains all specified views.
- *
- * @param views
- */
- public void setInitialTouchRegion(View ... views) {
- RectF bounds = new RectF();
- int p[] = new int[2];
- for (int i = 0; i < views.length; i++) {
- View view = views[i];
- if (view == null) continue;
- view.getLocationOnScreen(p);
- if (i == 0) {
- bounds.set(p[0], p[1], p[0] + view.getWidth(), p[1] + view.getHeight());
- } else {
- bounds.union(p[0], p[1], p[0] + view.getWidth(), p[1] + view.getHeight());
- }
- }
- mInitialTouch.set(bounds);
- }
-
- /**
- * When rotation is set to NO_SENSOR, then this allows swapping x/y for gesture detection
- * @param swap
- */
- public void setSwapXY(boolean swap) {
- mSwapXY = swap;
- }
-
- public void setDisabled(boolean disabled) {
- mDisabled = disabled;
- }
-} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index d444ea8..b88e5ca 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -856,6 +856,11 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
}
@Override
+ protected View getContentView() {
+ return getShowingLayout();
+ }
+
+ @Override
public void setActualHeight(int height, boolean notifyListeners) {
super.setActualHeight(height, notifyListeners);
int contentHeight = calculateContentHeightFromActualHeight(height);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java
index a18fff2..d77e050 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java
@@ -24,16 +24,21 @@ import android.util.AttributeSet;
import android.view.View;
import android.view.ViewOutlineProvider;
+import com.android.systemui.R;
+
/**
* Like {@link ExpandableView}, but setting an outline for the height and clipping.
*/
public abstract class ExpandableOutlineView extends ExpandableView {
private final Rect mOutlineRect = new Rect();
+ protected final int mRoundedRectCornerRadius;
private boolean mCustomOutline;
public ExpandableOutlineView(Context context, AttributeSet attrs) {
super(context, attrs);
+ mRoundedRectCornerRadius = getResources().getDimensionPixelSize(
+ R.dimen.notification_material_rounded_rect_radius);
setOutlineProvider(new ViewOutlineProvider() {
@Override
public void getOutline(View view, Outline outline) {
@@ -43,7 +48,7 @@ public abstract class ExpandableOutlineView extends ExpandableView {
getWidth(),
Math.max(getActualHeight(), mClipTopAmount));
} else {
- outline.setRect(mOutlineRect);
+ outline.setRoundRect(mOutlineRect, mRoundedRectCornerRadius);
}
}
});
@@ -66,12 +71,14 @@ public abstract class ExpandableOutlineView extends ExpandableView {
setOutlineRect(rect.left, rect.top, rect.right, rect.bottom);
} else {
mCustomOutline = false;
+ setClipToOutline(false);
invalidateOutline();
}
}
protected void setOutlineRect(float left, float top, float right, float bottom) {
mCustomOutline = true;
+ setClipToOutline(true);
mOutlineRect.set((int) left, (int) top, (int) right, (int) bottom);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
index 3feec9e..296538c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
@@ -43,6 +43,7 @@ public abstract class ExpandableView extends FrameLayout {
private ArrayList<View> mMatchParentViews = new ArrayList<View>();
private int mClipTopOptimization;
private static Rect mClipRect = new Rect();
+ private boolean mWillBeGone;
public ExpandableView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -133,6 +134,14 @@ public abstract class ExpandableView extends FrameLayout {
}
@Override
+ public boolean dispatchGenericMotionEvent(MotionEvent ev) {
+ if (filterMotionEvent(ev)) {
+ return super.dispatchGenericMotionEvent(ev);
+ }
+ return false;
+ }
+
+ @Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (filterMotionEvent(ev)) {
return super.dispatchTouchEvent(ev);
@@ -142,6 +151,8 @@ public abstract class ExpandableView extends FrameLayout {
protected boolean filterMotionEvent(MotionEvent event) {
return event.getActionMasked() != MotionEvent.ACTION_DOWN
+ && event.getActionMasked() != MotionEvent.ACTION_HOVER_ENTER
+ && event.getActionMasked() != MotionEvent.ACTION_HOVER_MOVE
|| event.getY() > mClipTopAmount && event.getY() < mActualHeight;
}
@@ -339,6 +350,13 @@ public abstract class ExpandableView extends FrameLayout {
outRect.top += getTranslationY() + getClipTopAmount();
}
+ @Override
+ public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
+ super.getBoundsOnScreen(outRect, clipToParent);
+ outRect.bottom = (int) (outRect.top + getActualHeight());
+ outRect.top += getClipTopAmount();
+ }
+
public int getContentHeight() {
return mActualHeight - getBottomDecorHeight();
}
@@ -374,6 +392,14 @@ public abstract class ExpandableView extends FrameLayout {
updateClipping();
}
+ public boolean willBeGone() {
+ return mWillBeGone;
+ }
+
+ public void setWillBeGone(boolean willBeGone) {
+ mWillBeGone = willBeGone;
+ }
+
/**
* A listener notifying when {@link #getActualHeight} changes.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowContainer.java
index 5fa7070..9653b67 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowContainer.java
@@ -18,6 +18,7 @@ package com.android.systemui.statusbar;
import android.content.Context;
import android.util.AttributeSet;
+import android.view.View;
import android.widget.TextView;
import com.android.systemui.R;
@@ -32,6 +33,7 @@ public class NotificationOverflowContainer extends ActivatableNotificationView {
private NotificationOverflowIconsView mIconsView;
private ViewInvertHelper mViewInvertHelper;
private boolean mDark;
+ private View mContent;
public NotificationOverflowContainer(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -43,7 +45,8 @@ public class NotificationOverflowContainer extends ActivatableNotificationView {
mIconsView = (NotificationOverflowIconsView) findViewById(R.id.overflow_icons_view);
mIconsView.setMoreText((TextView) findViewById(R.id.more_text));
mIconsView.setOverflowIndicator(findViewById(R.id.more_icon_overflow));
- mViewInvertHelper = new ViewInvertHelper(findViewById(R.id.content),
+ mContent = findViewById(R.id.content);
+ mViewInvertHelper = new ViewInvertHelper(mContent,
NotificationPanelView.DOZE_ANIMATION_DURATION);
}
@@ -59,6 +62,11 @@ public class NotificationOverflowContainer extends ActivatableNotificationView {
}
}
+ @Override
+ protected View getContentView() {
+ return mContent;
+ }
+
public NotificationOverflowIconsView getIconsView() {
return mIconsView;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StackScrollerDecorView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StackScrollerDecorView.java
index 64d80cc..2f66c41 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StackScrollerDecorView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StackScrollerDecorView.java
@@ -32,7 +32,6 @@ public abstract class StackScrollerDecorView extends ExpandableView {
protected View mContent;
private boolean mIsVisible;
private boolean mAnimating;
- private boolean mWillBeGone;
public StackScrollerDecorView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -134,13 +133,5 @@ public abstract class StackScrollerDecorView extends ExpandableView {
mContent.animate().cancel();
}
- public boolean willBeGone() {
- return mWillBeGone;
- }
-
- public void setWillBeGone(boolean willBeGone) {
- mWillBeGone = willBeGone;
- }
-
protected abstract View findContentView();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 636c511..f40f501 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -47,7 +47,6 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import com.android.systemui.R;
-import com.android.systemui.statusbar.DelegateViewHelper;
import com.android.systemui.statusbar.policy.DeadZone;
import com.android.systemui.statusbar.policy.KeyButtonView;
@@ -79,7 +78,6 @@ public class NavigationBarView extends LinearLayout {
private Drawable mRecentLandIcon;
private NavigationBarViewTaskSwitchHelper mTaskSwitchHelper;
- private DelegateViewHelper mDelegateHelper;
private DeadZone mDeadZone;
private final NavigationBarTransitions mBarTransitions;
@@ -92,7 +90,6 @@ public class NavigationBarView extends LinearLayout {
private OnVerticalChangedListener mOnVerticalChangedListener;
private boolean mIsLayoutRtl;
- private boolean mDelegateIntercepted;
private class NavTransitionListener implements TransitionListener {
private boolean mBackTransitioning;
@@ -180,7 +177,6 @@ public class NavigationBarView extends LinearLayout {
mBarSize = res.getDimensionPixelSize(R.dimen.navigation_bar_size);
mVertical = false;
mShowMenu = false;
- mDelegateHelper = new DelegateViewHelper(this);
mTaskSwitchHelper = new NavigationBarViewTaskSwitchHelper(context);
getIcons(res);
@@ -192,13 +188,8 @@ public class NavigationBarView extends LinearLayout {
return mBarTransitions;
}
- public void setDelegateView(View view) {
- mDelegateHelper.setDelegateView(view);
- }
-
public void setBar(PhoneStatusBar phoneStatusBar) {
mTaskSwitchHelper.setBar(phoneStatusBar);
- mDelegateHelper.setBar(phoneStatusBar);
}
public void setOnVerticalChangedListener(OnVerticalChangedListener onVerticalChangedListener) {
@@ -208,44 +199,21 @@ public class NavigationBarView extends LinearLayout {
@Override
public boolean onTouchEvent(MotionEvent event) {
- initDownStates(event);
- if (!mDelegateIntercepted && mTaskSwitchHelper.onTouchEvent(event)) {
+ if (mTaskSwitchHelper.onTouchEvent(event)) {
return true;
}
if (mDeadZone != null && event.getAction() == MotionEvent.ACTION_OUTSIDE) {
mDeadZone.poke(event);
}
- if (mDelegateHelper != null && mDelegateIntercepted) {
- boolean ret = mDelegateHelper.onInterceptTouchEvent(event);
- if (ret) return true;
- }
return super.onTouchEvent(event);
}
- private void initDownStates(MotionEvent ev) {
- if (ev.getAction() == MotionEvent.ACTION_DOWN) {
- mDelegateIntercepted = false;
- }
- }
-
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
- initDownStates(event);
- boolean intercept = mTaskSwitchHelper.onInterceptTouchEvent(event);
- if (!intercept) {
- mDelegateIntercepted = mDelegateHelper.onInterceptTouchEvent(event);
- intercept = mDelegateIntercepted;
- } else {
- MotionEvent cancelEvent = MotionEvent.obtain(event);
- cancelEvent.setAction(MotionEvent.ACTION_CANCEL);
- mDelegateHelper.onInterceptTouchEvent(cancelEvent);
- cancelEvent.recycle();
- }
- return intercept;
+ return mTaskSwitchHelper.onInterceptTouchEvent(event);
}
public void abortCurrentGesture() {
- mDelegateHelper.abortCurrentGesture();
getHomeButton().abortCurrentGesture();
}
@@ -461,10 +429,6 @@ public class NavigationBarView extends LinearLayout {
Log.d(TAG, "reorient(): rot=" + mDisplay.getRotation());
}
- // swap to x coordinate if orientation is not in vertical
- if (mDelegateHelper != null) {
- mDelegateHelper.setSwapXY(mVertical);
- }
updateTaskSwitchHelper();
setNavigationIconHints(mNavigationIconHints, true);
@@ -476,12 +440,6 @@ public class NavigationBarView extends LinearLayout {
}
@Override
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
- super.onLayout(changed, l, t, r, b);
- mDelegateHelper.setInitialTouchRegion(getHomeButton(), getBackButton(), getRecentsButton());
- }
-
- @Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
if (DEBUG) Log.d(TAG, String.format(
"onSizeChanged: (%dx%d) old: (%dx%d)", w, h, oldw, oldh));
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 9e1af82..a750572 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -487,6 +487,7 @@ public class NotificationPanelView extends PanelView implements
mStatusBar.dismissPopups();
mNotificationStackScroller.setOverScrollAmount(0f, true /* onTop */, false /* animate */,
true /* cancelAnimators */);
+ mNotificationStackScroller.resetScrollPosition();
}
public void closeQs() {
@@ -1716,12 +1717,16 @@ public class NotificationPanelView extends PanelView implements
float alphaQsExpansion = 1 - Math.min(1, getQsExpansionFraction() * 2);
mKeyguardStatusBar.setAlpha(Math.min(getKeyguardContentsAlpha(), alphaQsExpansion)
* mKeyguardStatusBarAnimateAlpha);
+ mKeyguardStatusBar.setVisibility(mKeyguardStatusBar.getAlpha() != 0f ? VISIBLE : INVISIBLE);
setQsTranslation(mQsExpansionHeight);
}
private void updateKeyguardBottomAreaAlpha() {
- mKeyguardBottomArea.setAlpha(
- Math.min(getKeyguardContentsAlpha(), 1 - getQsExpansionFraction()));
+ float alpha = Math.min(getKeyguardContentsAlpha(), 1 - getQsExpansionFraction());
+ mKeyguardBottomArea.setAlpha(alpha);
+ mKeyguardBottomArea.setImportantForAccessibility(alpha == 0f
+ ? IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
+ : IMPORTANT_FOR_ACCESSIBILITY_AUTO);
}
private float getNotificationsTopY() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
index 54bd3e9..552a0b2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
@@ -81,10 +81,13 @@ public class PanelBar extends FrameLayout {
}
public void setBouncerShowing(boolean showing) {
+ int important = showing ? IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
+ : IMPORTANT_FOR_ACCESSIBILITY_AUTO;
+
+ setImportantForAccessibility(important);
+
if (mPanelHolder != null) {
- mPanelHolder.setImportantForAccessibility(
- showing ? IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
- : IMPORTANT_FOR_ACCESSIBILITY_AUTO);
+ mPanelHolder.setImportantForAccessibility(important);
}
}
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 a5b18f9..33e8e59 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -707,7 +707,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
R.layout.status_bar_notification_keyguard_overflow, mStackScroller, false);
mKeyguardIconOverflowContainer.setOnActivatedListener(this);
mKeyguardIconOverflowContainer.setOnClickListener(mOverflowClickListener);
- mStackScroller.addView(mKeyguardIconOverflowContainer);
+ mStackScroller.setOverflowContainer(mKeyguardIconOverflowContainer);
SpeedBumpView speedBump = (SpeedBumpView) LayoutInflater.from(mContext).inflate(
R.layout.status_bar_notification_speed_bump, mStackScroller, false);
@@ -1861,6 +1861,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
public void setQsExpanded(boolean expanded) {
mStatusBarWindowManager.setQsExpanded(expanded);
+ mKeyguardStatusView.setImportantForAccessibility(expanded
+ ? View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
+ : View.IMPORTANT_FOR_ACCESSIBILITY_AUTO);
}
public boolean isGoingToNotificationShade() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index 7f1fea1..634270c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -83,6 +83,10 @@ public class StatusBarWindowView extends FrameLayout {
insets.top = 0;
insets.right = 0;
} else {
+ if (mRightInset != 0) {
+ mRightInset = 0;
+ applyMargins();
+ }
boolean changed = getPaddingLeft() != 0
|| getPaddingRight() != 0
|| getPaddingTop() != 0
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
index 6e30803..98bbe7c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
@@ -552,6 +552,7 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL
}
public void updateEntry() {
+ mSortedEntries.remove(HeadsUpEntry.this);
long currentTime = mClock.currentTimeMillis();
earliestRemovaltime = currentTime + mMinimumDisplayTime;
postTime = Math.max(postTime, currentTime);
@@ -561,13 +562,13 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL
long removeDelay = Math.max(finishTime - currentTime, mMinimumDisplayTime);
mHandler.postDelayed(mRemoveHeadsUpRunnable, removeDelay);
}
- updateSortOrder(HeadsUpEntry.this);
+ mSortedEntries.add(HeadsUpEntry.this);
}
@Override
public int compareTo(HeadsUpEntry o) {
return postTime < o.postTime ? 1
- : postTime == o.postTime ? 0
+ : postTime == o.postTime ? entry.key.compareTo(o.entry.key)
: -1;
}
@@ -592,16 +593,6 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL
}
}
- /**
- * Update the sorted heads up order.
- *
- * @param headsUpEntry the headsUp that changed
- */
- private void updateSortOrder(HeadsUpEntry headsUpEntry) {
- mSortedEntries.remove(headsUpEntry);
- mSortedEntries.add(headsUpEntry);
- }
-
public static class Clock {
public long currentTimeMillis() {
return SystemClock.elapsedRealtime();
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 1460e5f..5cf6156 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java
@@ -30,7 +30,7 @@ import android.view.ViewStub;
import android.view.animation.AnimationUtils;
import android.widget.FrameLayout;
-import com.android.keyguard.AppearAnimationUtils;
+import com.android.settingslib.animation.AppearAnimationUtils;
import com.android.systemui.R;
import com.android.systemui.qs.tiles.UserDetailItemView;
import com.android.systemui.statusbar.phone.KeyguardStatusBarView;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index d8f6bcd..1bf4547 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -43,6 +43,7 @@ import com.android.systemui.statusbar.EmptyShadeView;
import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.ExpandableView;
import com.android.systemui.statusbar.NotificationData;
+import com.android.systemui.statusbar.NotificationOverflowContainer;
import com.android.systemui.statusbar.SpeedBumpView;
import com.android.systemui.statusbar.StackScrollerDecorView;
import com.android.systemui.statusbar.StatusBarState;
@@ -226,6 +227,7 @@ public class NotificationStackScrollLayout extends ViewGroup
private boolean mTrackingHeadsUp;
private ScrimController mScrimController;
private boolean mForceNoOverlappingRendering;
+ private NotificationOverflowContainer mOverflowContainer;
public NotificationStackScrollLayout(Context context) {
this(context, null);
@@ -1368,17 +1370,11 @@ public class NotificationStackScrollLayout extends ViewGroup
int childCount = getChildCount();
int count = 0;
for (int i = 0; i < childCount; i++) {
- View child = getChildAt(i);
- if (child.getVisibility() != View.GONE) {
+ ExpandableView child = (ExpandableView) getChildAt(i);
+ if (child.getVisibility() != View.GONE && !child.willBeGone()) {
count++;
}
}
- if (mDismissView.willBeGone()) {
- count--;
- }
- if (mEmptyShadeView.willBeGone()) {
- count--;
- }
return count;
}
@@ -2234,6 +2230,11 @@ public class NotificationStackScrollLayout extends ViewGroup
}
}
+ public void resetScrollPosition() {
+ mScroller.abortAnimation();
+ mOwnScrollY = 0;
+ }
+
private void setIsExpanded(boolean isExpanded) {
boolean changed = isExpanded != mIsExpanded;
mIsExpanded = isExpanded;
@@ -2291,6 +2292,10 @@ public class NotificationStackScrollLayout extends ViewGroup
public void onChildAnimationFinished() {
requestChildrenUpdate();
+ runAnimationFinishedRunnables();
+ }
+
+ private void runAnimationFinishedRunnables() {
for (Runnable runnable : mAnimationFinishedRunnables) {
runnable.run();
}
@@ -2348,6 +2353,7 @@ public class NotificationStackScrollLayout extends ViewGroup
if (mListener != null) {
mListener.onChildLocationsChanged(this);
}
+ runAnimationFinishedRunnables();
}
public void setSpeedBumpView(SpeedBumpView speedBumpView) {
@@ -2470,7 +2476,7 @@ public class NotificationStackScrollLayout extends ViewGroup
mEmptyShadeView.setVisibility(newVisibility);
mEmptyShadeView.setWillBeGone(false);
updateContentHeight();
- notifyHeightChangeListener(mDismissView);
+ notifyHeightChangeListener(mEmptyShadeView);
} else {
Runnable onFinishedRunnable = new Runnable() {
@Override
@@ -2478,7 +2484,7 @@ public class NotificationStackScrollLayout extends ViewGroup
mEmptyShadeView.setVisibility(GONE);
mEmptyShadeView.setWillBeGone(false);
updateContentHeight();
- notifyHeightChangeListener(mDismissView);
+ notifyHeightChangeListener(mEmptyShadeView);
}
};
if (mAnimationsEnabled) {
@@ -2492,6 +2498,45 @@ public class NotificationStackScrollLayout extends ViewGroup
}
}
+ public void setOverflowContainer(NotificationOverflowContainer overFlowContainer) {
+ mOverflowContainer = overFlowContainer;
+ addView(mOverflowContainer);
+ }
+
+ public void updateOverflowContainerVisibility(boolean visible) {
+ int oldVisibility = mOverflowContainer.willBeGone() ? GONE
+ : mOverflowContainer.getVisibility();
+ final int newVisibility = visible ? VISIBLE : GONE;
+ if (oldVisibility != newVisibility) {
+ Runnable onFinishedRunnable = new Runnable() {
+ @Override
+ public void run() {
+ mOverflowContainer.setVisibility(newVisibility);
+ mOverflowContainer.setWillBeGone(false);
+ updateContentHeight();
+ notifyHeightChangeListener(mOverflowContainer);
+ }
+ };
+ if (!mAnimationsEnabled || !mIsExpanded) {
+ mOverflowContainer.cancelAppearDrawing();
+ onFinishedRunnable.run();
+ } else if (newVisibility != GONE) {
+ mOverflowContainer.performAddAnimation(0,
+ StackStateAnimator.ANIMATION_DURATION_STANDARD);
+ mOverflowContainer.setVisibility(newVisibility);
+ mOverflowContainer.setWillBeGone(false);
+ updateContentHeight();
+ notifyHeightChangeListener(mOverflowContainer);
+ } else {
+ mOverflowContainer.performRemoveAnimation(
+ StackStateAnimator.ANIMATION_DURATION_STANDARD,
+ 0.0f,
+ onFinishedRunnable);
+ mOverflowContainer.setWillBeGone(true);
+ }
+ }
+ }
+
public void updateDismissView(boolean visible) {
int oldVisibility = mDismissView.willBeGone() ? GONE : mDismissView.getVisibility();
int newVisibility = visible ? VISIBLE : GONE;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
index feae590..a70ad43 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
@@ -210,7 +210,10 @@ public class StackScrollState {
int oldVisibility = view.getVisibility();
int newVisibility = becomesInvisible ? View.INVISIBLE : View.VISIBLE;
if (newVisibility != oldVisibility) {
- view.setVisibility(newVisibility);
+ if (!(view instanceof ExpandableView) || !((ExpandableView) view).willBeGone()) {
+ // We don't want views to change visibility when they are animating to GONE
+ view.setVisibility(newVisibility);
+ }
}
// apply yTranslation
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
index c31244c..c995c8e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
@@ -285,6 +285,10 @@ public class StackStateAnimator {
boolean scaleChanging = child.getScaleX() != viewState.scale;
float childAlpha = child.getVisibility() == View.INVISIBLE ? 0.0f : child.getAlpha();
boolean alphaChanging = viewState.alpha != childAlpha;
+ if (child instanceof ExpandableView) {
+ // We don't want views to change visibility when they are animating to GONE
+ alphaChanging &= !((ExpandableView) child).willBeGone();
+ }
// start translationY animation
if (yTranslationChanging) {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
index 29bea4d..49278c5 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
@@ -524,6 +524,7 @@ public class VolumeDialog {
}
}
Util.setVisOrInvis(row.settingsButton, false);
+ updateVolumeRowHeaderVisibleH(row);
row.header.setAlpha(mExpanded && isActive ? 1 : 0.5f);
updateVolumeRowSliderTintH(row, isActive);
}
@@ -606,25 +607,22 @@ public class VolumeDialog {
}
// update header visible
- if (row.cachedShowHeaders != mShowHeaders) {
- row.cachedShowHeaders = mShowHeaders;
- Util.setVisOrGone(row.header, mShowHeaders);
- }
+ updateVolumeRowHeaderVisibleH(row);
// update header text
- final String text;
- if (isRingZenNone) {
- text = mContext.getString(R.string.volume_stream_muted_dnd, ss.name);
- } else if (isRingVibrate && isRingLimited) {
- text = mContext.getString(R.string.volume_stream_vibrate_dnd, ss.name);
- } else if (isRingVibrate) {
- text = mContext.getString(R.string.volume_stream_vibrate, ss.name);
- } else if (ss.muted || mAutomute && ss.level == 0) {
- text = mContext.getString(R.string.volume_stream_muted, ss.name);
- } else if (isRingLimited) {
- text = mContext.getString(R.string.volume_stream_limited_dnd, ss.name);
- } else {
- text = ss.name;
+ String text = ss.name;
+ if (mShowHeaders) {
+ if (isRingZenNone) {
+ text = mContext.getString(R.string.volume_stream_muted_dnd, ss.name);
+ } else if (isRingVibrate && isRingLimited) {
+ text = mContext.getString(R.string.volume_stream_vibrate_dnd, ss.name);
+ } else if (isRingVibrate) {
+ text = mContext.getString(R.string.volume_stream_vibrate, ss.name);
+ } else if (ss.muted || mAutomute && ss.level == 0) {
+ text = mContext.getString(R.string.volume_stream_muted, ss.name);
+ } else if (isRingLimited) {
+ text = mContext.getString(R.string.volume_stream_limited_dnd, ss.name);
+ }
}
Util.setText(row.header, text);
@@ -663,6 +661,15 @@ public class VolumeDialog {
updateVolumeRowSliderH(row, enableSlider, vlevel);
}
+ private void updateVolumeRowHeaderVisibleH(VolumeRow row) {
+ final boolean dynamic = row.ss != null && row.ss.dynamic;
+ final boolean showHeaders = mShowHeaders || mExpanded && dynamic;
+ if (row.cachedShowHeaders != showHeaders) {
+ row.cachedShowHeaders = showHeaders;
+ Util.setVisOrGone(row.header, showHeaders);
+ }
+ }
+
private void updateVolumeRowSliderTintH(VolumeRow row, boolean isActive) {
final ColorStateList tint = isActive && row.slider.isEnabled() ? mActiveSliderTint
: mInactiveSliderTint;
diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
index ced1a3c..a0eb61f 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
@@ -153,7 +153,7 @@ public class ZenModePanel extends LinearLayout {
mZenButtons = (SegmentedButtons) findViewById(R.id.zen_buttons);
mZenButtons.addButton(R.string.interruption_level_none_twoline,
- R.string.interruption_level_none,
+ R.string.interruption_level_none_with_warning,
Global.ZEN_MODE_NO_INTERRUPTIONS);
mZenButtons.addButton(R.string.interruption_level_alarms_twoline,
R.string.interruption_level_alarms,
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 2f68aa8..9c6e16f 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -100,6 +100,7 @@ import android.util.Xml;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IBatteryStats;
import com.android.internal.net.LegacyVpnInfo;
import com.android.internal.net.NetworkStatsFactory;
@@ -768,7 +769,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
return mNextNetworkRequestId++;
}
- private int reserveNetId() {
+ @VisibleForTesting
+ protected int reserveNetId() {
synchronized (mNetworkForNetId) {
for (int i = MIN_NET_ID; i <= MAX_NET_ID; i++) {
int netId = mNextNetId;
@@ -1665,6 +1667,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
private static final String DEFAULT_TCP_RWND_KEY = "net.tcp.default_init_rwnd";
// Overridden for testing purposes to avoid writing to SystemProperties.
+ @VisibleForTesting
protected int getDefaultTcpRwnd() {
return SystemProperties.getInt(DEFAULT_TCP_RWND_KEY, 0);
}
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 4c7b523..ad34b37 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -22,6 +22,7 @@ import android.app.AlarmManager;
import android.app.AppGlobals;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -29,12 +30,14 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.database.ContentObserver;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.hardware.TriggerEvent;
import android.hardware.TriggerEventListener;
import android.hardware.display.DisplayManager;
import android.net.INetworkPolicyManager;
+import android.net.Uri;
import android.os.Binder;
import android.os.Environment;
import android.os.FileUtils;
@@ -48,11 +51,11 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.UserHandle;
+import android.provider.Settings;
import android.util.ArrayMap;
import android.util.ArraySet;
-import android.util.Log;
+import android.util.KeyValueListParser;
import android.util.Slog;
-import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.SparseLongArray;
import android.util.TimeUtils;
@@ -62,7 +65,6 @@ import android.view.Display;
import com.android.internal.app.IBatteryStats;
import com.android.internal.os.AtomicFile;
import com.android.internal.os.BackgroundThread;
-import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.XmlUtils;
import com.android.server.am.BatteryStatsService;
@@ -103,84 +105,7 @@ public class DeviceIdleController extends SystemService
// TODO: These need to be moved to system settings.
- /**
- * This is the time, after becoming inactive, at which we start looking at the
- * motion sensor to determine if the device is being left alone. We don't do this
- * immediately after going inactive just because we don't want to be continually running
- * the significant motion sensor whenever the screen is off.
- */
-
- private static final long DEFAULT_INACTIVE_TIMEOUT = !COMPRESS_TIME ? 30*60*1000L
- : 3 * 60 * 1000L;
-
- /**
- * If we don't receive a callback from AnyMotion in this amount of time, we will change from
- * STATE_SENSING to STATE_INACTIVE, and any AnyMotion callbacks while not in STATE_SENSING will
- * be ignored.
- */
- private static final long DEFAULT_SENSING_TIMEOUT = !DEBUG ? 5 * 60 * 1000L : 60 * 1000L;
-
- /**
- * This is the time, after seeing motion, that we wait after becoming inactive from
- * that until we start looking for motion again.
- */
- private static final long DEFAULT_MOTION_INACTIVE_TIMEOUT = !COMPRESS_TIME ? 10*60*1000L
- : 60 * 1000L;
-
- /**
- * This is the time, after the inactive timeout elapses, that we will wait looking
- * for significant motion until we truly consider the device to be idle.
- */
-
- private static final long DEFAULT_IDLE_AFTER_INACTIVE_TIMEOUT = !COMPRESS_TIME ? 30*60*1000L
- : 3 * 60 * 1000L;
-
- /**
- * This is the initial time, after being idle, that we will allow ourself to be back
- * in the IDLE_PENDING state allowing the system to run normally until we return to idle.
- */
-
- private static final long DEFAULT_IDLE_PENDING_TIMEOUT = !COMPRESS_TIME ? 5*60*1000L
- : 30 * 1000L;
-
- /**
- * Maximum pending idle timeout (time spent running) we will be allowed to use.
- */
- private static final long DEFAULT_MAX_IDLE_PENDING_TIMEOUT = !COMPRESS_TIME ? 10*60*1000L
- : 60 * 1000L;
- /**
- * Scaling factor to apply to current pending idle timeout each time we cycle through
- * that state.
- */
- private static final float DEFAULT_IDLE_PENDING_FACTOR = 2f;
- /**
- * This is the initial time that we want to sit in the idle state before waking up
- * again to return to pending idle and allowing normal work to run.
- */
-
- private static final long DEFAULT_IDLE_TIMEOUT = !COMPRESS_TIME ? 60*60*1000L
- : 6 * 60 * 1000L;
-
- /**
- * Maximum idle duration we will be allowed to use.
- */
- private static final long DEFAULT_MAX_IDLE_TIMEOUT = !COMPRESS_TIME ? 6*60*60*1000L
- : 30 * 60 * 1000L;
- /**
- * Scaling factor to apply to current idle timeout each time we cycle through that state.
- */
- private static final float DEFAULT_IDLE_FACTOR = 2f;
- /**
- * This is the minimum time we will allow until the next upcoming alarm for us to
- * actually go in to idle mode.
- */
- private static final long DEFAULT_MIN_TIME_TO_ALARM = !COMPRESS_TIME ? 60*60*1000L
- : 6 * 60 * 1000L;
- /**
- * Max amount of time to temporarily whitelist an app when it receives a high priority tickle.
- */
- private static final long MAX_TEMP_APP_WHITELIST_DURATION = 5 * 60 * 1000L;
private AlarmManager mAlarmManager;
private IBatteryStats mBatteryStats;
@@ -306,6 +231,230 @@ public class DeviceIdleController extends SystemService
}
};
+ /**
+ * All times are in milliseconds. These constants are kept synchronized with the system
+ * global Settings. Any access to this class or its fields should be done while
+ * holding the DeviceIdleController lock.
+ */
+ private class Constants extends ContentObserver {
+ // Key names stored in the settings value.
+ private static final String KEY_INACTIVE_TIMEOUT = "inactive_to";
+ private static final String KEY_SENSING_TIMEOUT = "sensing_to";
+ private static final String KEY_MOTION_INACTIVE_TIMEOUT = "motion_inactive_to";
+ private static final String KEY_IDLE_AFTER_INACTIVE_TIMEOUT = "idle_after_inactive_to";
+ private static final String KEY_IDLE_PENDING_TIMEOUT = "idle_pending_to";
+ private static final String KEY_MAX_IDLE_PENDING_TIMEOUT = "max_idle_pending_to";
+ private static final String KEY_IDLE_PENDING_FACTOR = "idle_pending_factor";
+ private static final String KEY_IDLE_TIMEOUT = "idle_to";
+ private static final String KEY_MAX_IDLE_TIMEOUT = "max_idle_to";
+ private static final String KEY_IDLE_FACTOR = "idle_factor";
+ private static final String KEY_MIN_TIME_TO_ALARM = "min_time_to_alarm";
+ private static final String KEY_MAX_TEMP_APP_WHITELIST_DURATION =
+ "max_temp_app_whitelist_duration";
+
+ /**
+ * This is the time, after becoming inactive, at which we start looking at the
+ * motion sensor to determine if the device is being left alone. We don't do this
+ * immediately after going inactive just because we don't want to be continually running
+ * the significant motion sensor whenever the screen is off.
+ * @see Settings.Global#DEVICE_IDLE_CONSTANTS
+ * @see #KEY_INACTIVE_TIMEOUT
+ */
+ public long INACTIVE_TIMEOUT;
+
+ /**
+ * If we don't receive a callback from AnyMotion in this amount of time, we will change from
+ * STATE_SENSING to STATE_INACTIVE, and any AnyMotion callbacks while not in STATE_SENSING
+ * will be ignored.
+ * @see Settings.Global#DEVICE_IDLE_CONSTANTS
+ * @see #KEY_SENSING_TIMEOUT
+ */
+ public long SENSING_TIMEOUT;
+
+ /**
+ * This is the time, after seeing motion, that we wait after becoming inactive from
+ * that until we start looking for motion again.
+ * @see Settings.Global#DEVICE_IDLE_CONSTANTS
+ * @see #KEY_MOTION_INACTIVE_TIMEOUT
+ */
+ public long MOTION_INACTIVE_TIMEOUT;
+
+ /**
+ * This is the time, after the inactive timeout elapses, that we will wait looking
+ * for significant motion until we truly consider the device to be idle.
+ * @see Settings.Global#DEVICE_IDLE_CONSTANTS
+ * @see #KEY_IDLE_AFTER_INACTIVE_TIMEOUT
+ */
+ public long IDLE_AFTER_INACTIVE_TIMEOUT;
+
+ /**
+ * This is the initial time, after being idle, that we will allow ourself to be back
+ * in the IDLE_PENDING state allowing the system to run normally until we return to idle.
+ * @see Settings.Global#DEVICE_IDLE_CONSTANTS
+ * @see #KEY_IDLE_PENDING_TIMEOUT
+ */
+ public long IDLE_PENDING_TIMEOUT;
+
+ /**
+ * Maximum pending idle timeout (time spent running) we will be allowed to use.
+ * @see Settings.Global#DEVICE_IDLE_CONSTANTS
+ * @see #KEY_MAX_IDLE_PENDING_TIMEOUT
+ */
+ public long MAX_IDLE_PENDING_TIMEOUT;
+
+ /**
+ * Scaling factor to apply to current pending idle timeout each time we cycle through
+ * that state.
+ * @see Settings.Global#DEVICE_IDLE_CONSTANTS
+ * @see #KEY_IDLE_PENDING_FACTOR
+ */
+ public float IDLE_PENDING_FACTOR;
+
+ /**
+ * This is the initial time that we want to sit in the idle state before waking up
+ * again to return to pending idle and allowing normal work to run.
+ * @see Settings.Global#DEVICE_IDLE_CONSTANTS
+ * @see #KEY_IDLE_TIMEOUT
+ */
+ public long IDLE_TIMEOUT;
+
+ /**
+ * Maximum idle duration we will be allowed to use.
+ * @see Settings.Global#DEVICE_IDLE_CONSTANTS
+ * @see #KEY_MAX_IDLE_TIMEOUT
+ */
+ public long MAX_IDLE_TIMEOUT;
+
+ /**
+ * Scaling factor to apply to current idle timeout each time we cycle through that state.
+ * @see Settings.Global#DEVICE_IDLE_CONSTANTS
+ * @see #KEY_IDLE_FACTOR
+ */
+ public float IDLE_FACTOR;
+
+ /**
+ * This is the minimum time we will allow until the next upcoming alarm for us to
+ * actually go in to idle mode.
+ * @see Settings.Global#DEVICE_IDLE_CONSTANTS
+ * @see #KEY_MIN_TIME_TO_ALARM
+ */
+ public long MIN_TIME_TO_ALARM;
+
+ /**
+ * Max amount of time to temporarily whitelist an app when it receives a high priority
+ * tickle.
+ * @see Settings.Global#DEVICE_IDLE_CONSTANTS
+ * @see #KEY_MAX_TEMP_APP_WHITELIST_DURATION
+ */
+ public long MAX_TEMP_APP_WHITELIST_DURATION;
+
+ private final ContentResolver mResolver;
+ private final KeyValueListParser mParser = new KeyValueListParser(',');
+
+ public Constants(Handler handler, ContentResolver resolver) {
+ super(handler);
+ mResolver = resolver;
+ mResolver.registerContentObserver(
+ Settings.Global.getUriFor(Settings.Global.DEVICE_IDLE_CONSTANTS), false, this);
+ updateConstants();
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ updateConstants();
+ }
+
+ private void updateConstants() {
+ synchronized (DeviceIdleController.this) {
+ try {
+ mParser.setString(Settings.Global.getString(mResolver,
+ Settings.Global.DEVICE_IDLE_CONSTANTS));
+ } catch (IllegalArgumentException e) {
+ // Failed to parse the settings string, log this and move on
+ // with defaults.
+ Slog.e(TAG, "Bad device idle settings", e);
+ }
+
+ INACTIVE_TIMEOUT = mParser.getLong(KEY_INACTIVE_TIMEOUT,
+ !COMPRESS_TIME ? 30 * 60 * 1000L : 3 * 60 * 1000L);
+ SENSING_TIMEOUT = mParser.getLong(KEY_SENSING_TIMEOUT,
+ !DEBUG ? 5 * 60 * 1000L : 60 * 1000L);
+ MOTION_INACTIVE_TIMEOUT = mParser.getLong(KEY_MOTION_INACTIVE_TIMEOUT,
+ !COMPRESS_TIME ? 10 * 60 * 1000L : 60 * 1000L);
+ IDLE_AFTER_INACTIVE_TIMEOUT = mParser.getLong(KEY_IDLE_AFTER_INACTIVE_TIMEOUT,
+ !COMPRESS_TIME ? 30 * 60 * 1000L : 3 * 60 * 1000L);
+ IDLE_PENDING_TIMEOUT = mParser.getLong(KEY_IDLE_PENDING_TIMEOUT,
+ !COMPRESS_TIME ? 5 * 60 * 1000L : 30 * 1000L);
+ MAX_IDLE_PENDING_TIMEOUT = mParser.getLong(KEY_MAX_IDLE_PENDING_TIMEOUT,
+ !COMPRESS_TIME ? 10 * 60 * 1000L : 60 * 1000L);
+ IDLE_PENDING_FACTOR = mParser.getFloat(KEY_IDLE_PENDING_FACTOR,
+ 2f);
+ IDLE_TIMEOUT = mParser.getLong(KEY_IDLE_TIMEOUT,
+ !COMPRESS_TIME ? 60 * 60 * 1000L : 6 * 60 * 1000L);
+ MAX_IDLE_TIMEOUT = mParser.getLong(KEY_MAX_IDLE_TIMEOUT,
+ !COMPRESS_TIME ? 6 * 60 * 60 * 1000L : 30 * 60 * 1000L);
+ IDLE_FACTOR = mParser.getFloat(KEY_IDLE_FACTOR,
+ 2f);
+ MIN_TIME_TO_ALARM = mParser.getLong(KEY_MIN_TIME_TO_ALARM,
+ !COMPRESS_TIME ? 60 * 60 * 1000L : 6 * 60 * 1000L);
+ MAX_TEMP_APP_WHITELIST_DURATION = mParser.getLong(KEY_MAX_TEMP_APP_WHITELIST_DURATION,
+ 5 * 60 * 1000L);
+ }
+ }
+
+ void dump(PrintWriter pw) {
+ pw.println(" Settings:");
+
+ pw.print(" DOZE_INACTIVE_TIMEOUT=");
+ TimeUtils.formatDuration(INACTIVE_TIMEOUT, pw);
+ pw.println();
+
+ pw.print(" DOZE_SENSING_TIMEOUT=");
+ TimeUtils.formatDuration(SENSING_TIMEOUT, pw);
+ pw.println();
+
+ pw.print(" DOZE_MOTION_INACTIVE_TIMEOUT=");
+ TimeUtils.formatDuration(MOTION_INACTIVE_TIMEOUT, pw);
+ pw.println();
+
+ pw.print(" DOZE_IDLE_AFTER_INACTIVE_TIMEOUT=");
+ TimeUtils.formatDuration(IDLE_AFTER_INACTIVE_TIMEOUT, pw);
+ pw.println();
+
+ pw.print(" DOZE_IDLE_PENDING_TIMEOUT=");
+ TimeUtils.formatDuration(IDLE_PENDING_TIMEOUT, pw);
+ pw.println();
+
+ pw.print(" DOZE_MAX_IDLE_PENDING_TIMEOUT=");
+ TimeUtils.formatDuration(MAX_IDLE_PENDING_TIMEOUT, pw);
+ pw.println();
+
+ pw.print(" DOZE_IDLE_PENDING_FACTOR=");
+ pw.println(IDLE_PENDING_FACTOR);
+
+ pw.print(" DOZE_IDLE_TIMEOUT=");
+ TimeUtils.formatDuration(IDLE_TIMEOUT, pw);
+ pw.println();
+
+ pw.print(" DOZE_MAX_IDLE_TIMEOUT=");
+ TimeUtils.formatDuration(MAX_IDLE_TIMEOUT, pw);
+ pw.println();
+
+ pw.print(" DOZE_IDLE_FACTOR=");
+ pw.println(IDLE_FACTOR);
+
+ pw.print(" DOZE_MIN_TIME_TO_ALARM=");
+ TimeUtils.formatDuration(MIN_TIME_TO_ALARM, pw);
+ pw.println();
+
+ pw.print(" DOZE_MAX_TEMP_APP_WHITELIST_DURATION=");
+ TimeUtils.formatDuration(MAX_TEMP_APP_WHITELIST_DURATION, pw);
+ pw.println();
+ }
+ }
+
+ private Constants mConstants;
+
@Override
public void onAnyMotionResult(int result) {
if (DEBUG) Slog.d(TAG, "onAnyMotionResult(" + result + ")");
@@ -474,6 +623,8 @@ public class DeviceIdleController extends SystemService
}
}
+ mConstants = new Constants(mHandler, getContext().getContentResolver());
+
readConfigFileLocked();
updateWhitelistAppIdsLocked();
@@ -482,7 +633,7 @@ public class DeviceIdleController extends SystemService
// a battery update the next time the level drops.
mCharging = true;
mState = STATE_ACTIVE;
- mInactiveTimeout = DEFAULT_INACTIVE_TIMEOUT;
+ mInactiveTimeout = mConstants.INACTIVE_TIMEOUT;
}
publishBinderService(SERVICE_NAME, new BinderService());
@@ -613,14 +764,12 @@ public class DeviceIdleController extends SystemService
*/
public void addPowerSaveTempWhitelistAppInternal(String packageName, long duration,
int userId) {
- if (duration > MAX_TEMP_APP_WHITELIST_DURATION) {
- duration = MAX_TEMP_APP_WHITELIST_DURATION;
- }
try {
int uid = getContext().getPackageManager().getPackageUid(packageName, userId);
int appId = UserHandle.getAppId(uid);
final long timeNow = System.currentTimeMillis();
synchronized (this) {
+ duration = Math.min(duration, mConstants.MAX_TEMP_APP_WHITELIST_DURATION);
long currentEndTime = mTempWhitelistAppIdEndTimes.get(appId);
// Set the new end time
mTempWhitelistAppIdEndTimes.put(appId, timeNow + duration);
@@ -704,7 +853,7 @@ public class DeviceIdleController extends SystemService
EventLogTags.writeDeviceIdle(STATE_ACTIVE, reason);
scheduleReportActiveLocked(false);
mState = STATE_ACTIVE;
- mInactiveTimeout = DEFAULT_INACTIVE_TIMEOUT;
+ mInactiveTimeout = mConstants.INACTIVE_TIMEOUT;
mNextIdlePendingDelay = 0;
mNextIdleDelay = 0;
cancelAlarmLocked();
@@ -731,7 +880,7 @@ public class DeviceIdleController extends SystemService
* within the DEFAULT_SENSING_TIMEOUT, to return to STATE_INACTIVE.
*/
void enterInactiveStateLocked() {
- mInactiveTimeout = DEFAULT_INACTIVE_TIMEOUT;
+ mInactiveTimeout = mConstants.INACTIVE_TIMEOUT;
becomeInactiveIfAppropriateLocked();
}
@@ -740,7 +889,7 @@ public class DeviceIdleController extends SystemService
EventLogTags.writeDeviceIdleStep();
final long now = SystemClock.elapsedRealtime();
- if ((now+DEFAULT_MIN_TIME_TO_ALARM) > mAlarmManager.getNextWakeFromIdleTime()) {
+ if ((now+mConstants.MIN_TIME_TO_ALARM) > mAlarmManager.getNextWakeFromIdleTime()) {
// Whoops, there is an upcoming alarm. We don't actually want to go idle.
if (mState != STATE_ACTIVE) {
becomeActiveLocked("alarm");
@@ -753,10 +902,10 @@ public class DeviceIdleController extends SystemService
// We have now been inactive long enough, it is time to start looking
// for significant motion and sleep some more while doing so.
startMonitoringSignificantMotion();
- scheduleAlarmLocked(DEFAULT_IDLE_AFTER_INACTIVE_TIMEOUT, false);
+ scheduleAlarmLocked(mConstants.IDLE_AFTER_INACTIVE_TIMEOUT, false);
// Reset the upcoming idle delays.
- mNextIdlePendingDelay = DEFAULT_IDLE_PENDING_TIMEOUT;
- mNextIdleDelay = DEFAULT_IDLE_TIMEOUT;
+ mNextIdlePendingDelay = mConstants.IDLE_PENDING_TIMEOUT;
+ mNextIdleDelay = mConstants.IDLE_TIMEOUT;
mState = STATE_IDLE_PENDING;
if (DEBUG) Slog.d(TAG, "Moved from STATE_INACTIVE to STATE_IDLE_PENDING.");
EventLogTags.writeDeviceIdle(mState, "step");
@@ -764,7 +913,7 @@ public class DeviceIdleController extends SystemService
case STATE_IDLE_PENDING:
mState = STATE_SENSING;
if (DEBUG) Slog.d(TAG, "Moved from STATE_IDLE_PENDING to STATE_SENSING.");
- scheduleSensingAlarmLocked(DEFAULT_SENSING_TIMEOUT);
+ scheduleSensingAlarmLocked(mConstants.SENSING_TIMEOUT);
mAnyMotionDetector.checkForAnyMotion();
break;
case STATE_SENSING:
@@ -773,11 +922,9 @@ public class DeviceIdleController extends SystemService
scheduleAlarmLocked(mNextIdleDelay, true);
if (DEBUG) Slog.d(TAG, "Moved to STATE_IDLE. Next alarm in " + mNextIdleDelay +
" ms.");
- mNextIdleDelay = (long)(mNextIdleDelay * DEFAULT_IDLE_FACTOR);
+ mNextIdleDelay = (long)(mNextIdleDelay * mConstants.IDLE_FACTOR);
if (DEBUG) Slog.d(TAG, "Setting mNextIdleDelay = " + mNextIdleDelay);
- if (mNextIdleDelay > DEFAULT_MAX_IDLE_TIMEOUT) {
- mNextIdleDelay = DEFAULT_MAX_IDLE_TIMEOUT;
- }
+ mNextIdleDelay = Math.min(mNextIdleDelay, mConstants.MAX_IDLE_TIMEOUT);
mState = STATE_IDLE;
mHandler.sendEmptyMessage(MSG_REPORT_IDLE_ON);
break;
@@ -786,10 +933,8 @@ public class DeviceIdleController extends SystemService
scheduleAlarmLocked(mNextIdlePendingDelay, false);
if (DEBUG) Slog.d(TAG, "Moved from STATE_IDLE to STATE_IDLE_MAINTENANCE. " +
"Next alarm in " + mNextIdlePendingDelay + " ms.");
- mNextIdlePendingDelay = (long)(mNextIdlePendingDelay*DEFAULT_IDLE_PENDING_FACTOR);
- if (mNextIdlePendingDelay > DEFAULT_MAX_IDLE_PENDING_TIMEOUT) {
- mNextIdlePendingDelay = DEFAULT_MAX_IDLE_PENDING_TIMEOUT;
- }
+ mNextIdlePendingDelay = Math.min(mConstants.MAX_IDLE_PENDING_TIMEOUT,
+ (long)(mNextIdlePendingDelay * mConstants.IDLE_PENDING_FACTOR));
mState = STATE_IDLE_MAINTENANCE;
EventLogTags.writeDeviceIdle(mState, "step");
mHandler.sendEmptyMessage(MSG_REPORT_IDLE_OFF);
@@ -807,7 +952,7 @@ public class DeviceIdleController extends SystemService
if (mState != STATE_ACTIVE) {
scheduleReportActiveLocked(true);
mState = STATE_ACTIVE;
- mInactiveTimeout = DEFAULT_MOTION_INACTIVE_TIMEOUT;
+ mInactiveTimeout = mConstants.MOTION_INACTIVE_TIMEOUT;
EventLogTags.writeDeviceIdle(mState, "motion");
becomeInactiveIfAppropriateLocked();
}
@@ -1179,6 +1324,9 @@ public class DeviceIdleController extends SystemService
pw.println();
}
}
+
+ mConstants.dump(pw);
+
pw.print(" mSigMotionSensor="); pw.println(mSigMotionSensor);
pw.print(" mCurDisplay="); pw.println(mCurDisplay);
pw.print(" mIdleDisabled="); pw.println(mIdleDisabled);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 0d08c2a..27656d4 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -32,6 +32,7 @@ import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID;
import static com.android.server.am.TaskRecord.INVALID_TASK_ID;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_DONT_LOCK;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE;
+import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_PINNABLE;
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.START_TAG;
@@ -4197,9 +4198,9 @@ public final class ActivityManagerService extends ActivityManagerNative
if (rootR == null) {
Slog.w(TAG, "Finishing task with all activities already finished");
}
- // Do not allow task to finish if last task in lockTask mode. Launchable apps can
- // finish themselves.
- if (tr.mLockTaskAuth != LOCK_TASK_AUTH_LAUNCHABLE && rootR == r &&
+ // Do not allow task to finish if last task in lockTask mode. Launchable priv-apps can
+ // finish.
+ if (tr.mLockTaskAuth != LOCK_TASK_AUTH_LAUNCHABLE_PRIV && rootR == r &&
mStackSupervisor.isLastLockedTask(tr)) {
Slog.i(TAG, "Not finishing task in lock task mode");
mStackSupervisor.showLockTaskToast();
@@ -4361,9 +4362,10 @@ public final class ActivityManagerService extends ActivityManagerNative
return false;
}
- // Do not allow the last non-launchable task to finish in Lock Task mode.
+ // Do not allow task to finish if last task in lockTask mode. Launchable priv-apps
+ // can finish.
final TaskRecord task = r.task;
- if (task.mLockTaskAuth != LOCK_TASK_AUTH_LAUNCHABLE &&
+ if (task.mLockTaskAuth != LOCK_TASK_AUTH_LAUNCHABLE_PRIV &&
mStackSupervisor.isLastLockedTask(task) && task.getRootActivity() == r) {
mStackSupervisor.showLockTaskToast();
return false;
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 577a4f9..9e33f2a 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -35,6 +35,7 @@ import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
import static com.android.server.am.ActivityStack.ActivityState.*;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_DONT_LOCK;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE;
+import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_PINNABLE;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_WHITELISTED;
@@ -1179,7 +1180,8 @@ public final class ActivityStackSupervisor implements DisplayListener {
mService.updateOomAdjLocked();
final TaskRecord task = r.task;
- if (task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE) {
+ if (task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE ||
+ task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE_PRIV) {
setLockTaskModeLocked(task, LOCK_TASK_MODE_LOCKED, "mLockTaskAuth==LAUNCHABLE", false);
}
@@ -2019,15 +2021,22 @@ public final class ActivityStackSupervisor implements DisplayListener {
r, top.task);
top.deliverNewIntentLocked(callingUid, r.intent, r.launchedFromPackage);
} else {
- // A special case: we need to
- // start the activity because it is not currently
- // running, and the caller has asked to clear the
- // current task to have this activity at the top.
+ // A special case: we need to start the activity because it is not
+ // currently running, and the caller has asked to clear the current
+ // task to have this activity at the top.
addingToTask = true;
- // Now pretend like this activity is being started
- // by the top of its task, so it is put in the
- // right place.
+ // Now pretend like this activity is being started by the top of its
+ // task, so it is put in the right place.
sourceRecord = intentActivity;
+ TaskRecord task = sourceRecord.task;
+ if (task != null && task.stack == null) {
+ // Target stack got cleared when we all activities were removed
+ // above. Go ahead and reset it.
+ targetStack = computeStackFocus(sourceRecord, false /* newTask */);
+ targetStack.addTask(
+ task, !launchTaskBehind /* toTop */, false /* moving */);
+ }
+
}
} else if (r.realActivity.equals(intentActivity.task.realActivity)) {
// In this case the top activity on the task is the
@@ -3778,6 +3787,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
switch (lockTaskAuth) {
case LOCK_TASK_AUTH_DONT_LOCK:
return !mLockTaskModeTasks.isEmpty();
+ case LOCK_TASK_AUTH_LAUNCHABLE_PRIV:
case LOCK_TASK_AUTH_LAUNCHABLE:
case LOCK_TASK_AUTH_WHITELISTED:
return false;
@@ -3794,12 +3804,14 @@ public final class ActivityStackSupervisor implements DisplayListener {
boolean didSomething = false;
for (int taskNdx = mLockTaskModeTasks.size() - 1; taskNdx >= 0; --taskNdx) {
final TaskRecord lockedTask = mLockTaskModeTasks.get(taskNdx);
- if (lockedTask.mLockTaskMode != LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED) {
- continue;
- }
- final boolean wasLaunchable = lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE;
+ final boolean wasWhitelisted =
+ (lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE) ||
+ (lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_WHITELISTED);
lockedTask.setLockTaskAuth();
- if (wasLaunchable && lockedTask.mLockTaskAuth != LOCK_TASK_AUTH_LAUNCHABLE) {
+ final boolean isWhitelisted =
+ (lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE) ||
+ (lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_WHITELISTED);
+ if (wasWhitelisted && !isWhitelisted) {
// Lost whitelisting authorization. End it now.
if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "onLockTaskPackagesUpdated: removing " +
lockedTask + " mLockTaskAuth=" + lockedTask.lockTaskAuthToString());
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index f966bcf..78f9f18 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -134,12 +134,15 @@ final class TaskRecord {
/** Can't be put in lockTask mode. */
final static int LOCK_TASK_AUTH_DONT_LOCK = 0;
- /** Can enter lockTask with user approval. Can never start over existing lockTask task. */
+ /** Can enter app pinning with user approval. Can never start over existing lockTask task. */
final static int LOCK_TASK_AUTH_PINNABLE = 1;
/** Starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing lockTask task. */
final static int LOCK_TASK_AUTH_LAUNCHABLE = 2;
- /** Can enter lockTask with user approval. Can start over existing lockTask task. */
+ /** Can enter lockTask without user approval. Can start over existing lockTask task. */
final static int LOCK_TASK_AUTH_WHITELISTED = 3;
+ /** Priv-app that starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing
+ * lockTask task. */
+ final static int LOCK_TASK_AUTH_LAUNCHABLE_PRIV = 4;
int mLockTaskAuth = LOCK_TASK_AUTH_PINNABLE;
int mLockTaskUid = -1; // The uid of the application that called startLockTask().
@@ -747,11 +750,18 @@ final class TaskRecord {
case LOCK_TASK_AUTH_PINNABLE: return "LOCK_TASK_AUTH_PINNABLE";
case LOCK_TASK_AUTH_LAUNCHABLE: return "LOCK_TASK_AUTH_LAUNCHABLE";
case LOCK_TASK_AUTH_WHITELISTED: return "LOCK_TASK_AUTH_WHITELISTED";
+ case LOCK_TASK_AUTH_LAUNCHABLE_PRIV: return "LOCK_TASK_AUTH_LAUNCHABLE_PRIV";
default: return "unknown=" + mLockTaskAuth;
}
}
void setLockTaskAuth() {
+ if (!mPrivileged &&
+ (mLockTaskMode == LOCK_TASK_LAUNCH_MODE_ALWAYS ||
+ mLockTaskMode == LOCK_TASK_LAUNCH_MODE_NEVER)) {
+ // Non-priv apps are not allowed to use always or never, fall back to default
+ mLockTaskMode = LOCK_TASK_LAUNCH_MODE_DEFAULT;
+ }
switch (mLockTaskMode) {
case LOCK_TASK_LAUNCH_MODE_DEFAULT:
mLockTaskAuth = isLockTaskWhitelistedLocked() ?
@@ -759,13 +769,11 @@ final class TaskRecord {
break;
case LOCK_TASK_LAUNCH_MODE_NEVER:
- mLockTaskAuth = mPrivileged ?
- LOCK_TASK_AUTH_DONT_LOCK : LOCK_TASK_AUTH_PINNABLE;
+ mLockTaskAuth = LOCK_TASK_AUTH_DONT_LOCK;
break;
case LOCK_TASK_LAUNCH_MODE_ALWAYS:
- mLockTaskAuth = mPrivileged ?
- LOCK_TASK_AUTH_LAUNCHABLE: LOCK_TASK_AUTH_PINNABLE;
+ mLockTaskAuth = LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
break;
case LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED:
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 7440b8c..b2ab797 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -346,6 +346,8 @@ public final class DisplayManagerService extends SystemService {
synchronized (mTempDisplayStateWorkQueue) {
try {
// Update the display state within the lock.
+ // Note that we do not need to schedule traversals here although it
+ // may happen as a side-effect of displays changing state.
synchronized (mSyncRoot) {
if (mGlobalDisplayState == state
&& mGlobalDisplayBrightness == brightness) {
@@ -357,8 +359,7 @@ public final class DisplayManagerService extends SystemService {
+ ", brightness=" + brightness + ")");
mGlobalDisplayState = state;
mGlobalDisplayBrightness = brightness;
- updateGlobalDisplayStateLocked(mTempDisplayStateWorkQueue);
- scheduleTraversalLocked(false);
+ applyGlobalDisplayStateLocked(mTempDisplayStateWorkQueue);
}
// Setting the display power state can take hundreds of milliseconds
@@ -715,6 +716,7 @@ public final class DisplayManagerService extends SystemService {
handleDisplayDeviceRemovedLocked(device);
}
}
+
private void handleDisplayDeviceRemovedLocked(DisplayDevice device) {
DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
if (!mDisplayDevices.remove(device)) {
@@ -729,7 +731,7 @@ public final class DisplayManagerService extends SystemService {
scheduleTraversalLocked(false);
}
- private void updateGlobalDisplayStateLocked(List<Runnable> workQueue) {
+ private void applyGlobalDisplayStateLocked(List<Runnable> workQueue) {
final int count = mDisplayDevices.size();
for (int i = 0; i < count; i++) {
DisplayDevice device = mDisplayDevices.get(i);
diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java
index 4823769..6efc99a 100644
--- a/services/core/java/com/android/server/display/LogicalDisplay.java
+++ b/services/core/java/com/android/server/display/LogicalDisplay.java
@@ -133,6 +133,8 @@ final class LogicalDisplay {
mInfo.overscanBottom = mOverrideDisplayInfo.overscanBottom;
mInfo.rotation = mOverrideDisplayInfo.rotation;
mInfo.logicalDensityDpi = mOverrideDisplayInfo.logicalDensityDpi;
+ mInfo.physicalXDpi = mOverrideDisplayInfo.physicalXDpi;
+ mInfo.physicalYDpi = mOverrideDisplayInfo.physicalYDpi;
}
}
return mInfo;
diff --git a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
index 0462035..0bddff0 100644
--- a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
@@ -174,9 +174,11 @@ final class OverlayDisplayAdapter extends DisplayAdapter {
if (width >= MIN_WIDTH && width <= MAX_WIDTH
&& height >= MIN_HEIGHT && height <= MAX_HEIGHT
&& densityDpi >= DisplayMetrics.DENSITY_LOW
- && densityDpi <= DisplayMetrics.DENSITY_XXHIGH) {
+ && densityDpi <= DisplayMetrics.DENSITY_XXXHIGH) {
modes.add(new OverlayMode(width, height, densityDpi));
continue;
+ } else {
+ Slog.w(TAG, "Ignoring out-of-range overlay display mode: " + mode);
}
} catch (NumberFormatException ex) {
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index e2cc3f7..6c9fd3f 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -92,6 +92,7 @@ import android.content.ServiceConnection;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.FeatureInfo;
+import android.content.pm.IOnPermissionsChangeListener;
import android.content.pm.IPackageDataObserver;
import android.content.pm.IPackageDeleteObserver;
import android.content.pm.IPackageDeleteObserver2;
@@ -144,6 +145,7 @@ import android.os.Message;
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.Process;
+import android.os.RemoteCallback;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.SELinux;
@@ -523,6 +525,8 @@ public class PackageManagerService extends IPackageManager.Stub {
private AtomicInteger mNextMoveId = new AtomicInteger();
private final MoveCallbacks mMoveCallbacks;
+ private final OnPermissionChangeListeners mOnPermissionChangeListeners;
+
// Cache of users who need badging.
SparseBooleanArray mUserNeedsBadging = new SparseBooleanArray();
@@ -1731,6 +1735,9 @@ public class PackageManagerService extends IPackageManager.Stub {
mPackageDexOptimizer = new PackageDexOptimizer(this);
mMoveCallbacks = new MoveCallbacks(FgThread.get().getLooper());
+ mOnPermissionChangeListeners = new OnPermissionChangeListeners(
+ FgThread.get().getLooper());
+
getDefaultDisplayMetrics(context, mMetrics);
SystemConfig systemConfig = SystemConfig.getInstance();
@@ -3195,10 +3202,11 @@ public class PackageManagerService extends IPackageManager.Stub {
case PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED: {
gidsChanged = true;
- }
- break;
+ } break;
}
+ mOnPermissionChangeListeners.onPermissionsChanged(pkg.applicationInfo.uid);
+
// Not critical if that is lost - app has to request again.
mSettings.writeRuntimePermissionsForUserLPr(userId, false);
}
@@ -3255,6 +3263,8 @@ public class PackageManagerService extends IPackageManager.Stub {
return;
}
+ mOnPermissionChangeListeners.onPermissionsChanged(pkg.applicationInfo.uid);
+
// Critical, after this call app should never have the permission.
mSettings.writeRuntimePermissionsForUserLPr(userId, true);
}
@@ -3397,6 +3407,24 @@ public class PackageManagerService extends IPackageManager.Stub {
}
@Override
+ public void addOnPermissionsChangeListener(IOnPermissionsChangeListener listener) {
+ mContext.enforceCallingOrSelfPermission(
+ Manifest.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS,
+ "addOnPermissionsChangeListener");
+
+ synchronized (mPackages) {
+ mOnPermissionChangeListeners.addListenerLocked(listener);
+ }
+ }
+
+ @Override
+ public void removeOnPermissionsChangeListener(IOnPermissionsChangeListener listener) {
+ synchronized (mPackages) {
+ mOnPermissionChangeListeners.removeListenerLocked(listener);
+ }
+ }
+
+ @Override
public boolean isProtectedBroadcast(String actionName) {
synchronized (mPackages) {
return mProtectedBroadcasts.contains(actionName);
@@ -6368,6 +6396,16 @@ public class PackageManagerService extends IPackageManager.Stub {
if ((scanFlags & SCAN_NEW_INSTALL) == 0) {
derivePackageAbi(pkg, scanFile, cpuAbiOverride, true /* extract libs */);
+
+ // Some system apps still use directory structure for native libraries
+ // in which case we might end up not detecting abi solely based on apk
+ // structure. Try to detect abi based on directory structure.
+ if (isSystemApp(pkg) && !pkg.isUpdatedSystemApp() &&
+ pkg.applicationInfo.primaryCpuAbi == null) {
+ setBundledAppAbisAndRoots(pkg, pkgSetting);
+ setNativeLibraryPaths(pkg);
+ }
+
} else {
if ((scanFlags & SCAN_MOVE) != 0) {
// We haven't run dex-opt for this move (since we've moved the compiled output too)
@@ -7273,6 +7311,33 @@ public class PackageManagerService extends IPackageManager.Stub {
}
/**
+ * Calculate the abis and roots for a bundled app. These can uniquely
+ * be determined from the contents of the system partition, i.e whether
+ * it contains 64 or 32 bit shared libraries etc. We do not validate any
+ * of this information, and instead assume that the system was built
+ * sensibly.
+ */
+ private void setBundledAppAbisAndRoots(PackageParser.Package pkg,
+ PackageSetting pkgSetting) {
+ final String apkName = deriveCodePathName(pkg.applicationInfo.getCodePath());
+
+ // If "/system/lib64/apkname" exists, assume that is the per-package
+ // native library directory to use; otherwise use "/system/lib/apkname".
+ final String apkRoot = calculateBundledApkRoot(pkg.applicationInfo.sourceDir);
+ setBundledAppAbi(pkg, apkRoot, apkName);
+ // pkgSetting might be null during rescan following uninstall of updates
+ // to a bundled app, so accommodate that possibility. The settings in
+ // that case will be established later from the parsed package.
+ //
+ // If the settings aren't null, sync them up with what we've just derived.
+ // note that apkRoot isn't stored in the package settings.
+ if (pkgSetting != null) {
+ pkgSetting.primaryCpuAbiString = pkg.applicationInfo.primaryCpuAbi;
+ pkgSetting.secondaryCpuAbiString = pkg.applicationInfo.secondaryCpuAbi;
+ }
+ }
+
+ /**
* Deduces the ABI of a bundled app and sets the relevant fields on the
* parsed pkg object.
*
@@ -15260,4 +15325,57 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
}
+
+ private final class OnPermissionChangeListeners extends Handler {
+ private static final int MSG_ON_PERMISSIONS_CHANGED = 1;
+
+ private final RemoteCallbackList<IOnPermissionsChangeListener> mPermissionListeners =
+ new RemoteCallbackList<>();
+
+ public OnPermissionChangeListeners(Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_ON_PERMISSIONS_CHANGED: {
+ final int uid = msg.arg1;
+ handleOnPermissionsChanged(uid);
+ } break;
+ }
+ }
+
+ public void addListenerLocked(IOnPermissionsChangeListener listener) {
+ mPermissionListeners.register(listener);
+
+ }
+
+ public void removeListenerLocked(IOnPermissionsChangeListener listener) {
+ mPermissionListeners.unregister(listener);
+ }
+
+ public void onPermissionsChanged(int uid) {
+ if (mPermissionListeners.getRegisteredCallbackCount() > 0) {
+ obtainMessage(MSG_ON_PERMISSIONS_CHANGED, uid, 0).sendToTarget();
+ }
+ }
+
+ private void handleOnPermissionsChanged(int uid) {
+ final int count = mPermissionListeners.beginBroadcast();
+ try {
+ for (int i = 0; i < count; i++) {
+ IOnPermissionsChangeListener callback = mPermissionListeners
+ .getBroadcastItem(i);
+ try {
+ callback.onPermissionsChanged(uid);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Permission listener is dead", e);
+ }
+ }
+ } finally {
+ mPermissionListeners.finishBroadcast();
+ }
+ }
+ }
}
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 6e52358..25ca167 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -514,6 +514,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
boolean mDreamingLockscreen;
boolean mDreamingSleepTokenNeeded;
SleepToken mDreamingSleepToken;
+ SleepToken mScreenOffSleepToken;
boolean mKeyguardSecure;
boolean mKeyguardSecureIncludingHidden;
volatile boolean mKeyguardOccluded;
@@ -5385,6 +5386,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
public void screenTurnedOff() {
if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turned off...");
+ updateScreenOffSleepToken(true);
synchronized (mLock) {
mScreenOnEarly = false;
mScreenOnFully = false;
@@ -5399,6 +5401,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
public void screenTurningOn(final ScreenOnListener screenOnListener) {
if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turning on...");
+ updateScreenOffSleepToken(false);
synchronized (mLock) {
mScreenOnEarly = true;
mScreenOnFully = false;
@@ -6021,6 +6024,20 @@ public class PhoneWindowManager implements WindowManagerPolicy {
} else {
if (mDreamingSleepToken != null) {
mDreamingSleepToken.release();
+ mDreamingSleepToken = null;
+ }
+ }
+ }
+
+ private void updateScreenOffSleepToken(boolean acquire) {
+ if (acquire) {
+ if (mScreenOffSleepToken == null) {
+ mScreenOffSleepToken = mActivityManagerInternal.acquireSleepToken("ScreenOff");
+ }
+ } else {
+ if (mScreenOffSleepToken != null) {
+ mScreenOffSleepToken.release();
+ mScreenOffSleepToken = null;
}
}
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index feb0285..2753700 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -3129,7 +3129,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
@Override
- public void uninstallCaCert(ComponentName admin, String alias) {
+ public void uninstallCaCerts(ComponentName admin, String[] aliases) {
enforceCanManageCaCerts(admin);
final UserHandle userHandle = new UserHandle(UserHandle.getCallingUserId());
@@ -3137,7 +3137,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
try {
final KeyChainConnection keyChainConnection = KeyChain.bindAsUser(mContext, userHandle);
try {
- keyChainConnection.getService().deleteCaCertificate(alias);
+ for (int i = 0 ; i < aliases.length; i++) {
+ keyChainConnection.getService().deleteCaCertificate(aliases[i]);
+ }
} catch (RemoteException e) {
Log.e(LOG_TAG, "from CaCertUninstaller: ", e);
} finally {
@@ -5973,40 +5975,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
@Override
- public void sendDeviceInitializerStatus(int statusCode, String description) {
- synchronized (this) {
- String packageName = getDeviceInitializer();
- if (packageName == null) {
- throw new SecurityException("No device initializers");
- }
- UserHandle callingUser = Binder.getCallingUserHandle();
- int deviceInitializerUid = -1;
- try {
- deviceInitializerUid = mContext.getPackageManager().getPackageUid(
- packageName, callingUser.getIdentifier());
- } catch (NameNotFoundException e) {
- throw new SecurityException(e);
- }
- if (Binder.getCallingUid() != deviceInitializerUid) {
- throw new SecurityException("Caller must be a device initializer");
- }
- long id = Binder.clearCallingIdentity();
- try {
- Intent intent = new Intent(
- DevicePolicyManager.ACTION_SEND_DEVICE_INITIALIZER_STATUS);
- intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_INITIALIZER_STATUS_CODE,
- statusCode);
- intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_INITIALIZER_STATUS_DESCRIPTION,
- description);
- mContext.sendBroadcastAsUser(intent, callingUser,
- android.Manifest.permission.RECEIVE_DEVICE_INITIALIZER_STATUS);
- } finally {
- restoreCallingIdentity(id);
- }
- }
- }
-
- @Override
public boolean setKeyguardDisabled(ComponentName who, boolean disabled) {
Preconditions.checkNotNull(who, "ComponentName is null");
synchronized (this) {
diff --git a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
index 56f1d48c..bb0a36f 100644
--- a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
@@ -48,6 +48,7 @@ import android.net.Network;
import android.net.NetworkAgent;
import android.net.NetworkCapabilities;
import android.net.NetworkConfig;
+import android.net.NetworkFactory;
import android.net.NetworkInfo;
import android.net.NetworkInfo.DetailedState;
import android.net.NetworkMisc;
@@ -55,6 +56,7 @@ import android.net.NetworkRequest;
import android.net.RouteInfo;
import android.os.ConditionVariable;
import android.os.Handler;
+import android.os.HandlerThread;
import android.os.Looper;
import android.os.INetworkManagementService;
import android.test.AndroidTestCase;
@@ -68,6 +70,7 @@ import org.mockito.ArgumentCaptor;
import java.net.InetAddress;
import java.util.concurrent.Future;
+import java.util.concurrent.atomic.AtomicBoolean;
/**
* Tests for {@link ConnectivityService}.
@@ -224,6 +227,31 @@ public class ConnectivityServiceTest extends AndroidTestCase {
}
}
+ private static class MockNetworkFactory extends NetworkFactory {
+ final AtomicBoolean mNetworkStarted = new AtomicBoolean(false);
+
+ public MockNetworkFactory(Looper looper, Context context, String logTag,
+ NetworkCapabilities filter) {
+ super(looper, context, logTag, filter);
+ }
+
+ public int getMyRequestCount() {
+ return getRequestCount();
+ }
+
+ protected void startNetwork() {
+ mNetworkStarted.set(true);
+ }
+
+ protected void stopNetwork() {
+ mNetworkStarted.set(false);
+ }
+
+ public boolean getMyStartRequested() {
+ return mNetworkStarted.get();
+ }
+ }
+
private class WrappedConnectivityService extends ConnectivityService {
public WrappedConnectivityService(Context context, INetworkManagementService netManager,
INetworkStatsService statsService, INetworkPolicyManager policyManager) {
@@ -235,6 +263,27 @@ public class ConnectivityServiceTest extends AndroidTestCase {
// Prevent wrapped ConnectivityService from trying to write to SystemProperties.
return 0;
}
+
+ @Override
+ protected int reserveNetId() {
+ while (true) {
+ final int netId = super.reserveNetId();
+
+ // Don't overlap test NetIDs with real NetIDs as binding sockets to real networks
+ // can have odd side-effects, like network validations succeeding.
+ final Network[] networks = ConnectivityManager.from(getContext()).getAllNetworks();
+ boolean overlaps = false;
+ for (Network network : networks) {
+ if (netId == network.netId) {
+ overlaps = true;
+ break;
+ }
+ }
+ if (overlaps) continue;
+
+ return netId;
+ }
+ }
}
@Override
@@ -426,6 +475,71 @@ public class ConnectivityServiceTest extends AndroidTestCase {
verifyNoNetwork();
}
+ @LargeTest
+ public void testNetworkFactoryRequests() throws Exception {
+ NetworkCapabilities filter = new NetworkCapabilities();
+ filter.addCapability(NET_CAPABILITY_INTERNET);
+ final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
+ handlerThread.start();
+ MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
+ mServiceContext, "testFactory", filter);
+ testFactory.setScoreFilter(40);
+ testFactory.register();
+ try {
+ Thread.sleep(500);
+ } catch (Exception e) {}
+ assertEquals(1, testFactory.getMyRequestCount());
+ assertEquals(true, testFactory.getMyStartRequested());
+
+ // now bring in a higher scored network
+ MockNetworkAgent testAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ ConditionVariable cv = waitForConnectivityBroadcasts(1);
+ testAgent.connect(true);
+ cv.block();
+ // part of the bringup makes another network request and then releases it
+ // wait for the release
+ try { Thread.sleep(500); } catch (Exception e) {}
+ assertEquals(1, testFactory.getMyRequestCount());
+ assertEquals(false, testFactory.getMyStartRequested());
+
+ // bring in a bunch of requests..
+ ConnectivityManager.NetworkCallback[] networkCallbacks =
+ new ConnectivityManager.NetworkCallback[10];
+ for (int i = 0; i< networkCallbacks.length; i++) {
+ networkCallbacks[i] = new ConnectivityManager.NetworkCallback();
+ NetworkRequest.Builder builder = new NetworkRequest.Builder();
+ builder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ mCm.requestNetwork(builder.build(), networkCallbacks[i]);
+ }
+
+ try {
+ Thread.sleep(1000);
+ } catch (Exception e) {}
+ assertEquals(11, testFactory.getMyRequestCount());
+ assertEquals(false, testFactory.getMyStartRequested());
+
+ // remove the requests
+ for (int i = 0; i < networkCallbacks.length; i++) {
+ mCm.unregisterNetworkCallback(networkCallbacks[i]);
+ }
+ try {
+ Thread.sleep(500);
+ } catch (Exception e) {}
+ assertEquals(1, testFactory.getMyRequestCount());
+ assertEquals(false, testFactory.getMyStartRequested());
+
+ // drop the higher scored network
+ cv = waitForConnectivityBroadcasts(1);
+ testAgent.disconnect();
+ cv.block();
+ assertEquals(1, testFactory.getMyRequestCount());
+ assertEquals(true, testFactory.getMyStartRequested());
+
+ testFactory.unregister();
+ handlerThread.quit();
+ }
+
+
// @Override
// public void tearDown() throws Exception {
// super.tearDown();
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index d6a7dd1..588f8c6 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -91,6 +91,7 @@ public class UsbDeviceManager {
private static final int MSG_SYSTEM_READY = 3;
private static final int MSG_BOOT_COMPLETED = 4;
private static final int MSG_USER_SWITCHED = 5;
+ private static final int MSG_SET_USB_DATA_UNLOCKED = 6;
private static final int AUDIO_MODE_SOURCE = 1;
@@ -314,6 +315,7 @@ public class UsbDeviceManager {
// current USB state
private boolean mConnected;
private boolean mConfigured;
+ private boolean mUsbDataUnlocked;
private String mCurrentFunctions;
private UsbAccessory mCurrentAccessory;
private int mUsbNotificationId;
@@ -350,7 +352,7 @@ public class UsbDeviceManager {
SystemProperties.get(UsbManager.ADB_PERSISTENT_PROPERTY, "adb"),
UsbManager.USB_FUNCTION_ADB);
- mCurrentFunctions = mAdbEnabled ? "adb" : "none";
+ mCurrentFunctions = mAdbEnabled ? "adb" : UsbManager.USB_FUNCTION_MTP;
String state = FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim();
updateState(state);
@@ -459,6 +461,15 @@ public class UsbDeviceManager {
}
}
+ /**
+ * Stop and start the USB driver. This is needed to close all outstanding
+ * USB connections.
+ */
+ private void restartCurrentFunction() {
+ setUsbConfig("none");
+ setUsbConfig(mCurrentFunctions);
+ }
+
private void setEnabledFunctions(String functions) {
if (DEBUG) Slog.d(TAG, "setEnabledFunctions " + functions);
@@ -531,6 +542,7 @@ public class UsbDeviceManager {
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
intent.putExtra(UsbManager.USB_CONNECTED, mConnected);
intent.putExtra(UsbManager.USB_CONFIGURED, mConfigured);
+ intent.putExtra(UsbManager.USB_DATA_UNLOCKED, mUsbDataUnlocked);
if (mCurrentFunctions != null) {
String[] functions = mCurrentFunctions.split(",");
@@ -599,6 +611,10 @@ public class UsbDeviceManager {
case MSG_UPDATE_STATE:
mConnected = (msg.arg1 == 1);
mConfigured = (msg.arg2 == 1);
+ if (!mConnected) {
+ // When a disconnect occurs, relock access to sensitive user data
+ mUsbDataUnlocked = false;
+ }
updateUsbNotification();
updateAdbNotification();
if (containsFunction(mCurrentFunctions,
@@ -621,6 +637,12 @@ public class UsbDeviceManager {
String functions = (String)msg.obj;
setEnabledFunctions(functions);
break;
+ case MSG_SET_USB_DATA_UNLOCKED:
+ mUsbDataUnlocked = (msg.arg1 == 1);
+ updateUsbNotification();
+ updateUsbState();
+ restartCurrentFunction();
+ break;
case MSG_SYSTEM_READY:
setUsbConfig(mCurrentFunctions);
updatePersistentProperty();
@@ -676,7 +698,9 @@ public class UsbDeviceManager {
int id = 0;
Resources r = mContext.getResources();
if (mConnected) {
- if (containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_MTP)) {
+ if (!mUsbDataUnlocked) {
+ id = com.android.internal.R.string.usb_charging_notification_title;
+ } else if (containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_MTP)) {
id = com.android.internal.R.string.usb_mtp_notification_title;
} else if (containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_PTP)) {
id = com.android.internal.R.string.usb_ptp_notification_title;
@@ -771,7 +795,7 @@ public class UsbDeviceManager {
}
private String getDefaultFunctions() {
- return "none";
+ return UsbManager.USB_FUNCTION_MTP;
}
public void dump(FileDescriptor fd, PrintWriter pw) {
@@ -817,6 +841,16 @@ public class UsbDeviceManager {
mHandler.sendMessage(MSG_SET_CURRENT_FUNCTIONS, functions);
}
+ public void setUsbDataUnlocked(boolean unlocked) {
+ if (DEBUG) Slog.d(TAG, "setUsbDataUnlocked(" + unlocked + ")");
+ mHandler.sendMessage(MSG_SET_USB_DATA_UNLOCKED, unlocked);
+ }
+
+ public boolean isUsbDataUnlocked() {
+ if (DEBUG) Slog.d(TAG, "isUsbDataUnlocked() -> " + mHandler.mUsbDataUnlocked);
+ return mHandler.mUsbDataUnlocked;
+ }
+
private void readOemUsbOverrideConfig() {
String[] configList = mContext.getResources().getStringArray(
com.android.internal.R.array.config_oemUsbModeOverride);
diff --git a/services/usb/java/com/android/server/usb/UsbService.java b/services/usb/java/com/android/server/usb/UsbService.java
index 51281a2..7a3426c 100644
--- a/services/usb/java/com/android/server/usb/UsbService.java
+++ b/services/usb/java/com/android/server/usb/UsbService.java
@@ -271,6 +271,18 @@ public class UsbService extends IUsbManager.Stub {
}
@Override
+ public void setUsbDataUnlocked(boolean unlocked) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
+ mDeviceManager.setUsbDataUnlocked(unlocked);
+ }
+
+ @Override
+ public boolean isUsbDataUnlocked() {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
+ return mDeviceManager.isUsbDataUnlocked();
+ }
+
+ @Override
public void allowUsbDebugging(boolean alwaysAllow, String publicKey) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
mDeviceManager.allowUsbDebugging(alwaysAllow, publicKey);
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 0042414..9a63aa3 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -27,6 +27,7 @@ import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
+import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.view.Surface;
@@ -442,8 +443,7 @@ public abstract class Connection extends Conferenceable {
private static final int MSG_SET_PAUSE_IMAGE = 11;
private static final int MSG_REMOVE_VIDEO_CALLBACK = 12;
- private final VideoProvider.VideoProviderHandler
- mMessageHandler = new VideoProvider.VideoProviderHandler();
+ private VideoProvider.VideoProviderHandler mMessageHandler;
private final VideoProvider.VideoProviderBinder mBinder;
/**
@@ -455,6 +455,14 @@ public abstract class Connection extends Conferenceable {
* Default handler used to consolidate binder method calls onto a single thread.
*/
private final class VideoProviderHandler extends Handler {
+ public VideoProviderHandler() {
+ super();
+ }
+
+ public VideoProviderHandler(Looper looper) {
+ super(looper);
+ }
+
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
@@ -586,6 +594,18 @@ public abstract class Connection extends Conferenceable {
public VideoProvider() {
mBinder = new VideoProvider.VideoProviderBinder();
+ mMessageHandler = new VideoProvider.VideoProviderHandler();
+ }
+
+ /**
+ * Creates an instance of the {@link VideoProvider}, specifying the looper to use.
+ *
+ * @param looper The looper.
+ * @hide
+ */
+ public VideoProvider(Looper looper) {
+ mBinder = new VideoProvider.VideoProviderBinder();
+ mMessageHandler = new VideoProvider.VideoProviderHandler(looper);
}
/**
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index b74b52d..da0c547 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -114,17 +114,12 @@ public class CarrierConfigManager {
* (Some carriers require that emergency calls *not* be logged, presumably to avoid the risk of
* accidental redialing from the call log UI. This is a good idea, so the default here is
* false.)
- * <p>
- * TODO: on the other hand, it might still be useful to have some record of the emergency calls
- * you've made, or to be able to look up the exact date/time of an emergency call. So perhaps we
- * <b>should</b> log those calls, but instead fix the call log to disable the "call" button for
- * emergency numbers.
*/
public static final String
KEY_ALLOW_EMERGENCY_NUMBERS_IN_CALL_LOG_BOOL = "allow_emergency_numbers_in_call_log_bool";
/** If true, removes the Voice Privacy option from Call Settings */
- public static final String KEY_VOICE_PRIVACY_DISABLE_BOOL = "voice_privacy_disable_bool";
+ public static final String KEY_VOICE_PRIVACY_DISABLE_UI_BOOL = "voice_privacy_disable_ui_bool";
/** Control whether users can reach the carrier portions of Cellular Network Settings. */
public static final String
@@ -302,7 +297,7 @@ public class CarrierConfigManager {
sDefaults.putBoolean(KEY_USE_HFA_FOR_PROVISIONING_BOOL, false);
sDefaults.putBoolean(KEY_USE_OTASP_FOR_PROVISIONING_BOOL, false);
sDefaults.putBoolean(KEY_VOICEMAIL_NOTIFICATION_PERSISTENT_BOOL, false);
- sDefaults.putBoolean(KEY_VOICE_PRIVACY_DISABLE_BOOL, false);
+ sDefaults.putBoolean(KEY_VOICE_PRIVACY_DISABLE_UI_BOOL, false);
sDefaults.putBoolean(KEY_WORLD_PHONE_BOOL, false);
sDefaults.putInt(KEY_VOLTE_REPLACEMENT_RAT_INT, 0);
sDefaults.putString(KEY_VVM_DESTINATION_NUMBER_STRING, "");
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
index 7b58755..f02d109 100644
--- a/telephony/java/android/telephony/SignalStrength.java
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -469,7 +469,12 @@ public class SignalStrength implements Parcelable {
}
/**
- * Get signal level as an int from 0..4
+ * Retrieve an abstract level value for the overall signal strength.
+ *
+ * @return a single integer from 0 to 4 representing the general signal quality.
+ * This may take into account many different radio technology inputs.
+ * 0 represents very poor signal strength
+ * while 4 represents a very strong signal strength.
*/
public int getLevel() {
int level;
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 12f1644..1cc275d 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -193,7 +193,7 @@ public class TelephonyManager {
//
/**
- * Broadcast intent action indicating that the call state (cellular)
+ * Broadcast intent action indicating that the call state
* on the device has changed.
*
* <p>
@@ -2437,10 +2437,23 @@ public class TelephonyManager {
public static final int CALL_STATE_OFFHOOK = 2;
/**
- * Returns a constant indicating the call state (cellular) on the device.
+ * Returns one of the following constants that represents the current state of all
+ * phone calls.
+ *
+ * {@link TelephonyManager#CALL_STATE_RINGING}
+ * {@link TelephonyManager#CALL_STATE_OFFHOOK}
+ * {@link TelephonyManager#CALL_STATE_IDLE}
*/
public int getCallState() {
- return getCallState(getDefaultSubscription());
+ try {
+ ITelecomService telecom = getTelecomService();
+ if (telecom != null) {
+ return telecom.getCallState();
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling ITelecomService#getCallState", e);
+ }
+ return CALL_STATE_IDLE;
}
/**
@@ -3488,13 +3501,13 @@ public class TelephonyManager {
/**
* Values used to return status for hasCarrierPrivileges call.
*/
- /** @hide */
+ /** @hide */ @SystemApi
public static final int CARRIER_PRIVILEGE_STATUS_HAS_ACCESS = 1;
- /** @hide */
+ /** @hide */ @SystemApi
public static final int CARRIER_PRIVILEGE_STATUS_NO_ACCESS = 0;
- /** @hide */
+ /** @hide */ @SystemApi
public static final int CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED = -1;
- /** @hide */
+ /** @hide */ @SystemApi
public static final int CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES = -2;
/**
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index 3b7aa9f..ac92dc0 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -224,6 +224,18 @@ public class MockPackageManager extends PackageManager {
throw new UnsupportedOperationException();
}
+ /** @hide */
+ @Override
+ public void addOnPermissionsChangeListener(OnPermissionsChangedListener listener) {
+ throw new UnsupportedOperationException();
+ }
+
+ /** @hide */
+ @Override
+ public void removeOnPermissionsChangeListener(OnPermissionsChangedListener listener) {
+ throw new UnsupportedOperationException();
+ }
+
@Override
public int checkSignatures(String pkg1, String pkg2) {
throw new UnsupportedOperationException();