summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.mk11
-rw-r--r--api/current.txt19
-rw-r--r--api/system-current.txt43
-rw-r--r--api/test-current.txt19
-rw-r--r--core/java/android/accounts/AccountManager.java9
-rw-r--r--core/java/android/app/Activity.java2
-rw-r--r--core/java/android/app/ActivityManager.java21
-rw-r--r--core/java/android/app/SystemServiceRegistry.java16
-rw-r--r--core/java/android/bluetooth/BluetoothDevice.java28
-rw-r--r--core/java/android/bluetooth/BluetoothGatt.java8
-rw-r--r--core/java/android/bluetooth/BluetoothGattServer.java8
-rw-r--r--core/java/android/bluetooth/le/AdvertisingSetParameters.java38
-rw-r--r--core/java/android/bluetooth/le/BluetoothLeAdvertiser.java7
-rw-r--r--core/java/android/bluetooth/le/ScanResult.java25
-rw-r--r--core/java/android/bluetooth/le/ScanSettings.java15
-rw-r--r--core/java/android/content/Context.java12
-rw-r--r--core/java/android/content/Intent.java10
-rw-r--r--core/java/android/content/res/Configuration.java4
-rw-r--r--core/java/android/hardware/display/DisplayManager.java1
-rw-r--r--core/java/android/net/ConnectivityMetricsEvent.java5
-rw-r--r--core/java/android/net/NetworkCapabilities.java68
-rw-r--r--core/java/android/net/metrics/ConnectStats.java85
-rw-r--r--core/java/android/net/metrics/DnsEvent.java91
-rw-r--r--core/java/android/net/metrics/IpConnectivityLog.java5
-rw-r--r--core/java/android/os/UserManager.java2
-rw-r--r--core/java/android/os/VintfObject.java64
-rwxr-xr-xcore/java/android/provider/Settings.java9
-rw-r--r--core/java/android/service/oemlock/IOemLockService.aidl30
-rw-r--r--core/java/android/service/oemlock/OemLockManager.java110
-rw-r--r--core/java/android/service/persistentdata/PersistentDataBlockManager.java4
-rw-r--r--core/java/android/view/Display.java1
-rw-r--r--core/java/android/view/View.java5
-rw-r--r--core/java/android/view/autofill/AutofillManager.java14
-rw-r--r--core/java/android/view/autofill/IAutoFillManagerClient.aidl7
-rw-r--r--core/java/com/android/internal/app/AccessibilityButtonChooserActivity.java2
-rw-r--r--core/java/com/android/internal/os/ZygoteInit.java4
-rw-r--r--core/java/com/android/internal/util/BitUtils.java21
-rw-r--r--core/java/com/android/internal/util/DumpUtils.java15
-rw-r--r--core/jni/Android.mk1
-rw-r--r--core/jni/AndroidRuntime.cpp2
-rw-r--r--core/jni/android_os_VintfObject.cpp82
-rw-r--r--core/res/AndroidManifest.xml12
-rwxr-xr-xcore/res/res/drawable-hdpi/ic_accessibility_magnification.pngbin0 -> 4018 bytes
-rwxr-xr-xcore/res/res/drawable-mdpi/ic_accessibility_magnification.pngbin0 -> 2573 bytes
-rwxr-xr-xcore/res/res/drawable-xhdpi/ic_accessibility_magnification.pngbin0 -> 5547 bytes
-rwxr-xr-xcore/res/res/drawable-xxhdpi/ic_accessibility_magnification.pngbin0 -> 8939 bytes
-rwxr-xr-xcore/res/res/drawable-xxxhdpi/ic_accessibility_magnification.pngbin0 -> 12945 bytes
-rw-r--r--core/res/res/layout/autofill_dataset_picker.xml1
-rw-r--r--core/res/res/values/attrs.xml18
-rw-r--r--core/res/res/values/public.xml2
-rw-r--r--core/res/res/values/symbols.xml2
-rw-r--r--core/tests/coretests/src/android/os/VintfObjectTest.java30
-rw-r--r--data/fonts/fonts.xml3
-rw-r--r--graphics/java/android/graphics/ColorSpace.java28
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java32
-rw-r--r--packages/SettingsLib/tests/integ/src/com/android/settingslib/applications/ApplicationsStateTest.java16
-rw-r--r--packages/SystemUI/res/drawable-hdpi/pip_dismiss_scrim.9.pngbin518 -> 525 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/pip_dismiss_scrim.9.pngbin450 -> 436 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/pip_dismiss_scrim.9.pngbin544 -> 611 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/pip_dismiss_scrim.9.pngbin544 -> 633 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxxhdpi/pip_dismiss_scrim.9.pngbin556 -> 647 bytes
-rw-r--r--packages/SystemUI/res/layout/pip_dismiss_view.xml6
-rw-r--r--packages/SystemUI/res/values/dimens.xml2
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java1
-rw-r--r--services/Android.mk4
-rw-r--r--services/autofill/java/com/android/server/autofill/Session.java17
-rw-r--r--services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java8
-rw-r--r--services/autofill/java/com/android/server/autofill/ui/FillUi.java21
-rw-r--r--services/core/Android.mk14
-rw-r--r--services/core/java/com/android/server/OemLockService.java147
-rw-r--r--services/core/java/com/android/server/accounts/AccountManagerService.java9
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerConstants.java10
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java25
-rw-r--r--services/core/java/com/android/server/am/ActivityStackSupervisor.java22
-rw-r--r--services/core/java/com/android/server/am/PinnedActivityStack.java9
-rw-r--r--services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java83
-rw-r--r--services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java3
-rw-r--r--services/core/java/com/android/server/connectivity/NetdEventListenerService.java174
-rw-r--r--services/core/java/com/android/server/connectivity/NetworkMonitor.java48
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java25
-rw-r--r--services/core/java/com/android/server/wm/BoundsAnimationController.java75
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java7
-rw-r--r--services/core/java/com/android/server/wm/PinnedStackController.java26
-rw-r--r--services/core/java/com/android/server/wm/PinnedStackWindowController.java31
-rw-r--r--services/core/java/com/android/server/wm/PinnedStackWindowListener.java32
-rw-r--r--services/core/java/com/android/server/wm/StackWindowController.java7
-rw-r--r--services/core/java/com/android/server/wm/StackWindowListener.java6
-rw-r--r--services/core/java/com/android/server/wm/Task.java3
-rw-r--r--services/core/java/com/android/server/wm/TaskStack.java117
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java13
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java2
-rw-r--r--services/core/java/com/android/server/wm/WindowStateAnimator.java4
-rw-r--r--services/java/com/android/server/SystemServer.java5
-rw-r--r--services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java19
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/BoundsAnimationControllerTests.java348
-rw-r--r--services/usb/Android.mk4
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java25
-rw-r--r--telephony/java/com/android/internal/telephony/ITelephony.aidl6
-rw-r--r--tests/ActivityTests/AndroidManifest.xml8
-rw-r--r--tests/ActivityTests/res/drawable/splashscreen.xml24
-rw-r--r--tests/ActivityTests/res/values/themes.xml3
-rw-r--r--tests/ActivityTests/src/com/google/android/test/activity/CustomSplashscreenActivity.java35
-rw-r--r--tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java136
-rw-r--r--tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java141
-rw-r--r--tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java485
-rw-r--r--tools/aapt2/cmd/Link.cpp3
-rw-r--r--tools/aapt2/cmd/Optimize.cpp3
-rw-r--r--tools/aapt2/cmd/Util.cpp11
109 files changed, 2292 insertions, 983 deletions
diff --git a/Android.mk b/Android.mk
index b8b85baa95ee..991d18513be8 100644
--- a/Android.mk
+++ b/Android.mk
@@ -309,6 +309,7 @@ LOCAL_SRC_FILES += \
core/java/android/companion/IFindDeviceCallback.aidl \
core/java/android/service/dreams/IDreamManager.aidl \
core/java/android/service/dreams/IDreamService.aidl \
+ core/java/android/service/oemlock/IOemLockService.aidl \
core/java/android/service/persistentdata/IPersistentDataBlockService.aidl \
core/java/android/service/trust/ITrustAgentService.aidl \
core/java/android/service/trust/ITrustAgentServiceCallback.aidl \
@@ -569,11 +570,11 @@ LOCAL_JAVA_LIBRARIES := core-oj core-libart conscrypt okhttp bouncycastle ext
LOCAL_STATIC_JAVA_LIBRARIES := \
framework-protos \
- android.hardware.health@1.0-java-constants \
- android.hardware.thermal@1.0-java-constants \
- android.hardware.tv.input@1.0-java-constants \
- android.hardware.usb@1.0-java-constants \
- android.hardware.vibrator@1.0-java-constants \
+ android.hardware.health-V1.0-java-constants \
+ android.hardware.thermal-V1.0-java-constants \
+ android.hardware.tv.input-V1.0-java-constants \
+ android.hardware.usb-V1.0-java-constants \
+ android.hardware.vibrator-V1.0-java-constants \
# Loaded with System.loadLibrary by android.view.textclassifier
LOCAL_REQUIRED_MODULES += libtextclassifier
diff --git a/api/current.txt b/api/current.txt
index f9c8d46e4bff..bbed515ab11d 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -1541,6 +1541,7 @@ package android {
field public static final int windowShowAnimation = 16842934; // 0x10100b6
field public static final int windowShowWallpaper = 16843410; // 0x1010292
field public static final int windowSoftInputMode = 16843307; // 0x101022b
+ field public static final int windowSplashscreenContent = 16844135; // 0x1010567
field public static final int windowSwipeToDismiss = 16843763; // 0x10103f3
field public static final int windowTitleBackgroundStyle = 16842844; // 0x101005c
field public static final int windowTitleSize = 16842842; // 0x101005a
@@ -2999,6 +3000,7 @@ package android.accounts {
method public android.accounts.AccountManagerFuture<android.os.Bundle> startAddAccountSession(java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
method public android.accounts.AccountManagerFuture<android.os.Bundle> startUpdateCredentialsSession(android.accounts.Account, java.lang.String, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
method public android.accounts.AccountManagerFuture<android.os.Bundle> updateCredentials(android.accounts.Account, java.lang.String, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
+ field public static final java.lang.String ACTION_ACCOUNT_REMOVED = "android.accounts.action.ACCOUNT_REMOVED";
field public static final java.lang.String ACTION_AUTHENTICATOR_INTENT = "android.accounts.AccountAuthenticator";
field public static final java.lang.String AUTHENTICATOR_ATTRIBUTES_NAME = "account-authenticator";
field public static final java.lang.String AUTHENTICATOR_META_DATA_NAME = "android.accounts.AccountAuthenticator";
@@ -7606,9 +7608,11 @@ package android.bluetooth {
field public static final int PAIRING_VARIANT_PASSKEY_CONFIRMATION = 2; // 0x2
field public static final int PAIRING_VARIANT_PIN = 0; // 0x0
field public static final int PHY_LE_1M = 1; // 0x1
+ field public static final int PHY_LE_1M_MASK = 1; // 0x1
field public static final int PHY_LE_2M = 2; // 0x2
- field public static final int PHY_LE_ANY = 7; // 0x7
- field public static final int PHY_LE_CODED = 4; // 0x4
+ field public static final int PHY_LE_2M_MASK = 2; // 0x2
+ field public static final int PHY_LE_CODED = 3; // 0x3
+ field public static final int PHY_LE_CODED_MASK = 4; // 0x4
field public static final int PHY_OPTION_NO_PREFERRED = 0; // 0x0
field public static final int PHY_OPTION_S2 = 1; // 0x1
field public static final int PHY_OPTION_S8 = 2; // 0x2
@@ -8026,9 +8030,6 @@ package android.bluetooth.le {
field public static final int INTERVAL_MAX = 16777215; // 0xffffff
field public static final int INTERVAL_MEDIUM = 400; // 0x190
field public static final int INTERVAL_MIN = 160; // 0xa0
- field public static final int PHY_LE_1M = 1; // 0x1
- field public static final int PHY_LE_2M = 2; // 0x2
- field public static final int PHY_LE_CODED = 3; // 0x3
field public static final int TX_POWER_HIGH = 1; // 0x1
field public static final int TX_POWER_LOW = -15; // 0xfffffff1
field public static final int TX_POWER_MAX = 1; // 0x1
@@ -8157,9 +8158,6 @@ package android.bluetooth.le {
field public static final android.os.Parcelable.Creator<android.bluetooth.le.ScanResult> CREATOR;
field public static final int DATA_COMPLETE = 0; // 0x0
field public static final int DATA_TRUNCATED = 2; // 0x2
- field public static final int PHY_LE_1M = 1; // 0x1
- field public static final int PHY_LE_2M = 2; // 0x2
- field public static final int PHY_LE_CODED = 3; // 0x3
field public static final int PHY_UNUSED = 0; // 0x0
field public static final int SID_NOT_PRESENT = 255; // 0xff
}
@@ -8182,9 +8180,7 @@ package android.bluetooth.le {
field public static final int MATCH_NUM_FEW_ADVERTISEMENT = 2; // 0x2
field public static final int MATCH_NUM_MAX_ADVERTISEMENT = 3; // 0x3
field public static final int MATCH_NUM_ONE_ADVERTISEMENT = 1; // 0x1
- field public static final int PHY_LE_1M = 1; // 0x1
field public static final int PHY_LE_ALL_SUPPORTED = 255; // 0xff
- field public static final int PHY_LE_CODED = 3; // 0x3
field public static final int SCAN_MODE_BALANCED = 1; // 0x1
field public static final int SCAN_MODE_LOW_LATENCY = 2; // 0x2
field public static final int SCAN_MODE_LOW_POWER = 0; // 0x0
@@ -9465,6 +9461,7 @@ package android.content {
field public static final java.lang.String EXTRA_DONT_KILL_APP = "android.intent.extra.DONT_KILL_APP";
field public static final java.lang.String EXTRA_EMAIL = "android.intent.extra.EMAIL";
field public static final java.lang.String EXTRA_EXCLUDE_COMPONENTS = "android.intent.extra.EXCLUDE_COMPONENTS";
+ field public static final java.lang.String EXTRA_FROM_STORAGE = "android.intent.extra.FROM_STORAGE";
field public static final java.lang.String EXTRA_HTML_TEXT = "android.intent.extra.HTML_TEXT";
field public static final java.lang.String EXTRA_INDEX = "android.intent.extra.INDEX";
field public static final java.lang.String EXTRA_INITIAL_INTENTS = "android.intent.extra.INITIAL_INTENTS";
@@ -15749,7 +15746,6 @@ package android.hardware.display {
method public void unregisterDisplayListener(android.hardware.display.DisplayManager.DisplayListener);
field public static final java.lang.String DISPLAY_CATEGORY_PRESENTATION = "android.hardware.display.category.PRESENTATION";
field public static final int VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR = 16; // 0x10
- field public static final int VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 32; // 0x20
field public static final int VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY = 8; // 0x8
field public static final int VIRTUAL_DISPLAY_FLAG_PRESENTATION = 2; // 0x2
field public static final int VIRTUAL_DISPLAY_FLAG_PUBLIC = 1; // 0x1
@@ -43882,7 +43878,6 @@ package android.view {
method public boolean isValid();
method public boolean isWideColorGamut();
field public static final int DEFAULT_DISPLAY = 0; // 0x0
- field public static final int FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 32; // 0x20
field public static final int FLAG_PRESENTATION = 8; // 0x8
field public static final int FLAG_PRIVATE = 4; // 0x4
field public static final int FLAG_ROUND = 16; // 0x10
diff --git a/api/system-current.txt b/api/system-current.txt
index 4b01396881a4..f19fe6002634 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -142,12 +142,14 @@ package android {
field public static final java.lang.String MANAGE_APP_OPS_RESTRICTIONS = "android.permission.MANAGE_APP_OPS_RESTRICTIONS";
field public static final java.lang.String MANAGE_APP_TOKENS = "android.permission.MANAGE_APP_TOKENS";
field public static final java.lang.String MANAGE_AUTO_FILL = "android.permission.MANAGE_AUTO_FILL";
+ field public static final java.lang.String MANAGE_CARRIER_OEM_UNLOCK_STATE = "android.permission.MANAGE_CARRIER_OEM_UNLOCK_STATE";
field public static final java.lang.String MANAGE_CA_CERTIFICATES = "android.permission.MANAGE_CA_CERTIFICATES";
field public static final java.lang.String MANAGE_DEVICE_ADMINS = "android.permission.MANAGE_DEVICE_ADMINS";
field public static final java.lang.String MANAGE_DOCUMENTS = "android.permission.MANAGE_DOCUMENTS";
field public static final java.lang.String MANAGE_OWN_CALLS = "android.permission.MANAGE_OWN_CALLS";
field public static final java.lang.String MANAGE_USB = "android.permission.MANAGE_USB";
field public static final java.lang.String MANAGE_USERS = "android.permission.MANAGE_USERS";
+ field public static final java.lang.String MANAGE_USER_OEM_UNLOCK_STATE = "android.permission.MANAGE_USER_OEM_UNLOCK_STATE";
field public static final java.lang.String MASTER_CLEAR = "android.permission.MASTER_CLEAR";
field public static final java.lang.String MEDIA_CONTENT_CONTROL = "android.permission.MEDIA_CONTENT_CONTROL";
field public static final java.lang.String MODIFY_APPWIDGET_BIND_PERMISSIONS = "android.permission.MODIFY_APPWIDGET_BIND_PERMISSIONS";
@@ -1661,6 +1663,7 @@ package android {
field public static final int windowShowAnimation = 16842934; // 0x10100b6
field public static final int windowShowWallpaper = 16843410; // 0x1010292
field public static final int windowSoftInputMode = 16843307; // 0x101022b
+ field public static final int windowSplashscreenContent = 16844135; // 0x1010567
field public static final int windowSwipeToDismiss = 16843763; // 0x10103f3
field public static final int windowTitleBackgroundStyle = 16842844; // 0x101005c
field public static final int windowTitleSize = 16842842; // 0x101005a
@@ -3123,6 +3126,7 @@ package android.accounts {
method public android.accounts.AccountManagerFuture<android.os.Bundle> startAddAccountSession(java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
method public android.accounts.AccountManagerFuture<android.os.Bundle> startUpdateCredentialsSession(android.accounts.Account, java.lang.String, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
method public android.accounts.AccountManagerFuture<android.os.Bundle> updateCredentials(android.accounts.Account, java.lang.String, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
+ field public static final java.lang.String ACTION_ACCOUNT_REMOVED = "android.accounts.action.ACCOUNT_REMOVED";
field public static final java.lang.String ACTION_AUTHENTICATOR_INTENT = "android.accounts.AccountAuthenticator";
field public static final java.lang.String AUTHENTICATOR_ATTRIBUTES_NAME = "account-authenticator";
field public static final java.lang.String AUTHENTICATOR_META_DATA_NAME = "android.accounts.AccountAuthenticator";
@@ -8076,9 +8080,11 @@ package android.bluetooth {
field public static final int PAIRING_VARIANT_PASSKEY_CONFIRMATION = 2; // 0x2
field public static final int PAIRING_VARIANT_PIN = 0; // 0x0
field public static final int PHY_LE_1M = 1; // 0x1
+ field public static final int PHY_LE_1M_MASK = 1; // 0x1
field public static final int PHY_LE_2M = 2; // 0x2
- field public static final int PHY_LE_ANY = 7; // 0x7
- field public static final int PHY_LE_CODED = 4; // 0x4
+ field public static final int PHY_LE_2M_MASK = 2; // 0x2
+ field public static final int PHY_LE_CODED = 3; // 0x3
+ field public static final int PHY_LE_CODED_MASK = 4; // 0x4
field public static final int PHY_OPTION_NO_PREFERRED = 0; // 0x0
field public static final int PHY_OPTION_S2 = 1; // 0x1
field public static final int PHY_OPTION_S8 = 2; // 0x2
@@ -8496,9 +8502,6 @@ package android.bluetooth.le {
field public static final int INTERVAL_MAX = 16777215; // 0xffffff
field public static final int INTERVAL_MEDIUM = 400; // 0x190
field public static final int INTERVAL_MIN = 160; // 0xa0
- field public static final int PHY_LE_1M = 1; // 0x1
- field public static final int PHY_LE_2M = 2; // 0x2
- field public static final int PHY_LE_CODED = 3; // 0x3
field public static final int TX_POWER_HIGH = 1; // 0x1
field public static final int TX_POWER_LOW = -15; // 0xfffffff1
field public static final int TX_POWER_MAX = 1; // 0x1
@@ -8640,9 +8643,6 @@ package android.bluetooth.le {
field public static final android.os.Parcelable.Creator<android.bluetooth.le.ScanResult> CREATOR;
field public static final int DATA_COMPLETE = 0; // 0x0
field public static final int DATA_TRUNCATED = 2; // 0x2
- field public static final int PHY_LE_1M = 1; // 0x1
- field public static final int PHY_LE_2M = 2; // 0x2
- field public static final int PHY_LE_CODED = 3; // 0x3
field public static final int PHY_UNUSED = 0; // 0x0
field public static final int SID_NOT_PRESENT = 255; // 0xff
}
@@ -8665,9 +8665,7 @@ package android.bluetooth.le {
field public static final int MATCH_NUM_FEW_ADVERTISEMENT = 2; // 0x2
field public static final int MATCH_NUM_MAX_ADVERTISEMENT = 3; // 0x3
field public static final int MATCH_NUM_ONE_ADVERTISEMENT = 1; // 0x1
- field public static final int PHY_LE_1M = 1; // 0x1
field public static final int PHY_LE_ALL_SUPPORTED = 255; // 0xff
- field public static final int PHY_LE_CODED = 3; // 0x3
field public static final int SCAN_MODE_BALANCED = 1; // 0x1
field public static final int SCAN_MODE_LOW_LATENCY = 2; // 0x2
field public static final int SCAN_MODE_LOW_POWER = 0; // 0x0
@@ -9435,6 +9433,7 @@ package android.content {
field public static final java.lang.String NFC_SERVICE = "nfc";
field public static final java.lang.String NOTIFICATION_SERVICE = "notification";
field public static final java.lang.String NSD_SERVICE = "servicediscovery";
+ field public static final java.lang.String OEM_LOCK_SERVICE = "oem_lock";
field public static final java.lang.String PERSISTENT_DATA_BLOCK_SERVICE = "persistent_data_block";
field public static final java.lang.String POWER_SERVICE = "power";
field public static final java.lang.String PRINT_SERVICE = "print";
@@ -10013,6 +10012,7 @@ package android.content {
field public static final deprecated java.lang.String EXTRA_EMERGENCY_ONLY = "emergencyOnly";
field public static final java.lang.String EXTRA_EXCLUDE_COMPONENTS = "android.intent.extra.EXCLUDE_COMPONENTS";
field public static final java.lang.String EXTRA_FORCE_FACTORY_RESET = "android.intent.extra.FORCE_FACTORY_RESET";
+ field public static final java.lang.String EXTRA_FROM_STORAGE = "android.intent.extra.FROM_STORAGE";
field public static final java.lang.String EXTRA_HTML_TEXT = "android.intent.extra.HTML_TEXT";
field public static final java.lang.String EXTRA_INDEX = "android.intent.extra.INDEX";
field public static final java.lang.String EXTRA_INITIAL_INTENTS = "android.intent.extra.INITIAL_INTENTS";
@@ -16535,7 +16535,6 @@ package android.hardware.display {
method public void unregisterDisplayListener(android.hardware.display.DisplayManager.DisplayListener);
field public static final java.lang.String DISPLAY_CATEGORY_PRESENTATION = "android.hardware.display.category.PRESENTATION";
field public static final int VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR = 16; // 0x10
- field public static final int VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 32; // 0x20
field public static final int VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY = 8; // 0x8
field public static final int VIRTUAL_DISPLAY_FLAG_PRESENTATION = 2; // 0x2
field public static final int VIRTUAL_DISPLAY_FLAG_PUBLIC = 1; // 0x1
@@ -34663,7 +34662,7 @@ package android.os {
field public static final java.lang.String DISALLOW_MODIFY_ACCOUNTS = "no_modify_accounts";
field public static final java.lang.String DISALLOW_MOUNT_PHYSICAL_MEDIA = "no_physical_media";
field public static final java.lang.String DISALLOW_NETWORK_RESET = "no_network_reset";
- field public static final java.lang.String DISALLOW_OEM_UNLOCK = "no_oem_unlock";
+ field public static final deprecated java.lang.String DISALLOW_OEM_UNLOCK = "no_oem_unlock";
field public static final java.lang.String DISALLOW_OUTGOING_BEAM = "no_outgoing_beam";
field public static final java.lang.String DISALLOW_OUTGOING_CALLS = "no_outgoing_calls";
field public static final java.lang.String DISALLOW_REMOVE_MANAGED_PROFILE = "no_remove_managed_profile";
@@ -40621,15 +40620,26 @@ package android.service.notification {
}
+package android.service.oemlock {
+
+ public class OemLockManager {
+ method public boolean isOemUnlockAllowedByCarrier();
+ method public boolean isOemUnlockAllowedByUser();
+ method public void setOemUnlockAllowedByCarrier(boolean, byte[]);
+ method public void setOemUnlockAllowedByUser(boolean);
+ }
+
+}
+
package android.service.persistentdata {
public class PersistentDataBlockManager {
method public int getDataBlockSize();
method public int getFlashLockState();
method public long getMaximumDataBlockSize();
- method public boolean getOemUnlockEnabled();
+ method public deprecated boolean getOemUnlockEnabled();
method public byte[] read();
- method public void setOemUnlockEnabled(boolean);
+ method public deprecated void setOemUnlockEnabled(boolean);
method public void wipe();
method public int write(byte[]);
field public static final int FLASH_LOCK_LOCKED = 1; // 0x1
@@ -43682,7 +43692,7 @@ package android.telephony {
method public boolean isSmsCapable();
method public boolean isTtyModeSupported();
method public boolean isVideoCallingEnabled();
- method public boolean isVisualVoicemailEnabled(android.telecom.PhoneAccountHandle);
+ method public deprecated boolean isVisualVoicemailEnabled(android.telecom.PhoneAccountHandle);
method public boolean isVoiceCapable();
method public boolean isVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle);
method public boolean isWorldPhone();
@@ -43699,7 +43709,7 @@ package android.telephony {
method public boolean setPreferredNetworkTypeToGlobal();
method public boolean setRadio(boolean);
method public boolean setRadioPower(boolean);
- method public void setVisualVoicemailEnabled(android.telecom.PhoneAccountHandle, boolean);
+ method public deprecated void setVisualVoicemailEnabled(android.telecom.PhoneAccountHandle, boolean);
method public boolean setVoiceMailNumber(java.lang.String, java.lang.String);
method public void setVoicemailRingtoneUri(android.telecom.PhoneAccountHandle, android.net.Uri);
method public void setVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle, boolean);
@@ -47448,7 +47458,6 @@ package android.view {
method public boolean isValid();
method public boolean isWideColorGamut();
field public static final int DEFAULT_DISPLAY = 0; // 0x0
- field public static final int FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 32; // 0x20
field public static final int FLAG_PRESENTATION = 8; // 0x8
field public static final int FLAG_PRIVATE = 4; // 0x4
field public static final int FLAG_ROUND = 16; // 0x10
diff --git a/api/test-current.txt b/api/test-current.txt
index 43f4caf75f49..e74ca979885e 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -1541,6 +1541,7 @@ package android {
field public static final int windowShowAnimation = 16842934; // 0x10100b6
field public static final int windowShowWallpaper = 16843410; // 0x1010292
field public static final int windowSoftInputMode = 16843307; // 0x101022b
+ field public static final int windowSplashscreenContent = 16844135; // 0x1010567
field public static final int windowSwipeToDismiss = 16843763; // 0x10103f3
field public static final int windowTitleBackgroundStyle = 16842844; // 0x101005c
field public static final int windowTitleSize = 16842842; // 0x101005a
@@ -2999,6 +3000,7 @@ package android.accounts {
method public android.accounts.AccountManagerFuture<android.os.Bundle> startAddAccountSession(java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
method public android.accounts.AccountManagerFuture<android.os.Bundle> startUpdateCredentialsSession(android.accounts.Account, java.lang.String, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
method public android.accounts.AccountManagerFuture<android.os.Bundle> updateCredentials(android.accounts.Account, java.lang.String, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
+ field public static final java.lang.String ACTION_ACCOUNT_REMOVED = "android.accounts.action.ACCOUNT_REMOVED";
field public static final java.lang.String ACTION_AUTHENTICATOR_INTENT = "android.accounts.AccountAuthenticator";
field public static final java.lang.String AUTHENTICATOR_ATTRIBUTES_NAME = "account-authenticator";
field public static final java.lang.String AUTHENTICATOR_META_DATA_NAME = "android.accounts.AccountAuthenticator";
@@ -7637,9 +7639,11 @@ package android.bluetooth {
field public static final int PAIRING_VARIANT_PASSKEY_CONFIRMATION = 2; // 0x2
field public static final int PAIRING_VARIANT_PIN = 0; // 0x0
field public static final int PHY_LE_1M = 1; // 0x1
+ field public static final int PHY_LE_1M_MASK = 1; // 0x1
field public static final int PHY_LE_2M = 2; // 0x2
- field public static final int PHY_LE_ANY = 7; // 0x7
- field public static final int PHY_LE_CODED = 4; // 0x4
+ field public static final int PHY_LE_2M_MASK = 2; // 0x2
+ field public static final int PHY_LE_CODED = 3; // 0x3
+ field public static final int PHY_LE_CODED_MASK = 4; // 0x4
field public static final int PHY_OPTION_NO_PREFERRED = 0; // 0x0
field public static final int PHY_OPTION_S2 = 1; // 0x1
field public static final int PHY_OPTION_S8 = 2; // 0x2
@@ -8057,9 +8061,6 @@ package android.bluetooth.le {
field public static final int INTERVAL_MAX = 16777215; // 0xffffff
field public static final int INTERVAL_MEDIUM = 400; // 0x190
field public static final int INTERVAL_MIN = 160; // 0xa0
- field public static final int PHY_LE_1M = 1; // 0x1
- field public static final int PHY_LE_2M = 2; // 0x2
- field public static final int PHY_LE_CODED = 3; // 0x3
field public static final int TX_POWER_HIGH = 1; // 0x1
field public static final int TX_POWER_LOW = -15; // 0xfffffff1
field public static final int TX_POWER_MAX = 1; // 0x1
@@ -8188,9 +8189,6 @@ package android.bluetooth.le {
field public static final android.os.Parcelable.Creator<android.bluetooth.le.ScanResult> CREATOR;
field public static final int DATA_COMPLETE = 0; // 0x0
field public static final int DATA_TRUNCATED = 2; // 0x2
- field public static final int PHY_LE_1M = 1; // 0x1
- field public static final int PHY_LE_2M = 2; // 0x2
- field public static final int PHY_LE_CODED = 3; // 0x3
field public static final int PHY_UNUSED = 0; // 0x0
field public static final int SID_NOT_PRESENT = 255; // 0xff
}
@@ -8213,9 +8211,7 @@ package android.bluetooth.le {
field public static final int MATCH_NUM_FEW_ADVERTISEMENT = 2; // 0x2
field public static final int MATCH_NUM_MAX_ADVERTISEMENT = 3; // 0x3
field public static final int MATCH_NUM_ONE_ADVERTISEMENT = 1; // 0x1
- field public static final int PHY_LE_1M = 1; // 0x1
field public static final int PHY_LE_ALL_SUPPORTED = 255; // 0xff
- field public static final int PHY_LE_CODED = 3; // 0x3
field public static final int SCAN_MODE_BALANCED = 1; // 0x1
field public static final int SCAN_MODE_LOW_LATENCY = 2; // 0x2
field public static final int SCAN_MODE_LOW_POWER = 0; // 0x0
@@ -9499,6 +9495,7 @@ package android.content {
field public static final java.lang.String EXTRA_DONT_KILL_APP = "android.intent.extra.DONT_KILL_APP";
field public static final java.lang.String EXTRA_EMAIL = "android.intent.extra.EMAIL";
field public static final java.lang.String EXTRA_EXCLUDE_COMPONENTS = "android.intent.extra.EXCLUDE_COMPONENTS";
+ field public static final java.lang.String EXTRA_FROM_STORAGE = "android.intent.extra.FROM_STORAGE";
field public static final java.lang.String EXTRA_HTML_TEXT = "android.intent.extra.HTML_TEXT";
field public static final java.lang.String EXTRA_INDEX = "android.intent.extra.INDEX";
field public static final java.lang.String EXTRA_INITIAL_INTENTS = "android.intent.extra.INITIAL_INTENTS";
@@ -15798,7 +15795,6 @@ package android.hardware.display {
method public void unregisterDisplayListener(android.hardware.display.DisplayManager.DisplayListener);
field public static final java.lang.String DISPLAY_CATEGORY_PRESENTATION = "android.hardware.display.category.PRESENTATION";
field public static final int VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR = 16; // 0x10
- field public static final int VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 32; // 0x20
field public static final int VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY = 8; // 0x8
field public static final int VIRTUAL_DISPLAY_FLAG_PRESENTATION = 2; // 0x2
field public static final int VIRTUAL_DISPLAY_FLAG_PUBLIC = 1; // 0x1
@@ -44245,7 +44241,6 @@ package android.view {
method public boolean isValid();
method public boolean isWideColorGamut();
field public static final int DEFAULT_DISPLAY = 0; // 0x0
- field public static final int FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 32; // 0x20
field public static final int FLAG_PRESENTATION = 8; // 0x8
field public static final int FLAG_PRIVATE = 4; // 0x4
field public static final int FLAG_ROUND = 16; // 0x10
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index 80522886c78f..b320d5d83cc7 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -335,6 +335,7 @@ public class AccountManager {
* are removed, or an account's credentials (saved password, etc) are changed.
*
* @see #addOnAccountsUpdatedListener
+ * @see #ACTION_ACCOUNT_REMOVED
*
* @deprecated use {@link #addOnAccountsUpdatedListener} to get account updates in runtime.
*/
@@ -344,6 +345,14 @@ public class AccountManager {
"android.accounts.LOGIN_ACCOUNTS_CHANGED";
/**
+ * Action sent as a broadcast Intent by the AccountsService when any account is removed.
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ @BroadcastBehavior(includeBackground = true)
+ public static final String ACTION_ACCOUNT_REMOVED =
+ "android.accounts.action.ACCOUNT_REMOVED";
+
+ /**
* Action sent as a broadcast Intent to specific package by the AccountsService
* when account visibility or account's credentials (saved password, etc) are changed.
*
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 74822d132873..b9a78f1342c5 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -5941,7 +5941,7 @@ public class Activity extends ContextThemeWrapper
*/
public void setTaskDescription(ActivityManager.TaskDescription taskDescription) {
if (mTaskDescription != taskDescription) {
- mTaskDescription.copyFrom(taskDescription);
+ mTaskDescription.copyFromPreserveHiddenFields(taskDescription);
// Scale the icon down to something reasonable if it is provided
if (taskDescription.getIconFilename() == null && taskDescription.getIcon() != null) {
final int size = ActivityManager.getLauncherLargeIconSizeInner(this);
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 80482ca6e026..88598313724e 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -1222,6 +1222,27 @@ public class ActivityManager {
mNavigationBarColor = other.mNavigationBarColor;
}
+ /**
+ * Copies this the values from another TaskDescription, but preserves the hidden fields
+ * if they weren't set on {@code other}
+ * @hide
+ */
+ public void copyFromPreserveHiddenFields(TaskDescription other) {
+ mLabel = other.mLabel;
+ mIcon = other.mIcon;
+ mIconFilename = other.mIconFilename;
+ mColorPrimary = other.mColorPrimary;
+ if (other.mColorBackground != 0) {
+ mColorBackground = other.mColorBackground;
+ }
+ if (other.mStatusBarColor != 0) {
+ mStatusBarColor = other.mStatusBarColor;
+ }
+ if (other.mNavigationBarColor != 0) {
+ mNavigationBarColor = other.mNavigationBarColor;
+ }
+ }
+
private TaskDescription(Parcel source) {
readFromParcel(source);
}
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 19f7426863cb..40fe6af9627d 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -120,6 +120,8 @@ import android.print.IPrintManager;
import android.print.PrintManager;
import android.view.autofill.AutofillManager;
import android.view.autofill.IAutoFillManager;
+import android.service.oemlock.IOemLockService;
+import android.service.oemlock.OemLockManager;
import android.service.persistentdata.IPersistentDataBlockService;
import android.service.persistentdata.PersistentDataBlockManager;
import android.service.vr.IVrManager;
@@ -752,6 +754,20 @@ final class SystemServiceRegistry {
}
}});
+ registerService(Context.OEM_LOCK_SERVICE, OemLockManager.class,
+ new StaticServiceFetcher<OemLockManager>() {
+ @Override
+ public OemLockManager createService() throws ServiceNotFoundException {
+ IBinder b = ServiceManager.getServiceOrThrow(Context.OEM_LOCK_SERVICE);
+ IOemLockService oemLockService = IOemLockService.Stub.asInterface(b);
+ if (oemLockService != null) {
+ return new OemLockManager(oemLockService);
+ } else {
+ // not supported
+ return null;
+ }
+ }});
+
registerService(Context.MEDIA_PROJECTION_SERVICE, MediaProjectionManager.class,
new CachedServiceFetcher<MediaProjectionManager>() {
@Override
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index cb6fa052ddac..e6cebc0819f5 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -593,24 +593,34 @@ public final class BluetoothDevice implements Parcelable {
public static final int TRANSPORT_LE = 2;
/**
- * 1M initiating PHY.
+ * Bluetooth LE 1M PHY.
*/
public static final int PHY_LE_1M = 1;
/**
- * 2M initiating PHY.
+ * Bluetooth LE 2M PHY.
*/
public static final int PHY_LE_2M = 2;
/**
- * LE Coded initiating PHY.
+ * Bluetooth LE Coded PHY.
*/
- public static final int PHY_LE_CODED = 4;
+ public static final int PHY_LE_CODED = 3;
/**
- * Any LE PHY.
+ * Bluetooth LE 1M PHY mask.
*/
- public static final int PHY_LE_ANY = PHY_LE_1M | PHY_LE_2M | PHY_LE_CODED;
+ public static final int PHY_LE_1M_MASK = 1;
+
+ /**
+ * Bluetooth LE 2M PHY mask.
+ */
+ public static final int PHY_LE_2M_MASK = 2;
+
+ /**
+ * Bluetooth LE Coded PHY mask.
+ */
+ public static final int PHY_LE_CODED_MASK = 4;
/**
* No preferred coding when transmitting on the LE Coded PHY.
@@ -1651,7 +1661,7 @@ public final class BluetoothDevice implements Parcelable {
*/
public BluetoothGatt connectGatt(Context context, boolean autoConnect,
BluetoothGattCallback callback, int transport) {
- return (connectGatt(context, autoConnect,callback, TRANSPORT_AUTO, PHY_LE_1M));
+ return (connectGatt(context, autoConnect,callback, TRANSPORT_AUTO, PHY_LE_1M_MASK));
}
/**
@@ -1668,8 +1678,8 @@ public final class BluetoothDevice implements Parcelable {
* {@link BluetoothDevice#TRANSPORT_AUTO} or
* {@link BluetoothDevice#TRANSPORT_BREDR} or {@link BluetoothDevice#TRANSPORT_LE}
* @param phy preferred PHY for connections to remote LE device. Bitwise OR of any of
- * {@link BluetoothDevice#PHY_LE_1M}, {@link BluetoothDevice#PHY_LE_2M},
- * and {@link BluetoothDevice#PHY_LE_CODED}. This option does not take effect if
+ * {@link BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK},
+ * and {@link BluetoothDevice#PHY_LE_CODED_MASK}. This option does not take effect if
* {@code autoConnect} is set to true.
* @throws IllegalArgumentException if callback is null
*/
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index 5d1e8ec58ceb..4aaf6bd3eb17 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -785,11 +785,11 @@ public final class BluetoothGatt implements BluetoothProfile {
* if no PHY change happens. It is also triggered when remote device updates the PHY.
*
* @param txPhy preferred transmitter PHY. Bitwise OR of any of
- * {@link BluetoothDevice#PHY_LE_1M}, {@link BluetoothDevice#PHY_LE_2M}, and
- * {@link BluetoothDevice#PHY_LE_CODED}.
+ * {@link BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK},
+ * and {@link BluetoothDevice#PHY_LE_CODED_MASK}.
* @param rxPhy preferred receiver PHY. Bitwise OR of any of
- * {@link BluetoothDevice#PHY_LE_1M}, {@link BluetoothDevice#PHY_LE_2M}, and
- * {@link BluetoothDevice#PHY_LE_CODED}.
+ * {@link BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK},
+ * and {@link BluetoothDevice#PHY_LE_CODED_MASK}.
* @param phyOptions preferred coding to use when transmitting on the LE Coded PHY. Can be one
* of {@link BluetoothDevice#PHY_OPTION_NO_PREFERRED},
* {@link BluetoothDevice#PHY_OPTION_S2} or {@link BluetoothDevice#PHY_OPTION_S8}
diff --git a/core/java/android/bluetooth/BluetoothGattServer.java b/core/java/android/bluetooth/BluetoothGattServer.java
index 2df2ed8ff86f..eddc278851f4 100644
--- a/core/java/android/bluetooth/BluetoothGattServer.java
+++ b/core/java/android/bluetooth/BluetoothGattServer.java
@@ -558,11 +558,11 @@ public final class BluetoothGattServer implements BluetoothProfile {
*
* @param device The remote device to send this response to
* @param txPhy preferred transmitter PHY. Bitwise OR of any of
- * {@link BluetoothDevice#PHY_LE_1M}, {@link BluetoothDevice#PHY_LE_2M}, and
- * {@link BluetoothDevice#PHY_LE_CODED}.
+ * {@link BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK},
+ * and {@link BluetoothDevice#PHY_LE_CODED_MASK}.
* @param rxPhy preferred receiver PHY. Bitwise OR of any of
- * {@link BluetoothDevice#PHY_LE_1M}, {@link BluetoothDevice#PHY_LE_2M}, and
- * {@link BluetoothDevice#PHY_LE_CODED}.
+ * {@link BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK},
+ * and {@link BluetoothDevice#PHY_LE_CODED_MASK}.
* @param phyOptions preferred coding to use when transmitting on the LE Coded PHY. Can be one
* of {@link BluetoothDevice#PHY_OPTION_NO_PREFERRED},
* {@link BluetoothDevice#PHY_OPTION_S2} or {@link BluetoothDevice#PHY_OPTION_S8}
diff --git a/core/java/android/bluetooth/le/AdvertisingSetParameters.java b/core/java/android/bluetooth/le/AdvertisingSetParameters.java
index 4e9fac3ee22b..31d8f482090d 100644
--- a/core/java/android/bluetooth/le/AdvertisingSetParameters.java
+++ b/core/java/android/bluetooth/le/AdvertisingSetParameters.java
@@ -17,6 +17,7 @@
package android.bluetooth.le;
import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
import android.os.Parcel;
import android.os.Parcelable;
@@ -30,21 +31,6 @@ import android.os.Parcelable;
public final class AdvertisingSetParameters implements Parcelable {
/**
- * 1M advertiser PHY.
- */
- public static final int PHY_LE_1M = 1;
-
- /**
- * 2M advertiser PHY.
- */
- public static final int PHY_LE_2M = 2;
-
- /**
- * LE Coded advertiser PHY.
- */
- public static final int PHY_LE_CODED = 3;
-
- /**
* Advertise on low frequency, around every 1000ms. This is the default and
* preferred advertising mode as it consumes the least power.
*/
@@ -246,8 +232,8 @@ public final class AdvertisingSetParameters implements Parcelable {
private boolean isLegacy = false;
private boolean isAnonymous = false;
private boolean includeTxPower = false;
- private int primaryPhy = PHY_LE_1M;
- private int secondaryPhy = PHY_LE_1M;
+ private int primaryPhy = BluetoothDevice.PHY_LE_1M;
+ private int secondaryPhy = BluetoothDevice.PHY_LE_1M;
private int interval = INTERVAL_LOW;
private int txPowerLevel = TX_POWER_MEDIUM;
@@ -321,12 +307,13 @@ public final class AdvertisingSetParameters implements Parcelable {
* Use {@link BluetoothAdapter#isLeCodedPhySupported} to determine if LE Coded PHY is
* supported on this device.
* @param primaryPhy Primary advertising physical channel, can only be
- * {@link AdvertisingSetParameters#PHY_LE_1M} or
- * {@link AdvertisingSetParameters#PHY_LE_CODED}.
+ * {@link BluetoothDevice#PHY_LE_1M} or
+ * {@link BluetoothDevice#PHY_LE_CODED}.
* @throws IllegalArgumentException If the primaryPhy is invalid.
*/
public Builder setPrimaryPhy(int primaryPhy) {
- if (primaryPhy != PHY_LE_1M && primaryPhy != PHY_LE_CODED) {
+ if (primaryPhy != BluetoothDevice.PHY_LE_1M &&
+ primaryPhy != BluetoothDevice.PHY_LE_CODED) {
throw new IllegalArgumentException("bad primaryPhy " + primaryPhy);
}
this.primaryPhy = primaryPhy;
@@ -343,14 +330,15 @@ public final class AdvertisingSetParameters implements Parcelable {
* supported on this device.
*
* @param secondaryPhy Secondary advertising physical channel, can only be
- * one of {@link AdvertisingSetParameters#PHY_LE_1M},
- * {@link AdvertisingSetParameters#PHY_LE_2M} or
- * {@link AdvertisingSetParameters#PHY_LE_CODED}.
+ * one of {@link BluetoothDevice#PHY_LE_1M},
+ * {@link BluetoothDevice#PHY_LE_2M} or
+ * {@link BluetoothDevice#PHY_LE_CODED}.
* @throws IllegalArgumentException If the secondaryPhy is invalid.
*/
public Builder setSecondaryPhy(int secondaryPhy) {
- if (secondaryPhy != PHY_LE_1M && secondaryPhy !=PHY_LE_2M &&
- secondaryPhy != PHY_LE_CODED) {
+ if (secondaryPhy != BluetoothDevice.PHY_LE_1M &&
+ secondaryPhy != BluetoothDevice.PHY_LE_2M &&
+ secondaryPhy != BluetoothDevice.PHY_LE_CODED) {
throw new IllegalArgumentException("bad secondaryPhy " + secondaryPhy);
}
this.secondaryPhy = secondaryPhy;
diff --git a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
index 73fc1339afa6..ea3031b20177 100644
--- a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
+++ b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
@@ -17,6 +17,7 @@
package android.bluetooth.le;
import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothUuid;
import android.bluetooth.IBluetoothGatt;
@@ -363,12 +364,12 @@ public final class BluetoothLeAdvertiser {
boolean support2MPhy = mBluetoothAdapter.isLe2MPhySupported();
int pphy = parameters.getPrimaryPhy();
int sphy = parameters.getSecondaryPhy();
- if (pphy == AdvertisingSetParameters.PHY_LE_CODED && !supportCodedPhy) {
+ if (pphy == BluetoothDevice.PHY_LE_CODED && !supportCodedPhy) {
throw new IllegalArgumentException("Unsupported primary PHY selected");
}
- if ((sphy == AdvertisingSetParameters.PHY_LE_CODED && !supportCodedPhy)
- || (sphy == AdvertisingSetParameters.PHY_LE_2M && !support2MPhy)) {
+ if ((sphy == BluetoothDevice.PHY_LE_CODED && !supportCodedPhy)
+ || (sphy == BluetoothDevice.PHY_LE_2M && !support2MPhy)) {
throw new IllegalArgumentException("Unsupported secondary PHY selected");
}
diff --git a/core/java/android/bluetooth/le/ScanResult.java b/core/java/android/bluetooth/le/ScanResult.java
index 745cd16c78f9..5b2fa406cd3f 100644
--- a/core/java/android/bluetooth/le/ScanResult.java
+++ b/core/java/android/bluetooth/le/ScanResult.java
@@ -47,21 +47,6 @@ public final class ScanResult implements Parcelable {
public static final int PHY_UNUSED = 0x00;
/**
- * Bluetooth LE 1Mbit advertiser PHY.
- */
- public static final int PHY_LE_1M = 0x01;
-
- /**
- * Bluetooth LE 2Mbit advertiser PHY.
- */
- public static final int PHY_LE_2M = 0x02;
-
- /**
- * Bluetooth LE Coded advertiser PHY.
- */
- public static final int PHY_LE_CODED = 0x03;
-
- /**
* Advertising Set ID is not present in the packet.
*/
public static final int SID_NOT_PRESENT = 0xFF;
@@ -112,7 +97,7 @@ public final class ScanResult implements Parcelable {
mRssi = rssi;
mTimestampNanos = timestampNanos;
mEventType = (DATA_COMPLETE << 5) | ET_LEGACY_MASK | ET_CONNECTABLE_MASK;
- mPrimaryPhy = PHY_LE_1M;
+ mPrimaryPhy = BluetoothDevice.PHY_LE_1M;
mSecondaryPhy = PHY_UNUSED;
mAdvertisingSid = SID_NOT_PRESENT;
mTxPower = 127;
@@ -256,16 +241,16 @@ public final class ScanResult implements Parcelable {
/**
* Returns the primary Physical Layer
* on which this advertisment was received.
- * Can be one of {@link ScanResult#PHY_LE_1M} or
- * {@link ScanResult#PHY_LE_CODED}.
+ * Can be one of {@link BluetoothDevice#PHY_LE_1M} or
+ * {@link BluetoothDevice#PHY_LE_CODED}.
*/
public int getPrimaryPhy() { return mPrimaryPhy; }
/**
* Returns the secondary Physical Layer
* on which this advertisment was received.
- * Can be one of {@link ScanResult#PHY_LE_1M},
- * {@link ScanResult#PHY_LE_2M}, {@link ScanResult#PHY_LE_CODED}
+ * Can be one of {@link BluetoothDevice#PHY_LE_1M},
+ * {@link BluetoothDevice#PHY_LE_2M}, {@link BluetoothDevice#PHY_LE_CODED}
* or {@link ScanResult#PHY_UNUSED} - if the advertisement
* was not received on a secondary physical channel.
*/
diff --git a/core/java/android/bluetooth/le/ScanSettings.java b/core/java/android/bluetooth/le/ScanSettings.java
index 69c9a8cece3a..36e48e9bd0b8 100644
--- a/core/java/android/bluetooth/le/ScanSettings.java
+++ b/core/java/android/bluetooth/le/ScanSettings.java
@@ -17,6 +17,7 @@
package android.bluetooth.le;
import android.annotation.SystemApi;
+import android.bluetooth.BluetoothDevice;
import android.os.Parcel;
import android.os.Parcelable;
@@ -123,16 +124,6 @@ public final class ScanSettings implements Parcelable {
public static final int SCAN_RESULT_TYPE_ABBREVIATED = 1;
/**
- * Use the Bluetooth LE 1Mbit PHY for scanning.
- */
- public static final int PHY_LE_1M = 1;
-
- /**
- * Use Bluetooth LE Coded PHY for scanning.
- */
- public static final int PHY_LE_CODED = 3;
-
- /**
* Use all supported PHYs for scanning.
* This will check the controller capabilities, and start
* the scan on 1Mbit and LE Coded PHYs if supported, or on
@@ -412,8 +403,8 @@ public final class ScanSettings implements Parcelable {
* Selecting an unsupported phy will result in failure to start scan.
*
* @param phy Can be one of
- * {@link ScanSettings#PHY_LE_1M},
- * {@link ScanSettings#PHY_LE_CODED} or
+ * {@link BluetoothDevice#PHY_LE_1M},
+ * {@link BluetoothDevice#PHY_LE_CODED} or
* {@link ScanSettings#PHY_LE_ALL_SUPPORTED}
*/
public Builder setPhy(int phy) {
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 63757755aedd..18120c714793 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2897,6 +2897,7 @@ public abstract class Context {
BATTERY_SERVICE,
JOB_SCHEDULER_SERVICE,
//@hide: PERSISTENT_DATA_BLOCK_SERVICE,
+ //@hide: OEM_LOCK_SERVICE,
MEDIA_PROJECTION_SERVICE,
MIDI_SERVICE,
RADIO_SERVICE,
@@ -3819,6 +3820,17 @@ public abstract class Context {
/**
* Use with {@link #getSystemService} to retrieve a {@link
+ * android.service.oemlock.OemLockManager} instance for managing the OEM lock.
+ *
+ * @see #getSystemService
+ * @see android.service.oemlock.OemLockManager
+ * @hide
+ */
+ @SystemApi
+ public static final String OEM_LOCK_SERVICE = "oem_lock";
+
+ /**
+ * Use with {@link #getSystemService} to retrieve a {@link
* android.media.projection.MediaProjectionManager} instance for managing
* media projection sessions.
* @see #getSystemService
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 52a87609001d..2485bb8aacea 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -657,6 +657,16 @@ public class Intent implements Parcelable, Cloneable {
public static final String ACTION_VIEW = "android.intent.action.VIEW";
/**
+ * Extra that can be included on activity intents coming from the storage UI
+ * when it launches sub-activities to manage various types of storage. For example,
+ * it may use {@link #ACTION_VIEW} with a "image/*" MIME type to have an app show
+ * the images on the device, and in that case also include this extra to tell the
+ * app it is coming from the storage UI so should help the user manage storage of
+ * this type.
+ */
+ public static final String EXTRA_FROM_STORAGE = "android.intent.extra.FROM_STORAGE";
+
+ /**
* A synonym for {@link #ACTION_VIEW}, the "standard" action that is
* performed on a piece of data.
*/
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index c8353c9bffb9..88c1627f955b 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -127,7 +127,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
*/
public static final int COLOR_MODE_WIDE_COLOR_GAMUT_YES = 0x2;
- /** Constant for {@link #colorMode}: bits that encode whether the dynamic range of the screen. */
+ /** Constant for {@link #colorMode}: bits that encode the dynamic range of the screen. */
public static final int COLOR_MODE_HDR_MASK = 0xc;
/** Constant for {@link #colorMode}: bits shift to get the screen dynamic range. */
public static final int COLOR_MODE_HDR_SHIFT = 2;
@@ -155,7 +155,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
COLOR_MODE_HDR_UNDEFINED;
/**
- * Bit mask of for color capabilities of the screen. Currently there are two fields:
+ * Bit mask of color capabilities of the screen. Currently there are two fields:
* <p>The {@link #COLOR_MODE_WIDE_COLOR_GAMUT_MASK} bits define the color gamut of
* the screen. They may be one of
* {@link #COLOR_MODE_WIDE_COLOR_GAMUT_NO} or {@link #COLOR_MODE_WIDE_COLOR_GAMUT_YES}.</p>
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index a529c2ffba3d..32671721f58b 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -247,6 +247,7 @@ public final class DisplayManager {
* </p>
*
* @see #createVirtualDisplay
+ * @hide
*/
public static final int VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 1 << 5;
diff --git a/core/java/android/net/ConnectivityMetricsEvent.java b/core/java/android/net/ConnectivityMetricsEvent.java
index 63ccaaea14cf..46bb34670611 100644
--- a/core/java/android/net/ConnectivityMetricsEvent.java
+++ b/core/java/android/net/ConnectivityMetricsEvent.java
@@ -18,6 +18,7 @@ package android.net;
import android.os.Parcel;
import android.os.Parcelable;
+import com.android.internal.util.BitUtils;
/**
* Represents a core networking event defined in package android.net.metrics.
@@ -78,13 +79,15 @@ public final class ConnectivityMetricsEvent implements Parcelable {
public String toString() {
StringBuilder buffer = new StringBuilder("ConnectivityMetricsEvent(");
buffer.append(String.format("%tT.%tL", timestamp, timestamp));
- // TODO: add transports
if (netId != 0) {
buffer.append(", ").append(netId);
}
if (ifname != null) {
buffer.append(", ").append(ifname);
}
+ for (int t : BitUtils.unpackBits(transports)) {
+ buffer.append(", ").append(NetworkCapabilities.transportNameOf(t));
+ }
buffer.append("): ").append(data.toString());
return buffer.toString();
}
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index 8665b9c5cf52..a594befbd506 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -19,7 +19,7 @@ package android.net;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
-import java.lang.IllegalArgumentException;
+import com.android.internal.util.BitUtils;
/**
* This class represents the capabilities of a network. This is used both to specify
@@ -289,7 +289,7 @@ public final class NetworkCapabilities implements Parcelable {
* @hide
*/
public int[] getCapabilities() {
- return enumerateBits(mNetworkCapabilities);
+ return BitUtils.unpackBits(mNetworkCapabilities);
}
/**
@@ -305,19 +305,6 @@ public final class NetworkCapabilities implements Parcelable {
return ((mNetworkCapabilities & (1 << capability)) != 0);
}
- private int[] enumerateBits(long val) {
- int size = Long.bitCount(val);
- int[] result = new int[size];
- int index = 0;
- int resource = 0;
- while (val > 0) {
- if ((val & 1) == 1) result[index++] = resource;
- val = val >> 1;
- resource++;
- }
- return result;
- }
-
private void combineNetCapabilities(NetworkCapabilities nc) {
this.mNetworkCapabilities |= nc.mNetworkCapabilities;
}
@@ -428,6 +415,15 @@ public final class NetworkCapabilities implements Parcelable {
/** @hide */
public static final int MAX_TRANSPORT = TRANSPORT_WIFI_AWARE;
+ private static final String[] TRANSPORT_NAMES = {
+ "CELLULAR",
+ "WIFI",
+ "BLUETOOTH",
+ "ETHERNET",
+ "VPN",
+ "WIFI_AWARE"
+ };
+
/**
* Adds the given transport type to this {@code NetworkCapability} instance.
* Multiple transports may be applied sequentially. Note that when searching
@@ -474,18 +470,7 @@ public final class NetworkCapabilities implements Parcelable {
* @hide
*/
public int[] getTransportTypes() {
- return enumerateBits(mTransportTypes);
- }
-
- /**
- * Gets all the transports set on this {@code NetworkCapability} instance.
- *
- * @return a bit field composed of up bits at indexes defined by
- * {@code NetworkCapabilities.TRANSPORT_*} values for this instance.
- * @hide
- */
- public long getTransports() {
- return mTransportTypes;
+ return BitUtils.unpackBits(mTransportTypes);
}
/**
@@ -899,18 +884,23 @@ public final class NetworkCapabilities implements Parcelable {
* @hide
*/
public static String transportNamesOf(int[] types) {
- String transports = "";
- for (int i = 0; i < types.length;) {
- switch (types[i]) {
- case TRANSPORT_CELLULAR: transports += "CELLULAR"; break;
- case TRANSPORT_WIFI: transports += "WIFI"; break;
- case TRANSPORT_BLUETOOTH: transports += "BLUETOOTH"; break;
- case TRANSPORT_ETHERNET: transports += "ETHERNET"; break;
- case TRANSPORT_VPN: transports += "VPN"; break;
- case TRANSPORT_WIFI_AWARE: transports += "WIFI_AWARE"; break;
- }
- if (++i < types.length) transports += "|";
+ if (types == null || types.length == 0) {
+ return "";
+ }
+ StringBuilder transports = new StringBuilder();
+ for (int t : types) {
+ transports.append("|").append(transportNameOf(t));
+ }
+ return transports.substring(1);
+ }
+
+ /**
+ * @hide
+ */
+ public static String transportNameOf(int transport) {
+ if (transport < 0 || TRANSPORT_NAMES.length <= transport) {
+ return "UNKNOWN";
}
- return transports;
+ return TRANSPORT_NAMES[transport];
}
}
diff --git a/core/java/android/net/metrics/ConnectStats.java b/core/java/android/net/metrics/ConnectStats.java
index 214edeeb5382..30b2656227d0 100644
--- a/core/java/android/net/metrics/ConnectStats.java
+++ b/core/java/android/net/metrics/ConnectStats.java
@@ -16,53 +16,47 @@
package android.net.metrics;
+import android.net.NetworkCapabilities;
import android.system.OsConstants;
import android.util.IntArray;
import android.util.SparseIntArray;
+import com.android.internal.util.BitUtils;
import com.android.internal.util.TokenBucket;
-import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.ConnectStatistics;
-import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.Pair;
/**
- * A class that aggregates connect() statistics and helps build
- * IpConnectivityLogClass.ConnectStatistics instances.
- *
+ * A class that aggregates connect() statistics.
* {@hide}
*/
public class ConnectStats {
private final static int EALREADY = OsConstants.EALREADY;
private final static int EINPROGRESS = OsConstants.EINPROGRESS;
+ /** Network id of the network associated with the event, or 0 if unspecified. */
+ public final int netId;
+ /** Transports of the network associated with the event, as defined in NetworkCapabilities. */
+ public final long transports;
/** How many events resulted in a given errno. */
- private final SparseIntArray mErrnos = new SparseIntArray();
- /** Latencies of blocking connects. TODO: add non-blocking connects latencies. */
- private final IntArray mLatencies = new IntArray();
+ public final SparseIntArray errnos = new SparseIntArray();
+ /** Latencies of successful blocking connects. TODO: add non-blocking connects latencies. */
+ public final IntArray latencies = new IntArray();
/** TokenBucket for rate limiting latency recording. */
- private final TokenBucket mLatencyTb;
+ public final TokenBucket mLatencyTb;
/** Maximum number of latency values recorded. */
- private final int mMaxLatencyRecords;
+ public final int mMaxLatencyRecords;
/** Total count of successful connects. */
- private int mConnectCount = 0;
+ public int connectCount = 0;
/** Total count of successful connects done in blocking mode. */
- private int mConnectBlockingCount = 0;
+ public int connectBlockingCount = 0;
/** Total count of successful connects with IPv6 socket address. */
- private int mIpv6ConnectCount = 0;
+ public int ipv6ConnectCount = 0;
- public ConnectStats(TokenBucket tb, int maxLatencyRecords) {
+ public ConnectStats(int netId, long transports, TokenBucket tb, int maxLatencyRecords) {
+ this.netId = netId;
+ this.transports = transports;
mLatencyTb = tb;
mMaxLatencyRecords = maxLatencyRecords;
}
- public ConnectStatistics toProto() {
- ConnectStatistics stats = new ConnectStatistics();
- stats.connectCount = mConnectCount;
- stats.connectBlockingCount = mConnectBlockingCount;
- stats.ipv6AddrCount = mIpv6ConnectCount;
- stats.latenciesMs = mLatencies.toArray();
- stats.errnosCounters = toPairArrays(mErrnos);
- return stats;
- }
-
public void addEvent(int errno, int latencyMs, String ipAddr) {
if (isSuccess(errno)) {
countConnect(errno, ipAddr);
@@ -73,12 +67,12 @@ public class ConnectStats {
}
private void countConnect(int errno, String ipAddr) {
- mConnectCount++;
+ connectCount++;
if (!isNonBlocking(errno)) {
- mConnectBlockingCount++;
+ connectBlockingCount++;
}
if (isIPv6(ipAddr)) {
- mIpv6ConnectCount++;
+ ipv6ConnectCount++;
}
}
@@ -91,16 +85,16 @@ public class ConnectStats {
// Rate limited
return;
}
- if (mLatencies.size() >= mMaxLatencyRecords) {
+ if (latencies.size() >= mMaxLatencyRecords) {
// Hard limit the total number of latency measurements.
return;
}
- mLatencies.add(ms);
+ latencies.add(ms);
}
private void countError(int errno) {
- final int newcount = mErrnos.get(errno, 0) + 1;
- mErrnos.put(errno, newcount);
+ final int newcount = errnos.get(errno, 0) + 1;
+ errnos.put(errno, newcount);
}
private static boolean isSuccess(int errno) {
@@ -117,27 +111,18 @@ public class ConnectStats {
return ipAddr.contains(":");
}
- private static Pair[] toPairArrays(SparseIntArray counts) {
- final int s = counts.size();
- Pair[] pairs = new Pair[s];
- for (int i = 0; i < s; i++) {
- Pair p = new Pair();
- p.key = counts.keyAt(i);
- p.value = counts.valueAt(i);
- pairs[i] = p;
- }
- return pairs;
- }
-
@Override
public String toString() {
- StringBuilder builder = new StringBuilder("ConnectStats(")
- .append(String.format("%d success, ", mConnectCount))
- .append(String.format("%d blocking, ", mConnectBlockingCount))
- .append(String.format("%d IPv6 dst", mIpv6ConnectCount));
- for (int i = 0; i < mErrnos.size(); i++) {
- String errno = OsConstants.errnoName(mErrnos.keyAt(i));
- int count = mErrnos.valueAt(i);
+ StringBuilder builder = new StringBuilder("ConnectStats(").append(netId).append(", ");
+ for (int t : BitUtils.unpackBits(transports)) {
+ builder.append(NetworkCapabilities.transportNameOf(t)).append(", ");
+ }
+ builder.append(String.format("%d success, ", connectCount));
+ builder.append(String.format("%d blocking, ", connectBlockingCount));
+ builder.append(String.format("%d IPv6 dst", ipv6ConnectCount));
+ for (int i = 0; i < errnos.size(); i++) {
+ String errno = OsConstants.errnoName(errnos.keyAt(i));
+ int count = errnos.valueAt(i);
builder.append(String.format(", %s: %d", errno, count));
}
return builder.append(")").toString();
diff --git a/core/java/android/net/metrics/DnsEvent.java b/core/java/android/net/metrics/DnsEvent.java
index 89ae1c258ee6..a4970e4d0d28 100644
--- a/core/java/android/net/metrics/DnsEvent.java
+++ b/core/java/android/net/metrics/DnsEvent.java
@@ -16,67 +16,70 @@
package android.net.metrics;
-import android.os.Parcel;
-import android.os.Parcelable;
+import android.net.NetworkCapabilities;
+import java.util.Arrays;
+import com.android.internal.util.BitUtils;
/**
* A DNS event recorded by NetdEventListenerService.
* {@hide}
*/
-final public class DnsEvent implements Parcelable {
- public final int netId;
+final public class DnsEvent {
+
+ private static final int SIZE_LIMIT = 20000;
- // The event type is currently only 1 or 2, so we store it as a byte.
- public final byte[] eventTypes;
+ // Network id of the network associated with the event, or 0 if unspecified.
+ public final int netId;
+ // Transports of the network associated with the event, as defined in NetworkCapabilities.
+ // It is the caller responsability to ensure the value of transports does not change between
+ // calls to addResult.
+ public final long transports;
+ // The number of DNS queries recorded. Queries are stored in the structure-of-array style where
+ // the eventTypes, returnCodes, and latenciesMs arrays have the same length and the i-th event
+ // is spread across the three array at position i.
+ public int eventCount;
+ // The types of DNS queries as defined in INetdEventListener.
+ public byte[] eventTypes;
// Current getaddrinfo codes go from 1 to EAI_MAX = 15. gethostbyname returns errno, but there
// are fewer than 255 errno values. So we store the result code in a byte as well.
- public final byte[] returnCodes;
- // The latency is an integer because a) short arrays aren't parcelable and b) a short can only
- // store a maximum latency of 32757 or 65535 ms, which is too short for pathologically slow
- // queries.
- public final int[] latenciesMs;
+ public byte[] returnCodes;
+ // Latencies in milliseconds of queries, stored as ints.
+ public int[] latenciesMs;
- public DnsEvent(int netId, byte[] eventTypes, byte[] returnCodes, int[] latenciesMs) {
+ public DnsEvent(int netId, long transports, int initialCapacity) {
this.netId = netId;
- this.eventTypes = eventTypes;
- this.returnCodes = returnCodes;
- this.latenciesMs = latenciesMs;
+ this.transports = transports;
+ eventTypes = new byte[initialCapacity];
+ returnCodes = new byte[initialCapacity];
+ latenciesMs = new int[initialCapacity];
}
- private DnsEvent(Parcel in) {
- this.netId = in.readInt();
- this.eventTypes = in.createByteArray();
- this.returnCodes = in.createByteArray();
- this.latenciesMs = in.createIntArray();
- }
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeInt(netId);
- out.writeByteArray(eventTypes);
- out.writeByteArray(returnCodes);
- out.writeIntArray(latenciesMs);
+ public void addResult(byte eventType, byte returnCode, int latencyMs) {
+ if (eventCount >= SIZE_LIMIT) {
+ // TODO: implement better rate limiting that does not biases metrics.
+ return;
+ }
+ if (eventCount == eventTypes.length) {
+ resize((int) (1.4 * eventCount));
+ }
+ eventTypes[eventCount] = eventType;
+ returnCodes[eventCount] = returnCode;
+ latenciesMs[eventCount] = latencyMs;
+ eventCount++;
}
- @Override
- public int describeContents() {
- return 0;
+ public void resize(int newLength) {
+ eventTypes = Arrays.copyOf(eventTypes, newLength);
+ returnCodes = Arrays.copyOf(returnCodes, newLength);
+ latenciesMs = Arrays.copyOf(latenciesMs, newLength);
}
@Override
public String toString() {
- return String.format("DnsEvent(%d, %d events)", netId, eventTypes.length);
- }
-
- public static final Parcelable.Creator<DnsEvent> CREATOR = new Parcelable.Creator<DnsEvent>() {
- @Override
- public DnsEvent createFromParcel(Parcel in) {
- return new DnsEvent(in);
+ StringBuilder builder = new StringBuilder("DnsEvent(").append(netId).append(", ");
+ for (int t : BitUtils.unpackBits(transports)) {
+ builder.append(NetworkCapabilities.transportNameOf(t)).append(", ");
}
-
- @Override
- public DnsEvent[] newArray(int size) {
- return new DnsEvent[size];
- }
- };
+ return builder.append(eventCount).append(" events)").toString();
+ }
}
diff --git a/core/java/android/net/metrics/IpConnectivityLog.java b/core/java/android/net/metrics/IpConnectivityLog.java
index ac727ca2e4db..4e57efa4d47b 100644
--- a/core/java/android/net/metrics/IpConnectivityLog.java
+++ b/core/java/android/net/metrics/IpConnectivityLog.java
@@ -23,6 +23,7 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.BitUtils;
/**
* Class for logging IpConnectvity events with IpConnectivityMetrics
@@ -117,10 +118,10 @@ public class IpConnectivityLog {
* @param data is a Parcelable instance representing the event.
* @return true if the event was successfully logged.
*/
- public boolean log(int netid, long transports, Parcelable data) {
+ public boolean log(int netid, int[] transports, Parcelable data) {
ConnectivityMetricsEvent ev = makeEv(data);
ev.netId = netid;
- ev.transports = transports;
+ ev.transports = BitUtils.packBits(transports);
return log(ev);
}
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index a6bf2d26abb3..6f4c9cf7d7ff 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -682,8 +682,10 @@ public class UserManager {
* @see DevicePolicyManager#addUserRestriction(ComponentName, String)
* @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
* @see #getUserRestrictions()
+ * @deprecated use {@link OemLockManager#setOemUnlockAllowedByCarrier(boolean, byte[])} instead.
* @hide
*/
+ @Deprecated
@SystemApi
public static final String DISALLOW_OEM_UNLOCK = "no_oem_unlock";
diff --git a/core/java/android/os/VintfObject.java b/core/java/android/os/VintfObject.java
new file mode 100644
index 000000000000..1ef3916a743f
--- /dev/null
+++ b/core/java/android/os/VintfObject.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2017 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.os;
+
+import java.util.ArrayList;
+
+import android.util.Log;
+
+/** @hide */
+public class VintfObject {
+
+ private static final String LOG_TAG = "VintfObject";
+
+ /**
+ * Slurps all device information (both manifests)
+ * and report it.
+ * If any error in getting one of the manifests, it is not included in
+ * the list.
+ */
+ public static String[] report() {
+ ArrayList<String> ret = new ArrayList<>();
+ put(ret, getDeviceManifest(), "device manifest");
+ put(ret, getFrameworkManifest(), "framework manifest");
+ return ret.toArray(new String[0]);
+ }
+
+ /**
+ * Verify that the given metadata for an OTA package is compatible with
+ * this device.
+ *
+ * @param packageInfo a list of serialized form of HalMaanifest's /
+ * CompatibilityMatri'ces (XML).
+ * @return = 0 if success (compatible)
+ * > 0 if incompatible
+ * < 0 if any error (mount partition fails, illformed XML, etc.)
+ */
+ public static native int verify(String[] packageInfo);
+
+ // return null if any error, otherwise XML string.
+ private static native String getDeviceManifest();
+ private static native String getFrameworkManifest();
+
+ private static void put(ArrayList<String> list, String content, String message) {
+ if (content == null || content.length() == 0) {
+ Log.e(LOG_TAG, "Cannot get;" + message + "; check native logs for details.");
+ return;
+ }
+ list.add(content);
+ }
+}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 05bacae4bba3..539559d19c82 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -8844,6 +8844,15 @@ public final class Settings {
public static final String CAPTIVE_PORTAL_FALLBACK_URL = "captive_portal_fallback_url";
/**
+ * A comma separated list of URLs used for captive portal detection in addition to the
+ * fallback HTTP url associated with the CAPTIVE_PORTAL_FALLBACK_URL settings.
+ *
+ * @hide
+ */
+ public static final String CAPTIVE_PORTAL_OTHER_FALLBACK_URLS =
+ "captive_portal_other_fallback_urls";
+
+ /**
* Whether to use HTTPS for network validation. This is enabled by default and the setting
* needs to be set to 0 to disable it. This setting is a misnomer because captive portals
* don't actually use HTTPS, but it's consistent with the other settings.
diff --git a/core/java/android/service/oemlock/IOemLockService.aidl b/core/java/android/service/oemlock/IOemLockService.aidl
new file mode 100644
index 000000000000..2c606f97ab9f
--- /dev/null
+++ b/core/java/android/service/oemlock/IOemLockService.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.oemlock;
+
+/**
+ * Interface for communication with the OemLockService.
+ *
+ * @hide
+ */
+interface IOemLockService {
+ void setOemUnlockAllowedByCarrier(boolean allowed, in byte[] signature);
+ boolean isOemUnlockAllowedByCarrier();
+
+ void setOemUnlockAllowedByUser(boolean allowed);
+ boolean isOemUnlockAllowedByUser();
+}
diff --git a/core/java/android/service/oemlock/OemLockManager.java b/core/java/android/service/oemlock/OemLockManager.java
new file mode 100644
index 000000000000..c4fbe5ec7e1a
--- /dev/null
+++ b/core/java/android/service/oemlock/OemLockManager.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.oemlock;
+
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.os.RemoteException;
+
+/**
+ * Interface for managing the OEM lock on the device.
+ *
+ * This will only be available if the device implements OEM lock protection.
+ *
+ * Multiple actors have an opinion on whether the device can be OEM unlocked and they must all be in
+ * agreement for unlock to be possible.
+ *
+ * @hide
+ */
+@SystemApi
+public class OemLockManager {
+ private IOemLockService mService;
+
+ /** @hide */
+ public OemLockManager(IOemLockService service) {
+ mService = service;
+ }
+
+ /**
+ * Sets whether the carrier has allowed this device to be OEM unlocked.
+ *
+ * Depending on the implementation, the validity of the request might need to be proved. This
+ * can be acheived by passing a signature that the system will use to verify the request is
+ * legitimate.
+ *
+ * All actors involved must agree for OEM unlock to be possible.
+ *
+ * @param allowed Whether the device should be allowed to be unlocked.
+ * @param signature Optional proof of request validity, {@code null} for none.
+ * @throws IllegalArgumentException if a signature is required but was not provided.
+ * @throws SecurityException if the wrong signature was provided.
+ *
+ * @see #isOemUnlockAllowedByCarrier()
+ */
+ public void setOemUnlockAllowedByCarrier(boolean allowed, @Nullable byte[] signature) {
+ try {
+ mService.setOemUnlockAllowedByCarrier(allowed, signature);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Returns whether the carrier has allowed this device to be OEM unlocked.
+ * @return Whether OEM unlock is allowed by the carrier, or true if no OEM lock is present.
+ *
+ * @see #setOemUnlockAllowedByCarrier(boolean, byte[])
+ */
+ public boolean isOemUnlockAllowedByCarrier() {
+ try {
+ return mService.isOemUnlockAllowedByCarrier();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Sets whether the user has allowed this device to be unlocked.
+ *
+ * All actors involved must agree for OEM unlock to be possible.
+ *
+ * @param unlocked Whether the device should be made OEM unlocked.
+ *
+ * @see #isOemUnlockAllowedByUser()
+ */
+ public void setOemUnlockAllowedByUser(boolean allowed) {
+ try {
+ mService.setOemUnlockAllowedByUser(allowed);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Returns whether, or not, the user has allowed this device to be OEM unlocked.
+ * @return Whether OEM unlock is allowed by the user, or true if no OEM lock is present.
+ *
+ * @see #setOemUnlockAllowedByUser(boolean)
+ */
+ public boolean isOemUnlockAllowedByUser() {
+ try {
+ return mService.isOemUnlockAllowedByUser();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+}
diff --git a/core/java/android/service/persistentdata/PersistentDataBlockManager.java b/core/java/android/service/persistentdata/PersistentDataBlockManager.java
index cb021bc03087..326796afb3ad 100644
--- a/core/java/android/service/persistentdata/PersistentDataBlockManager.java
+++ b/core/java/android/service/persistentdata/PersistentDataBlockManager.java
@@ -146,6 +146,8 @@ public class PersistentDataBlockManager {
/**
* Writes a byte enabling or disabling the ability to "OEM unlock" the device.
+ *
+ * @deprecated use {@link OemLockManager#setOemUnlockAllowedByUser(boolean)} instead.
*/
public void setOemUnlockEnabled(boolean enabled) {
try {
@@ -157,6 +159,8 @@ public class PersistentDataBlockManager {
/**
* Returns whether or not "OEM unlock" is enabled or disabled on this device.
+ *
+ * @deprecated use {@link OemLockManager#isOemUnlockAllowedByUser()} instead.
*/
public boolean getOemUnlockEnabled() {
try {
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 6dedbde01995..3e9fab1aee27 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -205,6 +205,7 @@ public final class Display {
* </p>
*
* @see #getFlags
+ * @hide
*/
public static final int FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 1 << 5;
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 9072bf93d9d8..8b3e3fe17cc0 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -6970,7 +6970,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
dispatchPopulateAccessibilityEvent(event);
}
// In the beginning we called #isShown(), so we know that getParent() is not null.
- getParent().requestSendAccessibilityEvent(this, event);
+ ViewParent parent = getParent();
+ if (parent != null) {
+ getParent().requestSendAccessibilityEvent(this, event);
+ }
}
/**
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index e85a658a6316..41c209cc016a 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -1068,5 +1068,19 @@ public final class AutofillManager {
});
}
}
+
+ @Override
+ public void startIntentSender(IntentSender intentSender) {
+ final AutofillManager afm = mAfm.get();
+ if (afm != null) {
+ afm.mContext.getMainThreadHandler().post(() -> {
+ try {
+ afm.mContext.startIntentSender(intentSender, null, 0, 0, 0);
+ } catch (IntentSender.SendIntentException e) {
+ Log.e(TAG, "startIntentSender() failed for intent:" + intentSender, e);
+ }
+ });
+ }
+ }
}
}
diff --git a/core/java/android/view/autofill/IAutoFillManagerClient.aidl b/core/java/android/view/autofill/IAutoFillManagerClient.aidl
index 7bea17466ac5..176eaacb57ae 100644
--- a/core/java/android/view/autofill/IAutoFillManagerClient.aidl
+++ b/core/java/android/view/autofill/IAutoFillManagerClient.aidl
@@ -59,7 +59,12 @@ oneway interface IAutoFillManagerClient {
void requestHideFillUi(in IBinder windowToken, in AutofillId id);
/**
- * Nitifies no fill UI will be shown.
+ * Notifies no fill UI will be shown.
*/
void notifyNoFillUi(in IBinder windowToken, in AutofillId id);
+
+ /**
+ * Starts the provided intent sender
+ */
+ void startIntentSender(in IntentSender intentSender);
}
diff --git a/core/java/com/android/internal/app/AccessibilityButtonChooserActivity.java b/core/java/com/android/internal/app/AccessibilityButtonChooserActivity.java
index ee5d339a19d3..afac7626ba74 100644
--- a/core/java/com/android/internal/app/AccessibilityButtonChooserActivity.java
+++ b/core/java/com/android/internal/app/AccessibilityButtonChooserActivity.java
@@ -65,7 +65,7 @@ public class AccessibilityButtonChooserActivity extends Activity {
mMagnificationTarget = new AccessibilityButtonTarget(this, MAGNIFICATION_COMPONENT_ID,
R.string.accessibility_magnification_chooser_text,
- R.drawable.resolver_icon_placeholder);
+ R.drawable.ic_accessibility_magnification);
mTargets = getServiceAccessibilityButtonTargets(this);
if (Settings.Secure.getInt(getContentResolver(),
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 44fa99df7b73..142effbbf0c7 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -186,8 +186,8 @@ public class ZygoteInit {
private static void preloadOpenGL() {
String driverPackageName = SystemProperties.get(PROPERTY_GFX_DRIVER);
- if (!SystemProperties.getBoolean(PROPERTY_DISABLE_OPENGL_PRELOADING, false) ||
- driverPackageName == null || driverPackageName.isEmpty()) {
+ if (!SystemProperties.getBoolean(PROPERTY_DISABLE_OPENGL_PRELOADING, false) &&
+ (driverPackageName == null || driverPackageName.isEmpty())) {
EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
}
}
diff --git a/core/java/com/android/internal/util/BitUtils.java b/core/java/com/android/internal/util/BitUtils.java
index a208ccb8f35f..e349f3d4b473 100644
--- a/core/java/com/android/internal/util/BitUtils.java
+++ b/core/java/com/android/internal/util/BitUtils.java
@@ -55,4 +55,25 @@ public class BitUtils {
&& maskedEquals(a.getMostSignificantBits(), b.getMostSignificantBits(),
mask.getMostSignificantBits());
}
+
+ public static int[] unpackBits(long val) {
+ int size = Long.bitCount(val);
+ int[] result = new int[size];
+ int index = 0;
+ int bitPos = 0;
+ while (val > 0) {
+ if ((val & 1) == 1) result[index++] = bitPos;
+ val = val >> 1;
+ bitPos++;
+ }
+ return result;
+ }
+
+ public static long packBits(int[] bits) {
+ long packed = 0;
+ for (int b : bits) {
+ packed |= (1 << b);
+ }
+ return packed;
+ }
}
diff --git a/core/java/com/android/internal/util/DumpUtils.java b/core/java/com/android/internal/util/DumpUtils.java
index 4659d3c48a22..ce89501c970a 100644
--- a/core/java/com/android/internal/util/DumpUtils.java
+++ b/core/java/com/android/internal/util/DumpUtils.java
@@ -121,12 +121,15 @@ public final class DumpUtils {
final String[] pkgs = context.getPackageManager().getPackagesForUid(uid);
if (pkgs != null) {
for (String pkg : pkgs) {
- if (appOps.checkOpNoThrow(AppOpsManager.OP_GET_USAGE_STATS, uid,
- pkg) == AppOpsManager.MODE_ALLOWED) {
- appOps.noteOp(AppOpsManager.OP_GET_USAGE_STATS, uid, pkg);
- if (DEBUG) Slog.v(TAG, "Found package " + pkg + " with "
- + "android:get_usage_stats access");
- return true;
+ switch (appOps.checkOpNoThrow(AppOpsManager.OP_GET_USAGE_STATS, uid, pkg)) {
+ case AppOpsManager.MODE_ALLOWED:
+ if (DEBUG) Slog.v(TAG, "Found package " + pkg + " with "
+ + "android:get_usage_stats allowed");
+ return true;
+ case AppOpsManager.MODE_DEFAULT:
+ if (DEBUG) Slog.v(TAG, "Found package " + pkg + " with "
+ + "android:get_usage_stats default");
+ return true;
}
}
}
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 33fabfc4c2a5..96285cd4c17d 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -96,6 +96,7 @@ LOCAL_SRC_FILES:= \
android_os_SystemProperties.cpp \
android_os_Trace.cpp \
android_os_UEventObserver.cpp \
+ android_os_VintfObject.cpp \
android_net_LocalSocketImpl.cpp \
android_net_NetUtils.cpp \
android_net_TrafficStats.cpp \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index e237ce9f208f..8ca479478930 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -159,6 +159,7 @@ extern int register_android_os_HwRemoteBinder(JNIEnv *env);
extern int register_android_os_MessageQueue(JNIEnv* env);
extern int register_android_os_Parcel(JNIEnv* env);
extern int register_android_os_SELinux(JNIEnv* env);
+extern int register_android_os_VintfObject(JNIEnv *env);
extern int register_android_os_seccomp(JNIEnv* env);
extern int register_android_os_SystemProperties(JNIEnv *env);
extern int register_android_os_SystemClock(JNIEnv* env);
@@ -1302,6 +1303,7 @@ static const RegJNIRec gRegJNI[] = {
REG_JNI(register_android_os_HwBlob),
REG_JNI(register_android_os_HwParcel),
REG_JNI(register_android_os_HwRemoteBinder),
+ REG_JNI(register_android_os_VintfObject),
REG_JNI(register_android_nio_utils),
REG_JNI(register_android_graphics_Canvas),
REG_JNI(register_android_graphics_Graphics),
diff --git a/core/jni/android_os_VintfObject.cpp b/core/jni/android_os_VintfObject.cpp
new file mode 100644
index 000000000000..1883ecb9684a
--- /dev/null
+++ b/core/jni/android_os_VintfObject.cpp
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "VintfObject"
+//#define LOG_NDEBUG 0
+
+#include <JNIHelp.h>
+#include <vintf/VintfObject.h>
+#include <vintf/parse_xml.h>
+
+#include "core_jni_helpers.h"
+
+namespace android {
+
+using vintf::HalManifest;
+using vintf::RuntimeInfo;
+using vintf::VintfObject;
+using vintf::gHalManifestConverter;
+
+static jstring android_os_VintfObject_getDeviceManifest(JNIEnv* env, jclass clazz)
+{
+ const HalManifest *manifest = VintfObject::GetDeviceHalManifest();
+ if (manifest == nullptr) {
+ return nullptr;
+ }
+ std::string xml = gHalManifestConverter(*manifest);
+ return env->NewStringUTF(xml.c_str());
+}
+
+static jstring android_os_VintfObject_getFrameworkManifest(JNIEnv* env, jclass clazz)
+{
+ const HalManifest *manifest = VintfObject::GetFrameworkHalManifest();
+ if (manifest == nullptr) {
+ return nullptr;
+ }
+ std::string xml = gHalManifestConverter(*manifest);
+ return env->NewStringUTF(xml.c_str());
+}
+
+static jint android_os_VintfObject_verify(JNIEnv *env, jclass clazz, jobjectArray packageInfo) {
+ size_t count = env->GetArrayLength(packageInfo);
+ std::vector<std::string> cPackageInfo{count};
+ for (size_t i = 0; i < count; ++i) {
+ jstring element = (jstring)env->GetObjectArrayElement(packageInfo, i);
+ const char *cString = env->GetStringUTFChars(element, NULL /* isCopy */);
+ cPackageInfo[i] = cString;
+ env->ReleaseStringUTFChars(element, cString);
+ }
+ int32_t status = VintfObject::CheckCompatibility(cPackageInfo, false /* mount */);
+ return status;
+}
+
+// ----------------------------------------------------------------------------
+
+static const JNINativeMethod gVintfObjectMethods[] = {
+ {"getDeviceManifest", "()Ljava/lang/String;", (void*)android_os_VintfObject_getDeviceManifest},
+ {"getFrameworkManifest", "()Ljava/lang/String;", (void*)android_os_VintfObject_getFrameworkManifest},
+ {"verify", "([Ljava/lang/String;)I", (void*)android_os_VintfObject_verify},
+};
+
+const char* const kVintfObjectPathName = "android/os/VintfObject";
+
+int register_android_os_VintfObject(JNIEnv* env)
+{
+ return RegisterMethodsOrDie(env, kVintfObjectPathName, gVintfObjectMethods,
+ NELEM(gVintfObjectMethods));
+}
+
+};
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 7fc1f6870e2c..000c8c434ded 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -492,7 +492,9 @@
<protected-broadcast android:name="android.intent.action.ACTION_RADIO_OFF" />
<protected-broadcast android:name="android.accounts.LOGIN_ACCOUNTS_CHANGED" />
+ <protected-broadcast android:name="android.accounts.action.ACCOUNT_REMOVED" />
<protected-broadcast android:name="android.accounts.action.VISIBLE_ACCOUNTS_CHANGED" />
+
<protected-broadcast android:name="com.android.sync.SYNC_CONN_STATUS_CHANGED" />
<protected-broadcast android:name="com.android.phone.SIP_INCOMING_CALL" />
@@ -1524,6 +1526,16 @@
<permission android:name="android.permission.DVB_DEVICE"
android:protectionLevel="signature|privileged" />
+ <!-- @SystemApi Allows reading and enabling/disabling the OEM unlock allowed by carrier state
+ @hide <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.MANAGE_CARRIER_OEM_UNLOCK_STATE"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows reading and enabling/disabling the OEM unlock allowed by user state
+ @hide <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.MANAGE_USER_OEM_UNLOCK_STATE"
+ android:protectionLevel="signature|privileged" />
+
<!-- @SystemApi Allows reading the OEM unlock state
@hide <p>Not for use by third-party applications. -->
<permission android:name="android.permission.READ_OEM_UNLOCK_STATE"
diff --git a/core/res/res/drawable-hdpi/ic_accessibility_magnification.png b/core/res/res/drawable-hdpi/ic_accessibility_magnification.png
new file mode 100755
index 000000000000..a91bc6ec90ed
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_accessibility_magnification.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_accessibility_magnification.png b/core/res/res/drawable-mdpi/ic_accessibility_magnification.png
new file mode 100755
index 000000000000..9ec51075a5ed
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_accessibility_magnification.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_accessibility_magnification.png b/core/res/res/drawable-xhdpi/ic_accessibility_magnification.png
new file mode 100755
index 000000000000..0b3a32ed1792
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_accessibility_magnification.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_accessibility_magnification.png b/core/res/res/drawable-xxhdpi/ic_accessibility_magnification.png
new file mode 100755
index 000000000000..3eeb1c9f8dd8
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_accessibility_magnification.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/ic_accessibility_magnification.png b/core/res/res/drawable-xxxhdpi/ic_accessibility_magnification.png
new file mode 100755
index 000000000000..7d376126b4d7
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/ic_accessibility_magnification.png
Binary files differ
diff --git a/core/res/res/layout/autofill_dataset_picker.xml b/core/res/res/layout/autofill_dataset_picker.xml
index 5a835b7e8f4f..528efca49fc3 100644
--- a/core/res/res/layout/autofill_dataset_picker.xml
+++ b/core/res/res/layout/autofill_dataset_picker.xml
@@ -15,6 +15,7 @@
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/autofill_dataset_picker"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
style="@style/AutofillDatasetPicker">
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 5ede1c954ce5..67f6d190e586 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -430,10 +430,9 @@
<flag name="adjustNothing" value="0x30" />
</attr>
- <!-- Flag allowing you to disable the preview animation for a window.
- The default value is false; if set to true, the system can never
- use the window's theme to show a preview of it before your
- actual instance is shown to the user. -->
+ <!-- Flag allowing you to disable the splash screen for a window. The default value is
+ false; if set to true, the system can never use the window's theme to show a splash
+ screen before your actual instance is shown to the user. -->
<attr name="windowDisablePreview" format="boolean" />
<!-- Flag indicating that this window should not be displayed at all.
@@ -2049,6 +2048,17 @@
Corresponds to setting {@link android.view.View#SYSTEM_UI_FLAG_LIGHT_STATUS_BAR} on
the decor view. -->
<attr name="windowLightStatusBar" format="boolean" />
+
+ <!-- Reference to a drawable to be used as the splash screen content of the window. This
+ drawable will be placed on top of the {@link android.R.attr#windowBackground} with its
+ bounds inset by the system bars. If the drawable should not be inset by the system
+ bars, use a fullscreen theme.
+ <p>
+ Note that even if no splashscreen content is set on the theme, the system may still
+ show a splash screen using the other attributes on the theme, like the
+ {@link android.R.attr#windowBackground}.
+ -->
+ <attr name="windowSplashscreenContent" format="reference" />
</declare-styleable>
<!-- The set of attributes that describe a AlertDialog's theme. -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 31ece50c37fa..d6ed1786e760 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2816,6 +2816,7 @@
<public name="iconSpaceReserved"/>
<public name="defaultFocusHighlightEnabled" />
<public name="persistentFeature"/>
+ <public name="windowSplashscreenContent" />
</public-group>
<public-group type="style" first-id="0x010302e0">
@@ -2835,7 +2836,6 @@
<public name="paste_as_plain_text" />
</public-group>
-
<!-- ===============================================================
DO NOT ADD UN-GROUPED ITEMS HERE
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 44a4af723307..603e3769e75c 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2857,6 +2857,7 @@
<java-symbol type="id" name="accessibility_button_target_icon" />
<java-symbol type="id" name="accessibility_button_target_label" />
<java-symbol type="string" name="accessibility_magnification_chooser_text" />
+ <java-symbol type="drawable" name="ic_accessibility_magnification" />
<!-- com.android.internal.widget.RecyclerView -->
<java-symbol type="id" name="item_touch_helper_previous_elevation"/>
@@ -2867,6 +2868,7 @@
<!-- com.android.server.autofill -->
<java-symbol type="layout" name="autofill_save"/>
<java-symbol type="layout" name="autofill_dataset_picker"/>
+ <java-symbol type="id" name="autofill_dataset_picker"/>
<java-symbol type="id" name="autofill_dataset_list"/>
<java-symbol type="id" name="autofill" />
<java-symbol type="id" name="autofill_save_title" />
diff --git a/core/tests/coretests/src/android/os/VintfObjectTest.java b/core/tests/coretests/src/android/os/VintfObjectTest.java
new file mode 100644
index 000000000000..aaaf55ccf799
--- /dev/null
+++ b/core/tests/coretests/src/android/os/VintfObjectTest.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2017 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.os;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+public class VintfObjectTest extends TestCase {
+ public void testReport() {
+ String[] xmls = VintfObject.report();
+ assertTrue(xmls.length > 0);
+ // From /system/manifest.xml
+ assertTrue(String.join("", xmls).contains(
+ "<manifest version=\"1.0\" type=\"framework\">"));
+ }
+}
diff --git a/data/fonts/fonts.xml b/data/fonts/fonts.xml
index 3dab1f7e20e1..39b0bc7d6ca6 100644
--- a/data/fonts/fonts.xml
+++ b/data/fonts/fonts.xml
@@ -277,6 +277,9 @@
<font weight="400" style="normal">NotoSansCham-Regular.ttf</font>
<font weight="700" style="normal">NotoSansCham-Bold.ttf</font>
</family>
+ <family lang="und-Adlm">
+ <font weight="400" style="normal">NotoSansAdlam-Regular.ttf</font>
+ </family>
<family lang="und-Avst">
<font weight="400" style="normal">NotoSansAvestan-Regular.ttf</font>
</family>
diff --git a/graphics/java/android/graphics/ColorSpace.java b/graphics/java/android/graphics/ColorSpace.java
index f1804e5976de..8f78319e8380 100644
--- a/graphics/java/android/graphics/ColorSpace.java
+++ b/graphics/java/android/graphics/ColorSpace.java
@@ -885,8 +885,32 @@ public abstract class ColorSpace {
}
/**
- * Returns the name of this color space. The name is never null
- * and contains always at least 1 character.
+ * <p>Returns the name of this color space. The name is never null
+ * and contains always at least 1 character.</p>
+ *
+ * <p>Color space names are recommended to be unique but are not
+ * guaranteed to be. There is no defined format but the name usually
+ * falls in one of the following categories:</p>
+ * <ul>
+ * <li>Generic names used to identify color spaces in non-RGB
+ * color models. For instance: {@link Named#CIE_LAB Generic L*a*b*}.</li>
+ * <li>Names tied to a particular specification. For instance:
+ * {@link Named#SRGB sRGB IEC61966-2.1} or
+ * {@link Named#ACES SMPTE ST 2065-1:2012 ACES}.</li>
+ * <li>Ad-hoc names, often generated procedurally or by the user
+ * during a calibration workflow. These names often contain the
+ * make and model of the display.</li>
+ * </ul>
+ *
+ * <p>Because the format of color space names is not defined, it is
+ * not recommended to programmatically identify a color space by its
+ * name alone. Names can be used as a first approximation.</p>
+ *
+ * <p>It is however perfectly acceptable to display color space names to
+ * users in a UI, or in debuggers and logs. When displaying a color space
+ * name to the user, it is recommended to add extra information to avoid
+ * ambiguities: color model, a representation of the color space's gamut,
+ * white point, etc.</p>
*
* @return A non-null String of length >= 1
*/
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
index 02f1162fc968..8a86c13abb7d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
@@ -984,18 +984,27 @@ public class ApplicationsState {
mCurComputingSizeUserId = UserHandle.getUserId(entry.info.uid);
mBackgroundHandler.post(() -> {
- final StorageStats stats = mStats.queryStatsForPackage(
- mCurComputingSizeUuid, mCurComputingSizePkg,
- UserHandle.of(mCurComputingSizeUserId));
- final PackageStats legacyStats = new PackageStats(
- mCurComputingSizePkg, mCurComputingSizeUserId);
- legacyStats.codeSize = stats.getCodeBytes();
- legacyStats.dataSize = stats.getDataBytes();
- legacyStats.cacheSize = stats.getCacheBytes();
try {
- mStatsObserver.onGetStatsCompleted(legacyStats, true);
- } catch (RemoteException ignored) {
+ final StorageStats stats = mStats.queryStatsForPackage(
+ mCurComputingSizeUuid, mCurComputingSizePkg,
+ UserHandle.of(mCurComputingSizeUserId));
+ final PackageStats legacyStats = new PackageStats(
+ mCurComputingSizePkg, mCurComputingSizeUserId);
+ legacyStats.codeSize = stats.getCodeBytes();
+ legacyStats.dataSize = stats.getDataBytes();
+ legacyStats.cacheSize = stats.getCacheBytes();
+ try {
+ mStatsObserver.onGetStatsCompleted(legacyStats, true);
+ } catch (RemoteException ignored) {
+ }
+ } catch (IllegalStateException e) {
+ Log.e(TAG,"An exception occurred while fetching app size", e);
+ try {
+ mStatsObserver.onGetStatsCompleted(null, false);
+ } catch (RemoteException ignored) {
+ }
}
+
});
}
if (DEBUG_LOCKING) Log.v(TAG, "MSG_LOAD_SIZES releasing: now computing");
@@ -1493,7 +1502,8 @@ public class ApplicationsState {
@Override
public boolean filterApp(AppEntry entry) {
- return (entry.info.privateFlags & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) != 0;
+ return !AppUtils.isInstant(entry.info)
+ && (entry.info.privateFlags & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) != 0;
}
};
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/applications/ApplicationsStateTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/applications/ApplicationsStateTest.java
index c680b2a2ce4b..fed18fa1bcb0 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/applications/ApplicationsStateTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/applications/ApplicationsStateTest.java
@@ -201,6 +201,22 @@ public class ApplicationsStateTest {
}
@Test
+ public void testFilterWithDomainUrls() {
+ mEntry.info.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
+ // should included updated system apps
+ when(mEntry.info.isInstantApp()).thenReturn(false);
+ assertThat(ApplicationsState.FILTER_WITH_DOMAIN_URLS.filterApp(mEntry))
+ .isTrue();
+ mEntry.info.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
+ assertThat(ApplicationsState.FILTER_WITH_DOMAIN_URLS.filterApp(mEntry))
+ .isFalse();
+ mEntry.info.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
+ when(mEntry.info.isInstantApp()).thenReturn(true);
+ assertThat(ApplicationsState.FILTER_WITH_DOMAIN_URLS.filterApp(mEntry))
+ .isFalse();
+ }
+
+ @Test
public void testDisabledFilterRejectsInstantApp() {
mEntry.info.enabled = false;
assertThat(ApplicationsState.FILTER_DISABLED.filterApp(mEntry)).isTrue();
diff --git a/packages/SystemUI/res/drawable-hdpi/pip_dismiss_scrim.9.png b/packages/SystemUI/res/drawable-hdpi/pip_dismiss_scrim.9.png
index 6737c80fc8f9..32f1ed79c993 100644
--- a/packages/SystemUI/res/drawable-hdpi/pip_dismiss_scrim.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/pip_dismiss_scrim.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/pip_dismiss_scrim.9.png b/packages/SystemUI/res/drawable-mdpi/pip_dismiss_scrim.9.png
index d9e33eb3c54f..33826a664951 100644
--- a/packages/SystemUI/res/drawable-mdpi/pip_dismiss_scrim.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/pip_dismiss_scrim.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/pip_dismiss_scrim.9.png b/packages/SystemUI/res/drawable-xhdpi/pip_dismiss_scrim.9.png
index 64daf208d235..c1157f4316cf 100644
--- a/packages/SystemUI/res/drawable-xhdpi/pip_dismiss_scrim.9.png
+++ b/packages/SystemUI/res/drawable-xhdpi/pip_dismiss_scrim.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/pip_dismiss_scrim.9.png b/packages/SystemUI/res/drawable-xxhdpi/pip_dismiss_scrim.9.png
index 49e0499c3bc8..8d58a7e01b42 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/pip_dismiss_scrim.9.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/pip_dismiss_scrim.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/pip_dismiss_scrim.9.png b/packages/SystemUI/res/drawable-xxxhdpi/pip_dismiss_scrim.9.png
index 0e6ca16fd5f1..6c04d1aaccea 100644
--- a/packages/SystemUI/res/drawable-xxxhdpi/pip_dismiss_scrim.9.png
+++ b/packages/SystemUI/res/drawable-xxxhdpi/pip_dismiss_scrim.9.png
Binary files differ
diff --git a/packages/SystemUI/res/layout/pip_dismiss_view.xml b/packages/SystemUI/res/layout/pip_dismiss_view.xml
index 34228d9f2e2d..058f59faa566 100644
--- a/packages/SystemUI/res/layout/pip_dismiss_view.xml
+++ b/packages/SystemUI/res/layout/pip_dismiss_view.xml
@@ -27,6 +27,10 @@
android:layout_gravity="bottom|center_horizontal"
android:text="@string/pip_phone_dismiss_hint"
android:textColor="#FFFFFFFF"
- android:textSize="14sp" />
+ android:textSize="14sp"
+ android:shadowColor="@android:color/black"
+ android:shadowDx="-2"
+ android:shadowDy="2"
+ android:shadowRadius="0.01" />
</FrameLayout> \ No newline at end of file
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 68373404ba2b..6d8a07784a30 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -738,7 +738,7 @@
<dimen name="pip_dismiss_gradient_height">196dp</dimen>
<!-- The bottom margin of the PIP drag to dismiss info text shown when moving a PIP. -->
- <dimen name="pip_dismiss_text_bottom_margin">36dp</dimen>
+ <dimen name="pip_dismiss_text_bottom_margin">24dp</dimen>
<!-- The shortest-edge size of the expanded PiP. -->
<dimen name="pip_expanded_shortest_edge_size">160dp</dimen>
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
index 114a59407487..c5653733bac7 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
@@ -86,6 +86,7 @@ public class PipManager implements BasePipManager {
ComponentName topPipActivity = PipUtils.getTopPinnedActivity(mContext,
mActivityManager);
+ mMenuController.hideMenu();
mNotificationController.onActivityUnpinned(topPipActivity);
SystemServicesProxy.getInstance(mContext).setPipVisibility(topPipActivity != null);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index c3c09a015bd3..3f26fddb1b3c 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -662,6 +662,7 @@ public class PipTouchHandler implements TunerService.Tunable {
mMenuController.showMenu(MENU_STATE_FULL, mMotionHelper.getBounds(),
mMovementBounds, true /* allowMenuTimeout */);
} else {
+ mMenuController.hideMenu();
mMotionHelper.expandPip();
}
return true;
diff --git a/services/Android.mk b/services/Android.mk
index 44525434c545..a4c891b46011 100644
--- a/services/Android.mk
+++ b/services/Android.mk
@@ -40,8 +40,8 @@ services := \
# The convention is to name each service module 'services.$(module_name)'
LOCAL_STATIC_JAVA_LIBRARIES := $(addprefix services.,$(services)) \
- android.hidl.base@1.0-java-static \
- android.hardware.biometrics.fingerprint@2.1-java-static
+ android.hidl.base-V1.0-java-static \
+ android.hardware.biometrics.fingerprint-V2.1-java-static
ifeq ($(EMMA_INSTRUMENT_FRAMEWORK),true)
LOCAL_EMMA_INSTRUMENT := true
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 67c2314cac35..67b52825f3b6 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -370,6 +370,23 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
}
}
+ // AutoFillUiCallback
+ @Override
+ public void startIntentSender(IntentSender intentSender) {
+ synchronized (mLock) {
+ removeSelfLocked();
+ }
+ mHandlerCaller.getHandler().post(() -> {
+ try {
+ synchronized (mLock) {
+ mClient.startIntentSender(intentSender);
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Error launching auth intent", e);
+ }
+ });
+ }
+
public void setAuthenticationResultLocked(Bundle data) {
if ((mResponseWaitingAuth == null && mDatasetWaitingAuth == null) || data == null) {
removeSelf();
diff --git a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
index 0f18c87bf5f9..4449da92b19c 100644
--- a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
+++ b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
@@ -67,6 +67,7 @@ public final class AutoFillUI {
void requestShowFillUi(AutofillId id, int width, int height,
IAutofillWindowPresenter presenter);
void requestHideFillUi(AutofillId id);
+ void startIntentSender(IntentSender intentSender);
}
public AutoFillUI(@NonNull Context context) {
@@ -201,6 +202,13 @@ public final class AutoFillUI {
mCallback.requestHideFillUi(focusedId);
}
}
+
+ @Override
+ public void startIntentSender(IntentSender intentSender) {
+ if (mCallback != null) {
+ mCallback.startIntentSender(intentSender);
+ }
+ }
});
});
}
diff --git a/services/autofill/java/com/android/server/autofill/ui/FillUi.java b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
index a89df9223e31..b68e3b1e2543 100644
--- a/services/autofill/java/com/android/server/autofill/ui/FillUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
@@ -17,7 +17,10 @@ package com.android.server.autofill.ui;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.PendingIntent;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentSender;
import android.graphics.Rect;
import android.service.autofill.Dataset;
import android.service.autofill.FillResponse;
@@ -55,6 +58,7 @@ final class FillUi {
void requestShowFillUi(int width, int height,
IAutofillWindowPresenter windowPresenter);
void requestHideFillUi();
+ void startIntentSender(IntentSender intentSender);
}
private final @NonNull AutofillWindowPresenter mWindowPresenter =
@@ -84,13 +88,24 @@ final class FillUi {
final ViewGroup decor = (ViewGroup) inflater.inflate(
R.layout.autofill_dataset_picker, null);
+ final RemoteViews.OnClickHandler interceptionHandler = new RemoteViews.OnClickHandler() {
+ @Override
+ public boolean onClickHandler(View view, PendingIntent pendingIntent,
+ Intent fillInIntent) {
+ if (pendingIntent != null) {
+ mCallback.startIntentSender(pendingIntent.getIntentSender());
+ }
+ return true;
+ }
+ };
+
if (response.getAuthentication() != null) {
mListView = null;
mAdapter = null;
final View content;
try {
- content = response.getPresentation().apply(context, decor);
+ content = response.getPresentation().apply(context, decor, interceptionHandler);
decor.addView(content);
} catch (RuntimeException e) {
callback.onCanceled();
@@ -101,7 +116,7 @@ final class FillUi {
final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
content.measure(widthMeasureSpec, heightMeasureSpec);
- content.setOnClickListener(v -> mCallback.onResponsePicked(response));
+ decor.setOnClickListener(v -> mCallback.onResponsePicked(response));
// TODO(b/33197203 , b/36660292): temporary limiting maximum height and minimum width
mContentWidth = Math.max(content.getMeasuredWidth(), 1000);
mContentHeight = Math.min(content.getMeasuredHeight(), 500);
@@ -118,7 +133,7 @@ final class FillUi {
final RemoteViews presentation = dataset.getFieldPresentation(index);
final View view;
try {
- view = presentation.apply(context, null);
+ view = presentation.apply(context, null, interceptionHandler);
} catch (RuntimeException e) {
Slog.e(TAG, "Error inflating remote views", e);
continue;
diff --git a/services/core/Android.mk b/services/core/Android.mk
index 8003d21d165e..f89647897d09 100644
--- a/services/core/Android.mk
+++ b/services/core/Android.mk
@@ -20,17 +20,17 @@ LOCAL_AIDL_INCLUDES += \
LOCAL_JAVA_LIBRARIES := \
services.net \
- android.hardware.light@2.0-java \
- android.hardware.power@1.0-java \
- android.hardware.tv.cec@1.0-java \
- android.hidl.manager@1.0-java
+ android.hardware.light-V2.0-java \
+ android.hardware.power-V1.0-java \
+ android.hardware.tv.cec-V1.0-java \
+ android.hidl.manager-V1.0-java
LOCAL_STATIC_JAVA_LIBRARIES := \
tzdata_shared2 \
tzdata_update2 \
- android.hidl.base@1.0-java-static \
- android.hardware.biometrics.fingerprint@2.1-java-static \
- android.hardware.vibrator@1.0-java-constants \
+ android.hidl.base-V1.0-java-static \
+ android.hardware.biometrics.fingerprint-V2.1-java-static \
+ android.hardware.vibrator-V1.0-java-constants \
ifneq ($(INCREMENTAL_BUILDS),)
LOCAL_PROGUARD_ENABLED := disabled
diff --git a/services/core/java/com/android/server/OemLockService.java b/services/core/java/com/android/server/OemLockService.java
new file mode 100644
index 000000000000..03f82a8e5d8e
--- /dev/null
+++ b/services/core/java/com/android/server/OemLockService.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import android.Manifest;
+import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.content.Context;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.service.oemlock.IOemLockService;
+import android.service.persistentdata.PersistentDataBlockManager;
+
+/**
+ * Service for managing the OEM lock state of the device.
+ *
+ * The current implementation is a wrapper around the previous implementation of OEM lock.
+ * - the DISALLOW_OEM_UNLOCK user restriction was set if the carrier disallowed unlock
+ * - the user allows unlock in settings which calls PDBM.setOemUnlockEnabled()
+ */
+public class OemLockService extends SystemService {
+ private Context mContext;
+
+ public OemLockService(Context context) {
+ super(context);
+ mContext = context;
+ }
+
+ @Override
+ public void onStart() {
+ publishBinderService(Context.OEM_LOCK_SERVICE, mService);
+ }
+
+ private boolean doIsOemUnlockAllowedByCarrier() {
+ return !UserManager.get(mContext).hasUserRestriction(UserManager.DISALLOW_OEM_UNLOCK);
+ }
+
+ private boolean doIsOemUnlockAllowedByUser() {
+ final PersistentDataBlockManager pdbm = (PersistentDataBlockManager)
+ mContext.getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ return pdbm.getOemUnlockEnabled();
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Implements the binder interface for the service.
+ */
+ private final IBinder mService = new IOemLockService.Stub() {
+ @Override
+ public void setOemUnlockAllowedByCarrier(boolean allowed, @Nullable byte[] signature) {
+ enforceManageCarrierOemUnlockPermission();
+ enforceUserIsAdmin();
+
+ // Note: this implementation does not require a signature
+
+ // Continue using user restriction for backwards compatibility
+ final UserHandle userHandle = UserHandle.of(UserHandle.getCallingUserId());
+ final long token = Binder.clearCallingIdentity();
+ try {
+ UserManager.get(mContext)
+ .setUserRestriction(UserManager.DISALLOW_OEM_UNLOCK, !allowed, userHandle);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
+ public boolean isOemUnlockAllowedByCarrier() {
+ enforceManageCarrierOemUnlockPermission();
+ return doIsOemUnlockAllowedByCarrier();
+ }
+
+ @Override
+ public void setOemUnlockAllowedByUser(boolean allowedByUser) {
+ if (ActivityManager.isUserAMonkey()) {
+ // Prevent a monkey from changing this
+ return;
+ }
+
+ enforceManageUserOemUnlockPermission();
+ enforceUserIsAdmin();
+
+ final PersistentDataBlockManager pdbm = (PersistentDataBlockManager)
+ mContext.getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ // The method name is misleading as it really just means whether or not the device
+ // can be unlocked but doesn't actually do any unlocking.
+ pdbm.setOemUnlockEnabled(allowedByUser);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
+ public boolean isOemUnlockAllowedByUser() {
+ enforceManageUserOemUnlockPermission();
+ return doIsOemUnlockAllowedByUser();
+ }
+ };
+
+ private void enforceManageCarrierOemUnlockPermission() {
+ mContext.enforceCallingOrSelfPermission(
+ Manifest.permission.MANAGE_CARRIER_OEM_UNLOCK_STATE,
+ "Can't manage OEM unlock allowed by carrier");
+ }
+
+ private void enforceManageUserOemUnlockPermission() {
+ mContext.enforceCallingOrSelfPermission(
+ Manifest.permission.MANAGE_USER_OEM_UNLOCK_STATE,
+ "Can't manage OEM unlock allowed by user");
+ }
+
+ private void enforceUserIsAdmin() {
+ final int userId = UserHandle.getCallingUserId();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ if (!UserManager.get(mContext).isUserAdmin(userId)) {
+ throw new SecurityException("Must be an admin user");
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 5f585cc799c9..eb58e4c54246 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -959,6 +959,12 @@ public class AccountManagerService
mContext.sendBroadcastAsUser(ACCOUNTS_CHANGED_INTENT, new UserHandle(userId));
}
+ private void sendAccountRemovedBroadcast(int userId) {
+ Intent intent = new Intent(AccountManager.ACTION_ACCOUNT_REMOVED);
+ intent.setFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
+ mContext.sendBroadcastAsUser(intent, new UserHandle(userId));
+ }
+
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
@@ -1111,6 +1117,7 @@ public class AccountManagerService
notifyPackage(packageToVisibility.getKey(), accounts);
}
}
+ sendAccountRemovedBroadcast(accounts.userId);
} else {
ArrayList<String> accountNames = accountNamesByType.get(account.type);
if (accountNames == null) {
@@ -1971,6 +1978,7 @@ public class AccountManagerService
sendNotificationAccountUpdated(resultAccount, accounts);
sendAccountsChangedBroadcast(accounts.userId);
+ sendAccountRemovedBroadcast(accounts.userId);
}
}
return resultAccount;
@@ -2206,6 +2214,7 @@ public class AccountManagerService
// Only broadcast LOGIN_ACCOUNTS_CHANGED if a change occurred.
sendAccountsChangedBroadcast(accounts.userId);
+ sendAccountRemovedBroadcast(accounts.userId);
String action = userUnlocked ? AccountsDb.DEBUG_ACTION_ACCOUNT_REMOVE
: AccountsDb.DEBUG_ACTION_ACCOUNT_REMOVE_DE;
logRecord(action, AccountsDb.TABLE_ACCOUNTS, accountId, accounts);
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index df250b19beba..55ee18335410 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -32,16 +32,10 @@ import java.io.PrintWriter;
*/
final class ActivityManagerConstants extends ContentObserver {
// Key names stored in the settings value.
- private static final String KEY_ENFORCE_BG_CHECK = "enforce_bg_check";
private static final String KEY_MAX_CACHED_PROCESSES = "max_cached_processes";
- private static final boolean DEFAULT_ENFORCE_BG_CHECK = SystemProperties.getBoolean(
- "debug.bgcheck", true);
private static final int DEFAULT_MAX_CACHED_PROCESSES = 32;
- // Enforce background check on apps targeting O?
- public boolean ENFORCE_BG_CHECK = DEFAULT_ENFORCE_BG_CHECK;
-
// Maximum number of cached processes we will allow.
public int MAX_CACHED_PROCESSES = DEFAULT_MAX_CACHED_PROCESSES;
@@ -115,7 +109,6 @@ final class ActivityManagerConstants extends ContentObserver {
// with defaults.
Slog.e("ActivityManagerConstants", "Bad activity manager config settings", e);
}
- ENFORCE_BG_CHECK = mParser.getBoolean(KEY_ENFORCE_BG_CHECK, DEFAULT_ENFORCE_BG_CHECK);
MAX_CACHED_PROCESSES = mParser.getInt(KEY_MAX_CACHED_PROCESSES,
DEFAULT_MAX_CACHED_PROCESSES);
updateMaxCachedProcesses();
@@ -139,9 +132,6 @@ final class ActivityManagerConstants extends ContentObserver {
pw.println("ACTIVITY MANAGER SETTINGS (dumpsys activity settings) "
+ Settings.Global.ACTIVITY_MANAGER_CONSTANTS + ":");
- pw.print(" "); pw.print(KEY_ENFORCE_BG_CHECK); pw.print("=");
- pw.println(ENFORCE_BG_CHECK);
-
pw.print(" "); pw.print(KEY_MAX_CACHED_PROCESSES); pw.print("=");
pw.println(MAX_CACHED_PROCESSES);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index fd7dea152128..2be53136bb74 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -2717,17 +2717,6 @@ public class ActivityManagerService extends IActivityManager.Stub
mConstants = new ActivityManagerConstants(this, mHandler);
- if (DEBUG_BACKGROUND_CHECK) {
- Slog.d(TAG, "Enforcing O+ bg restrictions: " + mConstants.ENFORCE_BG_CHECK);
- StringBuilder sb = new StringBuilder(200);
- sb.append(" ");
- for (String a : getBackgroundLaunchBroadcasts()) {
- sb.append(' '); sb.append(a);
- }
- Slog.d(TAG, "Background implicit broadcasts:");
- Slog.d(TAG, sb.toString());
- }
-
/* static; one-time init here */
if (sKillHandler == null) {
sKillThread = new ServiceThread(TAG + ":kill",
@@ -7875,9 +7864,7 @@ public class ActivityManagerService extends IActivityManager.Stub
final float aspectRatio = r.pictureInPictureArgs.getAspectRatio();
final List<RemoteAction> actions = r.pictureInPictureArgs.getActions();
final Rect sourceBounds = r.pictureInPictureArgs.getSourceRectHint();
- final Rect destBounds = mWindowManager.getPictureInPictureBounds(DEFAULT_DISPLAY,
- aspectRatio);
- mStackSupervisor.moveActivityToPinnedStackLocked(r, sourceBounds, destBounds,
+ mStackSupervisor.moveActivityToPinnedStackLocked(r, sourceBounds, aspectRatio,
true /* moveHomeStackToFront */, "enterPictureInPictureMode");
final PinnedActivityStack stack = mStackSupervisor.getStack(PINNED_STACK_ID);
stack.setPictureInPictureAspectRatio(aspectRatio);
@@ -7938,7 +7925,7 @@ public class ActivityManagerService extends IActivityManager.Stub
// if it is not already expanding to fullscreen. Otherwise, the arguments will
// be used the next time the activity enters PiP
final PinnedActivityStack stack = r.getStack();
- if (!stack.isBoundsAnimatingToFullscreen()) {
+ if (!stack.isAnimatingBoundsToFullscreen()) {
stack.setPictureInPictureAspectRatio(
r.pictureInPictureArgs.getAspectRatio());
stack.setPictureInPictureActions(r.pictureInPictureArgs.getActions());
@@ -8309,7 +8296,7 @@ public class ActivityManagerService extends IActivityManager.Stub
// Unified app-op and target sdk check
int appRestrictedInBackgroundLocked(int uid, String packageName, int packageTargetSdk) {
// Apps that target O+ are always subject to background check
- if (mConstants.ENFORCE_BG_CHECK && packageTargetSdk >= Build.VERSION_CODES.O) {
+ if (packageTargetSdk >= Build.VERSION_CODES.O) {
if (DEBUG_BACKGROUND_CHECK) {
Slog.i(TAG, "App " + uid + "/" + packageName + " targets O+, restricted");
}
@@ -10547,8 +10534,10 @@ public class ActivityManagerService extends IActivityManager.Stub
if (stackId == PINNED_STACK_ID) {
final PinnedActivityStack pinnedStack =
mStackSupervisor.getStack(PINNED_STACK_ID);
- pinnedStack.animateResizePinnedStack(null /* sourceBounds */, destBounds,
- animationDuration);
+ if (pinnedStack != null) {
+ pinnedStack.animateResizePinnedStack(null /* sourceBounds */,
+ destBounds, animationDuration);
+ }
} else {
throw new IllegalArgumentException("Stack: " + stackId
+ " doesn't support animated resize.");
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 68e25c37dca8..4d16e33ad81c 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -174,6 +174,7 @@ import com.android.internal.util.ArrayUtils;
import com.android.internal.widget.LockPatternUtils;
import com.android.server.LocalServices;
import com.android.server.am.ActivityStack.ActivityState;
+import com.android.server.wm.PinnedStackWindowController;
import com.android.server.wm.WindowManagerService;
import java.io.FileDescriptor;
@@ -2492,11 +2493,21 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
}
void resizePinnedStackLocked(Rect pinnedBounds, Rect tempPinnedTaskBounds) {
- final ActivityStack stack = getStack(PINNED_STACK_ID);
+ final PinnedActivityStack stack = getStack(PINNED_STACK_ID);
if (stack == null) {
Slog.w(TAG, "resizePinnedStackLocked: pinned stack not found");
return;
}
+
+ // It is possible for the bounds animation from the WM to call this but be delayed by
+ // another AM call that is holding the AMS lock. In such a case, the pinnedBounds may be
+ // incorrect if AMS.resizeStackWithBoundsFromWindowManager() is already called while waiting
+ // for the AMS lock to be freed. So check and make sure these bounds are still good.
+ final PinnedStackWindowController stackController = stack.getWindowContainerController();
+ if (stackController.pinnedStackResizeAllowed()) {
+ return;
+ }
+
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizePinnedStack");
mWindowManager.deferSurfaceLayout();
try {
@@ -2857,12 +2868,12 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
return false;
}
- moveActivityToPinnedStackLocked(r, null /* sourceBounds */, destBounds,
+ moveActivityToPinnedStackLocked(r, null /* sourceBounds */, 0f /* aspectRatio */,
true /* moveHomeStackToFront */, "moveTopActivityToPinnedStack");
return true;
}
- void moveActivityToPinnedStackLocked(ActivityRecord r, Rect sourceBounds, Rect destBounds,
+ void moveActivityToPinnedStackLocked(ActivityRecord r, Rect sourceBounds, float aspectRatio,
boolean moveHomeStackToFront, String reason) {
mWindowManager.deferSurfaceLayout();
@@ -2932,6 +2943,11 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
resumeFocusedStackTopActivityLocked();
+ // Calculate the default bounds (don't use existing stack bounds as we may have just created
+ // the stack
+ final Rect destBounds = mWindowManager.getPictureInPictureBounds(DEFAULT_DISPLAY,
+ aspectRatio, false /* useExistingStackBounds */);
+
// TODO(b/36099777): Schedule the PiP mode change here immediately until we can defer all
// callbacks until after the bounds animation
scheduleUpdatePictureInPictureModeIfNeeded(r.getTask(), destBounds, true /* immediate */);
diff --git a/services/core/java/com/android/server/am/PinnedActivityStack.java b/services/core/java/com/android/server/am/PinnedActivityStack.java
index 394e902ec27e..cd9c42c7c643 100644
--- a/services/core/java/com/android/server/am/PinnedActivityStack.java
+++ b/services/core/java/com/android/server/am/PinnedActivityStack.java
@@ -21,7 +21,7 @@ import android.graphics.Rect;
import com.android.server.am.ActivityStackSupervisor.ActivityContainer;
import com.android.server.wm.PinnedStackWindowController;
-import com.android.server.wm.StackWindowController;
+import com.android.server.wm.PinnedStackWindowListener;
import java.util.ArrayList;
import java.util.List;
@@ -29,7 +29,8 @@ import java.util.List;
/**
* State and management of the pinned stack of activities.
*/
-class PinnedActivityStack extends ActivityStack<PinnedStackWindowController> {
+class PinnedActivityStack extends ActivityStack<PinnedStackWindowController>
+ implements PinnedStackWindowListener {
PinnedActivityStack(ActivityContainer activityContainer,
RecentTasks recentTasks, boolean onTop) {
@@ -55,8 +56,8 @@ class PinnedActivityStack extends ActivityStack<PinnedStackWindowController> {
getWindowContainerController().setPictureInPictureActions(actions);
}
- boolean isBoundsAnimatingToFullscreen() {
- return getWindowContainerController().isBoundsAnimatingToFullscreen();
+ boolean isAnimatingBoundsToFullscreen() {
+ return getWindowContainerController().isAnimatingBoundsToFullscreen();
}
@Override
diff --git a/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java b/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java
index ad66faa8cf04..5dee91de0e77 100644
--- a/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java
+++ b/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java
@@ -23,9 +23,6 @@ import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE;
-import static com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityEvent;
-import static com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityLog;
-import static com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.NetworkId;
import android.net.ConnectivityMetricsEvent;
import android.net.metrics.ApfProgramEvent;
@@ -34,6 +31,7 @@ import android.net.metrics.DefaultNetworkEvent;
import android.net.metrics.DhcpClientEvent;
import android.net.metrics.DhcpErrorEvent;
import android.net.metrics.DnsEvent;
+import android.net.metrics.ConnectStats;
import android.net.metrics.IpManagerEvent;
import android.net.metrics.IpReachabilityEvent;
import android.net.metrics.NetworkEvent;
@@ -41,7 +39,12 @@ import android.net.metrics.RaEvent;
import android.net.metrics.ValidationProbeEvent;
import android.os.Parcelable;
import android.util.SparseArray;
+import android.util.SparseIntArray;
import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass;
+import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityEvent;
+import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityLog;
+import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.NetworkId;
+import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.Pair;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@@ -77,20 +80,51 @@ final public class IpConnectivityEventBuilder {
}
public static IpConnectivityEvent toProto(ConnectivityMetricsEvent ev) {
- final IpConnectivityEvent out = new IpConnectivityEvent();
+ final IpConnectivityEvent out = buildEvent(ev.netId, ev.transports, ev.ifname);
+ out.timeMs = ev.timestamp;
if (!setEvent(out, ev.data)) {
return null;
}
- out.timeMs = ev.timestamp;
- out.networkId = ev.netId;
- out.transports = ev.transports;
- if (ev.ifname != null) {
- out.ifName = ev.ifname;
- }
- inferLinkLayer(out);
return out;
}
+ public static IpConnectivityEvent toProto(ConnectStats in) {
+ IpConnectivityLogClass.ConnectStatistics stats =
+ new IpConnectivityLogClass.ConnectStatistics();
+ stats.connectCount = in.connectCount;
+ stats.connectBlockingCount = in.connectBlockingCount;
+ stats.ipv6AddrCount = in.ipv6ConnectCount;
+ stats.latenciesMs = in.latencies.toArray();
+ stats.errnosCounters = toPairArray(in.errnos);
+ final IpConnectivityEvent out = buildEvent(in.netId, in.transports, null);
+ out.setConnectStatistics(stats);
+ return out;
+ }
+
+
+ public static IpConnectivityEvent toProto(DnsEvent in) {
+ IpConnectivityLogClass.DNSLookupBatch dnsLookupBatch =
+ new IpConnectivityLogClass.DNSLookupBatch();
+ in.resize(in.eventCount);
+ dnsLookupBatch.eventTypes = bytesToInts(in.eventTypes);
+ dnsLookupBatch.returnCodes = bytesToInts(in.returnCodes);
+ dnsLookupBatch.latenciesMs = in.latenciesMs;
+ final IpConnectivityEvent out = buildEvent(in.netId, in.transports, null);
+ out.setDnsLookupBatch(dnsLookupBatch);
+ return out;
+ }
+
+ private static IpConnectivityEvent buildEvent(int netId, long transports, String ifname) {
+ final IpConnectivityEvent ev = new IpConnectivityEvent();
+ ev.networkId = netId;
+ ev.transports = transports;
+ if (ifname != null) {
+ ev.ifName = ifname;
+ }
+ inferLinkLayer(ev);
+ return ev;
+ }
+
private static boolean setEvent(IpConnectivityEvent out, Parcelable in) {
if (in instanceof DhcpErrorEvent) {
setDhcpErrorEvent(out, (DhcpErrorEvent) in);
@@ -102,11 +136,6 @@ final public class IpConnectivityEventBuilder {
return true;
}
- if (in instanceof DnsEvent) {
- setDnsEvent(out, (DnsEvent) in);
- return true;
- }
-
if (in instanceof IpManagerEvent) {
setIpManagerEvent(out, (IpManagerEvent) in);
return true;
@@ -163,16 +192,6 @@ final public class IpConnectivityEventBuilder {
out.setDhcpEvent(dhcpEvent);
}
- private static void setDnsEvent(IpConnectivityEvent out, DnsEvent in) {
- IpConnectivityLogClass.DNSLookupBatch dnsLookupBatch =
- new IpConnectivityLogClass.DNSLookupBatch();
- dnsLookupBatch.networkId = netIdOf(in.netId);
- dnsLookupBatch.eventTypes = bytesToInts(in.eventTypes);
- dnsLookupBatch.returnCodes = bytesToInts(in.returnCodes);
- dnsLookupBatch.latenciesMs = in.latenciesMs;
- out.setDnsLookupBatch(dnsLookupBatch);
- }
-
private static void setIpManagerEvent(IpConnectivityEvent out, IpManagerEvent in) {
IpConnectivityLogClass.IpProvisioningEvent ipProvisioningEvent =
new IpConnectivityLogClass.IpProvisioningEvent();
@@ -268,6 +287,18 @@ final public class IpConnectivityEventBuilder {
return out;
}
+ private static Pair[] toPairArray(SparseIntArray counts) {
+ final int s = counts.size();
+ Pair[] pairs = new Pair[s];
+ for (int i = 0; i < s; i++) {
+ Pair p = new Pair();
+ p.key = counts.keyAt(i);
+ p.value = counts.valueAt(i);
+ pairs[i] = p;
+ }
+ return pairs;
+ }
+
private static NetworkId netIdOf(int netid) {
final NetworkId ni = new NetworkId();
ni.networkId = netid;
diff --git a/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java b/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java
index da56a07d2396..475d786aedd1 100644
--- a/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java
+++ b/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java
@@ -76,7 +76,8 @@ final public class IpConnectivityMetrics extends SystemService {
@VisibleForTesting
public final Impl impl = new Impl();
- private NetdEventListenerService mNetdListener;
+ @VisibleForTesting
+ NetdEventListenerService mNetdListener;
@GuardedBy("mLock")
private ArrayList<ConnectivityMetricsEvent> mBuffer;
diff --git a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
index 7b9c60ca6ef3..214cfced8a3e 100644
--- a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
+++ b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
@@ -18,10 +18,9 @@ package com.android.server.connectivity;
import android.content.Context;
import android.net.ConnectivityManager;
-import android.net.ConnectivityManager.NetworkCallback;
import android.net.INetdEventCallback;
import android.net.Network;
-import android.net.NetworkRequest;
+import android.net.NetworkCapabilities;
import android.net.metrics.ConnectStats;
import android.net.metrics.DnsEvent;
import android.net.metrics.INetdEventListener;
@@ -29,17 +28,17 @@ import android.net.metrics.IpConnectivityLog;
import android.os.RemoteException;
import android.text.format.DateUtils;
import android.util.Log;
+import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.BitUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.TokenBucket;
-import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.ConnectStatistics;
import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityEvent;
import java.io.PrintWriter;
-import java.util.Arrays;
import java.util.List;
-import java.util.SortedMap;
-import java.util.TreeMap;
+import java.util.function.Function;
+import java.util.function.IntFunction;
/**
* Implementation of the INetdEventListener interface.
@@ -52,8 +51,7 @@ public class NetdEventListenerService extends INetdEventListener.Stub {
private static final boolean DBG = false;
private static final boolean VDBG = false;
- // TODO: read this constant from system property
- private static final int MAX_LOOKUPS_PER_DNS_EVENT = 100;
+ private static final int INITIAL_DNS_BATCH_SIZE = 100;
// Rate limit connect latency logging to 1 measurement per 15 seconds (5760 / day) with maximum
// bursts of 5000 measurements.
@@ -61,81 +59,17 @@ public class NetdEventListenerService extends INetdEventListener.Stub {
private static final int CONNECT_LATENCY_FILL_RATE = 15 * (int) DateUtils.SECOND_IN_MILLIS;
private static final int CONNECT_LATENCY_MAXIMUM_RECORDS = 20000;
- // Stores the results of a number of consecutive DNS lookups on the same network.
- // This class is not thread-safe and it is the responsibility of the service to call its methods
- // on one thread at a time.
- private class DnsEventBatch {
- private final int mNetId;
-
- private final byte[] mEventTypes = new byte[MAX_LOOKUPS_PER_DNS_EVENT];
- private final byte[] mReturnCodes = new byte[MAX_LOOKUPS_PER_DNS_EVENT];
- private final int[] mLatenciesMs = new int[MAX_LOOKUPS_PER_DNS_EVENT];
- private int mEventCount;
-
- public DnsEventBatch(int netId) {
- mNetId = netId;
- }
-
- public void addResult(byte eventType, byte returnCode, int latencyMs) {
- mEventTypes[mEventCount] = eventType;
- mReturnCodes[mEventCount] = returnCode;
- mLatenciesMs[mEventCount] = latencyMs;
- mEventCount++;
- if (mEventCount == MAX_LOOKUPS_PER_DNS_EVENT) {
- logAndClear();
- }
- }
-
- public void logAndClear() {
- // Did we lose a race with addResult?
- if (mEventCount == 0) {
- return;
- }
-
- // Only log as many events as we actually have.
- byte[] eventTypes = Arrays.copyOf(mEventTypes, mEventCount);
- byte[] returnCodes = Arrays.copyOf(mReturnCodes, mEventCount);
- int[] latenciesMs = Arrays.copyOf(mLatenciesMs, mEventCount);
- mMetricsLog.log(new DnsEvent(mNetId, eventTypes, returnCodes, latenciesMs));
- maybeLog("Logging %d results for netId %d", mEventCount, mNetId);
- mEventCount = 0;
- }
-
- // For debugging and unit tests only.
- public String toString() {
- return String.format("%s %d %d", getClass().getSimpleName(), mNetId, mEventCount);
- }
- }
-
- // Only sorted for ease of debugging. Because we only typically have a handful of networks up
- // at any given time, performance is not a concern.
+ // Sparse arrays of DNS and connect events, grouped by net id.
+ @GuardedBy("this")
+ private final SparseArray<DnsEvent> mDnsEvents = new SparseArray<>();
@GuardedBy("this")
- private final SortedMap<Integer, DnsEventBatch> mEventBatches = new TreeMap<>();
+ private final SparseArray<ConnectStats> mConnectEvents = new SparseArray<>();
- // We register a NetworkCallback to ensure that when a network disconnects, we flush the DNS
- // queries we've logged on that network. Because we do not do this periodically, we might lose
- // up to MAX_LOOKUPS_PER_DNS_EVENT lookup stats on each network when the system is shutting
- // down. We believe this to be sufficient for now.
private final ConnectivityManager mCm;
- private final IpConnectivityLog mMetricsLog;
- private final NetworkCallback mNetworkCallback = new NetworkCallback() {
- @Override
- public void onLost(Network network) {
- synchronized (NetdEventListenerService.this) {
- DnsEventBatch batch = mEventBatches.remove(network.netId);
- if (batch != null) {
- batch.logAndClear();
- }
- }
- }
- };
@GuardedBy("this")
private final TokenBucket mConnectTb =
new TokenBucket(CONNECT_LATENCY_FILL_RATE, CONNECT_LATENCY_BURST_LIMIT);
- @GuardedBy("this")
- private ConnectStats mConnectStats = makeConnectStats();
-
// Callback should only be registered/unregistered when logging is being enabled/disabled in DPM
// by the device owner. It's DevicePolicyManager's responsibility to ensure that.
@GuardedBy("this")
@@ -152,16 +86,13 @@ public class NetdEventListenerService extends INetdEventListener.Stub {
}
public NetdEventListenerService(Context context) {
- this(context.getSystemService(ConnectivityManager.class), new IpConnectivityLog());
+ this(context.getSystemService(ConnectivityManager.class));
}
@VisibleForTesting
- public NetdEventListenerService(ConnectivityManager cm, IpConnectivityLog log) {
+ public NetdEventListenerService(ConnectivityManager cm) {
// We are started when boot is complete, so ConnectivityService should already be running.
mCm = cm;
- mMetricsLog = log;
- final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
- mCm.registerNetworkCallback(request, mNetworkCallback);
}
@Override
@@ -172,16 +103,16 @@ public class NetdEventListenerService extends INetdEventListener.Stub {
throws RemoteException {
maybeVerboseLog("onDnsEvent(%d, %d, %d, %dms)", netId, eventType, returnCode, latencyMs);
- DnsEventBatch batch = mEventBatches.get(netId);
- if (batch == null) {
- batch = new DnsEventBatch(netId);
- mEventBatches.put(netId, batch);
+ DnsEvent dnsEvent = mDnsEvents.get(netId);
+ if (dnsEvent == null) {
+ dnsEvent = makeDnsEvent(netId);
+ mDnsEvents.put(netId, dnsEvent);
}
- batch.addResult((byte) eventType, (byte) returnCode, latencyMs);
+ dnsEvent.addResult((byte) eventType, (byte) returnCode, latencyMs);
if (mNetdEventCallback != null) {
- mNetdEventCallback.onDnsEvent(hostname, ipAddresses, ipAddressesCount,
- System.currentTimeMillis(), uid);
+ long timestamp = System.currentTimeMillis();
+ mNetdEventCallback.onDnsEvent(hostname, ipAddresses, ipAddressesCount, timestamp, uid);
}
}
@@ -192,7 +123,12 @@ public class NetdEventListenerService extends INetdEventListener.Stub {
int port, int uid) throws RemoteException {
maybeVerboseLog("onConnectEvent(%d, %d, %dms)", netId, error, latencyMs);
- mConnectStats.addEvent(error, latencyMs, ipAddr);
+ ConnectStats connectStats = mConnectEvents.get(netId);
+ if (connectStats == null) {
+ connectStats = makeConnectStats(netId);
+ mConnectEvents.put(netId, connectStats);
+ }
+ connectStats.addEvent(error, latencyMs, ipAddr);
if (mNetdEventCallback != null) {
mNetdEventCallback.onConnectEvent(ipAddr, port, System.currentTimeMillis(), uid);
@@ -200,21 +136,8 @@ public class NetdEventListenerService extends INetdEventListener.Stub {
}
public synchronized void flushStatistics(List<IpConnectivityEvent> events) {
- events.add(flushConnectStats());
- // TODO: migrate DnsEventBatch to IpConnectivityLogClass.DNSLatencies
- }
-
- private IpConnectivityEvent connectStatsProto() {
- // TODO: add transport information
- IpConnectivityEvent ev = new IpConnectivityEvent();
- ev.setConnectStatistics(mConnectStats.toProto());
- return ev;
- }
-
- private IpConnectivityEvent flushConnectStats() {
- IpConnectivityEvent ev = connectStatsProto();
- mConnectStats = makeConnectStats();
- return ev;
+ flushProtos(events, mConnectEvents, IpConnectivityEventBuilder::toProto);
+ flushProtos(events, mDnsEvents, IpConnectivityEventBuilder::toProto);
}
public synchronized void dump(PrintWriter writer) {
@@ -226,18 +149,47 @@ public class NetdEventListenerService extends INetdEventListener.Stub {
}
public synchronized void list(PrintWriter pw) {
- for (DnsEventBatch batch : mEventBatches.values()) {
- pw.println(batch.toString());
- }
- pw.println(mConnectStats.toString());
+ listEvents(pw, mConnectEvents, (x) -> x);
+ listEvents(pw, mDnsEvents, (x) -> x);
}
public synchronized void listAsProtos(PrintWriter pw) {
- pw.println(connectStatsProto().toString());
+ listEvents(pw, mConnectEvents, IpConnectivityEventBuilder::toProto);
+ listEvents(pw, mDnsEvents, IpConnectivityEventBuilder::toProto);
+ }
+
+ private static <T> void flushProtos(List<IpConnectivityEvent> out, SparseArray<T> in,
+ Function<T, IpConnectivityEvent> mapper) {
+ for (int i = 0; i < in.size(); i++) {
+ out.add(mapper.apply(in.valueAt(i)));
+ }
+ in.clear();
}
- private ConnectStats makeConnectStats() {
- return new ConnectStats(mConnectTb, CONNECT_LATENCY_MAXIMUM_RECORDS);
+ public static <T> void listEvents(
+ PrintWriter pw, SparseArray<T> events, Function<T, Object> mapper) {
+ for (int i = 0; i < events.size(); i++) {
+ pw.println(mapper.apply(events.valueAt(i)).toString());
+ }
+ }
+
+ private ConnectStats makeConnectStats(int netId) {
+ long transports = getTransports(netId);
+ return new ConnectStats(netId, transports, mConnectTb, CONNECT_LATENCY_MAXIMUM_RECORDS);
+ }
+
+ private DnsEvent makeDnsEvent(int netId) {
+ long transports = getTransports(netId);
+ return new DnsEvent(netId, transports, INITIAL_DNS_BATCH_SIZE);
+ }
+
+ private long getTransports(int netId) {
+ // TODO: directly query ConnectivityService instead of going through Binder interface.
+ NetworkCapabilities nc = mCm.getNetworkCapabilities(new Network(netId));
+ if (nc == null) {
+ return 0;
+ }
+ return BitUtils.packBits(nc.getTransportTypes());
}
private static void maybeLog(String s, Object... args) {
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index 3e53aca43441..d3c74e6d755a 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -70,6 +70,7 @@ import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.UnknownHostException;
+import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
@@ -90,6 +91,8 @@ public class NetworkMonitor extends StateMachine {
private static final String DEFAULT_HTTP_URL =
"http://connectivitycheck.gstatic.com/generate_204";
private static final String DEFAULT_FALLBACK_URL = "http://www.google.com/gen_204";
+ private static final String DEFAULT_OTHER_FALLBACK_URLS =
+ "http://play.googleapis.com/generate_204";
private static final String DEFAULT_USER_AGENT = "Mozilla/5.0 (X11; Linux x86_64) "
+ "AppleWebKit/537.36 (KHTML, like Gecko) "
+ "Chrome/52.0.2743.82 Safari/537.36";
@@ -263,7 +266,8 @@ public class NetworkMonitor extends StateMachine {
private final String mCaptivePortalUserAgent;
private final URL mCaptivePortalHttpsUrl;
private final URL mCaptivePortalHttpUrl;
- private final URL mCaptivePortalFallbackUrl;
+ private final URL[] mCaptivePortalFallbackUrls;
+ private int mNextFallbackUrlIndex = 0;
public NetworkMonitor(Context context, Handler handler, NetworkAgentInfo networkAgentInfo,
NetworkRequest defaultRequest) {
@@ -302,7 +306,7 @@ public class NetworkMonitor extends StateMachine {
mCaptivePortalUserAgent = getCaptivePortalUserAgent(context);
mCaptivePortalHttpsUrl = makeURL(getCaptivePortalServerHttpsUrl(context));
mCaptivePortalHttpUrl = makeURL(getCaptivePortalServerHttpUrl(context));
- mCaptivePortalFallbackUrl = makeURL(getCaptivePortalFallbackUrl(context));
+ mCaptivePortalFallbackUrls = makeCaptivePortalFallbackUrls(context);
start();
}
@@ -450,7 +454,7 @@ public class NetworkMonitor extends StateMachine {
intent.putExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_URL,
mLastPortalProbeResult.detectUrl);
intent.putExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_USER_AGENT,
- getCaptivePortalUserAgent(mContext));
+ mCaptivePortalUserAgent);
intent.setFlags(
Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivityAsUser(intent, UserHandle.CURRENT);
@@ -666,9 +670,24 @@ public class NetworkMonitor extends StateMachine {
return getSetting(context, Settings.Global.CAPTIVE_PORTAL_HTTP_URL, DEFAULT_HTTP_URL);
}
- private static String getCaptivePortalFallbackUrl(Context context) {
- return getSetting(context,
+ private URL[] makeCaptivePortalFallbackUrls(Context context) {
+ String separator = ",";
+ String firstUrl = getSetting(context,
Settings.Global.CAPTIVE_PORTAL_FALLBACK_URL, DEFAULT_FALLBACK_URL);
+ String joinedUrls = firstUrl + separator + getSetting(context,
+ Settings.Global.CAPTIVE_PORTAL_OTHER_FALLBACK_URLS, DEFAULT_OTHER_FALLBACK_URLS);
+ List<URL> urls = new ArrayList<>();
+ for (String s : joinedUrls.split(separator)) {
+ URL u = makeURL(s);
+ if (u == null) {
+ continue;
+ }
+ urls.add(u);
+ }
+ if (urls.isEmpty()) {
+ Log.e(TAG, String.format("could not create any url from %s", joinedUrls));
+ }
+ return urls.toArray(new URL[urls.size()]);
}
private static String getCaptivePortalUserAgent(Context context) {
@@ -680,6 +699,15 @@ public class NetworkMonitor extends StateMachine {
return value != null ? value : defaultValue;
}
+ private URL nextFallbackUrl() {
+ if (mCaptivePortalFallbackUrls.length == 0) {
+ return null;
+ }
+ int idx = Math.abs(mNextFallbackUrlIndex) % mCaptivePortalFallbackUrls.length;
+ mNextFallbackUrlIndex += new Random().nextInt(); // randomely change url without memory.
+ return mCaptivePortalFallbackUrls[idx];
+ }
+
@VisibleForTesting
protected CaptivePortalProbeResult isCaptivePortal() {
if (!mIsCaptivePortalCheckEnabled) {
@@ -690,7 +718,6 @@ public class NetworkMonitor extends StateMachine {
URL pacUrl = null;
URL httpsUrl = mCaptivePortalHttpsUrl;
URL httpUrl = mCaptivePortalHttpUrl;
- URL fallbackUrl = mCaptivePortalFallbackUrl;
// On networks with a PAC instead of fetching a URL that should result in a 204
// response, we instead simply fetch the PAC script. This is done for a few reasons:
@@ -727,7 +754,7 @@ public class NetworkMonitor extends StateMachine {
if (pacUrl != null) {
result = sendDnsAndHttpProbes(null, pacUrl, ValidationProbeEvent.PROBE_PAC);
} else if (mUseHttps) {
- result = sendParallelHttpProbes(proxyInfo, httpsUrl, httpUrl, fallbackUrl);
+ result = sendParallelHttpProbes(proxyInfo, httpsUrl, httpUrl);
} else {
result = sendDnsAndHttpProbes(proxyInfo, httpUrl, ValidationProbeEvent.PROBE_HTTP);
}
@@ -863,7 +890,7 @@ public class NetworkMonitor extends StateMachine {
}
private CaptivePortalProbeResult sendParallelHttpProbes(
- ProxyInfo proxy, URL httpsUrl, URL httpUrl, URL fallbackUrl) {
+ ProxyInfo proxy, URL httpsUrl, URL httpUrl) {
// Number of probes to wait for. If a probe completes with a conclusive answer
// it shortcuts the latch immediately by forcing the count to 0.
final CountDownLatch latch = new CountDownLatch(2);
@@ -922,7 +949,8 @@ public class NetworkMonitor extends StateMachine {
if (httpsResult.isPortal() || httpsResult.isSuccessful()) {
return httpsResult;
}
- // If a fallback url is specified, use a fallback probe to try again portal detection.
+ // If a fallback url exists, use a fallback probe to try again portal detection.
+ URL fallbackUrl = nextFallbackUrl();
if (fallbackUrl != null) {
CaptivePortalProbeResult result =
sendHttpProbe(fallbackUrl, ValidationProbeEvent.PROBE_FALLBACK);
@@ -1061,7 +1089,7 @@ public class NetworkMonitor extends StateMachine {
}
private void logValidationProbe(long durationMs, int probeType, int probeResult) {
- long transports = mNetworkAgentInfo.networkCapabilities.getTransports();
+ int[] transports = mNetworkAgentInfo.networkCapabilities.getTransportTypes();
boolean isFirstValidation = validationStage().isFirstValidation;
ValidationProbeEvent ev = new ValidationProbeEvent();
ev.probeType = ValidationProbeEvent.makeProbeType(probeType, isFirstValidation);
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 95fb5af37b60..4f29bfa2829e 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -145,6 +145,7 @@ import android.content.res.TypedArray;
import android.database.ContentObserver;
import android.graphics.PixelFormat;
import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
import android.hardware.display.DisplayManager;
import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.HdmiPlaybackClient;
@@ -221,6 +222,7 @@ import android.view.accessibility.AccessibilityManager;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.AnimationUtils;
+import android.widget.ImageView;
import com.android.internal.R;
import com.android.internal.logging.MetricsLogger;
@@ -2809,6 +2811,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
+ overrideConfig + " to starting window resId=" + resId);
context = overrideContext;
}
+ typedArray.recycle();
}
final PhoneWindow win = new PhoneWindow(context);
@@ -2868,6 +2871,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
params.setTitle("Splash Screen " + packageName);
+ addSplashscreenContent(win, context);
+
wm = (WindowManager) context.getSystemService(WINDOW_SERVICE);
view = win.getDecorView();
@@ -2898,6 +2903,24 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return null;
}
+ private void addSplashscreenContent(PhoneWindow win, Context ctx) {
+ final TypedArray a = ctx.obtainStyledAttributes(R.styleable.Window);
+ final int resId = a.getResourceId(R.styleable.Window_windowSplashscreenContent, 0);
+ a.recycle();
+ if (resId == 0) {
+ return;
+ }
+ final Drawable drawable = ctx.getDrawable(resId);
+ if (drawable == null) {
+ return;
+ }
+
+ // We wrap this into a view so the system insets get applied to the drawable.
+ final View v = new View(ctx);
+ v.setBackground(drawable);
+ win.setContentView(v);
+ }
+
/** Obtain proper context for showing splash screen on the provided display. */
private Context getDisplayContext(Context context, int displayId) {
if (displayId == Display.DEFAULT_DISPLAY) {
@@ -5238,7 +5261,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
@Override
public void applyPostLayoutPolicyLw(WindowState win, WindowManager.LayoutParams attrs,
WindowState attached, WindowState imeTarget) {
- final boolean visible = !win.isGoneForLayoutLw();
+ final boolean visible = !win.isGoneForLayoutLw() && win.getAttrs().alpha > 0f;
if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": isVisible=" + visible);
applyKeyguardPolicyLw(win, imeTarget);
final int fl = PolicyControl.getWindowFlags(win, attrs);
diff --git a/services/core/java/com/android/server/wm/BoundsAnimationController.java b/services/core/java/com/android/server/wm/BoundsAnimationController.java
index 2811145bcf5f..f41eed53cbca 100644
--- a/services/core/java/com/android/server/wm/BoundsAnimationController.java
+++ b/services/core/java/com/android/server/wm/BoundsAnimationController.java
@@ -33,6 +33,8 @@ import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.view.WindowManagerInternal;
+import com.android.internal.annotations.VisibleForTesting;
+
/**
* Enables animating bounds of objects.
*
@@ -103,7 +105,8 @@ public class BoundsAnimationController {
com.android.internal.R.interpolator.fast_out_slow_in);
}
- private final class BoundsAnimator extends ValueAnimator
+ @VisibleForTesting
+ final class BoundsAnimator extends ValueAnimator
implements ValueAnimator.AnimatorUpdateListener, ValueAnimator.AnimatorListener {
private final AnimateBoundsUser mTarget;
private final Rect mFrom = new Rect();
@@ -113,10 +116,12 @@ public class BoundsAnimationController {
private final boolean mMoveToFullScreen;
// True if this this animation was cancelled and will be replaced the another animation from
// the same {@link #AnimateBoundsUser} target.
- private boolean mSkipAnimationEnd;
+ private boolean mSkipFinalResize;
// True if this animation replaced a previous animation of the same
// {@link #AnimateBoundsUser} target.
private final boolean mSkipAnimationStart;
+ // True if this animation was cancelled by the user, not as a part of a replacing animation
+ private boolean mSkipAnimationEnd;
// True if this animation is not replacing a previous animation, or if the previous
// animation is animating to a different fullscreen state than the current animation.
// We use this to ensure that we always provide a consistent set/order of callbacks when we
@@ -200,7 +205,11 @@ public class BoundsAnimationController {
// Whoops, the target doesn't feel like animating anymore. Let's immediately finish
// any further animation.
if (DEBUG) Slog.d(TAG, "animateUpdate: cancelled");
- animation.cancel();
+
+ // Since we are cancelling immediately without a replacement animation, send the
+ // animation end to maintain callback parity, but also skip any further resizes
+ prepareCancel(false /* skipAnimationEnd */, true /* skipFinalResize */);
+ cancel();
}
}
@@ -208,7 +217,7 @@ public class BoundsAnimationController {
public void onAnimationEnd(Animator animation) {
if (DEBUG) Slog.d(TAG, "onAnimationEnd: mTarget=" + mTarget
+ " mMoveToFullScreen=" + mMoveToFullScreen
- + " mSkipAnimationEnd=" + mSkipAnimationEnd
+ + " mSkipFinalResize=" + mSkipFinalResize
+ " mFinishAnimationAfterTransition=" + mFinishAnimationAfterTransition
+ " mAppTransitionIsRunning=" + mAppTransition.isRunning());
@@ -222,10 +231,15 @@ public class BoundsAnimationController {
return;
}
+ if (!mSkipFinalResize) {
+ // If not cancelled, resize the pinned stack to the final size. All calls to
+ // setPinnedStackSize() must be done between onAnimationStart() and onAnimationEnd()
+ mTarget.setPinnedStackSize(mTo, null);
+ }
+
finishAnimation();
- mTarget.setPinnedStackSize(mTo, null);
- if (mMoveToFullScreen && !mSkipAnimationEnd) {
+ if (mMoveToFullScreen && !mSkipFinalResize) {
mTarget.moveToFullscreen();
}
}
@@ -235,10 +249,16 @@ public class BoundsAnimationController {
finishAnimation();
}
+ public void prepareCancel(boolean skipAnimationEnd, boolean skipFinalResize) {
+ if (DEBUG) Slog.d(TAG, "prepareCancel: skipAnimationEnd=" + skipAnimationEnd
+ + " skipFinalResize=" + skipFinalResize);
+ mSkipAnimationEnd = skipAnimationEnd;
+ mSkipFinalResize = skipFinalResize;
+ }
+
@Override
public void cancel() {
- mSkipAnimationEnd = true;
- if (DEBUG) Slog.d(TAG, "cancel: willReplace mTarget=" + mTarget);
+ if (DEBUG) Slog.d(TAG, "cancel: mTarget=" + mTarget);
super.cancel();
}
@@ -273,19 +293,15 @@ public class BoundsAnimationController {
public interface AnimateBoundsUser {
/**
- * Asks the target to directly (without any intermediate steps, like scheduling animation)
- * resize its bounds.
- *
- * @return Whether the target still wants to be animated and successfully finished the
- * operation. If it returns false, the animation will immediately be cancelled. The target
- * should return false when something abnormal happened, e.g. it was completely removed
- * from the hierarchy and is not valid anymore.
- */
- boolean setSize(Rect bounds);
- /**
- * Behaves as setSize, but freezes the bounds of any tasks in the target at taskBounds,
+ * Sets the size of the target (without any intermediate steps, like scheduling animation)
+ * but freezes the bounds of any tasks in the target at taskBounds,
* to allow for more flexibility during resizing. Only works for the pinned stack at the
* moment.
+ *
+ * @return Whether the target should continue to be animated and this call was successful.
+ * If false, the animation will be cancelled because the user has determined that the
+ * animation is now invalid and not required. In such a case, the cancel will trigger the
+ * animation end callback as well, but will not send any further size changes.
*/
boolean setPinnedStackSize(Rect bounds, Rect taskBounds);
@@ -310,11 +326,20 @@ public class BoundsAnimationController {
*/
void onAnimationEnd();
+ /**
+ * Callback for the target to inform it to reparent to the fullscreen stack.
+ */
void moveToFullscreen();
}
- void animateBounds(final AnimateBoundsUser target, Rect from, Rect to, int animationDuration,
- boolean moveToFullscreen) {
+ public void animateBounds(final AnimateBoundsUser target, Rect from, Rect to,
+ int animationDuration, boolean moveToFullscreen) {
+ animateBoundsImpl(target, from, to, animationDuration, moveToFullscreen);
+ }
+
+ @VisibleForTesting
+ BoundsAnimator animateBoundsImpl(final AnimateBoundsUser target, Rect from, Rect to,
+ int animationDuration, boolean moveToFullscreen) {
final BoundsAnimator existing = mRunningAnimations.get(target);
final boolean replacing = existing != null;
final boolean animatingToNewFullscreenState = (existing == null) ||
@@ -326,12 +351,15 @@ public class BoundsAnimationController {
if (replacing) {
if (existing.isAnimatingTo(to)) {
- // Just les the current animation complete if it has the same destination as the
+ // Just let the current animation complete if it has the same destination as the
// one we are trying to start.
if (DEBUG) Slog.d(TAG, "animateBounds: same destination as existing=" + existing
+ " ignoring...");
- return;
+ return existing;
}
+ // Since we are replacing, we skip both animation start and end callbacks, and don't
+ // animate to the final bounds when cancelling
+ existing.prepareCancel(true /* skipAnimationEnd */, true /* skipFinalResize */);
existing.cancel();
}
final BoundsAnimator animator = new BoundsAnimator(target, from, to, moveToFullscreen,
@@ -342,5 +370,6 @@ public class BoundsAnimationController {
: DEFAULT_TRANSITION_DURATION) * DEBUG_ANIMATION_SLOW_DOWN_FACTOR);
animator.setInterpolator(mFastOutSlowInInterpolator);
animator.start();
+ return animator;
}
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 2f64cd42e668..058fdae17f9f 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -1420,6 +1420,13 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
changedStackList.add(stack.mStackId);
}
}
+
+ // If there was no pinned stack, we still need to notify the controller of the display info
+ // update as a result of the config change. We do this here to consolidate the flow between
+ // changes when there is and is not a stack.
+ if (getStackById(PINNED_STACK_ID) == null) {
+ mPinnedStackControllerLocked.onDisplayInfoChanged();
+ }
}
@Override
diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java
index 3ce61f027b4c..16848780fe47 100644
--- a/services/core/java/com/android/server/wm/PinnedStackController.java
+++ b/services/core/java/com/android/server/wm/PinnedStackController.java
@@ -147,7 +147,6 @@ class PinnedStackController {
void onConfigurationChanged() {
reloadResources();
- notifyMovementBoundsChanged(false /* fromImeAdjustment */);
}
/**
@@ -241,13 +240,31 @@ class PinnedStackController {
}
/**
+ * In the case where the display rotation is changed but there is no stack, we can't depend on
+ * onTaskStackBoundsChanged() to be called. But we still should update our known display info
+ * with the new state so that we can update SystemUI.
+ */
+ synchronized void onDisplayInfoChanged() {
+ mDisplayInfo.copyFrom(mDisplayContent.getDisplayInfo());
+ notifyMovementBoundsChanged(false /* fromImeAdjustment */);
+ }
+
+ /**
* Updates the display info, calculating and returning the new stack and movement bounds in the
* new orientation of the device if necessary.
*/
- void onTaskStackBoundsChanged(Rect targetBounds, Rect outBounds) {
+ boolean onTaskStackBoundsChanged(Rect targetBounds, Rect outBounds) {
final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
if (mDisplayInfo.equals(displayInfo)) {
- return;
+ // We are already in the right orientation, ignore
+ outBounds.setEmpty();
+ return false;
+ } else if (targetBounds.isEmpty()) {
+ // The stack is null, we are just initializing the stack, so just store the display info
+ // and ignore
+ mDisplayInfo.copyFrom(displayInfo);
+ outBounds.setEmpty();
+ return false;
}
mTmpRect.set(targetBounds);
@@ -272,6 +289,7 @@ class PinnedStackController {
notifyMovementBoundsChanged(false /* fromImeAdjustment */);
outBounds.set(postChangeStackBounds);
+ return true;
}
/**
@@ -371,7 +389,7 @@ class PinnedStackController {
final Rect animatingBounds = mTmpAnimatingBoundsRect;
final TaskStack pinnedStack = mDisplayContent.getStackById(PINNED_STACK_ID);
if (pinnedStack != null) {
- pinnedStack.getAnimatingBounds(animatingBounds);
+ pinnedStack.getAnimationOrCurrentBounds(animatingBounds);
} else {
animatingBounds.set(normalBounds);
}
diff --git a/services/core/java/com/android/server/wm/PinnedStackWindowController.java b/services/core/java/com/android/server/wm/PinnedStackWindowController.java
index 0145454d5ce1..135832e619a4 100644
--- a/services/core/java/com/android/server/wm/PinnedStackWindowController.java
+++ b/services/core/java/com/android/server/wm/PinnedStackWindowController.java
@@ -32,8 +32,8 @@ public class PinnedStackWindowController extends StackWindowController {
private Rect mTmpBoundsRect = new Rect();
- public PinnedStackWindowController(int stackId, StackWindowListener listener, int displayId,
- boolean onTop, Rect outBounds) {
+ public PinnedStackWindowController(int stackId, PinnedStackWindowListener listener,
+ int displayId, boolean onTop, Rect outBounds) {
super(stackId, listener, displayId, onTop, outBounds, WindowManagerService.getInstance());
}
@@ -63,7 +63,7 @@ public class PinnedStackWindowController extends StackWindowController {
final Rect originalBounds = new Rect();
mContainer.getBounds(originalBounds);
- mContainer.setAnimatingBounds(sourceBounds, toBounds);
+ mContainer.setAnimationFinalBounds(sourceBounds, toBounds);
UiThread.getHandler().post(() -> {
if (mContainer == null) {
return;
@@ -84,9 +84,10 @@ public class PinnedStackWindowController extends StackWindowController {
}
final int displayId = mContainer.getDisplayContent().getDisplayId();
- final Rect toBounds = mService.getPictureInPictureBounds(displayId, aspectRatio);
+ final Rect toBounds = mService.getPictureInPictureBounds(displayId, aspectRatio,
+ true /* useExistingStackBounds */);
final Rect targetBounds = new Rect();
- mContainer.getAnimatingBounds(targetBounds);
+ mContainer.getAnimationOrCurrentBounds(targetBounds);
final PinnedStackController pinnedStackController =
mContainer.getDisplayContent().getPinnedStackController();
@@ -117,8 +118,12 @@ public class PinnedStackWindowController extends StackWindowController {
/**
* @return whether the bounds are currently animating to fullscreen.
*/
- public boolean isBoundsAnimatingToFullscreen() {
- return mContainer.isBoundsAnimatingToFullscreen();
+ public boolean isAnimatingBoundsToFullscreen() {
+ return mContainer.isAnimatingBoundsToFullscreen();
+ }
+
+ public boolean pinnedStackResizeAllowed() {
+ return mContainer.pinnedStackResizeAllowed();
}
/**
@@ -132,4 +137,16 @@ public class PinnedStackWindowController extends StackWindowController {
}
return bounds;
}
+
+ /**
+ * The following calls are made from WM to AM.
+ */
+
+ /** Calls directly into activity manager so window manager lock shouldn't held. */
+ public void updatePictureInPictureModeForPinnedStackAnimation(Rect targetStackBounds) {
+ if (mListener != null) {
+ PinnedStackWindowListener listener = (PinnedStackWindowListener) mListener;
+ listener.updatePictureInPictureModeForPinnedStackAnimation(targetStackBounds);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/wm/PinnedStackWindowListener.java b/services/core/java/com/android/server/wm/PinnedStackWindowListener.java
new file mode 100644
index 000000000000..12b9c1f0c552
--- /dev/null
+++ b/services/core/java/com/android/server/wm/PinnedStackWindowListener.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.wm;
+
+import android.graphics.Rect;
+
+/**
+ * Interface used by the creator of {@link PinnedStackWindowController} to listen to changes with
+ * the stack container.
+ */
+public interface PinnedStackWindowListener extends StackWindowListener {
+
+ /**
+ * Called when the stack container pinned stack animation will change the picture-in-picture
+ * mode. This is a direct call into ActivityManager.
+ */
+ default void updatePictureInPictureModeForPinnedStackAnimation(Rect targetStackBounds) {}
+}
diff --git a/services/core/java/com/android/server/wm/StackWindowController.java b/services/core/java/com/android/server/wm/StackWindowController.java
index bf024cfdd7c3..b927e670bc28 100644
--- a/services/core/java/com/android/server/wm/StackWindowController.java
+++ b/services/core/java/com/android/server/wm/StackWindowController.java
@@ -368,13 +368,6 @@ public class StackWindowController
}
}
- /** Calls directly into activity manager so window manager lock shouldn't held. */
- void updatePictureInPictureModeForPinnedStackAnimation(Rect targetStackBounds) {
- if (mListener != null) {
- mListener.updatePictureInPictureModeForPinnedStackAnimation(targetStackBounds);
- }
- }
-
void requestResize(Rect bounds) {
mHandler.obtainMessage(H.REQUEST_RESIZE, bounds).sendToTarget();
}
diff --git a/services/core/java/com/android/server/wm/StackWindowListener.java b/services/core/java/com/android/server/wm/StackWindowListener.java
index a55f9dfa2d60..c763c175687f 100644
--- a/services/core/java/com/android/server/wm/StackWindowListener.java
+++ b/services/core/java/com/android/server/wm/StackWindowListener.java
@@ -26,10 +26,4 @@ public interface StackWindowListener extends WindowContainerListener {
/** Called when the stack container would like its controller to resize. */
void requestResize(Rect bounds);
-
- /**
- * Called when the stack container pinned stack animation will change the picture-in-picture
- * mode. This is a direct call into ActivityManager.
- */
- default void updatePictureInPictureModeForPinnedStackAnimation(Rect targetStackBounds) {}
}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index b816d8199aa6..5c46ca9aa443 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -595,8 +595,7 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU
* we will have a jump at the end.
*/
boolean isFloating() {
- return StackId.tasksAreFloating(mStack.mStackId)
- && !mStack.isBoundsAnimatingToFullscreen();
+ return StackId.tasksAreFloating(mStack.mStackId) && !mStack.isAnimatingBoundsToFullscreen();
}
WindowState getTopVisibleAppMainWindow() {
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 1a67ac73021d..d7c41d335b72 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -77,6 +77,7 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
/** For comparison with DisplayContent bounds. */
private Rect mTmpRect = new Rect();
private Rect mTmpRect2 = new Rect();
+ private Rect mTmpRect3 = new Rect();
/** Content limits relative to the DisplayContent this sits in. */
private Rect mBounds = new Rect();
@@ -125,7 +126,11 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
// perfectly fit the region it would have been cropped to. We may also avoid certain logic we
// would otherwise apply while resizing, while resizing in the bounds animating mode.
private boolean mBoundsAnimating = false;
+ // Set when an animation has been requested but has not yet started from the UI thread. This is
+ // cleared when the animation actually starts.
+ private boolean mBoundsAnimatingRequested = false;
private boolean mBoundsAnimatingToFullscreen = false;
+ private boolean mCancelCurrentBoundsAnimation = false;
private Rect mBoundsAnimationTarget = new Rect();
private Rect mBoundsAnimationSourceBounds = new Rect();
@@ -262,12 +267,6 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
if (mDisplayContent != null) {
mDisplayContent.mDimLayerController.updateDimLayer(this);
- if (mStackId == PINNED_STACK_ID) {
- // Update the bounds based on any changes to the display info
- getAnimatingBounds(mTmpRect2);
- mDisplayContent.mPinnedStackControllerLocked.onTaskStackBoundsChanged(mTmpRect2,
- bounds);
- }
mAnimationBackgroundSurface.setBounds(bounds);
}
@@ -320,10 +319,11 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
}
/**
- * Sets the bounds animation target bounds. This can't currently be done in onAnimationStart()
- * since that is started on the UiThread.
+ * Sets the bounds animation target bounds ahead of an animation. This can't currently be done
+ * in onAnimationStart() since that is started on the UiThread.
*/
- void setAnimatingBounds(Rect sourceBounds, Rect destBounds) {
+ void setAnimationFinalBounds(Rect sourceBounds, Rect destBounds) {
+ mBoundsAnimatingRequested = true;
if (sourceBounds != null) {
mBoundsAnimationSourceBounds.set(sourceBounds);
} else {
@@ -337,23 +337,26 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
}
/**
- * @return the source bounds for the bounds animation.
+ * @return the final bounds for the bounds animation.
*/
- void getAnimatingSourceBounds(Rect outBounds) {
- if (!mBoundsAnimationSourceBounds.isEmpty()) {
- outBounds.set(mBoundsAnimationSourceBounds);
- return;
- }
- outBounds.setEmpty();
+ void getFinalAnimationBounds(Rect outBounds) {
+ outBounds.set(mBoundsAnimationTarget);
}
/**
- * @return the bounds that the task stack is currently being animated towards, or the current
- * stack bounds if there is no animation in progress.
+ * @return the final source bounds for the bounds animation.
*/
- void getAnimatingBounds(Rect outBounds) {
- if (!mBoundsAnimationTarget.isEmpty()) {
- outBounds.set(mBoundsAnimationTarget);
+ void getFinalAnimationSourceBounds(Rect outBounds) {
+ outBounds.set(mBoundsAnimationSourceBounds);
+ }
+
+ /**
+ * @return the final animation bounds if the task stack is currently being animated, or the
+ * current stack bounds otherwise.
+ */
+ void getAnimationOrCurrentBounds(Rect outBounds) {
+ if ((mBoundsAnimatingRequested || mBoundsAnimating) && !mBoundsAnimationTarget.isEmpty()) {
+ getFinalAnimationBounds(outBounds);
return;
}
getBounds(outBounds);
@@ -398,6 +401,24 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
// as it's going away soon anyway.
return false;
}
+
+ if (mStackId == PINNED_STACK_ID) {
+ getAnimationOrCurrentBounds(mTmpRect2);
+ boolean updated = mDisplayContent.mPinnedStackControllerLocked.onTaskStackBoundsChanged(
+ mTmpRect2, mTmpRect3);
+ if (updated) {
+ mBoundsAfterRotation.set(mTmpRect3);
+
+ // Once we've set the bounds based on the rotation of the old bounds in the new
+ // orientation, clear the animation target bounds since they are obsolete, and
+ // cancel any currently running animations
+ mBoundsAnimationTarget.setEmpty();
+ mBoundsAnimationSourceBounds.setEmpty();
+ mCancelCurrentBoundsAnimation = true;
+ return true;
+ }
+ }
+
final int newRotation = getDisplayInfo().rotation;
final int newDensity = getDisplayInfo().logicalDensityDpi;
@@ -413,20 +434,6 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
return false;
}
- if (StackId.tasksAreFloating(mStackId)) {
- // Update stack bounds again since the display info has changed since updateDisplayInfo,
- // however, for floating tasks, we don't need to apply the new rotation to the bounds,
- // we can just update and return them here
- setBounds(mBounds);
- mBoundsAfterRotation.set(mBounds);
-
- // Once we've set the bounds based on the rotation of the old bounds in the new
- // orientation, clear the animation target bounds since they are obsolete
- mBoundsAnimationTarget.setEmpty();
- mBoundsAnimationSourceBounds.setEmpty();
- return true;
- }
-
mTmpRect2.set(mBounds);
mDisplayContent.rotateBounds(mRotation, newRotation, mTmpRect2);
switch (mStackId) {
@@ -692,6 +699,14 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
getStackDockedModeBounds(mTmpRect, bounds, mStackId, mTmpRect2,
mDisplayContent.mDividerControllerLocked.getContentWidth(),
dockedOnTopOrLeft);
+ } else if (mStackId == PINNED_STACK_ID) {
+ // Update the bounds based on any changes to the display info
+ getAnimationOrCurrentBounds(mTmpRect2);
+ boolean updated = mDisplayContent.mPinnedStackControllerLocked.onTaskStackBoundsChanged(
+ mTmpRect2, mTmpRect3);
+ if (updated) {
+ bounds = new Rect(mTmpRect3);
+ }
}
updateDisplayInfo(bounds);
@@ -1443,21 +1458,11 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
}
}
- @Override // AnimatesBounds
- public boolean setSize(Rect bounds) {
- synchronized (mService.mWindowMap) {
- if (mDisplayContent == null) {
- return false;
- }
- }
- try {
- mService.mActivityManager.resizeStack(mStackId, bounds, false, true, false, -1);
- } catch (RemoteException e) {
+ public boolean setPinnedStackSize(Rect bounds, Rect tempTaskBounds) {
+ if (mCancelCurrentBoundsAnimation) {
+ return false;
}
- return true;
- }
- public boolean setPinnedStackSize(Rect bounds, Rect tempTaskBounds) {
try {
mService.mActivityManager.resizePinnedStack(bounds, tempTaskBounds);
} catch (RemoteException e) {
@@ -1469,8 +1474,10 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
@Override // AnimatesBounds
public void onAnimationStart(boolean toFullscreen) {
synchronized (mService.mWindowMap) {
+ mBoundsAnimatingRequested = false;
mBoundsAnimating = true;
mBoundsAnimatingToFullscreen = toFullscreen;
+ mCancelCurrentBoundsAnimation = false;
}
if (mStackId == PINNED_STACK_ID) {
@@ -1484,7 +1491,8 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
@Override // AnimatesBounds
public void updatePictureInPictureMode(Rect targetStackBounds) {
- final StackWindowController controller = getController();
+ final PinnedStackWindowController controller =
+ (PinnedStackWindowController) getController();
if (controller != null) {
controller.updatePictureInPictureModeForPinnedStackAnimation(targetStackBounds);
}
@@ -1523,14 +1531,21 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
return mBoundsAnimating;
}
- public boolean getBoundsAnimating() {
+ public boolean isAnimatingBounds() {
return mBoundsAnimating;
}
- public boolean isBoundsAnimatingToFullscreen() {
+ public boolean isAnimatingBoundsToFullscreen() {
return mBoundsAnimating && mBoundsAnimatingToFullscreen;
}
+ public boolean pinnedStackResizeAllowed() {
+ if (mBoundsAnimating && mCancelCurrentBoundsAnimation) {
+ return true;
+ }
+ return false;
+ }
+
/** Returns true if a removal action is still being deferred. */
boolean checkCompleteDeferredRemoval() {
if (isAnimating()) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 0f4707e56164..0049585f5c52 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -31,7 +31,6 @@ import static android.os.Process.SHELL_UID;
import static android.os.Process.SYSTEM_UID;
import static android.os.Process.THREAD_PRIORITY_DISPLAY;
import static android.os.Process.myPid;
-import static android.os.Process.myTid;
import static android.os.UserHandle.USER_NULL;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.DOCKED_INVALID;
@@ -148,7 +147,6 @@ import android.os.ParcelFileDescriptor;
import android.os.PowerManager;
import android.os.PowerManagerInternal;
import android.os.PowerSaveState;
-import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.StrictMode;
@@ -2758,7 +2756,12 @@ public class WindowManagerService extends IWindowManager.Stub
mDockedStackCreateBounds = bounds;
}
- public Rect getPictureInPictureBounds(int displayId, float aspectRatio) {
+ /**
+ * @param useExistingStackBounds Apply {@param aspectRatio} to the existing target stack bounds
+ * if possible
+ */
+ public Rect getPictureInPictureBounds(int displayId, float aspectRatio,
+ boolean useExistingStackBounds) {
synchronized (mWindowMap) {
if (!mSupportsPictureInPicture) {
return null;
@@ -2773,11 +2776,11 @@ public class WindowManagerService extends IWindowManager.Stub
final PinnedStackController pinnedStackController =
displayContent.getPinnedStackController();
final TaskStack stack = displayContent.getStackById(PINNED_STACK_ID);
- if (stack != null) {
+ if (stack != null && useExistingStackBounds) {
// If the stack exists, then use its final bounds to calculate the new aspect ratio
// bounds.
stackBounds = new Rect();
- stack.getAnimatingBounds(stackBounds);
+ stack.getAnimationOrCurrentBounds(stackBounds);
} else {
// Otherwise, just calculate the aspect ratio bounds from the default bounds
stackBounds = pinnedStackController.getDefaultBounds();
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 979af7e35614..0b96f3fbc1fc 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1090,7 +1090,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
// notify the client of frame changes in this case. Not only is it a lot of churn, but
// the frame may not correspond to the surface size or the onscreen area at various
// phases in the animation, and the client will become sad and confused.
- if (task != null && task.mStack.getBoundsAnimating()) {
+ if (task != null && task.mStack.isAnimatingBounds()) {
return;
}
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index ae17d086611d..fa353367c6e4 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -1360,11 +1360,11 @@ class WindowStateAnimator {
int posX = mTmpSize.left;
int posY = mTmpSize.top;
task.mStack.getDimBounds(mTmpStackBounds);
- task.mStack.getAnimatingSourceBounds(mTmpSourceBounds);
+ task.mStack.getFinalAnimationSourceBounds(mTmpSourceBounds);
if (!mTmpSourceBounds.isEmpty()) {
// Get the final target stack bounds, if we are not animating, this is just the
// current stack bounds
- task.mStack.getAnimatingBounds(mTmpAnimatingBounds);
+ task.mStack.getFinalAnimationBounds(mTmpAnimatingBounds);
// Calculate the current progress and interpolate the difference between the target
// and source bounds
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 67f1a0a5c658..42a92327bd4e 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -981,6 +981,11 @@ public final class SystemServer {
traceBeginAndSlog("StartPersistentDataBlock");
mSystemServiceManager.startService(PersistentDataBlockService.class);
traceEnd();
+
+ // Implementation depends on persistent data block
+ traceBeginAndSlog("StartOemLockService");
+ mSystemServiceManager.startService(OemLockService.class);
+ traceEnd();
}
traceBeginAndSlog("StartDeviceIdleController");
diff --git a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
index 00f6273d14bf..20839c5f7a18 100644
--- a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
@@ -117,6 +117,7 @@ public class AccountManagerServiceTest extends AndroidTestCase {
@Captor private ArgumentCaptor<Bundle> mBundleCaptor;
private int mVisibleAccountsChangedBroadcasts;
private int mLoginAccountsChangedBroadcasts;
+ private int mAccountRemovedBroadcasts;
private static final int LATCH_TIMEOUT_MS = 500;
private static final String PREN_DB = "pren.db";
@@ -2510,6 +2511,7 @@ public class AccountManagerServiceTest extends AndroidTestCase {
updateBroadcastCounters(2);
assertEquals(mVisibleAccountsChangedBroadcasts, 0); // broadcast was not sent
assertEquals(mLoginAccountsChangedBroadcasts, 2);
+ assertEquals(mAccountRemovedBroadcasts, 0);
}
@SmallTest
@@ -2533,9 +2535,10 @@ public class AccountManagerServiceTest extends AndroidTestCase {
mAms.registerAccountListener( null /* accountTypes */, "testpackage");
mAms.removeAccountInternal(AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE);
- updateBroadcastCounters(6);
+ updateBroadcastCounters(8);
assertEquals(mVisibleAccountsChangedBroadcasts, 2);
assertEquals(mLoginAccountsChangedBroadcasts, 4);
+ assertEquals(mAccountRemovedBroadcasts, 2);
}
@SmallTest
@@ -2560,17 +2563,19 @@ public class AccountManagerServiceTest extends AndroidTestCase {
"testpackage3"); // opPackageName
// Remove account with 2 active listeners.
mAms.removeAccountInternal(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS);
- updateBroadcastCounters(7);
+ updateBroadcastCounters(8);
assertEquals(mVisibleAccountsChangedBroadcasts, 5);
assertEquals(mLoginAccountsChangedBroadcasts, 2); // 3 add, 2 remove
+ assertEquals(mAccountRemovedBroadcasts, 1);
// Add account of another type.
mAms.addAccountExplicitly(
AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS_TYPE_2, "p11", null);
- updateBroadcastCounters(8);
+ updateBroadcastCounters(9);
assertEquals(mVisibleAccountsChangedBroadcasts, 5);
assertEquals(mLoginAccountsChangedBroadcasts, 3);
+ assertEquals(mAccountRemovedBroadcasts, 1);
}
@SmallTest
@@ -2602,16 +2607,20 @@ public class AccountManagerServiceTest extends AndroidTestCase {
private void updateBroadcastCounters (int expectedBroadcasts){
mVisibleAccountsChangedBroadcasts = 0;
mLoginAccountsChangedBroadcasts = 0;
+ mAccountRemovedBroadcasts = 0;
ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
verify(mMockContext, times(expectedBroadcasts)).sendBroadcastAsUser(captor.capture(),
any(UserHandle.class));
for (Intent intent : captor.getAllValues()) {
- if (AccountManager.ACTION_VISIBLE_ACCOUNTS_CHANGED. equals(intent.getAction())) {
+ if (AccountManager.ACTION_VISIBLE_ACCOUNTS_CHANGED.equals(intent.getAction())) {
mVisibleAccountsChangedBroadcasts++;
}
- if (AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION. equals(intent.getAction())) {
+ if (AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION.equals(intent.getAction())) {
mLoginAccountsChangedBroadcasts++;
}
+ if (AccountManager.ACTION_ACCOUNT_REMOVED.equals(intent.getAction())) {
+ mAccountRemovedBroadcasts++;
+ }
}
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/BoundsAnimationControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/BoundsAnimationControllerTests.java
new file mode 100644
index 000000000000..85dc7125e3cc
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/wm/BoundsAnimationControllerTests.java
@@ -0,0 +1,348 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.wm;
+
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.graphics.Rect;
+import android.os.Handler;
+import android.os.Looper;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.annotation.UiThreadTest;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.WindowManagerInternal.AppTransitionListener;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import com.android.server.wm.BoundsAnimationController.BoundsAnimator;
+
+/**
+ * Test class for {@link BoundsAnimationController} to ensure that it sends the right callbacks
+ * depending on the various interactions.
+ *
+ * Build/Install/Run:
+ * bit FrameworksServicesTests:com.android.server.wm.BoundsAnimationControllerTests
+ */
+@SmallTest
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class BoundsAnimationControllerTests extends WindowTestsBase {
+
+ /**
+ * Mock value animator to simulate updates with.
+ */
+ private class MockValueAnimator extends ValueAnimator {
+
+ private float mFraction;
+
+ public MockValueAnimator getWithValue(float fraction) {
+ mFraction = fraction;
+ return this;
+ }
+
+ @Override
+ public Object getAnimatedValue() {
+ return mFraction;
+ }
+ }
+
+ /**
+ * Mock app transition to fire notifications to the bounds animator.
+ */
+ private class MockAppTransition extends AppTransition {
+
+ private AppTransitionListener mListener;
+
+ MockAppTransition(Context context) {
+ super(context, null);
+ }
+
+ @Override
+ void registerListenerLocked(AppTransitionListener listener) {
+ mListener = listener;
+ }
+
+ public void notifyTransitionPending() {
+ mListener.onAppTransitionPendingLocked();
+ }
+
+ public void notifyTransitionCancelled(int transit) {
+ mListener.onAppTransitionCancelledLocked(transit);
+ }
+
+ public void notifyTransitionStarting(int transit) {
+ mListener.onAppTransitionStartingLocked(transit, null, null, null, null);
+ }
+
+ public void notifyTransitionFinished() {
+ mListener.onAppTransitionFinishedLocked(null);
+ }
+ }
+
+ /**
+ * A test animate bounds user to track callbacks from the bounds animation.
+ */
+ private class TestAnimateBoundsUser implements BoundsAnimationController.AnimateBoundsUser {
+
+ boolean mMovedToFullscreen;
+ boolean mAnimationStarted;
+ boolean mAnimationStartedToFullscreen;
+ boolean mAnimationEnded;
+ boolean mUpdatedPictureInPictureModeWithBounds;
+ boolean mBoundsUpdated;
+ Rect mStackBounds;
+ Rect mTaskBounds;
+
+ boolean mRequestCancelAnimation = false;
+
+ void reinitialize(Rect stackBounds, Rect taskBounds) {
+ mMovedToFullscreen = false;
+ mAnimationStarted = false;
+ mAnimationStartedToFullscreen = false;
+ mAnimationEnded = false;
+ mUpdatedPictureInPictureModeWithBounds = false;
+ mStackBounds = stackBounds;
+ mTaskBounds = taskBounds;
+ mBoundsUpdated = false;
+ mRequestCancelAnimation = false;
+ }
+
+ @Override
+ public void onAnimationStart(boolean toFullscreen) {
+ mAnimationStarted = true;
+ mAnimationStartedToFullscreen = toFullscreen;
+ }
+
+ @Override
+ public void updatePictureInPictureMode(Rect targetStackBounds) {
+ mUpdatedPictureInPictureModeWithBounds = true;
+ }
+
+ @Override
+ public boolean setPinnedStackSize(Rect stackBounds, Rect taskBounds) {
+ // TODO: Once we break the runs apart, we should fail() here if this is called outside
+ // of onAnimationStart() and onAnimationEnd()
+ if (mRequestCancelAnimation) {
+ return false;
+ } else {
+ mBoundsUpdated = true;
+ mStackBounds = stackBounds;
+ mTaskBounds = taskBounds;
+ return true;
+ }
+ }
+
+ @Override
+ public void onAnimationEnd() {
+ mAnimationEnded = true;
+ }
+
+ @Override
+ public void moveToFullscreen() {
+ mMovedToFullscreen = true;
+ }
+ }
+
+ // Constants
+ private static final boolean MOVE_TO_FULLSCREEN = true;
+
+ // Some dummy bounds to represent fullscreen and floating bounds
+ private static final Rect BOUNDS_FULL = new Rect(0, 0, 100, 100);
+ private static final Rect BOUNDS_FLOATING = new Rect(80, 80, 95, 95);
+ private static final Rect BOUNDS_ALT_FLOATING = new Rect(60, 60, 95, 95);
+
+ // Some dummy duration
+ private static final int DURATION = 100;
+
+ // Common
+ private MockAppTransition mAppTransition;
+ private MockValueAnimator mAnimator;
+ private TestAnimateBoundsUser mTarget;
+ private BoundsAnimationController mController;
+
+ // Temp
+ private Rect mTmpRect = new Rect();
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+
+ final Context context = InstrumentationRegistry.getTargetContext();
+ final Handler handler = new Handler(Looper.getMainLooper());
+ mAppTransition = new MockAppTransition(context);
+ mAnimator = new MockValueAnimator();
+ mTarget = new TestAnimateBoundsUser();
+ mController = new BoundsAnimationController(context, mAppTransition, handler);
+ }
+
+ @UiThreadTest
+ @Test
+ public void testFullscreenToFloatingTransition() throws Exception {
+ // Create and start the animation
+ mTarget.reinitialize(BOUNDS_FULL, null);
+ final BoundsAnimator boundsAnimator = mController.animateBoundsImpl(mTarget, BOUNDS_FULL,
+ BOUNDS_FLOATING, DURATION, !MOVE_TO_FULLSCREEN);
+
+ // Assert that when we are started, and that we are not going to fullscreen
+ assertTrue(mTarget.mAnimationStarted);
+ assertFalse(mTarget.mAnimationStartedToFullscreen);
+ // Ensure we are not triggering a PiP mode change
+ assertFalse(mTarget.mUpdatedPictureInPictureModeWithBounds);
+ // Ensure that the task stack bounds are already frozen to the larger source stack bounds
+ assertEquals(BOUNDS_FULL, mTarget.mStackBounds);
+ assertEquals(BOUNDS_FULL, offsetToZero(mTarget.mTaskBounds));
+
+ // Drive some animation updates, ensure that only the stack bounds change and the task
+ // bounds are frozen to the original stack bounds (adjusted for the offset)
+ boundsAnimator.onAnimationUpdate(mAnimator.getWithValue(0.5f));
+ assertNotEquals(BOUNDS_FULL, mTarget.mStackBounds);
+ assertEquals(BOUNDS_FULL, offsetToZero(mTarget.mTaskBounds));
+ boundsAnimator.onAnimationUpdate(mAnimator.getWithValue(1f));
+ assertNotEquals(BOUNDS_FULL, mTarget.mStackBounds);
+ assertEquals(BOUNDS_FULL, offsetToZero(mTarget.mTaskBounds));
+
+ // Finish the animation, ensure that it reaches the final bounds with the given state
+ boundsAnimator.end();
+ assertTrue(mTarget.mAnimationEnded);
+ assertEquals(BOUNDS_FLOATING, mTarget.mStackBounds);
+ assertNull(mTarget.mTaskBounds);
+ }
+
+ @UiThreadTest
+ @Test
+ public void testFloatingToFullscreenTransition() throws Exception {
+ // Create and start the animation
+ mTarget.reinitialize(BOUNDS_FULL, null);
+ final BoundsAnimator boundsAnimator = mController.animateBoundsImpl(mTarget, BOUNDS_FLOATING,
+ BOUNDS_FULL, DURATION, MOVE_TO_FULLSCREEN);
+
+ // Assert that when we are started, and that we are going to fullscreen
+ assertTrue(mTarget.mAnimationStarted);
+ assertTrue(mTarget.mAnimationStartedToFullscreen);
+ // Ensure that we update the PiP mode change with the new fullscreen bounds
+ assertTrue(mTarget.mUpdatedPictureInPictureModeWithBounds);
+ // Ensure that the task stack bounds are already frozen to the larger target stack bounds
+ assertEquals(BOUNDS_FLOATING, mTarget.mStackBounds);
+ assertEquals(BOUNDS_FULL, offsetToZero(mTarget.mTaskBounds));
+
+ // Drive some animation updates, ensure that only the stack bounds change and the task
+ // bounds are frozen to the original stack bounds (adjusted for the offset)
+ boundsAnimator.onAnimationUpdate(mAnimator.getWithValue(0.5f));
+ assertNotEquals(BOUNDS_FLOATING, mTarget.mStackBounds);
+ assertEquals(BOUNDS_FULL, offsetToZero(mTarget.mTaskBounds));
+ boundsAnimator.onAnimationUpdate(mAnimator.getWithValue(1f));
+ assertNotEquals(BOUNDS_FLOATING, mTarget.mStackBounds);
+ assertEquals(BOUNDS_FULL, offsetToZero(mTarget.mTaskBounds));
+
+ // Finish the animation, ensure that it reaches the final bounds with the given state
+ boundsAnimator.end();
+ assertTrue(mTarget.mAnimationEnded);
+ assertEquals(BOUNDS_FULL, mTarget.mStackBounds);
+ assertNull(mTarget.mTaskBounds);
+ }
+
+ @UiThreadTest
+ @Test
+ public void testInterruptAnimationFromUser() throws Exception {
+ // Create and start the animation
+ mTarget.reinitialize(BOUNDS_FULL, null);
+ final BoundsAnimator boundsAnimator = mController.animateBoundsImpl(mTarget, BOUNDS_FULL,
+ BOUNDS_FLOATING, DURATION, !MOVE_TO_FULLSCREEN);
+
+ // Cancel the animation on the next update from the user
+ mTarget.mRequestCancelAnimation = true;
+ mTarget.mBoundsUpdated = false;
+ boundsAnimator.onAnimationUpdate(mAnimator.getWithValue(0.5f));
+ // Ensure that we got no more updates after returning false and the bounds are not updated
+ // to the end value
+ assertFalse(mTarget.mBoundsUpdated);
+ assertNotEquals(BOUNDS_FLOATING, mTarget.mStackBounds);
+ assertNotEquals(BOUNDS_FLOATING, mTarget.mTaskBounds);
+ // Ensure that we received the animation end call
+ assertTrue(mTarget.mAnimationEnded);
+ }
+
+ @UiThreadTest
+ @Test
+ public void testCancelAnimationFromNewAnimationToExistingBounds() throws Exception {
+ // Create and start the animation
+ mTarget.reinitialize(BOUNDS_FULL, null);
+ final BoundsAnimator boundsAnimator = mController.animateBoundsImpl(mTarget, BOUNDS_FULL,
+ BOUNDS_FLOATING, DURATION, !MOVE_TO_FULLSCREEN);
+
+ // Drive some animation updates
+ boundsAnimator.onAnimationUpdate(mAnimator.getWithValue(0.5f));
+
+ // Cancel the animation as a restart to the same bounds
+ mTarget.reinitialize(null, null);
+ final BoundsAnimator altBoundsAnimator = mController.animateBoundsImpl(mTarget, BOUNDS_FULL,
+ BOUNDS_FLOATING, DURATION, !MOVE_TO_FULLSCREEN);
+ // Ensure the animator is the same
+ assertSame(boundsAnimator, altBoundsAnimator);
+ // Ensure we haven't restarted or finished the animation
+ assertFalse(mTarget.mAnimationStarted);
+ assertFalse(mTarget.mAnimationEnded);
+ // Ensure that we haven't tried to update the PiP mode
+ assertFalse(mTarget.mUpdatedPictureInPictureModeWithBounds);
+ }
+
+ @UiThreadTest
+ @Test
+ public void testCancelAnimationFromNewAnimationToNewBounds() throws Exception {
+ // Create and start the animation
+ mTarget.reinitialize(BOUNDS_FULL, null);
+ final BoundsAnimator boundsAnimator = mController.animateBoundsImpl(mTarget, BOUNDS_FULL,
+ BOUNDS_FLOATING, DURATION, !MOVE_TO_FULLSCREEN);
+
+ // Drive some animation updates
+ boundsAnimator.onAnimationUpdate(mAnimator.getWithValue(0.5f));
+
+ // Cancel the animation as a restart to new bounds
+ mTarget.reinitialize(null, null);
+ final BoundsAnimator altBoundsAnimator = mController.animateBoundsImpl(mTarget, BOUNDS_FULL,
+ BOUNDS_ALT_FLOATING, DURATION, !MOVE_TO_FULLSCREEN);
+ // Ensure the animator is not the same
+ assertNotSame(boundsAnimator, altBoundsAnimator);
+ // Ensure that we did not get an animation start/end callback
+ assertFalse(mTarget.mAnimationStarted);
+ assertFalse(mTarget.mAnimationEnded);
+ // Ensure that we haven't tried to update the PiP mode
+ assertFalse(mTarget.mUpdatedPictureInPictureModeWithBounds);
+ }
+
+ /**
+ * @return the bounds offset to zero/zero.
+ */
+ private Rect offsetToZero(Rect bounds) {
+ mTmpRect.set(bounds);
+ mTmpRect.offsetTo(0, 0);
+ return mTmpRect;
+ }
+}
diff --git a/services/usb/Android.mk b/services/usb/Android.mk
index f560e71ebe6a..f6d212bccd1c 100644
--- a/services/usb/Android.mk
+++ b/services/usb/Android.mk
@@ -8,7 +8,7 @@ LOCAL_SRC_FILES += \
$(call all-java-files-under,java)
LOCAL_JAVA_LIBRARIES := services.core
-LOCAL_STATIC_JAVA_LIBRARIES := android.hardware.usb@1.0-java-static \
-android.hidl.manager@1.0-java-static
+LOCAL_STATIC_JAVA_LIBRARIES := android.hardware.usb-V1.0-java-static \
+android.hidl.manager-V1.0-java-static
include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index d60f25cb4db3..397aa0020d13 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -2710,19 +2710,12 @@ public class TelephonyManager {
* @param phoneAccountHandle the phone account to change the client state
* @param enabled the new state of the client
* @hide
+ * @deprecated Visual voicemail no longer in telephony. {@link VisualVoicemailService} should
+ * be implemented instead.
*/
@SystemApi
public void setVisualVoicemailEnabled(PhoneAccountHandle phoneAccountHandle, boolean enabled){
- try {
- ITelephony telephony = getITelephony();
- if (telephony != null) {
- telephony.setVisualVoicemailEnabled(mContext.getOpPackageName(), phoneAccountHandle,
- enabled);
- }
- } catch (RemoteException ex) {
- } catch (NullPointerException ex) {
- // This could happen before phone restarts due to crashing
- }
+
}
/**
@@ -2734,19 +2727,11 @@ public class TelephonyManager {
* @param phoneAccountHandle the phone account to check for.
* @return {@code true} when the visual voicemail client is enabled for this client
* @hide
+ * @deprecated Visual voicemail no longer in telephony. {@link VisualVoicemailService} should
+ * be implemented instead.
*/
@SystemApi
public boolean isVisualVoicemailEnabled(PhoneAccountHandle phoneAccountHandle){
- try {
- ITelephony telephony = getITelephony();
- if (telephony != null) {
- return telephony.isVisualVoicemailEnabled(
- mContext.getOpPackageName(), phoneAccountHandle);
- }
- } catch (RemoteException ex) {
- } catch (NullPointerException ex) {
- // This could happen before phone restarts due to crashing
- }
return false;
}
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index b461a7824965..dd08f67c9617 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -498,12 +498,6 @@ interface ITelephony {
*/
boolean isConcurrentVoiceAndDataAllowed(int subId);
- oneway void setVisualVoicemailEnabled(String callingPackage,
- in PhoneAccountHandle accountHandle, boolean enabled);
-
- boolean isVisualVoicemailEnabled(String callingPackage,
- in PhoneAccountHandle accountHandle);
-
String getVisualVoicemailPackageName(String callingPackage, int subId);
// Not oneway, caller needs to make sure the vaule is set before receiving a SMS
diff --git a/tests/ActivityTests/AndroidManifest.xml b/tests/ActivityTests/AndroidManifest.xml
index 64cdcf78fdcc..b381cbfbd0a9 100644
--- a/tests/ActivityTests/AndroidManifest.xml
+++ b/tests/ActivityTests/AndroidManifest.xml
@@ -87,5 +87,13 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
+ <activity android:name="CustomSplashscreenActivity"
+ android:label="CustomSplashscreen"
+ android:theme="@style/CustomSplashscreen">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
</application>
</manifest>
diff --git a/tests/ActivityTests/res/drawable/splashscreen.xml b/tests/ActivityTests/res/drawable/splashscreen.xml
new file mode 100644
index 000000000000..01fb6462fd95
--- /dev/null
+++ b/tests/ActivityTests/res/drawable/splashscreen.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2017 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>
+ <bitmap
+ android:gravity="center"
+ android:src="@drawable/icon"/>
+ </item>
+</layer-list> \ No newline at end of file
diff --git a/tests/ActivityTests/res/values/themes.xml b/tests/ActivityTests/res/values/themes.xml
index b8dd83039ed8..c11d2e48834a 100644
--- a/tests/ActivityTests/res/values/themes.xml
+++ b/tests/ActivityTests/res/values/themes.xml
@@ -26,4 +26,7 @@
<item name="android:colorBackground">@color/blue</item>
<item name="android:windowBackground">@color/blue</item>
</style>
+ <style name="CustomSplashscreen" parent="@android:style/Theme.Material.Light.NoActionBar">
+ <item name="android:windowSplashscreenContent">@drawable/splashscreen</item>
+ </style>
</resources>
diff --git a/tests/ActivityTests/src/com/google/android/test/activity/CustomSplashscreenActivity.java b/tests/ActivityTests/src/com/google/android/test/activity/CustomSplashscreenActivity.java
new file mode 100644
index 000000000000..0683df6d649f
--- /dev/null
+++ b/tests/ActivityTests/src/com/google/android/test/activity/CustomSplashscreenActivity.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2017 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.google.android.test.activity;
+
+import android.annotation.Nullable;
+import android.app.Activity;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.os.SystemClock;
+
+/**
+ * Activity for which we set a custom splash screen.
+ */
+public class CustomSplashscreenActivity extends Activity {
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ SystemClock.sleep(2000);
+ }
+}
diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
index d819b9642e0c..d11565abb917 100644
--- a/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
+++ b/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
@@ -45,7 +45,9 @@ import android.net.metrics.NetworkEvent;
import android.net.metrics.RaEvent;
import android.net.metrics.ValidationProbeEvent;
import android.test.suitebuilder.annotation.SmallTest;
+import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityEvent;
import java.util.Arrays;
+import java.util.List;
import junit.framework.TestCase;
// TODO: instead of comparing textpb to textpb, parse textpb and compare proto to proto.
@@ -57,7 +59,7 @@ public class IpConnectivityEventBuilderTest extends TestCase {
aType(IpReachabilityEvent.class),
anInt(IpReachabilityEvent.NUD_FAILED));
- String want = joinLines(
+ String want = String.join("\n",
"dropped_events: 0",
"events <",
" if_name: \"\"",
@@ -70,13 +72,13 @@ public class IpConnectivityEventBuilderTest extends TestCase {
" if_name: \"\"",
" >",
">",
- "version: 2");
+ "version: 2\n");
verifySerialization(want, ev);
ev.netId = 123;
ev.transports = 3; // transports have priority for inferrence of link layer
ev.ifname = "wlan0";
- want = joinLines(
+ want = String.join("\n",
"dropped_events: 0",
"events <",
" if_name: \"\"",
@@ -89,12 +91,12 @@ public class IpConnectivityEventBuilderTest extends TestCase {
" if_name: \"\"",
" >",
">",
- "version: 2");
+ "version: 2\n");
verifySerialization(want, ev);
ev.transports = 1;
ev.ifname = null;
- want = joinLines(
+ want = String.join("\n",
"dropped_events: 0",
"events <",
" if_name: \"\"",
@@ -107,12 +109,12 @@ public class IpConnectivityEventBuilderTest extends TestCase {
" if_name: \"\"",
" >",
">",
- "version: 2");
+ "version: 2\n");
verifySerialization(want, ev);
ev.transports = 0;
ev.ifname = "not_inferred";
- want = joinLines(
+ want = String.join("\n",
"dropped_events: 0",
"events <",
" if_name: \"not_inferred\"",
@@ -125,11 +127,11 @@ public class IpConnectivityEventBuilderTest extends TestCase {
" if_name: \"\"",
" >",
">",
- "version: 2");
+ "version: 2\n");
verifySerialization(want, ev);
ev.ifname = "bt-pan";
- want = joinLines(
+ want = String.join("\n",
"dropped_events: 0",
"events <",
" if_name: \"\"",
@@ -142,11 +144,11 @@ public class IpConnectivityEventBuilderTest extends TestCase {
" if_name: \"\"",
" >",
">",
- "version: 2");
+ "version: 2\n");
verifySerialization(want, ev);
ev.ifname = "rmnet_ipa0";
- want = joinLines(
+ want = String.join("\n",
"dropped_events: 0",
"events <",
" if_name: \"\"",
@@ -159,11 +161,11 @@ public class IpConnectivityEventBuilderTest extends TestCase {
" if_name: \"\"",
" >",
">",
- "version: 2");
+ "version: 2\n");
verifySerialization(want, ev);
ev.ifname = "wlan0";
- want = joinLines(
+ want = String.join("\n",
"dropped_events: 0",
"events <",
" if_name: \"\"",
@@ -176,7 +178,7 @@ public class IpConnectivityEventBuilderTest extends TestCase {
" if_name: \"\"",
" >",
">",
- "version: 2");
+ "version: 2\n");
verifySerialization(want, ev);
}
@@ -190,7 +192,7 @@ public class IpConnectivityEventBuilderTest extends TestCase {
aBool(true),
aBool(false));
- String want = joinLines(
+ String want = String.join("\n",
"dropped_events: 0",
"events <",
" if_name: \"\"",
@@ -211,7 +213,7 @@ public class IpConnectivityEventBuilderTest extends TestCase {
" transport_types: 3",
" >",
">",
- "version: 2");
+ "version: 2\n");
verifySerialization(want, ev);
}
@@ -223,7 +225,7 @@ public class IpConnectivityEventBuilderTest extends TestCase {
aString("SomeState"),
anInt(192));
- String want = joinLines(
+ String want = String.join("\n",
"dropped_events: 0",
"events <",
" if_name: \"\"",
@@ -237,7 +239,7 @@ public class IpConnectivityEventBuilderTest extends TestCase {
" state_transition: \"SomeState\"",
" >",
">",
- "version: 2");
+ "version: 2\n");
verifySerialization(want, ev);
}
@@ -248,7 +250,7 @@ public class IpConnectivityEventBuilderTest extends TestCase {
aType(DhcpErrorEvent.class),
anInt(DhcpErrorEvent.L4_NOT_UDP));
- String want = joinLines(
+ String want = String.join("\n",
"dropped_events: 0",
"events <",
" if_name: \"\"",
@@ -262,59 +264,7 @@ public class IpConnectivityEventBuilderTest extends TestCase {
" error_code: 50397184",
" >",
">",
- "version: 2");
-
- verifySerialization(want, ev);
- }
-
- @SmallTest
- public void testDnsEventSerialization() {
- ConnectivityMetricsEvent ev = describeIpEvent(
- aType(DnsEvent.class),
- anInt(101),
- aByteArray(b(1), b(1), b(2), b(1), b(1), b(1), b(2), b(2)),
- aByteArray(b(0), b(0), b(22), b(3), b(1), b(0), b(200), b(178)),
- anIntArray(3456, 267, 1230, 45, 2111, 450, 638, 1300));
-
- String want = joinLines(
- "dropped_events: 0",
- "events <",
- " if_name: \"\"",
- " link_layer: 0",
- " network_id: 0",
- " time_ms: 1",
- " transports: 0",
- " dns_lookup_batch <",
- " event_types: 1",
- " event_types: 1",
- " event_types: 2",
- " event_types: 1",
- " event_types: 1",
- " event_types: 1",
- " event_types: 2",
- " event_types: 2",
- " latencies_ms: 3456",
- " latencies_ms: 267",
- " latencies_ms: 1230",
- " latencies_ms: 45",
- " latencies_ms: 2111",
- " latencies_ms: 450",
- " latencies_ms: 638",
- " latencies_ms: 1300",
- " network_id <",
- " network_id: 101",
- " >",
- " return_codes: 0",
- " return_codes: 0",
- " return_codes: 22",
- " return_codes: 3",
- " return_codes: 1",
- " return_codes: 0",
- " return_codes: 200",
- " return_codes: 178",
- " >",
- ">",
- "version: 2");
+ "version: 2\n");
verifySerialization(want, ev);
}
@@ -326,7 +276,7 @@ public class IpConnectivityEventBuilderTest extends TestCase {
anInt(IpManagerEvent.PROVISIONING_OK),
aLong(5678));
- String want = joinLines(
+ String want = String.join("\n",
"dropped_events: 0",
"events <",
" if_name: \"\"",
@@ -340,7 +290,7 @@ public class IpConnectivityEventBuilderTest extends TestCase {
" latency_ms: 5678",
" >",
">",
- "version: 2");
+ "version: 2\n");
verifySerialization(want, ev);
}
@@ -351,7 +301,7 @@ public class IpConnectivityEventBuilderTest extends TestCase {
aType(IpReachabilityEvent.class),
anInt(IpReachabilityEvent.NUD_FAILED));
- String want = joinLines(
+ String want = String.join("\n",
"dropped_events: 0",
"events <",
" if_name: \"\"",
@@ -364,7 +314,7 @@ public class IpConnectivityEventBuilderTest extends TestCase {
" if_name: \"\"",
" >",
">",
- "version: 2");
+ "version: 2\n");
verifySerialization(want, ev);
}
@@ -377,7 +327,7 @@ public class IpConnectivityEventBuilderTest extends TestCase {
anInt(5),
aLong(20410));
- String want = joinLines(
+ String want = String.join("\n",
"dropped_events: 0",
"events <",
" if_name: \"\"",
@@ -393,7 +343,7 @@ public class IpConnectivityEventBuilderTest extends TestCase {
" >",
" >",
">",
- "version: 2");
+ "version: 2\n");
verifySerialization(want, ev);
}
@@ -406,7 +356,7 @@ public class IpConnectivityEventBuilderTest extends TestCase {
anInt(ValidationProbeEvent.PROBE_HTTP),
anInt(204));
- String want = joinLines(
+ String want = String.join("\n",
"dropped_events: 0",
"events <",
" if_name: \"\"",
@@ -420,7 +370,7 @@ public class IpConnectivityEventBuilderTest extends TestCase {
" probe_type: 1",
" >",
">",
- "version: 2");
+ "version: 2\n");
verifySerialization(want, ev);
}
@@ -436,7 +386,7 @@ public class IpConnectivityEventBuilderTest extends TestCase {
anInt(2048),
anInt(3));
- String want = joinLines(
+ String want = String.join("\n",
"dropped_events: 0",
"events <",
" if_name: \"\"",
@@ -454,7 +404,7 @@ public class IpConnectivityEventBuilderTest extends TestCase {
" program_length: 2048",
" >",
">",
- "version: 2");
+ "version: 2\n");
verifySerialization(want, ev);
}
@@ -474,7 +424,7 @@ public class IpConnectivityEventBuilderTest extends TestCase {
anInt(3),
anInt(2048));
- String want = joinLines(
+ String want = String.join("\n",
"dropped_events: 0",
"events <",
" if_name: \"\"",
@@ -495,7 +445,7 @@ public class IpConnectivityEventBuilderTest extends TestCase {
" zero_lifetime_ras: 1",
" >",
">",
- "version: 2");
+ "version: 2\n");
verifySerialization(want, ev);
}
@@ -511,7 +461,7 @@ public class IpConnectivityEventBuilderTest extends TestCase {
aLong(1000),
aLong(-1));
- String want = joinLines(
+ String want = String.join("\n",
"dropped_events: 0",
"events <",
" if_name: \"\"",
@@ -528,28 +478,20 @@ public class IpConnectivityEventBuilderTest extends TestCase {
" router_lifetime: 2000",
" >",
">",
- "version: 2");
+ "version: 2\n");
verifySerialization(want, ev);
}
static void verifySerialization(String want, ConnectivityMetricsEvent... input) {
try {
- byte[] got = IpConnectivityEventBuilder.serialize(0,
- IpConnectivityEventBuilder.toProto(Arrays.asList(input)));
+ List<IpConnectivityEvent> proto =
+ IpConnectivityEventBuilder.toProto(Arrays.asList(input));
+ byte[] got = IpConnectivityEventBuilder.serialize(0, proto);
IpConnectivityLog log = IpConnectivityLog.parseFrom(got);
assertEquals(want, log.toString());
} catch (Exception e) {
fail(e.toString());
}
}
-
- static String joinLines(String ... elems) {
- StringBuilder b = new StringBuilder();
- for (String s : elems) {
- b.append(s);
- b.append("\n");
- }
- return b.toString();
- }
}
diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
index 68786d0b4212..e01469b1825e 100644
--- a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
+++ b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
@@ -16,12 +16,22 @@
package com.android.server.connectivity;
+import static android.net.metrics.INetdEventListener.EVENT_GETADDRINFO;
+import static android.net.metrics.INetdEventListener.EVENT_GETHOSTBYNAME;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import android.content.Context;
+import android.net.ConnectivityManager;
import android.net.ConnectivityMetricsEvent;
import android.net.IIpConnectivityMetrics;
+import android.net.Network;
+import android.net.NetworkCapabilities;
import android.net.metrics.ApfProgramEvent;
import android.net.metrics.ApfStats;
import android.net.metrics.DefaultNetworkEvent;
@@ -31,7 +41,9 @@ import android.net.metrics.IpManagerEvent;
import android.net.metrics.IpReachabilityEvent;
import android.net.metrics.RaEvent;
import android.net.metrics.ValidationProbeEvent;
+import android.system.OsConstants;
import android.os.Parcelable;
+import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.Base64;
import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass;
@@ -41,26 +53,38 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
-import junit.framework.TestCase;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
-public class IpConnectivityMetricsTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class IpConnectivityMetricsTest {
static final IpReachabilityEvent FAKE_EV =
new IpReachabilityEvent(IpReachabilityEvent.NUD_FAILED);
+ private static final String EXAMPLE_IPV4 = "192.0.2.1";
+ private static final String EXAMPLE_IPV6 = "2001:db8:1200::2:1";
+
@Mock Context mCtx;
@Mock IIpConnectivityMetrics mMockService;
+ @Mock ConnectivityManager mCm;
IpConnectivityMetrics mService;
+ NetdEventListenerService mNetdListener;
+ @Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mService = new IpConnectivityMetrics(mCtx, (ctx) -> 2000);
+ mNetdListener = new NetdEventListenerService(mCm);
+ mService.mNetdListener = mNetdListener;
}
- @SmallTest
+ @Test
public void testLoggingEvents() throws Exception {
IpConnectivityLog logger = new IpConnectivityLog(mMockService);
@@ -74,7 +98,7 @@ public class IpConnectivityMetricsTest extends TestCase {
assertEventsEqual(expectedEvent(3), got.get(2));
}
- @SmallTest
+ @Test
public void testLoggingEventsWithMultipleCallers() throws Exception {
IpConnectivityLog logger = new IpConnectivityLog(mMockService);
@@ -91,7 +115,7 @@ public class IpConnectivityMetricsTest extends TestCase {
}.start();
}
- List<ConnectivityMetricsEvent> got = verifyEvents(nCallers * nEvents, 100);
+ List<ConnectivityMetricsEvent> got = verifyEvents(nCallers * nEvents, 200);
Collections.sort(got, EVENT_COMPARATOR);
Iterator<ConnectivityMetricsEvent> iter = got.iterator();
for (int i = 0; i < nCallers; i++) {
@@ -102,7 +126,7 @@ public class IpConnectivityMetricsTest extends TestCase {
}
}
- @SmallTest
+ @Test
public void testBufferFlushing() {
String output1 = getdump("flush");
assertEquals("", output1);
@@ -115,7 +139,7 @@ public class IpConnectivityMetricsTest extends TestCase {
assertEquals("", output3);
}
- @SmallTest
+ @Test
public void testRateLimiting() {
final IpConnectivityLog logger = new IpConnectivityLog(mService.impl);
final ApfProgramEvent ev = new ApfProgramEvent();
@@ -137,11 +161,19 @@ public class IpConnectivityMetricsTest extends TestCase {
assertEquals("", output2);
}
- @SmallTest
- public void testEndToEndLogging() {
+ @Test
+ public void testEndToEndLogging() throws Exception {
// TODO: instead of comparing textpb to textpb, parse textpb and compare proto to proto.
IpConnectivityLog logger = new IpConnectivityLog(mService.impl);
+ NetworkCapabilities ncWifi = new NetworkCapabilities();
+ NetworkCapabilities ncCell = new NetworkCapabilities();
+ ncWifi.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
+ ncCell.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
+
+ when(mCm.getNetworkCapabilities(new Network(100))).thenReturn(ncWifi);
+ when(mCm.getNetworkCapabilities(new Network(101))).thenReturn(ncCell);
+
ApfStats apfStats = new ApfStats();
apfStats.durationMs = 45000;
apfStats.receivedRas = 10;
@@ -177,7 +209,22 @@ public class IpConnectivityMetricsTest extends TestCase {
logger.log(ev);
}
- String want = joinLines(
+ // netId, errno, latency, destination
+ connectEvent(100, OsConstants.EALREADY, 0, EXAMPLE_IPV4);
+ connectEvent(100, OsConstants.EINPROGRESS, 0, EXAMPLE_IPV6);
+ connectEvent(100, 0, 110, EXAMPLE_IPV4);
+ connectEvent(101, 0, 23, EXAMPLE_IPV4);
+ connectEvent(101, 0, 45, EXAMPLE_IPV6);
+ connectEvent(100, OsConstants.EAGAIN, 0, EXAMPLE_IPV4);
+
+ // netId, type, return code, latency
+ dnsEvent(100, EVENT_GETADDRINFO, 0, 3456);
+ dnsEvent(100, EVENT_GETADDRINFO, 3, 45);
+ dnsEvent(100, EVENT_GETHOSTBYNAME, 0, 638);
+ dnsEvent(101, EVENT_GETADDRINFO, 0, 56);
+ dnsEvent(101, EVENT_GETHOSTBYNAME, 0, 34);
+
+ String want = String.join("\n",
"dropped_events: 0",
"events <",
" if_name: \"\"",
@@ -279,7 +326,71 @@ public class IpConnectivityMetricsTest extends TestCase {
" router_lifetime: 2000",
" >",
">",
- "version: 2");
+ "events <",
+ " if_name: \"\"",
+ " link_layer: 4",
+ " network_id: 100",
+ " time_ms: 0",
+ " transports: 2",
+ " connect_statistics <",
+ " connect_blocking_count: 1",
+ " connect_count: 3",
+ " errnos_counters <",
+ " key: 11",
+ " value: 1",
+ " >",
+ " ipv6_addr_count: 1",
+ " latencies_ms: 110",
+ " >",
+ ">",
+ "events <",
+ " if_name: \"\"",
+ " link_layer: 2",
+ " network_id: 101",
+ " time_ms: 0",
+ " transports: 1",
+ " connect_statistics <",
+ " connect_blocking_count: 2",
+ " connect_count: 2",
+ " ipv6_addr_count: 1",
+ " latencies_ms: 23",
+ " latencies_ms: 45",
+ " >",
+ ">",
+ "events <",
+ " if_name: \"\"",
+ " link_layer: 4",
+ " network_id: 100",
+ " time_ms: 0",
+ " transports: 2",
+ " dns_lookup_batch <",
+ " event_types: 1",
+ " event_types: 1",
+ " event_types: 2",
+ " latencies_ms: 3456",
+ " latencies_ms: 45",
+ " latencies_ms: 638",
+ " return_codes: 0",
+ " return_codes: 3",
+ " return_codes: 0",
+ " >",
+ ">",
+ "events <",
+ " if_name: \"\"",
+ " link_layer: 2",
+ " network_id: 101",
+ " time_ms: 0",
+ " transports: 1",
+ " dns_lookup_batch <",
+ " event_types: 1",
+ " event_types: 2",
+ " latencies_ms: 56",
+ " latencies_ms: 34",
+ " return_codes: 0",
+ " return_codes: 0",
+ " >",
+ ">",
+ "version: 2\n");
verifySerialization(want, getdump("flush"));
}
@@ -291,6 +402,14 @@ public class IpConnectivityMetricsTest extends TestCase {
return buffer.toString();
}
+ void connectEvent(int netid, int error, int latencyMs, String ipAddr) throws Exception {
+ mNetdListener.onConnectEvent(netid, error, latencyMs, ipAddr, 80, 1);
+ }
+
+ void dnsEvent(int netId, int type, int result, int latency) throws Exception {
+ mNetdListener.onDnsEvent(netId, type, result, latency, "", null, 0, 0);
+ }
+
List<ConnectivityMetricsEvent> verifyEvents(int n, int timeoutMs) throws Exception {
ArgumentCaptor<ConnectivityMetricsEvent> captor =
ArgumentCaptor.forClass(ConnectivityMetricsEvent.class);
diff --git a/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java b/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java
index 0ab440641d53..f98ab3d06921 100644
--- a/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java
+++ b/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java
@@ -16,190 +16,182 @@
package com.android.server.connectivity;
+import static android.net.metrics.INetdEventListener.EVENT_GETADDRINFO;
+import static android.net.metrics.INetdEventListener.EVENT_GETHOSTBYNAME;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
import android.net.ConnectivityManager;
-import android.net.ConnectivityManager.NetworkCallback;
import android.net.Network;
-import android.net.metrics.ConnectStats;
-import android.net.metrics.DnsEvent;
-import android.net.metrics.INetdEventListener;
-import android.net.metrics.IpConnectivityLog;
-import android.os.Parcelable;
-import android.os.RemoteException;
+import android.net.NetworkCapabilities;
+import android.support.test.runner.AndroidJUnit4;
import android.system.OsConstants;
import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Base64;
+import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.DNSLookupBatch;
import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityEvent;
+import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityLog;
import java.io.FileOutputStream;
import java.io.PrintWriter;
+import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
-import java.util.OptionalInt;
-import java.util.stream.IntStream;
-import junit.framework.TestCase;
import org.junit.Before;
import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.anyInt;
-import static org.mockito.Mockito.eq;
-import static org.mockito.Mockito.timeout;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-public class NetdEventListenerServiceTest extends TestCase {
-
- // TODO: read from NetdEventListenerService after this constant is read from system property
- static final int BATCH_SIZE = 100;
- static final int EVENT_TYPE = INetdEventListener.EVENT_GETADDRINFO;
- // TODO: read from INetdEventListener
- static final int RETURN_CODE = 1;
-
- static final byte[] EVENT_TYPES = new byte[BATCH_SIZE];
- static final byte[] RETURN_CODES = new byte[BATCH_SIZE];
- static final int[] LATENCIES = new int[BATCH_SIZE];
- static {
- for (int i = 0; i < BATCH_SIZE; i++) {
- EVENT_TYPES[i] = EVENT_TYPE;
- RETURN_CODES[i] = RETURN_CODE;
- LATENCIES[i] = i;
- }
- }
+import org.junit.runner.RunWith;
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class NetdEventListenerServiceTest {
private static final String EXAMPLE_IPV4 = "192.0.2.1";
private static final String EXAMPLE_IPV6 = "2001:db8:1200::2:1";
NetdEventListenerService mNetdEventListenerService;
+ ConnectivityManager mCm;
- @Mock ConnectivityManager mCm;
- @Mock IpConnectivityLog mLog;
- ArgumentCaptor<NetworkCallback> mCallbackCaptor;
- ArgumentCaptor<DnsEvent> mDnsEvCaptor;
-
+ @Before
public void setUp() {
- MockitoAnnotations.initMocks(this);
- mCallbackCaptor = ArgumentCaptor.forClass(NetworkCallback.class);
- mDnsEvCaptor = ArgumentCaptor.forClass(DnsEvent.class);
- mNetdEventListenerService = new NetdEventListenerService(mCm, mLog);
-
- verify(mCm, times(1)).registerNetworkCallback(any(), mCallbackCaptor.capture());
- }
-
- @SmallTest
- public void testOneDnsBatch() throws Exception {
- log(105, LATENCIES);
- log(106, Arrays.copyOf(LATENCIES, BATCH_SIZE - 1)); // one lookup short of a batch event
+ NetworkCapabilities ncWifi = new NetworkCapabilities();
+ NetworkCapabilities ncCell = new NetworkCapabilities();
+ ncWifi.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
+ ncCell.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
- verifyLoggedDnsEvents(new DnsEvent(105, EVENT_TYPES, RETURN_CODES, LATENCIES));
+ mCm = mock(ConnectivityManager.class);
+ when(mCm.getNetworkCapabilities(new Network(100))).thenReturn(ncWifi);
+ when(mCm.getNetworkCapabilities(new Network(101))).thenReturn(ncCell);
- log(106, Arrays.copyOfRange(LATENCIES, BATCH_SIZE - 1, BATCH_SIZE));
-
- mDnsEvCaptor = ArgumentCaptor.forClass(DnsEvent.class); // reset argument captor
- verifyLoggedDnsEvents(
- new DnsEvent(105, EVENT_TYPES, RETURN_CODES, LATENCIES),
- new DnsEvent(106, EVENT_TYPES, RETURN_CODES, LATENCIES));
- }
-
- @SmallTest
- public void testSeveralDmsBatches() throws Exception {
- log(105, LATENCIES);
- log(106, LATENCIES);
- log(105, LATENCIES);
- log(107, LATENCIES);
-
- verifyLoggedDnsEvents(
- new DnsEvent(105, EVENT_TYPES, RETURN_CODES, LATENCIES),
- new DnsEvent(106, EVENT_TYPES, RETURN_CODES, LATENCIES),
- new DnsEvent(105, EVENT_TYPES, RETURN_CODES, LATENCIES),
- new DnsEvent(107, EVENT_TYPES, RETURN_CODES, LATENCIES));
+ mNetdEventListenerService = new NetdEventListenerService(mCm);
}
- @SmallTest
- public void testDnsBatchAndNetworkLost() throws Exception {
- byte[] eventTypes = Arrays.copyOf(EVENT_TYPES, 20);
- byte[] returnCodes = Arrays.copyOf(RETURN_CODES, 20);
- int[] latencies = Arrays.copyOf(LATENCIES, 20);
-
- log(105, LATENCIES);
- log(105, latencies);
- mCallbackCaptor.getValue().onLost(new Network(105));
- log(105, LATENCIES);
-
- verifyLoggedDnsEvents(
- new DnsEvent(105, eventTypes, returnCodes, latencies),
- new DnsEvent(105, EVENT_TYPES, RETURN_CODES, LATENCIES),
- new DnsEvent(105, EVENT_TYPES, RETURN_CODES, LATENCIES));
- }
-
- @SmallTest
- public void testConcurrentDnsBatchesAndDumps() throws Exception {
- final long stop = System.currentTimeMillis() + 100;
- final PrintWriter pw = new PrintWriter(new FileOutputStream("/dev/null"));
- new Thread() {
- public void run() {
- while (System.currentTimeMillis() < stop) {
- mNetdEventListenerService.dump(pw);
- }
- }
- }.start();
-
- logDnsAsync(105, LATENCIES);
- logDnsAsync(106, LATENCIES);
- logDnsAsync(107, LATENCIES);
-
- verifyLoggedDnsEvents(500,
- new DnsEvent(105, EVENT_TYPES, RETURN_CODES, LATENCIES),
- new DnsEvent(106, EVENT_TYPES, RETURN_CODES, LATENCIES),
- new DnsEvent(107, EVENT_TYPES, RETURN_CODES, LATENCIES));
- }
-
- @SmallTest
- public void testConcurrentDnsBatchesAndNetworkLoss() throws Exception {
- logDnsAsync(105, LATENCIES);
- Thread.sleep(10L);
- // call onLost() asynchronously to logDnsAsync's onDnsEvent() calls.
- mCallbackCaptor.getValue().onLost(new Network(105));
-
- // do not verify batch with unpredictable length
- verify(mLog, timeout(500).times(1)).log(any(Parcelable.class));
+ @Test
+ public void testDnsLogging() throws Exception {
+ asyncDump(100);
+
+ dnsEvent(100, EVENT_GETADDRINFO, 0, 3456);
+ dnsEvent(100, EVENT_GETADDRINFO, 0, 267);
+ dnsEvent(100, EVENT_GETHOSTBYNAME, 22, 1230);
+ dnsEvent(100, EVENT_GETADDRINFO, 3, 45);
+ dnsEvent(100, EVENT_GETADDRINFO, 1, 2111);
+ dnsEvent(100, EVENT_GETADDRINFO, 0, 450);
+ dnsEvent(100, EVENT_GETHOSTBYNAME, 200, 638);
+ dnsEvent(100, EVENT_GETHOSTBYNAME, 178, 1300);
+ dnsEvent(101, EVENT_GETADDRINFO, 0, 56);
+ dnsEvent(101, EVENT_GETADDRINFO, 0, 78);
+ dnsEvent(101, EVENT_GETADDRINFO, 0, 14);
+ dnsEvent(101, EVENT_GETHOSTBYNAME, 0, 56);
+ dnsEvent(101, EVENT_GETADDRINFO, 0, 78);
+ dnsEvent(101, EVENT_GETADDRINFO, 0, 14);
+
+ String got = flushStatistics();
+ String want = String.join("\n",
+ "dropped_events: 0",
+ "events <",
+ " if_name: \"\"",
+ " link_layer: 4",
+ " network_id: 100",
+ " time_ms: 0",
+ " transports: 2",
+ " dns_lookup_batch <",
+ " event_types: 1",
+ " event_types: 1",
+ " event_types: 2",
+ " event_types: 1",
+ " event_types: 1",
+ " event_types: 1",
+ " event_types: 2",
+ " event_types: 2",
+ " latencies_ms: 3456",
+ " latencies_ms: 267",
+ " latencies_ms: 1230",
+ " latencies_ms: 45",
+ " latencies_ms: 2111",
+ " latencies_ms: 450",
+ " latencies_ms: 638",
+ " latencies_ms: 1300",
+ " return_codes: 0",
+ " return_codes: 0",
+ " return_codes: 22",
+ " return_codes: 3",
+ " return_codes: 1",
+ " return_codes: 0",
+ " return_codes: 200",
+ " return_codes: 178",
+ " >",
+ ">",
+ "events <",
+ " if_name: \"\"",
+ " link_layer: 2",
+ " network_id: 101",
+ " time_ms: 0",
+ " transports: 1",
+ " dns_lookup_batch <",
+ " event_types: 1",
+ " event_types: 1",
+ " event_types: 1",
+ " event_types: 2",
+ " event_types: 1",
+ " event_types: 1",
+ " latencies_ms: 56",
+ " latencies_ms: 78",
+ " latencies_ms: 14",
+ " latencies_ms: 56",
+ " latencies_ms: 78",
+ " latencies_ms: 14",
+ " return_codes: 0",
+ " return_codes: 0",
+ " return_codes: 0",
+ " return_codes: 0",
+ " return_codes: 0",
+ " return_codes: 0",
+ " >",
+ ">",
+ "version: 2\n");
+ assertEquals(want, got);
}
- @SmallTest
+ @Test
public void testConnectLogging() throws Exception {
+ asyncDump(100);
+
final int OK = 0;
Thread[] logActions = {
// ignored
- connectEventAction(OsConstants.EALREADY, 0, EXAMPLE_IPV4),
- connectEventAction(OsConstants.EALREADY, 0, EXAMPLE_IPV6),
- connectEventAction(OsConstants.EINPROGRESS, 0, EXAMPLE_IPV4),
- connectEventAction(OsConstants.EINPROGRESS, 0, EXAMPLE_IPV6),
- connectEventAction(OsConstants.EINPROGRESS, 0, EXAMPLE_IPV6),
+ connectEventAction(100, OsConstants.EALREADY, 0, EXAMPLE_IPV4),
+ connectEventAction(100, OsConstants.EALREADY, 0, EXAMPLE_IPV6),
+ connectEventAction(100, OsConstants.EINPROGRESS, 0, EXAMPLE_IPV4),
+ connectEventAction(101, OsConstants.EINPROGRESS, 0, EXAMPLE_IPV6),
+ connectEventAction(101, OsConstants.EINPROGRESS, 0, EXAMPLE_IPV6),
// valid latencies
- connectEventAction(OK, 110, EXAMPLE_IPV4),
- connectEventAction(OK, 23, EXAMPLE_IPV4),
- connectEventAction(OK, 45, EXAMPLE_IPV4),
- connectEventAction(OK, 56, EXAMPLE_IPV4),
- connectEventAction(OK, 523, EXAMPLE_IPV6),
- connectEventAction(OK, 214, EXAMPLE_IPV6),
- connectEventAction(OK, 67, EXAMPLE_IPV6),
+ connectEventAction(100, OK, 110, EXAMPLE_IPV4),
+ connectEventAction(100, OK, 23, EXAMPLE_IPV4),
+ connectEventAction(100, OK, 45, EXAMPLE_IPV4),
+ connectEventAction(101, OK, 56, EXAMPLE_IPV4),
+ connectEventAction(101, OK, 523, EXAMPLE_IPV6),
+ connectEventAction(101, OK, 214, EXAMPLE_IPV6),
+ connectEventAction(101, OK, 67, EXAMPLE_IPV6),
// errors
- connectEventAction(OsConstants.EPERM, 0, EXAMPLE_IPV4),
- connectEventAction(OsConstants.EPERM, 0, EXAMPLE_IPV4),
- connectEventAction(OsConstants.EAGAIN, 0, EXAMPLE_IPV4),
- connectEventAction(OsConstants.EACCES, 0, EXAMPLE_IPV4),
- connectEventAction(OsConstants.EACCES, 0, EXAMPLE_IPV4),
- connectEventAction(OsConstants.EACCES, 0, EXAMPLE_IPV6),
- connectEventAction(OsConstants.EADDRINUSE, 0, EXAMPLE_IPV4),
- connectEventAction(OsConstants.ETIMEDOUT, 0, EXAMPLE_IPV4),
- connectEventAction(OsConstants.ETIMEDOUT, 0, EXAMPLE_IPV6),
- connectEventAction(OsConstants.ETIMEDOUT, 0, EXAMPLE_IPV6),
- connectEventAction(OsConstants.ECONNREFUSED, 0, EXAMPLE_IPV4),
+ connectEventAction(100, OsConstants.EPERM, 0, EXAMPLE_IPV4),
+ connectEventAction(101, OsConstants.EPERM, 0, EXAMPLE_IPV4),
+ connectEventAction(100, OsConstants.EAGAIN, 0, EXAMPLE_IPV4),
+ connectEventAction(100, OsConstants.EACCES, 0, EXAMPLE_IPV4),
+ connectEventAction(101, OsConstants.EACCES, 0, EXAMPLE_IPV4),
+ connectEventAction(101, OsConstants.EACCES, 0, EXAMPLE_IPV6),
+ connectEventAction(100, OsConstants.EADDRINUSE, 0, EXAMPLE_IPV4),
+ connectEventAction(101, OsConstants.ETIMEDOUT, 0, EXAMPLE_IPV4),
+ connectEventAction(100, OsConstants.ETIMEDOUT, 0, EXAMPLE_IPV6),
+ connectEventAction(100, OsConstants.ETIMEDOUT, 0, EXAMPLE_IPV6),
+ connectEventAction(101, OsConstants.ECONNREFUSED, 0, EXAMPLE_IPV4),
};
for (Thread t : logActions) {
@@ -209,113 +201,124 @@ public class NetdEventListenerServiceTest extends TestCase {
t.join();
}
- List<IpConnectivityEvent> events = new ArrayList<>();
- mNetdEventListenerService.flushStatistics(events);
-
- IpConnectivityEvent got = events.get(0);
+ String got = flushStatistics();
String want = String.join("\n",
- "if_name: \"\"",
- "link_layer: 0",
- "network_id: 0",
- "time_ms: 0",
- "transports: 0",
- "connect_statistics <",
- " connect_blocking_count: 7",
- " connect_count: 12",
- " errnos_counters <",
- " key: 1",
- " value: 2",
- " >",
- " errnos_counters <",
- " key: 11",
- " value: 1",
- " >",
- " errnos_counters <",
- " key: 13",
- " value: 3",
+ "dropped_events: 0",
+ "events <",
+ " if_name: \"\"",
+ " link_layer: 4",
+ " network_id: 100",
+ " time_ms: 0",
+ " transports: 2",
+ " connect_statistics <",
+ " connect_blocking_count: 3",
+ " connect_count: 6",
+ " errnos_counters <",
+ " key: 1",
+ " value: 1",
+ " >",
+ " errnos_counters <",
+ " key: 11",
+ " value: 1",
+ " >",
+ " errnos_counters <",
+ " key: 13",
+ " value: 1",
+ " >",
+ " errnos_counters <",
+ " key: 98",
+ " value: 1",
+ " >",
+ " errnos_counters <",
+ " key: 110",
+ " value: 2",
+ " >",
+ " ipv6_addr_count: 1",
+ " latencies_ms: 23",
+ " latencies_ms: 45",
+ " latencies_ms: 110",
" >",
- " errnos_counters <",
- " key: 98",
- " value: 1",
+ ">",
+ "events <",
+ " if_name: \"\"",
+ " link_layer: 2",
+ " network_id: 101",
+ " time_ms: 0",
+ " transports: 1",
+ " connect_statistics <",
+ " connect_blocking_count: 4",
+ " connect_count: 6",
+ " errnos_counters <",
+ " key: 1",
+ " value: 1",
+ " >",
+ " errnos_counters <",
+ " key: 13",
+ " value: 2",
+ " >",
+ " errnos_counters <",
+ " key: 110",
+ " value: 1",
+ " >",
+ " errnos_counters <",
+ " key: 111",
+ " value: 1",
+ " >",
+ " ipv6_addr_count: 5",
+ " latencies_ms: 56",
+ " latencies_ms: 67",
+ " latencies_ms: 214",
+ " latencies_ms: 523",
" >",
- " errnos_counters <",
- " key: 110",
- " value: 3",
- " >",
- " errnos_counters <",
- " key: 111",
- " value: 1",
- " >",
- " ipv6_addr_count: 6",
- " latencies_ms: 23",
- " latencies_ms: 45",
- " latencies_ms: 56",
- " latencies_ms: 67",
- " latencies_ms: 110",
- " latencies_ms: 214",
- " latencies_ms: 523",
- ">\n");
- verifyConnectEvent(want, got);
+ ">",
+ "version: 2\n");
+ assertEquals(want, got);
}
- Thread connectEventAction(int error, int latencyMs, String ipAddr) {
+ Thread connectEventAction(int netId, int error, int latencyMs, String ipAddr) {
return new Thread(() -> {
try {
- mNetdEventListenerService.onConnectEvent(100, error, latencyMs, ipAddr, 80, 1);
+ mNetdEventListenerService.onConnectEvent(netId, error, latencyMs, ipAddr, 80, 1);
} catch (Exception e) {
fail(e.toString());
}
});
}
- void log(int netId, int[] latencies) {
- try {
- for (int l : latencies) {
- mNetdEventListenerService.onDnsEvent(netId, EVENT_TYPE, RETURN_CODE, l, null, null,
- 0, 0);
- }
- } catch (RemoteException re) {
- throw re.rethrowFromSystemServer();
- }
- }
-
- void logDnsAsync(int netId, int[] latencies) {
- new Thread(() -> log(netId, latencies)).start();
- }
-
- void verifyLoggedDnsEvents(DnsEvent... expected) {
- verifyLoggedDnsEvents(0, expected);
- }
-
- void verifyLoggedDnsEvents(int wait, DnsEvent... expectedEvents) {
- verify(mLog, timeout(wait).times(expectedEvents.length)).log(mDnsEvCaptor.capture());
- for (DnsEvent got : mDnsEvCaptor.getAllValues()) {
- OptionalInt index = IntStream.range(0, expectedEvents.length)
- .filter(i -> dnsEventsEqual(expectedEvents[i], got))
- .findFirst();
- // Don't match same expected event more than once.
- index.ifPresent(i -> expectedEvents[i] = null);
- assertTrue(index.isPresent());
- }
+ void dnsEvent(int netId, int type, int result, int latency) throws Exception {
+ mNetdEventListenerService.onDnsEvent(netId, type, result, latency, "", null, 0, 0);
}
- /** equality function for DnsEvent to avoid overriding equals() and hashCode(). */
- static boolean dnsEventsEqual(DnsEvent expected, DnsEvent got) {
- return (expected == got) || ((expected != null) && (got != null)
- && (expected.netId == got.netId)
- && Arrays.equals(expected.eventTypes, got.eventTypes)
- && Arrays.equals(expected.returnCodes, got.returnCodes)
- && Arrays.equals(expected.latenciesMs, got.latenciesMs));
+ void asyncDump(long durationMs) throws Exception {
+ final long stop = System.currentTimeMillis() + durationMs;
+ final PrintWriter pw = new PrintWriter(new FileOutputStream("/dev/null"));
+ new Thread(() -> {
+ while (System.currentTimeMillis() < stop) {
+ mNetdEventListenerService.dump(pw);
+ }
+ }).start();
}
- static void verifyConnectEvent(String expected, IpConnectivityEvent got) {
- try {
- Arrays.sort(got.getConnectStatistics().latenciesMs);
- Arrays.sort(got.getConnectStatistics().errnosCounters,
+ // TODO: instead of comparing textpb to textpb, parse textpb and compare proto to proto.
+ String flushStatistics() throws Exception {
+ IpConnectivityMetrics metricsService =
+ new IpConnectivityMetrics(mock(Context.class), (ctx) -> 2000);
+ metricsService.mNetdListener = mNetdEventListenerService;
+
+ StringWriter buffer = new StringWriter();
+ PrintWriter writer = new PrintWriter(buffer);
+ metricsService.impl.dump(null, writer, new String[]{"flush"});
+ byte[] bytes = Base64.decode(buffer.toString(), Base64.DEFAULT);
+ IpConnectivityLog log = IpConnectivityLog.parseFrom(bytes);
+ for (IpConnectivityEvent ev : log.events) {
+ if (ev.getConnectStatistics() == null) {
+ continue;
+ }
+ // Sort repeated fields of connect() events arriving in non-deterministic order.
+ Arrays.sort(ev.getConnectStatistics().latenciesMs);
+ Arrays.sort(ev.getConnectStatistics().errnosCounters,
Comparator.comparingInt((p) -> p.key));
- assertEquals(expected, got.toString());
- } catch (Exception e) {
- fail(e.toString());
}
+ return log.toString();
}
}
diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp
index 97e02f969801..b86188fa8503 100644
--- a/tools/aapt2/cmd/Link.cpp
+++ b/tools/aapt2/cmd/Link.cpp
@@ -1873,7 +1873,8 @@ int Link(const std::vector<StringPiece>& args) {
&options.extensions_to_not_compress)
.OptionalFlagList("--split",
"Split resources matching a set of configs out to a Split APK.\n"
- "Syntax: path/to/output.apk:<config>[,<config>[...]].",
+ "Syntax: path/to/output.apk:<config>[,<config>[...]].\n"
+ "On Windows, use a semicolon ';' separator instead.",
&split_args)
.OptionalSwitch("-v", "Enables verbose logging.", &verbose);
diff --git a/tools/aapt2/cmd/Optimize.cpp b/tools/aapt2/cmd/Optimize.cpp
index 8f8e0c8e4f6d..e99ee8aa93c2 100644
--- a/tools/aapt2/cmd/Optimize.cpp
+++ b/tools/aapt2/cmd/Optimize.cpp
@@ -302,7 +302,8 @@ int Optimize(const std::vector<StringPiece>& args) {
&configs)
.OptionalFlagList("--split",
"Split resources matching a set of configs out to a "
- "Split APK.\nSyntax: path/to/output.apk:<config>[,<config>[...]].",
+ "Split APK.\nSyntax: path/to/output.apk;<config>[,<config>[...]].\n"
+ "On Windows, use a semicolon ';' separator instead.",
&split_args)
.OptionalSwitch("--enable-sparse-encoding",
"Enables encoding sparse entries using a binary search tree.\n"
diff --git a/tools/aapt2/cmd/Util.cpp b/tools/aapt2/cmd/Util.cpp
index fd94bbc0a1c3..14d426061e56 100644
--- a/tools/aapt2/cmd/Util.cpp
+++ b/tools/aapt2/cmd/Util.cpp
@@ -57,10 +57,17 @@ bool ParseSplitParameter(const StringPiece& arg, IDiagnostics* diag, std::string
CHECK(out_path != nullptr);
CHECK(out_split != nullptr);
- std::vector<std::string> parts = util::Split(arg, ':');
+#ifdef _WIN32
+ const char sSeparator = ';';
+#else
+ const char sSeparator = ':';
+#endif
+
+ std::vector<std::string> parts = util::Split(arg, sSeparator);
if (parts.size() != 2) {
diag->Error(DiagMessage() << "invalid split parameter '" << arg << "'");
- diag->Note(DiagMessage() << "should be --split path/to/output.apk:<config>[,<config>...]");
+ diag->Note(DiagMessage() << "should be --split path/to/output.apk" << sSeparator
+ << "<config>[,<config>...].");
return false;
}