diff options
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 Binary files differnew file mode 100755 index 000000000000..a91bc6ec90ed --- /dev/null +++ b/core/res/res/drawable-hdpi/ic_accessibility_magnification.png diff --git a/core/res/res/drawable-mdpi/ic_accessibility_magnification.png b/core/res/res/drawable-mdpi/ic_accessibility_magnification.png Binary files differnew file mode 100755 index 000000000000..9ec51075a5ed --- /dev/null +++ b/core/res/res/drawable-mdpi/ic_accessibility_magnification.png diff --git a/core/res/res/drawable-xhdpi/ic_accessibility_magnification.png b/core/res/res/drawable-xhdpi/ic_accessibility_magnification.png Binary files differnew file mode 100755 index 000000000000..0b3a32ed1792 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_accessibility_magnification.png diff --git a/core/res/res/drawable-xxhdpi/ic_accessibility_magnification.png b/core/res/res/drawable-xxhdpi/ic_accessibility_magnification.png Binary files differnew file mode 100755 index 000000000000..3eeb1c9f8dd8 --- /dev/null +++ b/core/res/res/drawable-xxhdpi/ic_accessibility_magnification.png diff --git a/core/res/res/drawable-xxxhdpi/ic_accessibility_magnification.png b/core/res/res/drawable-xxxhdpi/ic_accessibility_magnification.png Binary files differnew file mode 100755 index 000000000000..7d376126b4d7 --- /dev/null +++ b/core/res/res/drawable-xxxhdpi/ic_accessibility_magnification.png 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 Binary files differindex 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 diff --git a/packages/SystemUI/res/drawable-mdpi/pip_dismiss_scrim.9.png b/packages/SystemUI/res/drawable-mdpi/pip_dismiss_scrim.9.png Binary files differindex 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 diff --git a/packages/SystemUI/res/drawable-xhdpi/pip_dismiss_scrim.9.png b/packages/SystemUI/res/drawable-xhdpi/pip_dismiss_scrim.9.png Binary files differindex 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 diff --git a/packages/SystemUI/res/drawable-xxhdpi/pip_dismiss_scrim.9.png b/packages/SystemUI/res/drawable-xxhdpi/pip_dismiss_scrim.9.png Binary files differindex 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 diff --git a/packages/SystemUI/res/drawable-xxxhdpi/pip_dismiss_scrim.9.png b/packages/SystemUI/res/drawable-xxxhdpi/pip_dismiss_scrim.9.png Binary files differindex 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 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;    }  |