summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp16
-rwxr-xr-xapi/current.txt21
-rw-r--r--api/system-current.txt25
-rw-r--r--api/test-current.txt4
-rw-r--r--cmds/statsd/src/StatsLogProcessor.h3
-rw-r--r--cmds/statsd/src/StatsService.cpp7
-rw-r--r--cmds/statsd/src/StatsService.h5
-rw-r--r--cmds/statsd/src/atom_field_options.proto14
-rw-r--r--cmds/statsd/src/atoms.proto360
-rw-r--r--cmds/statsd/src/hash.cpp12
-rw-r--r--cmds/statsd/src/main.cpp35
-rw-r--r--cmds/statsd/src/stats_log.proto1
-rw-r--r--config/hiddenapi-light-greylist.txt3
-rw-r--r--core/java/android/app/AppDetailsActivity.java36
-rw-r--r--core/java/android/app/SystemServiceRegistry.java10
-rw-r--r--core/java/android/app/backup/BackupAgent.java13
-rw-r--r--core/java/android/bluetooth/BluetoothDevice.java20
-rw-r--r--core/java/android/bluetooth/BluetoothGatt.java2
-rw-r--r--core/java/android/bluetooth/BluetoothGattServer.java4
-rw-r--r--core/java/android/bluetooth/BluetoothServerSocket.java4
-rw-r--r--core/java/android/bluetooth/le/AdvertisingSetCallback.java2
-rw-r--r--core/java/android/content/AbstractThreadedSyncAdapter.java2
-rw-r--r--core/java/android/content/ClipData.java4
-rw-r--r--core/java/android/content/ContentProviderOperation.java2
-rw-r--r--core/java/android/content/ContentResolver.java4
-rw-r--r--core/java/android/content/Context.java4
-rw-r--r--core/java/android/content/CursorLoader.java2
-rw-r--r--core/java/android/content/Intent.java8
-rw-r--r--core/java/android/content/IntentFilter.java2
-rw-r--r--core/java/android/content/pm/ActivityInfo.java8
-rw-r--r--core/java/android/content/pm/ApplicationInfo.java2
-rw-r--r--core/java/android/content/pm/PackageManager.java1
-rw-r--r--core/java/android/content/pm/PackageManagerInternal.java24
-rw-r--r--core/java/android/content/pm/PackageParser.java87
-rw-r--r--core/java/android/database/sqlite/SQLiteStatement.java2
-rw-r--r--core/java/android/hardware/camera2/CameraMetadata.java2
-rw-r--r--core/java/android/hardware/location/ContextHubClient.java2
-rw-r--r--core/java/android/hardware/location/ContextHubManager.java4
-rw-r--r--core/java/android/net/ConnectivityManager.java31
-rw-r--r--core/java/android/os/Build.java24
-rw-r--r--core/java/android/os/DumpstateOptions.java57
-rw-r--r--core/java/android/os/Message.java12
-rw-r--r--core/java/android/os/UserManager.java1
-rw-r--r--core/java/android/permission/PermissionManager.java55
-rw-r--r--core/java/android/service/textclassifier/TextClassifierService.java4
-rw-r--r--core/java/android/text/style/TextAppearanceSpan.java29
-rw-r--r--core/java/android/transition/Visibility.java24
-rw-r--r--core/java/android/view/DisplayCutout.java34
-rw-r--r--core/java/android/view/TouchDelegate.java25
-rw-r--r--core/java/android/view/View.java56
-rw-r--r--core/java/android/view/Window.java17
-rw-r--r--core/java/android/view/WindowManager.java18
-rw-r--r--core/java/android/view/accessibility/AccessibilityNodeInfo.java275
-rw-r--r--core/java/android/view/inputmethod/InputMethodManager.java170
-rw-r--r--core/java/android/widget/TextView.java8
-rw-r--r--core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java7
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java2
-rw-r--r--core/java/com/android/internal/os/LooperStats.java28
-rw-r--r--core/java/com/android/internal/os/ProcessCpuTracker.java1
-rw-r--r--core/java/com/android/internal/view/IInputMethodManager.aidl3
-rw-r--r--core/java/com/android/internal/view/InputBindResult.java29
-rw-r--r--core/java/com/android/internal/widget/AlertDialogLayout.java2
-rw-r--r--core/java/com/android/internal/widget/ButtonBarLayout.java2
-rw-r--r--core/java/com/android/internal/widget/DialogTitle.java2
-rw-r--r--core/java/com/android/server/SystemConfig.java8
-rw-r--r--core/proto/android/internal/powerprofile.proto26
-rw-r--r--core/proto/android/stats/enums.proto (renamed from proto/src/stats_enums.proto)3
-rw-r--r--core/proto/android/telephony/enums.proto61
-rw-r--r--core/res/AndroidManifest.xml26
-rw-r--r--core/res/res/values/config.xml4
-rw-r--r--core/res/res/values/strings.xml13
-rw-r--r--core/res/res/values/symbols.xml2
-rw-r--r--core/res/res/xml/sms_short_codes.xml11
-rw-r--r--core/tests/coretests/Android.mk4
-rw-r--r--core/tests/coretests/apks/install_multi_package/Android.mk4
-rw-r--r--core/tests/coretests/apks/install_verifier_bad/Android.mk4
-rw-r--r--core/tests/coretests/apks/install_verifier_good/Android.mk4
-rw-r--r--core/tests/coretests/src/android/content/pm/dex/DexMetadataHelperTest.java4
-rw-r--r--core/tests/coretests/src/android/os/FileUtilsTest.java3
-rw-r--r--core/tests/coretests/src/android/text/format/DateUtilsTest.java2
-rw-r--r--core/tests/coretests/src/android/view/DisplayCutoutTest.java12
-rw-r--r--core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java2
-rw-r--r--core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java68
-rw-r--r--data/etc/privapp-permissions-platform.xml1
-rw-r--r--graphics/java/android/graphics/ColorSpace.java4
-rw-r--r--graphics/java/android/graphics/drawable/Icon.java3
-rw-r--r--graphics/java/android/graphics/pdf/PdfEditor.java1
-rw-r--r--keystore/OWNERS4
-rw-r--r--libs/androidfw/Android.bp2
-rw-r--r--libs/androidfw/AssetManager2.cpp8
-rw-r--r--libs/androidfw/LoadedArsc.cpp34
-rw-r--r--libs/androidfw/PosixUtils.cpp112
-rw-r--r--libs/androidfw/include/androidfw/AssetManager2.h9
-rw-r--r--libs/androidfw/include/androidfw/LoadedArsc.h50
-rw-r--r--libs/androidfw/include/androidfw/PosixUtils.h36
-rw-r--r--libs/androidfw/tests/LoadedArsc_test.cpp48
-rw-r--r--libs/androidfw/tests/PosixUtils_test.cpp55
-rw-r--r--location/java/android/location/LocationManager.java4
-rw-r--r--media/java/android/media/ExifInterface.java6
-rw-r--r--media/java/android/media/MediaPlayer2Impl.java11
-rw-r--r--packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java1
-rw-r--r--packages/CtsShim/build/Android.mk8
-rw-r--r--packages/EasterEgg/src/com/android/egg/paint/CutoutAvoidingToolbar.kt13
-rw-r--r--packages/EasterEgg/src/com/android/egg/paint/Painting.kt35
-rw-r--r--packages/EasterEgg/src/com/android/egg/paint/ToolbarView.kt22
-rw-r--r--packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java4
-rw-r--r--packages/PrintSpooler/Android.bp38
-rw-r--r--packages/PrintSpooler/Android.mk45
-rw-r--r--packages/PrintSpooler/tests/Android.mk19
-rw-r--r--packages/PrintSpooler/tests/outofprocess/Android.bp30
-rw-r--r--packages/PrintSpooler/tests/outofprocess/Android.mk30
-rw-r--r--packages/SettingsLib/RestrictedLockUtils/src/com/android/settingslib/RestrictedLockUtils.java8
-rw-r--r--packages/SettingsLib/SettingsSpinner/src/com/android/settingslib/widget/settingsspinner/SettingsSpinnerAdapter.java2
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java6
-rw-r--r--packages/Shell/AndroidManifest.xml1
-rw-r--r--packages/SystemUI/plugin/src/com/android/systemui/plugins/SensorManagerPlugin.java27
-rw-r--r--packages/SystemUI/res/layout/notification_info.xml3
-rw-r--r--packages/SystemUI/res/layout/status_bar.xml11
-rw-r--r--packages/SystemUI/res/values/strings.xml5
-rw-r--r--packages/SystemUI/src/com/android/systemui/ScreenDecorations.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/SlicePermissionActivity.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java53
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java43
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java60
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/TunablePadding.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java149
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java22
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java4
-rw-r--r--proto/src/metrics_constants/metrics_constants.proto15
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java10
-rw-r--r--services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java13
-rw-r--r--services/core/Android.bp3
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java69
-rw-r--r--services/core/java/com/android/server/LooperStatsService.java24
-rw-r--r--services/core/java/com/android/server/NetworkManagementService.java22
-rw-r--r--services/core/java/com/android/server/TelephonyRegistry.java5
-rw-r--r--services/core/java/com/android/server/am/ActivityDisplay.java2
-rw-r--r--services/core/java/com/android/server/am/ActivityLaunchParamsModifier.java65
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java1
-rw-r--r--services/core/java/com/android/server/am/ActivityMetricsLogger.java17
-rw-r--r--services/core/java/com/android/server/am/ActivityRecord.java39
-rw-r--r--services/core/java/com/android/server/am/ActivityStack.java12
-rw-r--r--services/core/java/com/android/server/am/ActivityStackSupervisor.java46
-rw-r--r--services/core/java/com/android/server/am/ActivityStarter.java81
-rw-r--r--services/core/java/com/android/server/am/ActivityTaskManagerService.java25
-rw-r--r--services/core/java/com/android/server/am/LaunchParamsController.java66
-rw-r--r--services/core/java/com/android/server/am/ProcessList.java53
-rw-r--r--services/core/java/com/android/server/am/TaskLaunchParamsModifier.java862
-rw-r--r--services/core/java/com/android/server/connectivity/NetworkMonitor.java5
-rw-r--r--services/core/java/com/android/server/connectivity/ProxyTracker.java91
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodManagerService.java74
-rw-r--r--services/core/java/com/android/server/location/ContextHubClientBroker.java65
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java18
-rw-r--r--services/core/java/com/android/server/os/DeviceIdentifiersPolicyService.java4
-rw-r--r--services/core/java/com/android/server/pm/LauncherAppsService.java79
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java47
-rw-r--r--services/core/java/com/android/server/pm/dex/TEST_MAPPING19
-rw-r--r--services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java4
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java13
-rw-r--r--services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java20
-rw-r--r--services/core/java/com/android/server/stats/StatsCompanionService.java5
-rw-r--r--services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java25
-rw-r--r--services/core/java/com/android/server/wm/AppWindowToken.java34
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java20
-rw-r--r--services/core/java/com/android/server/wm/TaskPositioningController.java2
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerInternal.java19
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java40
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java4
-rw-r--r--services/java/com/android/server/SystemServer.java6
-rw-r--r--services/net/java/android/net/ip/IpNeighborMonitor.java1
-rw-r--r--services/net/java/android/net/ip/RouterAdvertisementDaemon.java1
-rw-r--r--services/net/java/android/net/netlink/NetlinkSocket.java1
-rw-r--r--services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java50
-rw-r--r--services/tests/servicestests/src/com/android/server/am/ActivityLaunchParamsModifierTests.java144
-rw-r--r--services/tests/servicestests/src/com/android/server/am/TaskLaunchParamsModifierTests.java1189
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java32
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/DragDropControllerTests.java24
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java9
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java26
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java23
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/ZOrderingTests.java58
-rw-r--r--telecomm/java/android/telecom/Call.java14
-rw-r--r--telephony/java/android/provider/Telephony.java1
-rw-r--r--telephony/java/android/telephony/NeighboringCellInfo.java4
-rw-r--r--telephony/java/android/telephony/NetworkRegistrationState.java44
-rw-r--r--telephony/java/android/telephony/ServiceState.java158
-rw-r--r--telephony/java/android/telephony/SubscriptionManager.java53
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java34
-rw-r--r--telephony/java/android/telephony/data/ApnSetting.java4
-rw-r--r--telephony/java/com/android/internal/telephony/RILConstants.java1
-rw-r--r--telephony/java/com/android/internal/telephony/TelephonyPermissions.java57
-rw-r--r--tests/ActivityTests/Android.mk4
-rw-r--r--tests/NetworkSecurityConfigTest/Android.mk1
-rw-r--r--tests/net/Android.mk6
-rw-r--r--tools/aapt2/cmd/Convert.cpp22
-rw-r--r--tools/stats_log_api_gen/Collation.cpp4
-rw-r--r--tools/stats_log_api_gen/test.proto24
-rw-r--r--wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java11
-rw-r--r--wifi/tests/src/android/net/wifi/hotspot2/pps/HomeSpTest.java3
208 files changed, 5099 insertions, 1945 deletions
diff --git a/Android.bp b/Android.bp
index 7e71bdfe35c7..f9b60e67e659 100644
--- a/Android.bp
+++ b/Android.bp
@@ -614,6 +614,7 @@ java_defaults {
":netd_aidl",
":vold_aidl",
":installd_aidl",
+ ":dumpstate_aidl",
"lowpan/java/android/net/lowpan/ILowpanEnergyScanCallback.aidl",
"lowpan/java/android/net/lowpan/ILowpanNetScanCallback.aidl",
@@ -660,6 +661,7 @@ java_defaults {
include_dirs: [
"system/update_engine/binder_bindings",
"frameworks/native/aidl/binder",
+ "frameworks/native/cmds/dumpstate/binder",
"frameworks/av/camera/aidl",
"frameworks/av/media/libaudioclient/aidl",
"frameworks/native/aidl/gui",
@@ -682,9 +684,6 @@ java_defaults {
no_framework_libs: true,
libs: [
- "conscrypt",
- "okhttp",
- "bouncycastle",
"ext",
],
@@ -706,6 +705,7 @@ java_defaults {
"android.hardware.radio-V1.0-java",
"android.hardware.radio-V1.3-java",
"android.hardware.usb.gadget-V1.0-java",
+ "netd_aidl_interface-java",
],
// Loaded with System.loadLibrary by android.view.textclassifier
@@ -835,7 +835,6 @@ java_library_host {
"cmds/statsd/src/**/*.proto",
"core/proto/**/*.proto",
"libs/incident/proto/**/*.proto",
- "proto/src/stats_enums.proto",
],
proto: {
include_dirs: ["external/protobuf/src"],
@@ -873,7 +872,6 @@ java_library {
srcs: [
"core/proto/**/*.proto",
"libs/incident/proto/android/os/**/*.proto",
- "proto/src/stats_enums.proto",
],
// Protos have lots of MissingOverride and similar.
errorprone: {
@@ -899,7 +897,6 @@ cc_library {
srcs: [
"core/proto/**/*.proto",
"libs/incident/**/*.proto",
- "proto/src/stats_enums.proto",
],
target: {
@@ -1096,14 +1093,13 @@ framework_docs_args = "-android -manifest $(location core/res/AndroidManifest.xm
"-federationapi SupportLib $(location current/support-api.txt) "
framework_docs_only_args = " -android -manifest $(location core/res/AndroidManifest.xml) " +
+ "-werror -lerror -hide 111 -hide 113 -hide 125 -hide 126 -hide 127 -hide 128 " +
"-overview $(location core/java/overview.html) " +
// Federate Support Library references against local API file.
"-federate SupportLib https://developer.android.com " +
"-federationapi SupportLib $(location current/support-api.txt) "
framework_docs_only_libs = [
- "conscrypt",
- "bouncycastle",
"voip-common",
"android.test.mock",
"android-support-annotations",
@@ -1183,7 +1179,8 @@ stubs_defaults {
doc_defaults {
name: "framework-docs-default",
- libs: framework_docs_only_libs,
+ libs: framework_docs_only_libs +
+ ["stub-annotations"],
html_dirs: [
"docs/html",
],
@@ -1580,7 +1577,6 @@ filegroup {
"core/java/org/apache/http/params/CoreConnectionPNames.java",
"core/java/org/apache/http/params/HttpConnectionParams.java",
"core/java/org/apache/http/params/HttpParams.java",
- "core/java/android/net/http/HttpResponseCache.java",
"core/java/android/net/http/SslCertificate.java",
"core/java/android/net/http/SslError.java",
"core/java/com/android/internal/util/HexDump.java",
diff --git a/api/current.txt b/api/current.txt
index 3a44d348bedc..9269d979104f 100755
--- a/api/current.txt
+++ b/api/current.txt
@@ -17,6 +17,7 @@ package android {
field public static final java.lang.String ACCESS_NOTIFICATION_POLICY = "android.permission.ACCESS_NOTIFICATION_POLICY";
field public static final java.lang.String ACCESS_WIFI_STATE = "android.permission.ACCESS_WIFI_STATE";
field public static final java.lang.String ACCOUNT_MANAGER = "android.permission.ACCOUNT_MANAGER";
+ field public static final java.lang.String ACTIVITY_RECOGNITION = "android.permission.ACTIVITY_RECOGNITION";
field public static final java.lang.String ADD_VOICEMAIL = "com.android.voicemail.permission.ADD_VOICEMAIL";
field public static final java.lang.String ANSWER_PHONE_CALLS = "android.permission.ANSWER_PHONE_CALLS";
field public static final java.lang.String BATTERY_STATS = "android.permission.BATTERY_STATS";
@@ -168,6 +169,7 @@ package android {
public static final class Manifest.permission_group {
ctor public Manifest.permission_group();
+ field public static final java.lang.String ACTIVITY_RECOGNITION = "android.permission-group.ACTIVITY_RECOGNITION";
field public static final java.lang.String CALENDAR = "android.permission-group.CALENDAR";
field public static final java.lang.String CALL_LOG = "android.permission-group.CALL_LOG";
field public static final java.lang.String CAMERA = "android.permission-group.CAMERA";
@@ -32540,7 +32542,7 @@ package android.os {
public class Build {
ctor public Build();
- method public static java.util.List<android.os.Build.Partition> getPartitions();
+ method public static java.util.List<android.os.Build.Partition> getFingerprintedPartitions();
method public static java.lang.String getRadioVersion();
method public static java.lang.String getSerial();
field public static final java.lang.String BOARD;
@@ -32571,9 +32573,9 @@ package android.os {
public static class Build.Partition {
ctor public Build.Partition();
+ method public long getBuildTimeMillis();
method public java.lang.String getFingerprint();
method public java.lang.String getName();
- method public long getTimeMillis();
field public static final java.lang.String PARTITION_NAME_SYSTEM = "system";
}
@@ -43323,7 +43325,7 @@ package android.telephony.data {
field public static final int PROTOCOL_IPV6 = 1; // 0x1
field public static final int PROTOCOL_PPP = 3; // 0x3
field public static final int TYPE_CBS = 128; // 0x80
- field public static final int TYPE_DEFAULT = 1; // 0x1
+ field public static final int TYPE_DEFAULT = 17; // 0x11
field public static final int TYPE_DUN = 8; // 0x8
field public static final int TYPE_EMERGENCY = 512; // 0x200
field public static final int TYPE_FOTA = 32; // 0x20
@@ -48025,6 +48027,7 @@ package android.view {
public class TouchDelegate {
ctor public TouchDelegate(android.graphics.Rect, android.view.View);
+ method public android.view.accessibility.AccessibilityNodeInfo.TouchDelegateInfo getTouchDelegateInfo();
method public boolean onTouchEvent(android.view.MotionEvent);
field public static final int ABOVE = 1; // 0x1
field public static final int BELOW = 2; // 0x2
@@ -50007,6 +50010,7 @@ package android.view.accessibility {
method public int getTextSelectionEnd();
method public int getTextSelectionStart();
method public java.lang.CharSequence getTooltipText();
+ method public android.view.accessibility.AccessibilityNodeInfo.TouchDelegateInfo getTouchDelegateInfo();
method public android.view.accessibility.AccessibilityNodeInfo getTraversalAfter();
method public android.view.accessibility.AccessibilityNodeInfo getTraversalBefore();
method public java.lang.String getViewIdResourceName();
@@ -50097,6 +50101,7 @@ package android.view.accessibility {
method public void setTextEntryKey(boolean);
method public void setTextSelection(int, int);
method public void setTooltipText(java.lang.CharSequence);
+ method public void setTouchDelegateInfo(android.view.accessibility.AccessibilityNodeInfo.TouchDelegateInfo);
method public void setTraversalAfter(android.view.View);
method public void setTraversalAfter(android.view.View, int);
method public void setTraversalBefore(android.view.View);
@@ -50223,6 +50228,16 @@ package android.view.accessibility {
field public static final int RANGE_TYPE_PERCENT = 2; // 0x2
}
+ public static final class AccessibilityNodeInfo.TouchDelegateInfo implements android.os.Parcelable {
+ ctor public AccessibilityNodeInfo.TouchDelegateInfo(java.util.Map<android.graphics.Region, android.view.View>);
+ method public int describeContents();
+ method public android.graphics.Region getRegionAt(int);
+ method public int getRegionCount();
+ method public android.view.accessibility.AccessibilityNodeInfo getTargetForRegion(android.graphics.Region);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.view.accessibility.AccessibilityNodeInfo.TouchDelegateInfo> CREATOR;
+ }
+
public abstract class AccessibilityNodeProvider {
ctor public AccessibilityNodeProvider();
method public void addExtraDataToAccessibilityNodeInfo(int, android.view.accessibility.AccessibilityNodeInfo, java.lang.String, android.os.Bundle);
diff --git a/api/system-current.txt b/api/system-current.txt
index ac8fc9c23cb8..88fa0f7155d9 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -119,6 +119,7 @@ package android {
field public static final java.lang.String MOUNT_FORMAT_FILESYSTEMS = "android.permission.MOUNT_FORMAT_FILESYSTEMS";
field public static final java.lang.String MOUNT_UNMOUNT_FILESYSTEMS = "android.permission.MOUNT_UNMOUNT_FILESYSTEMS";
field public static final java.lang.String MOVE_PACKAGE = "android.permission.MOVE_PACKAGE";
+ field public static final java.lang.String NETWORK_SETUP_WIZARD = "android.permission.NETWORK_SETUP_WIZARD";
field public static final java.lang.String NOTIFICATION_DURING_SETUP = "android.permission.NOTIFICATION_DURING_SETUP";
field public static final java.lang.String NOTIFY_TV_INPUTS = "android.permission.NOTIFY_TV_INPUTS";
field public static final java.lang.String OBSERVE_APP_USAGE = "android.permission.OBSERVE_APP_USAGE";
@@ -1280,14 +1281,6 @@ package android.content.pm.permission {
}
-package android.graphics.drawable {
-
- public final class Icon implements android.os.Parcelable {
- method public static android.graphics.drawable.Icon createWithResource(android.content.res.Resources, int);
- }
-
-}
-
package android.hardware {
public final class Sensor {
@@ -3189,6 +3182,7 @@ package android.net {
public class ConnectivityManager {
method public java.lang.String getCaptivePortalServerUrl();
method public boolean isTetheringSupported();
+ method public void setAirplaneMode(boolean);
method public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback);
method public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback, android.os.Handler);
method public void stopTethering(int);
@@ -4136,7 +4130,6 @@ package android.os {
public class UserManager {
method public void clearSeedAccountData();
- method public int[] getProfileIds(int, boolean);
method public java.lang.String getSeedAccountName();
method public android.os.PersistableBundle getSeedAccountOptions();
method public java.lang.String getSeedAccountType();
@@ -4201,8 +4194,8 @@ package android.permission {
}
public static final class PermissionManager.SplitPermissionInfo {
- method public java.lang.String[] getNewPermissions();
- method public java.lang.String getRootPermission();
+ method public java.util.List<java.lang.String> getNewPermissions();
+ method public java.lang.String getSplitPermission();
method public int getTargetSdk();
}
@@ -5287,6 +5280,7 @@ package android.telephony {
method public int getRejectCause();
method public int getTransportType();
method public boolean isEmergencyEnabled();
+ method public boolean isRoaming();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.telephony.NetworkRegistrationState> CREATOR;
field public static final int DOMAIN_CS = 1; // 0x1
@@ -5374,6 +5368,8 @@ package android.telephony {
method public void setSubscriptionPlans(int, java.util.List<android.telephony.SubscriptionPlan>);
field public static final java.lang.String ACTION_MANAGE_SUBSCRIPTION_PLANS = "android.telephony.action.MANAGE_SUBSCRIPTION_PLANS";
field public static final java.lang.String ACTION_REFRESH_SUBSCRIPTION_PLANS = "android.telephony.action.REFRESH_SUBSCRIPTION_PLANS";
+ field public static final android.net.Uri ENHANCED_4G_ENABLED_CONTENT_URI;
+ field public static final android.net.Uri WFC_ENABLED_CONTENT_URI;
}
public final class SubscriptionPlan implements android.os.Parcelable {
@@ -6653,7 +6649,7 @@ package android.util {
package android.view {
public abstract class Window {
- method public void addPrivateFlags(int);
+ method public void addSystemFlags(int);
}
public abstract interface WindowManager implements android.view.ViewManager {
@@ -6663,7 +6659,10 @@ package android.view {
public static class WindowManager.LayoutParams extends android.view.ViewGroup.LayoutParams implements android.os.Parcelable {
method public final long getUserActivityTimeout();
method public final void setUserActivityTimeout(long);
- field public static final int PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS = 524288; // 0x80000
+ field public static final int SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS = 524288; // 0x80000
+ }
+
+ public static abstract class WindowManager.LayoutParams.SystemFlags implements java.lang.annotation.Annotation {
}
}
diff --git a/api/test-current.txt b/api/test-current.txt
index 937c2660ec0a..463c9d358985 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -1609,6 +1609,10 @@ package android.view.accessibility {
method public void writeToParcelNoRecycle(android.os.Parcel, int);
}
+ public static final class AccessibilityNodeInfo.TouchDelegateInfo implements android.os.Parcelable {
+ method public long getAccessibilityIdForRegion(android.graphics.Region);
+ }
+
public final class AccessibilityWindowInfo implements android.os.Parcelable {
method public static void setNumInstancesInUseCounter(java.util.concurrent.atomic.AtomicInteger);
}
diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h
index 4091d951ba06..6a9e8a1bf688 100644
--- a/cmds/statsd/src/StatsLogProcessor.h
+++ b/cmds/statsd/src/StatsLogProcessor.h
@@ -39,7 +39,8 @@ enum DumpReportReason {
GET_DATA_CALLED = 4,
ADB_DUMP = 5,
CONFIG_RESET = 6,
- STATSCOMPANION_DIED = 7
+ STATSCOMPANION_DIED = 7,
+ TERMINATION_SIGNAL_RECEIVED = 8
};
class StatsLogProcessor : public ConfigListener {
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index 8da2d447a163..fb6f8c8d4590 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -867,6 +867,13 @@ void StatsService::Startup() {
mConfigManager->Startup();
}
+void StatsService::Terminate() {
+ ALOGI("StatsService::Terminating");
+ if (mProcessor != nullptr) {
+ mProcessor->WriteDataToDisk(TERMINATION_SIGNAL_RECEIVED);
+ }
+}
+
void StatsService::OnLogEvent(LogEvent* event) {
mProcessor->OnLogEvent(event);
if (mShellSubscriber != nullptr) {
diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h
index 1f1d782af235..cbf34292c1d4 100644
--- a/cmds/statsd/src/StatsService.h
+++ b/cmds/statsd/src/StatsService.h
@@ -84,6 +84,11 @@ public:
void Startup();
/**
+ * Called when terminiation signal received.
+ */
+ void Terminate();
+
+ /**
* Called by LogReader when there's a log event to process.
*/
virtual void OnLogEvent(LogEvent* event);
diff --git a/cmds/statsd/src/atom_field_options.proto b/cmds/statsd/src/atom_field_options.proto
index a2a03b14c073..453bf7e126cd 100644
--- a/cmds/statsd/src/atom_field_options.proto
+++ b/cmds/statsd/src/atom_field_options.proto
@@ -36,8 +36,8 @@ enum StateField {
// exclusive state field, and any number of primary key fields.
// For example,
// message UidProcessStateChanged {
-// optional int32 uid = 1 [(stateFieldOption).option = PRIMARY];
-// optional android.app.ProcessStateEnum state = 2 [(stateFieldOption).option = EXCLUSIVE];
+// optional int32 uid = 1 [(state_field_option).option = PRIMARY];
+// optional android.app.ProcessStateEnum state = 2 [(state_field_option).option = EXCLUSIVE];
// }
// Each of this UidProcessStateChanged atom represents a state change for a specific uid.
// A new state automatically overrides the previous state.
@@ -46,16 +46,16 @@ enum StateField {
// the primary key.
// For example:
// message ThreadStateChanged {
-// optional int32 pid = 1 [(stateFieldOption).option = PRIMARY];
-// optional int32 tid = 2 [(stateFieldOption).option = PRIMARY];
-// optional int32 state = 3 [(stateFieldOption).option = EXCLUSIVE];
+// optional int32 pid = 1 [(state_field_option).option = PRIMARY];
+// optional int32 tid = 2 [(state_field_option).option = PRIMARY];
+// optional int32 state = 3 [(state_field_option).option = EXCLUSIVE];
// }
//
// Sometimes, there is no primary key field, when the state is GLOBAL.
// For example,
//
// message ScreenStateChanged {
-// optional android.view.DisplayStateEnum state = 1 [(stateFieldOption).option = EXCLUSIVE];
+// optional android.view.DisplayStateEnum state = 1 [(state_field_option).option = EXCLUSIVE];
// }
//
// Only fields of primary types can be annotated. AttributionNode cannot be primary keys (and they
@@ -66,7 +66,7 @@ message StateAtomFieldOption {
extend google.protobuf.FieldOptions {
// Flags to decorate an atom that presents a state change.
- optional StateAtomFieldOption stateFieldOption = 50000;
+ optional StateAtomFieldOption state_field_option = 50000;
// Flags to decorate the uid fields in an atom.
optional bool is_uid = 50001 [default = false];
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 9d83afdeb819..501b59388aed 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -26,12 +26,11 @@ import "frameworks/base/core/proto/android/app/job/enums.proto";
import "frameworks/base/core/proto/android/bluetooth/enums.proto";
import "frameworks/base/core/proto/android/os/enums.proto";
import "frameworks/base/core/proto/android/server/enums.proto";
+import "frameworks/base/core/proto/android/service/procstats_enum.proto";
+import "frameworks/base/core/proto/android/stats/enums.proto";
import "frameworks/base/core/proto/android/telecomm/enums.proto";
import "frameworks/base/core/proto/android/telephony/enums.proto";
import "frameworks/base/core/proto/android/view/enums.proto";
-import "frameworks/base/proto/src/stats_enums.proto";
-import "frameworks/base/core/proto/android/service/procstats.proto";
-import "frameworks/base/core/proto/android/internal/powerprofile.proto";
/**
* The master atom class. This message defines all of the available
@@ -142,6 +141,8 @@ message Atom {
BatteryHealthSnapshot battery_health_snapshot = 91;
SlowIo slow_io = 92;
BatteryCausedShutdown battery_caused_shutdown = 93;
+ PhoneServiceStateChanged phone_service_state_changed = 94;
+ PhoneStateChanged phone_state_changed = 95;
}
// Pulled events will start at field 10000.
@@ -273,7 +274,7 @@ message ThermalThrottlingStateChanged {
*/
message ScreenStateChanged {
// New screen state, from frameworks/base/core/proto/android/view/enums.proto.
- optional android.view.DisplayStateEnum state = 1 [(stateFieldOption).option = EXCLUSIVE];
+ optional android.view.DisplayStateEnum state = 1 [(state_field_option).option = EXCLUSIVE];
}
/**
@@ -284,10 +285,10 @@ message ScreenStateChanged {
* frameworks/base/services/core/java/com/android/server/am/BatteryStatsService.java
*/
message UidProcessStateChanged {
- optional int32 uid = 1 [(stateFieldOption).option = PRIMARY, (is_uid) = true];
+ optional int32 uid = 1 [(state_field_option).option = PRIMARY, (is_uid) = true];
// The state, from frameworks/base/core/proto/android/app/enums.proto.
- optional android.app.ProcessStateEnum state = 2 [(stateFieldOption).option = EXCLUSIVE];
+ optional android.app.ProcessStateEnum state = 2 [(state_field_option).option = EXCLUSIVE];
}
/**
@@ -319,7 +320,7 @@ message ActivityManagerSleepStateChanged {
ASLEEP = 1;
AWAKE = 2;
}
- optional State state = 1 [(stateFieldOption).option = EXCLUSIVE];
+ optional State state = 1 [(state_field_option).option = EXCLUSIVE];
}
/**
@@ -338,7 +339,7 @@ message MemoryFactorStateChanged {
CRITICAL = 4; // critical memory.
}
- optional State factor = 1 [(stateFieldOption).option = EXCLUSIVE];
+ optional State factor = 1 [(state_field_option).option = EXCLUSIVE];
}
/**
@@ -1406,6 +1407,33 @@ message PhoneSignalStrengthChanged {
optional android.telephony.SignalStrengthEnum signal_strength = 1;
}
+
+/**
+ * Logs when the phone state, sim state or signal strength changes
+ *
+ * Logged from:
+ * frameworks/base/core/java/com/android/internal/os/BatteryStatsImpl.java
+ */
+message PhoneServiceStateChanged {
+ optional android.telephony.ServiceStateEnum state = 1;
+ optional android.telephony.SimStateEnum sim_state = 2;
+ optional android.telephony.SignalStrengthEnum signal_strength = 3;
+}
+
+/**
+ * Logs when the phone becomes on or off.
+ *
+ * Logged from:
+ * frameworks/base/core/java/com/android/internal/os/TelephonyRegistry.java
+ */
+message PhoneStateChanged {
+ enum State {
+ OFF = 0;
+ ON = 1;
+ }
+ optional State state = 1;
+}
+
/**
* Logs that a setting was updated.
* Logged from:
@@ -1912,7 +1940,7 @@ message LmkKillOccurred {
*/
message AppDied {
// timestamp(elapsedRealtime) of record creation
- optional uint64 timestamp_millis = 1 [(stateFieldOption).option = EXCLUSIVE];
+ optional uint64 timestamp_millis = 1 [(state_field_option).option = EXCLUSIVE];
}
/**
@@ -1923,7 +1951,7 @@ message GenericAtom {
optional int32 uid = 1 [(is_uid) = true];
// An event_id indicates the type of event.
- optional android.os.statsd.EventType event_id = 2;
+ optional android.stats.EventType event_id = 2;
}
/**
@@ -2527,8 +2555,7 @@ message LooperStats {
// recorded_message_count.
//
// If recorded_message_count is different than message_count, it means data
- // collection has been sampled. All the fields below will be sampled in this
- // case.
+ // collection has been sampled. The fields below will be sampled in this case.
optional int64 recorded_message_count = 7;
// Total latency of all processed messages.
@@ -2544,6 +2571,32 @@ message LooperStats {
// True if the screen was interactive PowerManager#isInteractive at the end of the call.
optional bool screen_interactive = 10;
+
+ // Max recorded CPU usage of all processed messages.
+ optional int64 recorded_max_cpu_micros = 11;
+
+ // Max recorded latency of all processed messages.
+ optional int64 recorded_max_latency_micros = 12;
+
+ // Total number of messages we tracked the dispatching delay for. If we
+ // collected data for all the messages, message_count will be equal to
+ // recorded_delay_message_count.
+ //
+ // If recorded_delay_message_count is different than message_count, it means data
+ // collection has been sampled or/and not all messages specified the target dispatch time.
+ // The fields below will be sampled in this case.
+ optional int64 recorded_delay_message_count = 13;
+
+ // Total dispatching delay of all processed messages.
+ // Calculated as a difference between the target dispatching time (Message.when)
+ // and the actual dispatching time.
+ // Average can be computed using recorded_total_delay_millis / recorded_delay_message_count.
+ optional int64 recorded_total_delay_millis = 14;
+
+ // Max dispatching delay of all processed messages.
+ // Calculated as a difference between the target dispatching time (Message.when)
+ // and the actual dispatching time.
+ optional int64 recorded_max_delay_millis = 15;
}
/**
@@ -2662,11 +2715,288 @@ message NumFingerprints {
optional int32 num_fingerprints = 2;
}
+message AggStats {
+ optional int64 min = 1;
+
+ optional int64 average = 2;
+
+ optional int64 max = 3;
+}
+
+message ProcessStatsStateProto {
+ optional android.service.procstats.ScreenState screen_state = 1;
+
+ optional android.service.procstats.MemoryState memory_state = 2;
+
+ // this enum list is from frameworks/base/core/java/com/android/internal/app/procstats/ProcessStats.java
+ // and not frameworks/base/core/java/android/app/ActivityManager.java
+ optional android.service.procstats.ProcessState process_state = 3;
+
+ // Millisecond uptime duration spent in this state
+ optional int64 duration_ms = 4;
+
+ // Millisecond elapsed realtime duration spent in this state
+ optional int64 realtime_duration_ms = 9;
+
+ // # of samples taken
+ optional int32 sample_size = 5;
+
+ // PSS is memory reserved for this process
+ optional AggStats pss = 6;
+
+ // USS is memory shared between processes, divided evenly for accounting
+ optional AggStats uss = 7;
+
+ // RSS is memory resident for this process
+ optional AggStats rss = 8;
+}
+
+// Next Tag: 7
+message ProcessStatsProto {
+ // Name of process.
+ optional string process = 1;
+
+ // Uid of the process.
+ optional int32 uid = 2;
+
+ // Information about how often kills occurred
+ message Kill {
+ // Count of excessive CPU kills
+ optional int32 cpu = 1;
+
+ // Count of kills when cached
+ optional int32 cached = 2;
+
+ // PSS stats during cached kill
+ optional AggStats cached_pss = 3;
+ }
+ optional Kill kill = 3;
+
+ // Time and memory spent in various states.
+ repeated ProcessStatsStateProto states = 5;
+
+ // Total time process has been running... screen_state, memory_state, and process_state
+ // will not be set.
+ optional ProcessStatsStateProto total_running_state = 6;
+}
+
+message PackageServiceOperationStatsProto {
+ // Operate enum: Started, Foreground, Bound, Executing
+ optional android.service.procstats.ServiceOperationState operation = 1;
+
+ // Number of times the service was in this operation.
+ optional int32 count = 2;
+
+ // Information about a state the service can be in.
+ message StateStats {
+ // Screen state enum.
+ optional android.service.procstats.ScreenState screen_state = 1;
+ // Memory state enum.
+ optional android.service.procstats.MemoryState memory_state = 2;
+
+ // duration in milliseconds.
+ optional int64 duration_ms = 3;
+ // Millisecond elapsed realtime duration spent in this state
+ optional int64 realtime_duration_ms = 4;
+ }
+ repeated StateStats state_stats = 3;
+}
+
+message PackageServiceStatsProto {
+ // Name of service component.
+ optional string service_name = 1;
+
+ // The operation stats.
+ // The package_name, package_uid, package_version, service_name will not be set to save space.
+ repeated PackageServiceOperationStatsProto operation_stats = 2;
+}
+
+message PackageAssociationSourceProcessStatsProto {
+ // Uid of the process.
+ optional int32 process_uid = 1;
+ // Process name.
+ optional string process_name = 2;
+
+ // Total count of the times this association appeared.
+ optional int32 total_count = 3;
+
+ // Millisecond uptime total duration this association was around.
+ optional int64 total_duration_ms = 4;
+
+ // Total count of the times this association became actively impacting its target process.
+ optional int32 active_count = 5;
+
+ // Information on one source in this association.
+ message StateStats {
+ // Process state enum.
+ optional android.service.procstats.ProcessState process_state = 1;
+ // Millisecond uptime duration spent in this state
+ optional int64 duration_ms = 2;
+ // Millisecond elapsed realtime duration spent in this state
+ optional int64 realtime_duration_ms = 3;
+ }
+ repeated StateStats active_state_stats = 6;
+}
+
+message PackageAssociationProcessStatsProto {
+ // Name of the target component.
+ optional string component_name = 1;
+ // Information on one source in this association.
+ repeated PackageAssociationSourceProcessStatsProto sources = 2;
+}
+
+
+message ProcessStatsPackageProto {
+ // Name of package.
+ optional string package = 1;
+
+ // Uid of the package.
+ optional int32 uid = 2;
+
+ // Version of the package.
+ optional int64 version = 3;
+
+ // Stats for each process running with the package loaded in to it.
+ repeated ProcessStatsProto process_stats = 4;
+
+ // Stats for each of the package's services.
+ repeated PackageServiceStatsProto service_stats = 5;
+
+ // Stats for each association with the package.
+ repeated PackageAssociationProcessStatsProto association_stats = 6;
+}
+
+message ProcessStatsSectionProto {
+ // Elapsed realtime at start of report.
+ optional int64 start_realtime_ms = 1;
+
+ // Elapsed realtime at end of report.
+ optional int64 end_realtime_ms = 2;
+
+ // CPU uptime at start of report.
+ optional int64 start_uptime_ms = 3;
+
+ // CPU uptime at end of report.
+ optional int64 end_uptime_ms = 4;
+
+ // System runtime library. e.g. "libdvm.so", "libart.so".
+ optional string runtime = 5;
+
+ // whether kernel reports swapped pss.
+ optional bool has_swapped_pss = 6;
+
+ // Data completeness. e.g. "complete", "partial", shutdown", or "sysprops".
+ enum Status {
+ STATUS_UNKNOWN = 0;
+ STATUS_COMPLETE = 1;
+ STATUS_PARTIAL = 2;
+ STATUS_SHUTDOWN = 3;
+ STATUS_SYSPROPS = 4;
+ }
+ repeated Status status = 7;
+
+ // Stats for each process.
+ repeated ProcessStatsProto process_stats = 8;
+
+ // Stats for each package.
+ repeated ProcessStatsPackageProto package_stats = 9;
+}
+
/**
* Pulled from ProcessStatsService.java
*/
message ProcStats {
- optional android.service.procstats.ProcessStatsSectionProto proc_stats_section = 1;
+ optional ProcessStatsSectionProto proc_stats_section = 1;
+}
+
+message PowerProfileProto {
+ optional double cpu_suspend = 1;
+
+ optional double cpu_idle = 2;
+
+ optional double cpu_active = 3;
+
+ message CpuCluster {
+ optional int32 id = 1;
+ optional double cluster_power = 2;
+ optional int32 cores = 3;
+ repeated int64 speed = 4;
+ repeated double core_power = 5;
+ }
+
+ repeated CpuCluster cpu_cluster = 40;
+
+ optional double wifi_scan = 4;
+
+ optional double wifi_on = 5;
+
+ optional double wifi_active = 6;
+
+ optional double wifi_controller_idle = 7;
+
+ optional double wifi_controller_rx = 8;
+
+ optional double wifi_controller_tx = 9;
+
+ repeated double wifi_controller_tx_levels = 10;
+
+ optional double wifi_controller_operating_voltage = 11;
+
+ optional double bluetooth_controller_idle = 12;
+
+ optional double bluetooth_controller_rx = 13;
+
+ optional double bluetooth_controller_tx = 14;
+
+ optional double bluetooth_controller_operating_voltage = 15;
+
+ optional double modem_controller_sleep = 16;
+
+ optional double modem_controller_idle = 17;
+
+ optional double modem_controller_rx = 18;
+
+ repeated double modem_controller_tx = 19;
+
+ optional double modem_controller_operating_voltage = 20;
+
+ optional double gps_on = 21;
+
+ repeated double gps_signal_quality_based = 22;
+
+ optional double gps_operating_voltage = 23;
+
+ optional double bluetooth_on = 24;
+
+ optional double bluetooth_active = 25;
+
+ optional double bluetooth_at_cmd = 26;
+
+ optional double ambient_display = 27;
+
+ optional double screen_on = 28;
+
+ optional double radio_on = 29;
+
+ optional double radio_scanning = 30;
+
+ optional double radio_active = 31;
+
+ optional double screen_full = 32;
+
+ optional double audio = 33;
+
+ optional double video = 34;
+
+ optional double flashlight = 35;
+
+ optional double memory = 36;
+
+ optional double camera = 37;
+
+ optional double wifi_batched_scan = 38;
+
+ optional double battery_capacity = 39;
}
/**
@@ -2674,5 +3004,5 @@ message ProcStats {
* Pulled from PowerProfile.java
*/
message PowerProfile {
- optional com.android.internal.os.PowerProfileProto power_profile_proto = 1;
-} \ No newline at end of file
+ optional PowerProfileProto power_profile = 1;
+}
diff --git a/cmds/statsd/src/hash.cpp b/cmds/statsd/src/hash.cpp
index c501c9f818b9..543a748adedb 100644
--- a/cmds/statsd/src/hash.cpp
+++ b/cmds/statsd/src/hash.cpp
@@ -16,6 +16,10 @@
#include "hash.h"
+#ifndef FALLTHROUGH_INTENDED
+#define FALLTHROUGH_INTENDED [[fallthrough]]
+#endif
+
namespace android {
namespace os {
namespace statsd {
@@ -67,8 +71,10 @@ uint32_t Hash32(const char *data, size_t n, uint32_t seed) {
switch (n) {
case 3:
h ^= ByteAs32(data[2]) << 16;
+ FALLTHROUGH_INTENDED;
case 2:
h ^= ByteAs32(data[1]) << 8;
+ FALLTHROUGH_INTENDED;
case 1:
h ^= ByteAs32(data[0]);
h *= m;
@@ -104,16 +110,22 @@ uint64_t Hash64(const char* data, size_t n, uint64_t seed) {
switch (n) {
case 7:
h ^= ByteAs64(data[6]) << 48;
+ FALLTHROUGH_INTENDED;
case 6:
h ^= ByteAs64(data[5]) << 40;
+ FALLTHROUGH_INTENDED;
case 5:
h ^= ByteAs64(data[4]) << 32;
+ FALLTHROUGH_INTENDED;
case 4:
h ^= ByteAs64(data[3]) << 24;
+ FALLTHROUGH_INTENDED;
case 3:
h ^= ByteAs64(data[2]) << 16;
+ FALLTHROUGH_INTENDED;
case 2:
h ^= ByteAs64(data[1]) << 8;
+ FALLTHROUGH_INTENDED;
case 1:
h ^= ByteAs64(data[0]);
h *= m;
diff --git a/cmds/statsd/src/main.cpp b/cmds/statsd/src/main.cpp
index a5dac0836238..6b8c12a893e8 100644
--- a/cmds/statsd/src/main.cpp
+++ b/cmds/statsd/src/main.cpp
@@ -46,6 +46,27 @@ struct log_reader_thread_data {
sp<StatsService> service;
};
+
+sp<StatsService> gStatsService = nullptr;
+
+void sigHandler(int sig) {
+ if (gStatsService != nullptr) {
+ gStatsService->Terminate();
+ }
+}
+
+void registerSigHandler()
+{
+ struct sigaction sa;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = 0;
+ sa.sa_handler = sigHandler;
+ sigaction(SIGHUP, &sa, nullptr);
+ sigaction(SIGINT, &sa, nullptr);
+ sigaction(SIGQUIT, &sa, nullptr);
+ sigaction(SIGTERM, &sa, nullptr);
+}
+
int main(int /*argc*/, char** /*argv*/) {
// Set up the looper
sp<Looper> looper(Looper::prepare(0 /* opts */));
@@ -60,23 +81,25 @@ int main(int /*argc*/, char** /*argv*/) {
::android::hardware::configureRpcThreadpool(1 /*threads*/, false /*willJoin*/);
// Create the service
- sp<StatsService> service = new StatsService(looper);
- if (defaultServiceManager()->addService(String16("stats"), service) != 0) {
+ gStatsService = new StatsService(looper);
+ if (defaultServiceManager()->addService(String16("stats"), gStatsService) != 0) {
ALOGE("Failed to add service as AIDL service");
return -1;
}
- auto ret = service->registerAsService();
+ auto ret = gStatsService->registerAsService();
if (ret != ::android::OK) {
ALOGE("Failed to add service as HIDL service");
return 1; // or handle error
}
- service->sayHiToStatsCompanion();
+ registerSigHandler();
+
+ gStatsService->sayHiToStatsCompanion();
- service->Startup();
+ gStatsService->Startup();
- sp<StatsSocketListener> socketListener = new StatsSocketListener(service);
+ sp<StatsSocketListener> socketListener = new StatsSocketListener(gStatsService);
ALOGI("using statsd socket");
// Backlog and /proc/sys/net/unix/max_dgram_qlen set to large value
diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto
index ab0b23cc009d..10ed7f3ebaa1 100644
--- a/cmds/statsd/src/stats_log.proto
+++ b/cmds/statsd/src/stats_log.proto
@@ -271,6 +271,7 @@ message ConfigMetricsReport {
ADB_DUMP = 5;
CONFIG_RESET = 6;
STATSCOMPANION_DIED = 7;
+ TERMINATION_SIGNAL_RECEIVED = 8;
}
optional DumpReportReason dump_report_reason = 8;
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index 6af34f9151b9..b71274cf5dc2 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -523,7 +523,6 @@ Landroid/net/IConnectivityManager;->getTetherableWifiRegexs()[Ljava/lang/String;
Landroid/net/IConnectivityManager;->getTetheredIfaces()[Ljava/lang/String;
Landroid/net/IConnectivityManager;->getTetheringErroredIfaces()[Ljava/lang/String;
Landroid/net/IConnectivityManager;->reportInetCondition(II)V
-Landroid/net/IConnectivityManager;->setAirplaneMode(Z)V
Landroid/net/IConnectivityManager;->startLegacyVpn(Lcom/android/internal/net/VpnProfile;)V
Landroid/net/INetworkManagementEventObserver$Stub;-><init>()V
Landroid/net/INetworkPolicyListener$Stub;-><init>()V
@@ -2216,6 +2215,7 @@ Lcom/android/org/conscrypt/OpenSSLKey;->fromPrivateKey(Ljava/security/PrivateKey
Lcom/android/org/conscrypt/OpenSSLKey;->getNativeRef()Lcom/android/org/conscrypt/NativeRef$EVP_PKEY;
Lcom/android/org/conscrypt/OpenSSLKey;->getPublicKey()Ljava/security/PublicKey;
Lcom/android/org/conscrypt/OpenSSLProvider;-><init>()V
+Lcom/android/org/conscrypt/OpenSSLRandom;-><init>()V
Lcom/android/org/conscrypt/OpenSSLSocketImpl;->getAlpnSelectedProtocol()[B
Lcom/android/org/conscrypt/OpenSSLSocketImpl;->getChannelId()[B
Lcom/android/org/conscrypt/OpenSSLSocketImpl;->getHostname()Ljava/lang/String;
@@ -2791,6 +2791,7 @@ Ljavax/net/ssl/SSLServerSocketFactory;->defaultServerSocketFactory:Ljavax/net/ss
Ljavax/net/ssl/SSLSocketFactory;->createSocket(Ljava/net/Socket;Ljava/io/InputStream;Z)Ljava/net/Socket;
Ljavax/net/ssl/SSLSocketFactory;->defaultSocketFactory:Ljavax/net/ssl/SSLSocketFactory;
Llibcore/icu/ICU;->addLikelySubtags(Ljava/util/Locale;)Ljava/util/Locale;
+Llibcore/io/Libcore;->os:Llibcore/io/Os;
Llibcore/io/Memory;->peekByte(J)B
Llibcore/io/Memory;->peekByteArray(J[BII)V
Llibcore/io/Memory;->peekInt(JZ)I
diff --git a/core/java/android/app/AppDetailsActivity.java b/core/java/android/app/AppDetailsActivity.java
new file mode 100644
index 000000000000..cd36e634f54b
--- /dev/null
+++ b/core/java/android/app/AppDetailsActivity.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import android.content.Intent;
+import android.os.Bundle;
+
+/**
+ * Helper activity that forwards you to app details page.
+ *
+ * @hide
+ */
+public class AppDetailsActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ Intent intent = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
+ intent.setData(android.net.Uri.fromParts("package", getPackageName(), null));
+ startActivity(intent);
+ finish();
+ }
+}
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 6c87fe75740e..0044005c51f2 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -377,15 +377,11 @@ final class SystemServiceRegistry {
return new DisplayManager(ctx.getOuterContext());
}});
- // InputMethodManager has its own cache strategy based on display id to support apps that
- // still assume InputMethodManager is a per-process singleton and it's safe to directly
- // access internal fields via reflection. Hence directly use ServiceFetcher instead of
- // StaticServiceFetcher/CachedServiceFetcher.
registerService(Context.INPUT_METHOD_SERVICE, InputMethodManager.class,
- new ServiceFetcher<InputMethodManager>() {
+ new StaticServiceFetcher<InputMethodManager>() {
@Override
- public InputMethodManager getService(ContextImpl ctx) {
- return InputMethodManager.forContext(ctx);
+ public InputMethodManager createService() {
+ return InputMethodManager.getInstanceInternal();
}});
registerService(Context.TEXT_SERVICES_MANAGER_SERVICE, TextServicesManager.class,
diff --git a/core/java/android/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java
index df27d583d361..c983d4f68710 100644
--- a/core/java/android/app/backup/BackupAgent.java
+++ b/core/java/android/app/backup/BackupAgent.java
@@ -29,6 +29,7 @@ import android.os.Looper;
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
@@ -222,6 +223,18 @@ public abstract class BackupAgent extends ContextWrapper {
}
/**
+ * Provided as a convenience for agent implementations that need an opportunity
+ * to do one-time initialization before the actual backup or restore operation
+ * is begun with information about the calling user.
+ * <p>
+ *
+ * @hide
+ */
+ public void onCreate(UserHandle user) {
+ onCreate();
+ }
+
+ /**
* Provided as a convenience for agent implementations that need to do some
* sort of shutdown process after backup or restore is completed.
* <p>
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index 30d5fbc7fe99..0aa053580a6d 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -107,20 +107,6 @@ public final class BluetoothDevice implements Parcelable {
"android.bluetooth.device.action.FOUND";
/**
- * Broadcast Action: Remote device disappeared.
- * <p>Sent when a remote device that was found in the last discovery is not
- * found in the current discovery.
- * <p>Always contains the extra field {@link #EXTRA_DEVICE}.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
- *
- * @hide
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- @UnsupportedAppUsage
- public static final String ACTION_DISAPPEARED =
- "android.bluetooth.device.action.DISAPPEARED";
-
- /**
* Broadcast Action: Bluetooth class of a remote device has changed.
* <p>Always contains the extra fields {@link #EXTRA_DEVICE} and {@link
* #EXTRA_CLASS}.
@@ -654,7 +640,7 @@ public final class BluetoothDevice implements Parcelable {
public static final int ACCESS_REJECTED = 2;
/**
- * No preferrence of physical transport for GATT connections to remote dual-mode devices
+ * No preference of physical transport for GATT connections to remote dual-mode devices
*/
public static final int TRANSPORT_AUTO = 0;
@@ -1971,9 +1957,7 @@ public final class BluetoothDevice implements Parcelable {
* <p>The remote device will be authenticated and communication on this socket will be
* encrypted.
* <p> Use this socket if an authenticated socket link is possible. Authentication refers
- * to the authentication of the link key to prevent man-in-the-middle type of attacks. When a
- * secure socket connection is not possible, use {@link createInsecureLeL2capCocSocket(int,
- * int)}.
+ * to the authentication of the link key to prevent man-in-the-middle type of attacks.
*
* @param psm dynamic PSM value from remote device
* @return a CoC #BluetoothSocket ready for an outgoing connection
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index 29d5a1c583a1..9b7c173a1ec5 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -1292,7 +1292,7 @@ public final class BluetoothGatt implements BluetoothProfile {
* <p>After all characteristics have been queued up and verified,
* {@link #executeReliableWrite} will execute all writes. If a characteristic
* was not written correctly, calling {@link #abortReliableWrite} will
- * cancel the current transaction without commiting any values on the
+ * cancel the current transaction without committing any values on the
* remote device.
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
diff --git a/core/java/android/bluetooth/BluetoothGattServer.java b/core/java/android/bluetooth/BluetoothGattServer.java
index ef1b0bd71885..13b1b4f93cf0 100644
--- a/core/java/android/bluetooth/BluetoothGattServer.java
+++ b/core/java/android/bluetooth/BluetoothGattServer.java
@@ -522,7 +522,7 @@ public final class BluetoothGattServer implements BluetoothProfile {
* {@link BluetoothGattServerCallback#onConnectionStateChange} callback will be
* invoked when the connection state changes as a result of this function.
*
- * <p>The autoConnect paramter determines whether to actively connect to
+ * <p>The autoConnect parameter determines whether to actively connect to
* the remote device, or rather passively scan and finalize the connection
* when the remote device is in range/available. Generally, the first ever
* connection to a device should be direct (autoConnect set to false) and
@@ -695,7 +695,7 @@ public final class BluetoothGattServer implements BluetoothProfile {
/**
* Add a service to the list of services to be hosted.
*
- * <p>Once a service has been addded to the the list, the service and its
+ * <p>Once a service has been addded to the list, the service and its
* included characteristics will be provided by the local device.
*
* <p>If the local device has already exposed services when this function
diff --git a/core/java/android/bluetooth/BluetoothServerSocket.java b/core/java/android/bluetooth/BluetoothServerSocket.java
index 758c68db1c5f..4e886250b4fa 100644
--- a/core/java/android/bluetooth/BluetoothServerSocket.java
+++ b/core/java/android/bluetooth/BluetoothServerSocket.java
@@ -203,8 +203,8 @@ public final class BluetoothServerSocket implements Closeable {
/**
* Returns the assigned dynamic protocol/service multiplexer (PSM) value for the listening L2CAP
* Connection-oriented Channel (CoC) server socket. This server socket must be returned by the
- * {@link BluetoothAdapter.listenUsingL2capChannel()} or {@link
- * BluetoothAdapter.listenUsingInsecureL2capChannel()}. The returned value is undefined if this
+ * {@link BluetoothAdapter#listenUsingL2capChannel()} or {@link
+ * BluetoothAdapter#listenUsingInsecureL2capChannel()}. The returned value is undefined if this
* method is called on non-L2CAP server sockets.
*
* @return the assigned PSM or LE_PSM value depending on transport
diff --git a/core/java/android/bluetooth/le/AdvertisingSetCallback.java b/core/java/android/bluetooth/le/AdvertisingSetCallback.java
index 58a3696fc092..51324fdb01ff 100644
--- a/core/java/android/bluetooth/le/AdvertisingSetCallback.java
+++ b/core/java/android/bluetooth/le/AdvertisingSetCallback.java
@@ -56,7 +56,7 @@ public abstract class AdvertisingSetCallback {
/**
* Callback triggered in response to {@link BluetoothLeAdvertiser#startAdvertisingSet}
* indicating result of the operation. If status is ADVERTISE_SUCCESS, then advertisingSet
- * contains the started set and it is advertising. If error occured, advertisingSet is
+ * contains the started set and it is advertising. If error occurred, advertisingSet is
* null, and status will be set to proper error code.
*
* @param advertisingSet The advertising set that was started or null if error.
diff --git a/core/java/android/content/AbstractThreadedSyncAdapter.java b/core/java/android/content/AbstractThreadedSyncAdapter.java
index b528e397906f..a086a308d0d9 100644
--- a/core/java/android/content/AbstractThreadedSyncAdapter.java
+++ b/core/java/android/content/AbstractThreadedSyncAdapter.java
@@ -95,7 +95,7 @@ import java.util.concurrent.atomic.AtomicInteger;
* the SyncManager will wait until the sync adapter is not in use before requesting that
* it sync an account's data.
* <li><code>android:isAlwaysSyncable</code> defaults to false and if true tells the SyncManager
- * to intialize the isSyncable state to 1 for that sync adapter for each account that is added.
+ * to initialize the isSyncable state to 1 for that sync adapter for each account that is added.
* <li><code>android:syncAdapterSettingsAction</code> defaults to null and if supplied it
* specifies an Intent action of an activity that can be used to adjust the sync adapter's
* sync settings. The activity must live in the same package as the sync adapter.
diff --git a/core/java/android/content/ClipData.java b/core/java/android/content/ClipData.java
index 089cf1098ffc..ed3d4557061e 100644
--- a/core/java/android/content/ClipData.java
+++ b/core/java/android/content/ClipData.java
@@ -224,7 +224,7 @@ public class ClipData implements Parcelable {
* Create an Item consisting of a single block of (possibly styled) text,
* with an alternative HTML formatted representation. You <em>must</em>
* supply a plain text representation in addition to HTML text; coercion
- * will not be done from HTML formated text into plain text.
+ * will not be done from HTML formatted text into plain text.
*/
public Item(CharSequence text, String htmlText) {
mText = text;
@@ -268,7 +268,7 @@ public class ClipData implements Parcelable {
* Create a complex Item, containing multiple representations of
* text, HTML text, Intent, and/or URI. If providing HTML text, you
* <em>must</em> supply a plain text representation as well; coercion
- * will not be done from HTML formated text into plain text.
+ * will not be done from HTML formatted text into plain text.
*/
public Item(CharSequence text, String htmlText, Intent intent, Uri uri) {
if (htmlText != null && text == null) {
diff --git a/core/java/android/content/ContentProviderOperation.java b/core/java/android/content/ContentProviderOperation.java
index 7dc45776715c..6a3fa6b2f197 100644
--- a/core/java/android/content/ContentProviderOperation.java
+++ b/core/java/android/content/ContentProviderOperation.java
@@ -637,7 +637,7 @@ public class ContentProviderOperation implements Parcelable {
/**
* The selection and arguments to use. An occurrence of '?' in the selection will be
- * replaced with the corresponding occurence of the selection argument. Any of the
+ * replaced with the corresponding occurrence of the selection argument. Any of the
* selection arguments may be overwritten by a selection argument back reference as
* specified by {@link #withSelectionBackReference}.
* This can only be used with builders of type update, delete, or assert.
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index a882434d9d98..c19909da3007 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -1877,7 +1877,7 @@ public abstract class ContentResolver {
* that services the content at uri, starting the provider if necessary. Returns
* null if there is no provider associated wih the uri. The caller must indicate that they are
* done with the provider by calling {@link ContentProviderClient#release} which will allow
- * the system to release the provider it it determines that there is no other reason for
+ * the system to release the provider if it determines that there is no other reason for
* keeping it active.
* @param uri specifies which provider should be acquired
* @return a {@link ContentProviderClient} that is associated with the {@link ContentProvider}
@@ -1897,7 +1897,7 @@ public abstract class ContentResolver {
* with the authority of name, starting the provider if necessary. Returns
* null if there is no provider associated wih the uri. The caller must indicate that they are
* done with the provider by calling {@link ContentProviderClient#release} which will allow
- * the system to release the provider it it determines that there is no other reason for
+ * the system to release the provider if it determines that there is no other reason for
* keeping it active.
* @param name specifies which provider should be acquired
* @return a {@link ContentProviderClient} that is associated with the {@link ContentProvider}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index d71157459fc8..db4adcfaaf35 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -187,7 +187,7 @@ public abstract class Context {
*
* <p>This was the legacy (but undocumented) behavior in and
* before Gingerbread (Android 2.3) and this flag is implied when
- * targetting such releases. For applications targetting SDK
+ * targeting such releases. For applications targeting SDK
* versions <em>greater than</em> Android 2.3, this flag must be
* explicitly set if desired.
*
@@ -2840,7 +2840,7 @@ public abstract class Context {
*
* @param service Description of the service to be stopped. The Intent must be either
* fully explicit (supplying a component name) or specify a specific package
- * name it is targetted to.
+ * name it is targeted to.
*
* @return If there is a service matching the given Intent that is already
* running, then it is stopped and {@code true} is returned; else {@code false} is returned.
diff --git a/core/java/android/content/CursorLoader.java b/core/java/android/content/CursorLoader.java
index 4e46d5716c7b..4ccafab741d8 100644
--- a/core/java/android/content/CursorLoader.java
+++ b/core/java/android/content/CursorLoader.java
@@ -36,7 +36,7 @@ import java.util.Arrays;
* perform, either through the
* {@link #CursorLoader(Context, Uri, String[], String, String[], String)} or
* creating an empty instance with {@link #CursorLoader(Context)} and filling
- * in the desired paramters with {@link #setUri(Uri)}, {@link #setSelection(String)},
+ * in the desired parameters with {@link #setUri(Uri)}, {@link #setSelection(String)},
* {@link #setSelectionArgs(String[])}, {@link #setSortOrder(String)},
* and {@link #setProjection(String[])}.
*
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index af910e047341..8913748e0c48 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -3955,6 +3955,12 @@ public class Intent implements Parcelable, Cloneable {
public static final String EXTRA_LTE_EARFCN_RSRP_BOOST = "LteEarfcnRsrpBoost";
/**
+ * An parcelable extra used with {@link #ACTION_SERVICE_STATE} representing the service state.
+ * @hide
+ */
+ public static final String EXTRA_SERVICE_STATE = "android.intent.extra.SERVICE_STATE";
+
+ /**
* The name of the extra used to define the text to be processed, as a
* CharSequence. Note that this may be a styled CharSequence, so you must use
* {@link Bundle#getCharSequence(String) Bundle.getCharSequence()} to retrieve it.
@@ -5523,7 +5529,7 @@ public class Intent implements Parcelable, Cloneable {
/**
* If set and this intent is being used to launch a new activity from an
* existing one, then the reply target of the existing activity will be
- * transfered to the new activity. This way the new activity can call
+ * transferred to the new activity. This way, the new activity can call
* {@link android.app.Activity#setResult} and have that result sent back to
* the reply target of the original activity.
*/
diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java
index 0469a9006b25..36d8a3720b5e 100644
--- a/core/java/android/content/IntentFilter.java
+++ b/core/java/android/content/IntentFilter.java
@@ -479,7 +479,7 @@ public class IntentFilter implements Parcelable {
/**
* Modify priority of this filter. This only affects receiver filters.
* The priority of activity filters are set in XML and cannot be changed
- * programatically. The default priority is 0. Positive values will be
+ * programmatically. The default priority is 0. Positive values will be
* before the default, lower values will be after it. Applications should
* use a value that is larger than {@link #SYSTEM_LOW_PRIORITY} and
* smaller than {@link #SYSTEM_HIGH_PRIORITY} .
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 5926af6f9082..0a4f4eb8506c 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -1408,5 +1408,13 @@ public class ActivityInfo extends ComponentInfo implements Parcelable {
* @attr ref android.R.styleable#AndroidManifestLayout_minHeight
*/
public final int minHeight;
+
+ /**
+ * Returns if this {@link WindowLayout} has specified bounds.
+ * @hide
+ */
+ public boolean hasSpecifiedSize() {
+ return width >= 0 || height >= 0 || widthFraction >= 0 || heightFraction >= 0;
+ }
}
}
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 225b6cfd9a8f..c33f143b4cbc 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -236,7 +236,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
/**
* Value for {@link #flags}: true when the application knows how to
- * accomodate different screen densities. Corresponds to
+ * accommodate different screen densities. Corresponds to
* {@link android.R.styleable#AndroidManifestSupportsScreens_anyDensity
* android:anyDensity}.
*/
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 3032d164ef46..733fbe566b09 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -5187,6 +5187,7 @@ public abstract class PackageManager {
* @param packageName The name of the package to query
* @throws IllegalArgumentException if the given package name is not installed
*/
+ @Nullable
public abstract String getInstallerPackageName(String packageName);
/**
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index b5b4432bbdb2..7b4c6fc64a69 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -19,6 +19,7 @@ package android.content.pm;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.UserIdInt;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.PackageManager.ApplicationInfoFlags;
@@ -205,6 +206,29 @@ public abstract class PackageManagerInternal {
@PackageInfoFlags int flags, int filterCallingUid, int userId);
/**
+ * Return a List of all application packages that are installed on the
+ * device, for a specific user. If flag GET_UNINSTALLED_PACKAGES has been
+ * set, a list of all applications including those deleted with
+ * {@code DONT_DELETE_DATA} (partially installed apps with data directory)
+ * will be returned.
+ *
+ * @param flags Additional option flags to modify the data returned.
+ * @param userId The user for whom the installed applications are to be
+ * listed
+ * @param callingUid The uid of the original caller app
+ * @return A List of ApplicationInfo objects, one for each installed
+ * application. In the unlikely case there are no installed
+ * packages, an empty list is returned. If flag
+ * {@code MATCH_UNINSTALLED_PACKAGES} is set, the application
+ * information is retrieved from the list of uninstalled
+ * applications (which includes installed applications as well as
+ * applications with data directory i.e. applications which had been
+ * deleted with {@code DONT_DELETE_DATA} flag set).
+ */
+ public abstract List<ApplicationInfo> getInstalledApplications(
+ @ApplicationInfoFlags int flags, @UserIdInt int userId, int callingUid);
+
+ /**
* Retrieve launcher extras for a suspended package provided to the system in
* {@link PackageManager#setPackagesSuspended(String[], boolean, PersistableBundle,
* PersistableBundle, String)}.
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 24675d301f4a..046e9e7108fd 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -47,6 +47,7 @@ import android.annotation.Nullable;
import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.app.ActivityTaskManager;
+import android.app.AppDetailsActivity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.IntentFilter;
@@ -2440,17 +2441,17 @@ public class PackageParser {
}
- final int NS = PermissionManager.SPLIT_PERMISSIONS.length;
+ final int NS = PermissionManager.SPLIT_PERMISSIONS.size();
for (int is=0; is<NS; is++) {
final PermissionManager.SplitPermissionInfo spi =
- PermissionManager.SPLIT_PERMISSIONS[is];
+ PermissionManager.SPLIT_PERMISSIONS.get(is);
if (pkg.applicationInfo.targetSdkVersion >= spi.getTargetSdk()
- || !pkg.requestedPermissions.contains(spi.getRootPermission())) {
+ || !pkg.requestedPermissions.contains(spi.getSplitPermission())) {
continue;
}
- final String[] newPerms = spi.getNewPermissions();
- for (int in = 0; in < newPerms.length; in++) {
- final String perm = newPerms[in];
+ final List<String> newPerms = spi.getNewPermissions();
+ for (int in = 0; in < newPerms.size(); in++) {
+ final String perm = newPerms.get(in);
if (!pkg.requestedPermissions.contains(perm)) {
pkg.requestedPermissions.add(perm);
}
@@ -3882,6 +3883,11 @@ public class PackageParser {
}
}
+ // Add a hidden app detail activity which forwards user to App Details page.
+ Activity a = generateAppDetailsHiddenActivity(owner, flags, outError,
+ owner.baseHardwareAccelerated);
+ owner.activities.add(a);
+
if (hasActivityOrder) {
Collections.sort(owner.activities, (a1, a2) -> Integer.compare(a2.order, a1.order));
}
@@ -4121,9 +4127,14 @@ public class PackageParser {
return false;
}
} else {
- outInfo.name
+ String outInfoName
= buildClassName(owner.applicationInfo.packageName, name, outError);
- if (outInfo.name == null) {
+ if (AppDetailsActivity.class.getName().equals(outInfoName)) {
+ outError[0] = tag + " invalid android:name";
+ return false;
+ }
+ outInfo.name = outInfoName;
+ if (outInfoName == null) {
return false;
}
}
@@ -4162,6 +4173,45 @@ public class PackageParser {
return true;
}
+ /**
+ * Generate activity object that forwards user to App Details page automatically.
+ * This activity should be invisible to user and user should not know or see it.
+ */
+ private @NonNull PackageParser.Activity generateAppDetailsHiddenActivity(
+ PackageParser.Package owner, int flags, String[] outError,
+ boolean hardwareAccelerated) {
+
+ // Build custom App Details activity info instead of parsing it from xml
+ Activity a = new Activity(owner, AppDetailsActivity.class.getName(), new ActivityInfo());
+ a.owner = owner;
+ a.setPackageName(owner.packageName);
+
+ a.info.theme = 0;
+ a.info.exported = true;
+ a.info.name = AppDetailsActivity.class.getName();
+ a.info.processName = owner.applicationInfo.processName;
+ a.info.uiOptions = a.info.applicationInfo.uiOptions;
+ a.info.taskAffinity = buildTaskAffinityName(owner.packageName, owner.packageName,
+ ":app_details", outError);
+ a.info.enabled = true;
+ a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
+ a.info.documentLaunchMode = ActivityInfo.DOCUMENT_LAUNCH_NONE;
+ a.info.maxRecents = ActivityTaskManager.getDefaultAppRecentsLimitStatic();
+ a.info.configChanges = getActivityConfigChanges(0, 0);
+ a.info.softInputMode = 0;
+ a.info.persistableMode = ActivityInfo.PERSIST_NEVER;
+ a.info.screenOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
+ a.info.resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
+ a.info.lockTaskLaunchMode = 0;
+ a.info.encryptionAware = a.info.directBootAware = false;
+ a.info.rotationAnimation = ROTATION_ANIMATION_UNSPECIFIED;
+ a.info.colorMode = ActivityInfo.COLOR_MODE_DEFAULT;
+ if (hardwareAccelerated) {
+ a.info.flags |= ActivityInfo.FLAG_HARDWARE_ACCELERATED;
+ }
+ return a;
+ }
+
private Activity parseActivity(Package owner, Resources res,
XmlResourceParser parser, int flags, String[] outError, CachedComponentArgs cachedArgs,
boolean receiver, boolean hardwareAccelerated)
@@ -7132,10 +7182,16 @@ public class PackageParser {
ComponentName componentName;
String componentShortName;
- public Component(Package _owner) {
- owner = _owner;
- intents = null;
- className = null;
+ public Component(Package owner, ArrayList<II> intents, String className) {
+ this.owner = owner;
+ this.intents = intents;
+ this.className = className;
+ }
+
+ public Component(Package owner) {
+ this.owner = owner;
+ this.intents = null;
+ this.className = null;
}
public Component(final ParsePackageItemArgs args, final PackageItemInfo outInfo) {
@@ -7600,6 +7656,13 @@ public class PackageParser {
return mHasMaxAspectRatio;
}
+ // To construct custom activity which does not exist in manifest
+ Activity(final Package owner, final String className, final ActivityInfo info) {
+ super(owner, new ArrayList<>(0), className);
+ this.info = info;
+ this.info.applicationInfo = owner.applicationInfo;
+ }
+
public Activity(final ParseComponentArgs args, final ActivityInfo _info) {
super(args, _info);
info = _info;
diff --git a/core/java/android/database/sqlite/SQLiteStatement.java b/core/java/android/database/sqlite/SQLiteStatement.java
index 8f8f67625a33..42e7ac7e8431 100644
--- a/core/java/android/database/sqlite/SQLiteStatement.java
+++ b/core/java/android/database/sqlite/SQLiteStatement.java
@@ -53,7 +53,7 @@ public final class SQLiteStatement extends SQLiteProgram {
}
/**
- * Execute this SQL statement, if the the number of rows affected by execution of this SQL
+ * Execute this SQL statement, if the number of rows affected by execution of this SQL
* statement is of any importance to the caller - for example, UPDATE / DELETE SQL statements.
*
* @return the number of rows affected by this SQL statement execution.
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index 486b054e1c00..d4dc181e5eec 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -2090,7 +2090,7 @@ public abstract class CameraMetadata<TKey> {
/**
* <p>Optimized for dim settings where the main light source
- * is a flame.</p>
+ * is a candle.</p>
* @see CaptureRequest#CONTROL_SCENE_MODE
*/
public static final int CONTROL_SCENE_MODE_CANDLELIGHT = 15;
diff --git a/core/java/android/hardware/location/ContextHubClient.java b/core/java/android/hardware/location/ContextHubClient.java
index 917644db4202..6609b76faac1 100644
--- a/core/java/android/hardware/location/ContextHubClient.java
+++ b/core/java/android/hardware/location/ContextHubClient.java
@@ -133,6 +133,7 @@ public class ContextHubClient implements Closeable {
*
* @hide
*/
+ @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
public boolean registerIntent(@NonNull PendingIntent intent, long nanoAppId) {
// TODO: Implement this
return false;
@@ -146,6 +147,7 @@ public class ContextHubClient implements Closeable {
*
* @hide
*/
+ @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
public boolean unregisterIntent(@NonNull PendingIntent intent) {
// TODO: Implement this
return false;
diff --git a/core/java/android/hardware/location/ContextHubManager.java b/core/java/android/hardware/location/ContextHubManager.java
index 36f3586aec2a..f94d69b7fa2d 100644
--- a/core/java/android/hardware/location/ContextHubManager.java
+++ b/core/java/android/hardware/location/ContextHubManager.java
@@ -749,6 +749,7 @@ public final class ContextHubManager {
*
* @see ContextHubClientCallback
*/
+ @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
@NonNull public ContextHubClient createClient(
@NonNull ContextHubInfo hubInfo, @NonNull ContextHubClientCallback callback,
@NonNull @CallbackExecutor Executor executor) {
@@ -785,6 +786,7 @@ public final class ContextHubManager {
*
* @see ContextHubClientCallback
*/
+ @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
@NonNull public ContextHubClient createClient(
@NonNull ContextHubInfo hubInfo, @NonNull ContextHubClientCallback callback) {
return createClient(hubInfo, callback, new HandlerExecutor(Handler.getMain()));
@@ -811,6 +813,7 @@ public final class ContextHubManager {
*
* @hide
*/
+ @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
@NonNull public ContextHubClient createClient(
@NonNull PendingIntent intent, @NonNull ContextHubInfo hubInfo,
@NonNull ContextHubClientCallback callback,
@@ -835,6 +838,7 @@ public final class ContextHubManager {
*
* @hide
*/
+ @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
@NonNull public ContextHubClient createClient(
@NonNull PendingIntent intent, @NonNull ContextHubInfo hubInfo,
@NonNull ContextHubClientCallback callback) {
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 8333b817add0..1fbfa40d5d64 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -83,6 +83,7 @@ import java.util.Map;
@SystemService(Context.CONNECTIVITY_SERVICE)
public class ConnectivityManager {
private static final String TAG = "ConnectivityManager";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
/**
* A change in network connectivity has occurred. A default connection has either
@@ -2493,6 +2494,7 @@ public class ConnectivityManager {
* {@hide}
*/
public void reportInetCondition(int networkType, int percentage) {
+ printStackTrace();
try {
mService.reportInetCondition(networkType, percentage);
} catch (RemoteException e) {
@@ -2513,6 +2515,7 @@ public class ConnectivityManager {
*/
@Deprecated
public void reportBadNetwork(Network network) {
+ printStackTrace();
try {
// One of these will be ignored because it matches system's current state.
// The other will trigger the necessary reevaluation.
@@ -2535,6 +2538,7 @@ public class ConnectivityManager {
* Internet using {@code network} or {@code false} if not.
*/
public void reportNetworkConnectivity(Network network, boolean hasConnectivity) {
+ printStackTrace();
try {
mService.reportNetworkConnectivity(network, hasConnectivity);
} catch (RemoteException e) {
@@ -2727,8 +2731,11 @@ public class ConnectivityManager {
*
* @hide
*/
- @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL)
- @UnsupportedAppUsage
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD,
+ android.Manifest.permission.NETWORK_STACK})
+ @SystemApi
public void setAirplaneMode(boolean enable) {
try {
mService.setAirplaneMode(enable);
@@ -3073,6 +3080,7 @@ public class ConnectivityManager {
private NetworkRequest sendRequestForNetwork(NetworkCapabilities need, NetworkCallback callback,
int timeoutMs, int action, int legacyType, CallbackHandler handler) {
+ printStackTrace();
checkCallbackNotNull(callback);
Preconditions.checkArgument(action == REQUEST || need != null, "null NetworkCapabilities");
final NetworkRequest request;
@@ -3332,6 +3340,7 @@ public class ConnectivityManager {
* {@link NetworkCapabilities#NET_CAPABILITY_CAPTIVE_PORTAL}.
*/
public void requestNetwork(NetworkRequest request, PendingIntent operation) {
+ printStackTrace();
checkPendingIntentNotNull(operation);
try {
mService.pendingRequestForNetwork(request.networkCapabilities, operation);
@@ -3355,6 +3364,7 @@ public class ConnectivityManager {
* corresponding NetworkRequest you'd like to remove. Cannot be null.
*/
public void releaseNetworkRequest(PendingIntent operation) {
+ printStackTrace();
checkPendingIntentNotNull(operation);
try {
mService.releasePendingNetworkRequest(operation);
@@ -3439,6 +3449,7 @@ public class ConnectivityManager {
*/
@RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
public void registerNetworkCallback(NetworkRequest request, PendingIntent operation) {
+ printStackTrace();
checkPendingIntentNotNull(operation);
try {
mService.pendingListenForNetwork(request.networkCapabilities, operation);
@@ -3520,6 +3531,7 @@ public class ConnectivityManager {
* @param networkCallback The {@link NetworkCallback} used when making the request.
*/
public void unregisterNetworkCallback(NetworkCallback networkCallback) {
+ printStackTrace();
checkCallbackNotNull(networkCallback);
final List<NetworkRequest> reqs = new ArrayList<>();
// Find all requests associated to this callback and stop callback triggers immediately.
@@ -3948,4 +3960,19 @@ public class ConnectivityManager {
throw e.rethrowFromSystemServer();
}
}
+
+ private void printStackTrace() {
+ if (DEBUG) {
+ final StackTraceElement[] callStack = Thread.currentThread().getStackTrace();
+ final StringBuffer sb = new StringBuffer();
+ for (int i = 3; i < callStack.length; i++) {
+ final String stackTrace = callStack[i].toString();
+ if (stackTrace == null || stackTrace.contains("android.os")) {
+ break;
+ }
+ sb.append(" [").append(stackTrace).append("]");
+ }
+ Log.d(TAG, "StackLog:" + sb.toString());
+ }
+ }
}
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 26c2033eac51..412a700de65b 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -17,6 +17,7 @@
package android.os;
import android.Manifest;
+import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SuppressAutoDoc;
import android.annotation.SystemApi;
@@ -1112,19 +1113,37 @@ public class Build {
}
/** The name of this partition, e.g. "system", or "vendor" */
+ @NonNull
public String getName() {
return mName;
}
/** The build fingerprint of this partition, see {@link Build#FINGERPRINT}. */
+ @NonNull
public String getFingerprint() {
return mFingerprint;
}
/** The time (ms since epoch), at which this partition was built, see {@link Build#TIME}. */
- public long getTimeMillis() {
+ public long getBuildTimeMillis() {
return mTimeMs;
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof Partition)) {
+ return false;
+ }
+ Partition op = (Partition) o;
+ return mName.equals(op.mName)
+ && mFingerprint.equals(op.mFingerprint)
+ && mTimeMs == op.mTimeMs;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mName, mFingerprint, mTimeMs);
+ }
}
/**
@@ -1133,7 +1152,8 @@ public class Build {
* The list includes partitions that are suitable candidates for over-the-air updates. This is
* not an exhaustive list of partitions on the device.
*/
- public static List<Partition> getPartitions() {
+ @NonNull
+ public static List<Partition> getFingerprintedPartitions() {
ArrayList<Partition> partitions = new ArrayList();
String[] names = new String[] {
diff --git a/core/java/android/os/DumpstateOptions.java b/core/java/android/os/DumpstateOptions.java
new file mode 100644
index 000000000000..53037b2499cd
--- /dev/null
+++ b/core/java/android/os/DumpstateOptions.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2018 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;
+
+/**
+ * Options passed to dumpstate service.
+ *
+ * @hide
+ */
+public final class DumpstateOptions implements Parcelable {
+ // If true the caller can get callbacks with per-section
+ // progress details.
+ private final boolean mGetSectionDetails;
+ // Name of the caller.
+ private final String mName;
+
+ public DumpstateOptions(Parcel in) {
+ mGetSectionDetails = in.readBoolean();
+ mName = in.readString();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeBoolean(mGetSectionDetails);
+ out.writeString(mName);
+ }
+
+ public static final Parcelable.Creator<DumpstateOptions> CREATOR =
+ new Parcelable.Creator<DumpstateOptions>() {
+ public DumpstateOptions createFromParcel(Parcel in) {
+ return new DumpstateOptions(in);
+ }
+
+ public DumpstateOptions[] newArray(int size) {
+ return new DumpstateOptions[size];
+ }
+ };
+}
diff --git a/core/java/android/os/Message.java b/core/java/android/os/Message.java
index cd3f301ebf08..5d5e5e233b35 100644
--- a/core/java/android/os/Message.java
+++ b/core/java/android/os/Message.java
@@ -19,6 +19,8 @@ package android.os;
import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;
+import com.android.internal.annotations.VisibleForTesting;
+
/**
*
* Defines a message containing a description and arbitrary data object that can be
@@ -111,7 +113,13 @@ public final class Message implements Parcelable {
/*package*/ int flags;
- /*package*/ long when;
+ /**
+ * The targeted delivery time of this message. The time-base is
+ * {@link SystemClock#uptimeMillis}.
+ * @hide Only for use within the tests.
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ public long when;
/*package*/ Bundle data;
@@ -382,7 +390,7 @@ public final class Message implements Parcelable {
* the <em>target</em> {@link Handler} that is receiving this Message to
* dispatch it. If
* not set, the message will be dispatched to the receiving Handler's
- * {@link Handler#handleMessage(Message Handler.handleMessage())}.
+ * {@link Handler#handleMessage(Message)}.
*/
public Runnable getCallback() {
return callback;
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 8123744281f4..7ea20082e660 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -2363,7 +2363,6 @@ public class UserManager {
*/
@RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
Manifest.permission.CREATE_USERS}, conditional = true)
- @SystemApi
public @NonNull int[] getProfileIds(@UserIdInt int userId, boolean enabledOnly) {
try {
return mService.getProfileIds(userId, enabledOnly);
diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java
index aa44eb7e3a26..7ffb22f189b8 100644
--- a/core/java/android/permission/PermissionManager.java
+++ b/core/java/android/permission/PermissionManager.java
@@ -25,7 +25,9 @@ import android.content.Context;
import com.android.internal.annotations.Immutable;
import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
+import java.util.Objects;
/**
* System level service for accessing the permission capabilities of the platform.
@@ -40,26 +42,28 @@ public final class PermissionManager {
*
* @hide
*/
- public static final SplitPermissionInfo[] SPLIT_PERMISSIONS = new SplitPermissionInfo[]{
+ public static final List<SplitPermissionInfo> SPLIT_PERMISSIONS = Arrays.asList(
// READ_EXTERNAL_STORAGE is always required when an app requests
// WRITE_EXTERNAL_STORAGE, because we can't have an app that has
// write access without read access. The hack here with the target
// target SDK version ensures that this grant is always done.
new SplitPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
- new String[]{android.Manifest.permission.READ_EXTERNAL_STORAGE},
+ Collections.singletonList(android.Manifest.permission.READ_EXTERNAL_STORAGE),
android.os.Build.VERSION_CODES.CUR_DEVELOPMENT + 1),
new SplitPermissionInfo(android.Manifest.permission.READ_CONTACTS,
- new String[]{android.Manifest.permission.READ_CALL_LOG},
+ Collections.singletonList(android.Manifest.permission.READ_CALL_LOG),
android.os.Build.VERSION_CODES.JELLY_BEAN),
new SplitPermissionInfo(android.Manifest.permission.WRITE_CONTACTS,
- new String[]{android.Manifest.permission.WRITE_CALL_LOG},
+ Collections.singletonList(android.Manifest.permission.WRITE_CALL_LOG),
android.os.Build.VERSION_CODES.JELLY_BEAN),
new SplitPermissionInfo(Manifest.permission.ACCESS_FINE_LOCATION,
- new String[]{android.Manifest.permission.ACCESS_BACKGROUND_LOCATION},
+ Collections.singletonList(
+ android.Manifest.permission.ACCESS_BACKGROUND_LOCATION),
android.os.Build.VERSION_CODES.P0),
new SplitPermissionInfo(Manifest.permission.ACCESS_COARSE_LOCATION,
- new String[]{android.Manifest.permission.ACCESS_BACKGROUND_LOCATION},
- android.os.Build.VERSION_CODES.P0)};
+ Collections.singletonList(
+ android.Manifest.permission.ACCESS_BACKGROUND_LOCATION),
+ android.os.Build.VERSION_CODES.P0));
private final @NonNull Context mContext;
@@ -74,7 +78,7 @@ public final class PermissionManager {
}
/**
- * Get list of permissions that have been split into more granular or dependent permissions.
+ * Get set of permissions that have been split into more granular or dependent permissions.
*
* <p>E.g. before {@link android.os.Build.VERSION_CODES#P0} an app that was granted
* {@link Manifest.permission#ACCESS_COARSE_LOCATION} could access he location while it was in
@@ -82,7 +86,7 @@ public final class PermissionManager {
* the location permission only grants location access while the app is in foreground. This
* would break apps that target before {@link android.os.Build.VERSION_CODES#P0}. Hence whenever
* such an old app asks for a location permission (i.e. the
- * {@link SplitPermissionInfo#getRootPermission()}), then the
+ * {@link SplitPermissionInfo#getSplitPermission()}), then the
* {@link Manifest.permission#ACCESS_BACKGROUND_LOCATION} permission (inside
* {@{@link SplitPermissionInfo#getNewPermissions}) is added.
*
@@ -91,8 +95,9 @@ public final class PermissionManager {
*
* @return All permissions that are split.
*/
- public @NonNull List<SplitPermissionInfo> getSplitPermissions() {
- return Arrays.asList(SPLIT_PERMISSIONS);
+ public @NonNull
+ List<SplitPermissionInfo> getSplitPermissions() {
+ return SPLIT_PERMISSIONS;
}
/**
@@ -101,21 +106,35 @@ public final class PermissionManager {
*/
@Immutable
public static final class SplitPermissionInfo {
- private final @NonNull String mRootPerm;
- private final @NonNull String[] mNewPerms;
+ private final @NonNull String mSplitPerm;
+ private final @NonNull List<String> mNewPerms;
private final int mTargetSdk;
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ SplitPermissionInfo that = (SplitPermissionInfo) o;
+ return mTargetSdk == that.mTargetSdk
+ && Objects.equals(mSplitPerm, that.mSplitPerm);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mSplitPerm, mTargetSdk);
+ }
+
/**
* Get the permission that is split.
*/
- public @NonNull String getRootPermission() {
- return mRootPerm;
+ public @NonNull String getSplitPermission() {
+ return mSplitPerm;
}
/**
* Get the permissions that are added.
*/
- public @NonNull String[] getNewPermissions() {
+ public @NonNull List<String> getNewPermissions() {
return mNewPerms;
}
@@ -126,9 +145,9 @@ public final class PermissionManager {
return mTargetSdk;
}
- private SplitPermissionInfo(@NonNull String rootPerm, @NonNull String[] newPerms,
+ private SplitPermissionInfo(@NonNull String rootPerm, @NonNull List<String> newPerms,
int targetSdk) {
- mRootPerm = rootPerm;
+ mSplitPerm = rootPerm;
mNewPerms = newPerms;
mTargetSdk = targetSdk;
}
diff --git a/core/java/android/service/textclassifier/TextClassifierService.java b/core/java/android/service/textclassifier/TextClassifierService.java
index b461c0daaca5..7af9db8ebf32 100644
--- a/core/java/android/service/textclassifier/TextClassifierService.java
+++ b/core/java/android/service/textclassifier/TextClassifierService.java
@@ -405,8 +405,8 @@ public abstract class TextClassifierService extends Service {
PackageManager.MATCH_SYSTEM_ONLY);
if ((ri == null) || (ri.serviceInfo == null)) {
- Slog.w(LOG_TAG, String.format("Package or service not found in package %s",
- packageName));
+ Slog.w(LOG_TAG, String.format("Package or service not found in package %s for user %d",
+ packageName, context.getUserId()));
return null;
}
final ServiceInfo si = ri.serviceInfo;
diff --git a/core/java/android/text/style/TextAppearanceSpan.java b/core/java/android/text/style/TextAppearanceSpan.java
index 2dc4f6001a06..648bd1bba20c 100644
--- a/core/java/android/text/style/TextAppearanceSpan.java
+++ b/core/java/android/text/style/TextAppearanceSpan.java
@@ -29,8 +29,33 @@ import android.text.TextPaint;
import android.text.TextUtils;
/**
- * Sets the text color, size, style, and typeface to match a TextAppearance
- * resource.
+ * Sets the text appearance using the given
+ * {@link android.R.styleable#TextAppearance TextAppearance} attributes.
+ * By default {@link TextAppearanceSpan} only changes the specified attributes in XML.
+ * {@link android.R.styleable#TextAppearance_textColorHighlight textColorHighlight},
+ * {@link android.R.styleable#TextAppearance_textColorHint textColorHint},
+ * {@link android.R.styleable#TextAppearance_textAllCaps textAllCaps} and
+ * {@link android.R.styleable#TextAppearance_fallbackLineSpacing fallbackLineSpacing}
+ * are not supported by {@link TextAppearanceSpan}.
+ *
+ * {@see android.widget.TextView#setTextAppearance(int)}
+ *
+ * @attr ref android.R.styleable#TextAppearance_fontFamily
+ * @attr ref android.R.styleable#TextAppearance_textColor
+ * @attr ref android.R.styleable#TextAppearance_textColorLink
+ * @attr ref android.R.styleable#TextAppearance_textFontWeight
+ * @attr ref android.R.styleable#TextAppearance_textSize
+ * @attr ref android.R.styleable#TextAppearance_textStyle
+ * @attr ref android.R.styleable#TextAppearance_typeface
+ * @attr ref android.R.styleable#TextAppearance_shadowColor
+ * @attr ref android.R.styleable#TextAppearance_shadowDx
+ * @attr ref android.R.styleable#TextAppearance_shadowDy
+ * @attr ref android.R.styleable#TextAppearance_shadowRadius
+ * @attr ref android.R.styleable#TextAppearance_elegantTextHeight
+ * @attr ref android.R.styleable#TextAppearance_letterSpacing
+ * @attr ref android.R.styleable#TextAppearance_fontFeatureSettings
+ * @attr ref android.R.styleable#TextAppearance_fontVariationSettings
+ *
*/
public class TextAppearanceSpan extends MetricAffectingSpan implements ParcelableSpan {
private final String mFamilyName;
diff --git a/core/java/android/transition/Visibility.java b/core/java/android/transition/Visibility.java
index 319f080bbe63..bd2bef4f11ae 100644
--- a/core/java/android/transition/Visibility.java
+++ b/core/java/android/transition/Visibility.java
@@ -25,6 +25,7 @@ import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewGroupOverlay;
import com.android.internal.R;
@@ -413,7 +414,6 @@ public abstract class Visibility extends Transition {
}
}
final int finalVisibility = endVisibility;
- final ViewGroup finalSceneRoot = sceneRoot;
if (overlayView != null) {
// TODO: Need to do this for general case of adding to overlay
@@ -424,16 +424,32 @@ public abstract class Visibility extends Transition {
sceneRoot.getLocationOnScreen(loc);
overlayView.offsetLeftAndRight((screenX - loc[0]) - overlayView.getLeft());
overlayView.offsetTopAndBottom((screenY - loc[1]) - overlayView.getTop());
- sceneRoot.getOverlay().add(overlayView);
+ final ViewGroupOverlay overlay = sceneRoot.getOverlay();
+ overlay.add(overlayView);
Animator animator = onDisappear(sceneRoot, overlayView, startValues, endValues);
if (animator == null) {
- sceneRoot.getOverlay().remove(overlayView);
+ overlay.remove(overlayView);
} else {
final View finalOverlayView = overlayView;
addListener(new TransitionListenerAdapter() {
+
+ @Override
+ public void onTransitionPause(Transition transition) {
+ overlay.remove(finalOverlayView);
+ }
+
+ @Override
+ public void onTransitionResume(Transition transition) {
+ if (finalOverlayView.getParent() == null) {
+ overlay.add(finalOverlayView);
+ } else {
+ cancel();
+ }
+ }
+
@Override
public void onTransitionEnd(Transition transition) {
- finalSceneRoot.getOverlay().remove(finalOverlayView);
+ overlay.remove(finalOverlayView);
transition.removeListener(this);
}
});
diff --git a/core/java/android/view/DisplayCutout.java b/core/java/android/view/DisplayCutout.java
index f428c798d7f5..e9f1edf52b5f 100644
--- a/core/java/android/view/DisplayCutout.java
+++ b/core/java/android/view/DisplayCutout.java
@@ -245,9 +245,8 @@ public final class DisplayCutout {
* passed, it's treated as an empty rectangle (0,0)-(0,0).
*/
// TODO(b/73953958): @VisibleForTesting(visibility = PRIVATE)
- public DisplayCutout(
- Insets safeInsets, @Nullable Rect boundLeft, @Nullable Rect boundTop,
- @Nullable Rect boundRight, @Nullable Rect boundBottom) {
+ public DisplayCutout(@NonNull Insets safeInsets, @Nullable Rect boundLeft,
+ @Nullable Rect boundTop, @Nullable Rect boundRight, @Nullable Rect boundBottom) {
this(safeInsets.toRect(), boundLeft, boundTop, boundRight, boundBottom, true);
}
@@ -262,7 +261,7 @@ public final class DisplayCutout {
*/
// TODO(b/73953958): @VisibleForTesting(visibility = PRIVATE)
@Deprecated
- public DisplayCutout(Rect safeInsets, List<Rect> boundingRects) {
+ public DisplayCutout(@Nullable Rect safeInsets, @Nullable List<Rect> boundingRects) {
this(safeInsets, extractBoundsFromList(safeInsets, boundingRects),
true /* copyArguments */);
}
@@ -313,18 +312,20 @@ public final class DisplayCutout {
for (int i = 0; i < sortedBounds.length; ++i) {
sortedBounds[i] = ZERO_RECT;
}
- for (Rect bound : boundingRects) {
- // There will be at most one non-functional area per short edge of the device, and none
- // on the long edges, so either safeInsets.right or safeInsets.bottom must be 0.
- // TODO(b/117199965): Refine the logic to handle edge cases.
- if (bound.left == 0) {
- sortedBounds[BOUNDS_POSITION_LEFT] = bound;
- } else if (bound.top == 0) {
- sortedBounds[BOUNDS_POSITION_TOP] = bound;
- } else if (safeInsets.right > 0) {
- sortedBounds[BOUNDS_POSITION_RIGHT] = bound;
- } else if (safeInsets.bottom > 0) {
- sortedBounds[BOUNDS_POSITION_BOTTOM] = bound;
+ if (safeInsets != null && boundingRects != null) {
+ for (Rect bound : boundingRects) {
+ // There is at most one non-functional area per short edge of the device, but none
+ // on the long edges, so either safeInsets.right or safeInsets.bottom must be 0.
+ // TODO(b/117199965): Refine the logic to handle edge cases.
+ if (bound.left == 0) {
+ sortedBounds[BOUNDS_POSITION_LEFT] = bound;
+ } else if (bound.top == 0) {
+ sortedBounds[BOUNDS_POSITION_TOP] = bound;
+ } else if (safeInsets.right > 0) {
+ sortedBounds[BOUNDS_POSITION_RIGHT] = bound;
+ } else if (safeInsets.bottom > 0) {
+ sortedBounds[BOUNDS_POSITION_BOTTOM] = bound;
+ }
}
}
return sortedBounds;
@@ -389,6 +390,7 @@ public final class DisplayCutout {
* @return a list of bounding {@code Rect}s, one for each display cutout area. No empty Rect is
* returned.
*/
+ @NonNull
public List<Rect> getBoundingRects() {
List<Rect> result = new ArrayList<>();
for (Rect bound : getBoundingRectsAll()) {
diff --git a/core/java/android/view/TouchDelegate.java b/core/java/android/view/TouchDelegate.java
index b361ab456b2a..06b73dd29b3d 100644
--- a/core/java/android/view/TouchDelegate.java
+++ b/core/java/android/view/TouchDelegate.java
@@ -16,8 +16,12 @@
package android.view;
+import android.annotation.NonNull;
import android.annotation.UnsupportedAppUsage;
import android.graphics.Rect;
+import android.graphics.Region;
+import android.util.ArrayMap;
+import android.view.accessibility.AccessibilityNodeInfo.TouchDelegateInfo;
/**
* Helper class to handle situations where you want a view to have a larger touch area than its
@@ -78,6 +82,11 @@ public class TouchDelegate {
private int mSlop;
/**
+ * Touch delegate information for accessibility
+ */
+ private TouchDelegateInfo mTouchDelegateInfo;
+
+ /**
* Constructor
*
* @param bounds Bounds in local coordinates of the containing view that should be mapped to
@@ -145,4 +154,20 @@ public class TouchDelegate {
}
return handled;
}
+
+ /**
+ * Return a {@link TouchDelegateInfo} mapping from regions (in view coordinates) to
+ * delegated views for accessibility usage.
+ *
+ * @return A TouchDelegateInfo.
+ */
+ @NonNull
+ public TouchDelegateInfo getTouchDelegateInfo() {
+ if (mTouchDelegateInfo == null) {
+ final ArrayMap<Region, View> targetMap = new ArrayMap<>(1);
+ targetMap.put(new Region(mBounds), mDelegateView);
+ mTouchDelegateInfo = new TouchDelegateInfo(targetMap);
+ }
+ return mTouchDelegateInfo;
+ }
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index cddd83c45c75..29d3742ba632 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -7315,17 +7315,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
// Here we check whether we still need the default focus highlight, and switch it on/off.
switchDefaultFocusHighlight();
- InputMethodManager imm = getContext().getSystemService(InputMethodManager.class);
if (!gainFocus) {
if (isPressed()) {
setPressed(false);
}
- if (imm != null && mAttachInfo != null && mAttachInfo.mHasWindowFocus) {
- imm.focusOut(this);
+ if (mAttachInfo != null && mAttachInfo.mHasWindowFocus) {
+ notifyFocusChangeToInputMethodManager(false /* hasFocus */);
}
onFocusLost();
- } else if (imm != null && mAttachInfo != null && mAttachInfo.mHasWindowFocus) {
- imm.focusIn(this);
+ } else if (mAttachInfo != null && mAttachInfo.mHasWindowFocus) {
+ notifyFocusChangeToInputMethodManager(true /* hasFocus */);
}
invalidate(true);
@@ -7341,6 +7340,26 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
notifyEnterOrExitForAutoFillIfNeeded(gainFocus);
}
+ /**
+ * Notify {@link InputMethodManager} about the focus change of the {@link View}.
+ *
+ * <p>Does nothing when {@link InputMethodManager} is not available.</p>
+ *
+ * @param hasFocus {@code true} when the {@link View} is being focused.
+ */
+ private void notifyFocusChangeToInputMethodManager(boolean hasFocus) {
+ final InputMethodManager imm =
+ getContext().getSystemService(InputMethodManager.class);
+ if (imm == null) {
+ return;
+ }
+ if (hasFocus) {
+ imm.focusIn(this);
+ } else {
+ imm.focusOut(this);
+ }
+ }
+
/** @hide */
public void notifyEnterOrExitForAutoFillIfNeeded(boolean enter) {
if (canNotifyAutofillEnterExitEvent()) {
@@ -8881,6 +8900,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
populateAccessibilityNodeInfoDrawingOrderInParent(info);
info.setPaneTitle(mAccessibilityPaneTitle);
info.setHeading(isAccessibilityHeading());
+
+ if (mTouchDelegate != null) {
+ info.setTouchDelegateInfo(mTouchDelegate.getTouchDelegateInfo());
+ }
}
/**
@@ -12481,7 +12504,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
onFinishTemporaryDetach();
if (hasWindowFocus() && hasFocus()) {
- getContext().getSystemService(InputMethodManager.class).focusIn(this);
+ notifyFocusChangeToInputMethodManager(true /* hasFocus */);
}
notifyEnterOrExitForAutoFillIfNeeded(true);
}
@@ -12872,20 +12895,19 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* focus, false otherwise.
*/
public void onWindowFocusChanged(boolean hasWindowFocus) {
- InputMethodManager imm = getContext().getSystemService(InputMethodManager.class);
if (!hasWindowFocus) {
if (isPressed()) {
setPressed(false);
}
mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
- if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
- imm.focusOut(this);
+ if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
+ notifyFocusChangeToInputMethodManager(false /* hasFocus */);
}
removeLongPressCallback();
removeTapCallback();
onFocusLost();
- } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
- imm.focusIn(this);
+ } else if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
+ notifyFocusChangeToInputMethodManager(true /* hasFocus */);
}
refreshDrawableState();
@@ -14255,9 +14277,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
if (mParent instanceof ViewGroup) {
- ((ViewGroup) mParent).onChildVisibilityChanged(this,
- (changed & VISIBILITY_MASK), newVisibility);
- ((View) mParent).invalidate(true);
+ ViewGroup parent = (ViewGroup) mParent;
+ parent.onChildVisibilityChanged(this, (changed & VISIBILITY_MASK),
+ newVisibility);
+ parent.invalidate(true);
} else if (mParent != null) {
mParent.invalidateChild(this, null);
}
@@ -17976,10 +17999,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
rebuildOutline();
if (isFocused()) {
- InputMethodManager imm = getContext().getSystemService(InputMethodManager.class);
- if (imm != null) {
- imm.focusIn(this);
- }
+ notifyFocusChangeToInputMethodManager(true /* hasFocus */);
}
}
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 982737aedc74..c1e94d8ff97e 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -1085,6 +1085,19 @@ public abstract class Window {
*
* <p>Refer to the individual flags for the permissions needed.
*
+ * @param flags The flag bits to add.
+ *
+ * @hide
+ */
+ public void addPrivateFlags(int flags) {
+ setPrivateFlags(flags, flags);
+ }
+
+ /**
+ * Add system flag bits.
+ *
+ * <p>Refer to the individual flags for the permissions needed.
+ *
* <p>Note: Only for updateable system components (aka. mainline modules)
*
* @param flags The flag bits to add.
@@ -1092,8 +1105,8 @@ public abstract class Window {
* @hide
*/
@SystemApi
- public void addPrivateFlags(int flags) {
- setPrivateFlags(flags, flags);
+ public void addSystemFlags(@WindowManager.LayoutParams.SystemFlags int flags) {
+ addPrivateFlags(flags);
}
/**
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 742df5e8a962..2d77cb4f3aca 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -1670,7 +1670,7 @@ public interface WindowManager extends ViewManager {
*/
@SystemApi
@RequiresPermission(permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS)
- public static final int PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS = 0x00080000;
+ public static final int SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS = 0x00080000;
/**
* Indicates that this window is the rounded corners overlay present on some
@@ -1708,6 +1708,18 @@ public interface WindowManager extends ViewManager {
public static final int PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION = 0x00800000;
/**
+ * An internal annotation for flags that can be specified to {@link #softInputMode}.
+ *
+ * @hide
+ */
+ @SystemApi
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag = true, prefix = { "SYSTEM_FLAG_" }, value = {
+ SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS,
+ })
+ public @interface SystemFlags {}
+
+ /**
* Control flags that are private to the platform.
* @hide
*/
@@ -1781,8 +1793,8 @@ public interface WindowManager extends ViewManager {
equals = PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE,
name = "SUSTAINED_PERFORMANCE_MODE"),
@ViewDebug.FlagToString(
- mask = PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS,
- equals = PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS,
+ mask = SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS,
+ equals = SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS,
name = "HIDE_NON_SYSTEM_OVERLAY_WINDOWS"),
@ViewDebug.FlagToString(
mask = PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY,
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 4d3f0fc20ecd..e129091f5913 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -23,10 +23,12 @@ import static java.util.Collections.EMPTY_LIST;
import android.accessibilityservice.AccessibilityService;
import android.accessibilityservice.AccessibilityServiceInfo;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.graphics.Rect;
+import android.graphics.Region;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -39,17 +41,21 @@ import android.text.style.AccessibilityClickableSpan;
import android.text.style.AccessibilityURLSpan;
import android.text.style.ClickableSpan;
import android.text.style.URLSpan;
+import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.LongArray;
import android.util.Pools.SynchronizedPool;
+import android.view.TouchDelegate;
import android.view.View;
import com.android.internal.R;
import com.android.internal.util.CollectionUtils;
+import com.android.internal.util.Preconditions;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
@@ -748,6 +754,8 @@ public class AccessibilityNodeInfo implements Parcelable {
private CollectionInfo mCollectionInfo;
private CollectionItemInfo mCollectionItemInfo;
+ private TouchDelegateInfo mTouchDelegateInfo;
+
/**
* Hide constructor from clients.
*/
@@ -810,7 +818,7 @@ public class AccessibilityNodeInfo implements Parcelable {
public AccessibilityNodeInfo findFocus(int focus) {
enforceSealed();
enforceValidFocusType(focus);
- if (!canPerformRequestOverConnection(mSourceNodeId)) {
+ if (!canPerformRequestOverConnection(mConnectionId, mWindowId, mSourceNodeId)) {
return null;
}
return AccessibilityInteractionClient.getInstance().findFocus(mConnectionId, mWindowId,
@@ -834,7 +842,7 @@ public class AccessibilityNodeInfo implements Parcelable {
public AccessibilityNodeInfo focusSearch(int direction) {
enforceSealed();
enforceValidFocusDirection(direction);
- if (!canPerformRequestOverConnection(mSourceNodeId)) {
+ if (!canPerformRequestOverConnection(mConnectionId, mWindowId, mSourceNodeId)) {
return null;
}
return AccessibilityInteractionClient.getInstance().focusSearch(mConnectionId, mWindowId,
@@ -866,7 +874,7 @@ public class AccessibilityNodeInfo implements Parcelable {
@UnsupportedAppUsage
public boolean refresh(Bundle arguments, boolean bypassCache) {
enforceSealed();
- if (!canPerformRequestOverConnection(mSourceNodeId)) {
+ if (!canPerformRequestOverConnection(mConnectionId, mWindowId, mSourceNodeId)) {
return false;
}
AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
@@ -967,7 +975,7 @@ public class AccessibilityNodeInfo implements Parcelable {
if (mChildNodeIds == null) {
return null;
}
- if (!canPerformRequestOverConnection(mSourceNodeId)) {
+ if (!canPerformRequestOverConnection(mConnectionId, mWindowId, mSourceNodeId)) {
return null;
}
final long childId = mChildNodeIds.get(index);
@@ -1271,7 +1279,7 @@ public class AccessibilityNodeInfo implements Parcelable {
*/
public AccessibilityNodeInfo getTraversalBefore() {
enforceSealed();
- return getNodeForAccessibilityId(mTraversalBefore);
+ return getNodeForAccessibilityId(mConnectionId, mWindowId, mTraversalBefore);
}
/**
@@ -1332,7 +1340,7 @@ public class AccessibilityNodeInfo implements Parcelable {
*/
public AccessibilityNodeInfo getTraversalAfter() {
enforceSealed();
- return getNodeForAccessibilityId(mTraversalAfter);
+ return getNodeForAccessibilityId(mConnectionId, mWindowId, mTraversalAfter);
}
/**
@@ -1489,7 +1497,7 @@ public class AccessibilityNodeInfo implements Parcelable {
*/
public boolean performAction(int action) {
enforceSealed();
- if (!canPerformRequestOverConnection(mSourceNodeId)) {
+ if (!canPerformRequestOverConnection(mConnectionId, mWindowId, mSourceNodeId)) {
return false;
}
AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
@@ -1512,7 +1520,7 @@ public class AccessibilityNodeInfo implements Parcelable {
*/
public boolean performAction(int action, Bundle arguments) {
enforceSealed();
- if (!canPerformRequestOverConnection(mSourceNodeId)) {
+ if (!canPerformRequestOverConnection(mConnectionId, mWindowId, mSourceNodeId)) {
return false;
}
AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
@@ -1536,7 +1544,7 @@ public class AccessibilityNodeInfo implements Parcelable {
*/
public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByText(String text) {
enforceSealed();
- if (!canPerformRequestOverConnection(mSourceNodeId)) {
+ if (!canPerformRequestOverConnection(mConnectionId, mWindowId, mSourceNodeId)) {
return Collections.emptyList();
}
AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
@@ -1567,7 +1575,7 @@ public class AccessibilityNodeInfo implements Parcelable {
*/
public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewId(String viewId) {
enforceSealed();
- if (!canPerformRequestOverConnection(mSourceNodeId)) {
+ if (!canPerformRequestOverConnection(mConnectionId, mWindowId, mSourceNodeId)) {
return Collections.emptyList();
}
AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
@@ -1584,7 +1592,7 @@ public class AccessibilityNodeInfo implements Parcelable {
*/
public AccessibilityWindowInfo getWindow() {
enforceSealed();
- if (!canPerformRequestOverConnection(mSourceNodeId)) {
+ if (!canPerformRequestOverConnection(mConnectionId, mWindowId, mSourceNodeId)) {
return null;
}
AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
@@ -1603,7 +1611,7 @@ public class AccessibilityNodeInfo implements Parcelable {
*/
public AccessibilityNodeInfo getParent() {
enforceSealed();
- return getNodeForAccessibilityId(mParentNodeId);
+ return getNodeForAccessibilityId(mConnectionId, mWindowId, mParentNodeId);
}
/**
@@ -2783,7 +2791,7 @@ public class AccessibilityNodeInfo implements Parcelable {
*/
public AccessibilityNodeInfo getLabelFor() {
enforceSealed();
- return getNodeForAccessibilityId(mLabelForId);
+ return getNodeForAccessibilityId(mConnectionId, mWindowId, mLabelForId);
}
/**
@@ -2835,7 +2843,7 @@ public class AccessibilityNodeInfo implements Parcelable {
*/
public AccessibilityNodeInfo getLabeledBy() {
enforceSealed();
- return getNodeForAccessibilityId(mLabeledById);
+ return getNodeForAccessibilityId(mConnectionId, mWindowId, mLabeledById);
}
/**
@@ -2975,6 +2983,43 @@ public class AccessibilityNodeInfo implements Parcelable {
}
/**
+ * Get the {@link TouchDelegateInfo} for touch delegate behavior with the represented view.
+ * It is possible for the same node to be pointed to by several regions. Use
+ * {@link TouchDelegateInfo#getRegionAt(int)} to get touch delegate target {@link Region}, and
+ * {@link TouchDelegateInfo#getTargetForRegion(Region)} for {@link AccessibilityNodeInfo} from
+ * the given region.
+ *
+ * @return {@link TouchDelegateInfo} or {@code null} if there are no touch delegates.
+ */
+ @Nullable
+ public TouchDelegateInfo getTouchDelegateInfo() {
+ if (mTouchDelegateInfo != null) {
+ mTouchDelegateInfo.setConnectionId(mConnectionId);
+ mTouchDelegateInfo.setWindowId(mWindowId);
+ }
+ return mTouchDelegateInfo;
+ }
+
+ /**
+ * Set touch delegate info if the represented view has a {@link TouchDelegate}.
+ * <p>
+ * <strong>Note:</strong> Cannot be called from an
+ * {@link android.accessibilityservice.AccessibilityService}.
+ * This class is made immutable before being delivered to an
+ * AccessibilityService.
+ * </p>
+ *
+ * @param delegatedInfo {@link TouchDelegateInfo} returned from
+ * {@link TouchDelegate#getTouchDelegateInfo()}.
+ *
+ * @throws IllegalStateException If called from an AccessibilityService.
+ */
+ public void setTouchDelegateInfo(@NonNull TouchDelegateInfo delegatedInfo) {
+ enforceNotSealed();
+ mTouchDelegateInfo = delegatedInfo;
+ }
+
+ /**
* Gets the value of a boolean property.
*
* @param property The property.
@@ -3340,6 +3385,10 @@ public class AccessibilityNodeInfo implements Parcelable {
if (!Objects.equals(mCollectionItemInfo, DEFAULT.mCollectionItemInfo)) {
nonDefaultFields |= bitAt(fieldIndex);
}
+ fieldIndex++;
+ if (!Objects.equals(mTouchDelegateInfo, DEFAULT.mTouchDelegateInfo)) {
+ nonDefaultFields |= bitAt(fieldIndex);
+ }
int totalFields = fieldIndex;
parcel.writeLong(nonDefaultFields);
@@ -3462,6 +3511,10 @@ public class AccessibilityNodeInfo implements Parcelable {
parcel.writeInt(mCollectionItemInfo.isSelected() ? 1 : 0);
}
+ if (isBitSet(nonDefaultFields, fieldIndex++)) {
+ mTouchDelegateInfo.writeToParcel(parcel, flags);
+ }
+
if (DEBUG) {
fieldIndex--;
if (totalFields != fieldIndex) {
@@ -3543,6 +3596,10 @@ public class AccessibilityNodeInfo implements Parcelable {
if (mCollectionItemInfo != null) mCollectionItemInfo.recycle();
mCollectionItemInfo = (other.mCollectionItemInfo != null)
? CollectionItemInfo.obtain(other.mCollectionItemInfo) : null;
+
+ final TouchDelegateInfo otherInfo = other.mTouchDelegateInfo;
+ mTouchDelegateInfo = (otherInfo != null)
+ ? new TouchDelegateInfo(otherInfo.mTargetMap, true) : null;
}
/**
@@ -3665,6 +3722,10 @@ public class AccessibilityNodeInfo implements Parcelable {
parcel.readInt() == 1)
: null;
+ if (isBitSet(nonDefaultFields, fieldIndex++)) {
+ mTouchDelegateInfo = TouchDelegateInfo.CREATOR.createFromParcel(parcel);
+ }
+
mSealed = sealed;
}
@@ -3813,10 +3874,11 @@ public class AccessibilityNodeInfo implements Parcelable {
}
}
- private boolean canPerformRequestOverConnection(long accessibilityNodeId) {
- return ((mWindowId != AccessibilityWindowInfo.UNDEFINED_WINDOW_ID)
+ private static boolean canPerformRequestOverConnection(int connectionId,
+ int windowId, long accessibilityNodeId) {
+ return ((windowId != AccessibilityWindowInfo.UNDEFINED_WINDOW_ID)
&& (getAccessibilityViewId(accessibilityNodeId) != UNDEFINED_ITEM_ID)
- && (mConnectionId != UNDEFINED_CONNECTION_ID));
+ && (connectionId != UNDEFINED_CONNECTION_ID));
}
@Override
@@ -3919,13 +3981,14 @@ public class AccessibilityNodeInfo implements Parcelable {
return builder.toString();
}
- private AccessibilityNodeInfo getNodeForAccessibilityId(long accessibilityId) {
- if (!canPerformRequestOverConnection(accessibilityId)) {
+ private static AccessibilityNodeInfo getNodeForAccessibilityId(int connectionId,
+ int windowId, long accessibilityId) {
+ if (!canPerformRequestOverConnection(connectionId, windowId, accessibilityId)) {
return null;
}
AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
- return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
- mWindowId, accessibilityId, false, FLAG_PREFETCH_PREDECESSORS
+ return client.findAccessibilityNodeInfoByAccessibilityId(connectionId,
+ windowId, accessibilityId, false, FLAG_PREFETCH_PREDECESSORS
| FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS, null);
}
@@ -4896,6 +4959,176 @@ public class AccessibilityNodeInfo implements Parcelable {
}
/**
+ * Class with information of touch delegated views and regions from {@link TouchDelegate} for
+ * the {@link AccessibilityNodeInfo}.
+ *
+ * @see AccessibilityNodeInfo#setTouchDelegateInfo(TouchDelegateInfo)
+ */
+ public static final class TouchDelegateInfo implements Parcelable {
+ private ArrayMap<Region, Long> mTargetMap;
+ // Two ids are initialized lazily in AccessibilityNodeInfo#getTouchDelegateInfo
+ private int mConnectionId;
+ private int mWindowId;
+
+ /**
+ * Create a new instance of {@link TouchDelegateInfo}.
+ *
+ * @param targetMap A map from regions (in view coordinates) to delegated views.
+ * @throws IllegalArgumentException if targetMap is empty or {@code null} in
+ * Regions or Views.
+ */
+ public TouchDelegateInfo(@NonNull Map<Region, View> targetMap) {
+ Preconditions.checkArgument(!targetMap.isEmpty()
+ && !targetMap.containsKey(null) && !targetMap.containsValue(null));
+ mTargetMap = new ArrayMap<>(targetMap.size());
+ for (final Region region : targetMap.keySet()) {
+ final View view = targetMap.get(region);
+ mTargetMap.put(region, (long) view.getAccessibilityViewId());
+ }
+ }
+
+ /**
+ * Create a new instance from target map.
+ *
+ * @param targetMap A map from regions (in view coordinates) to delegated views'
+ * accessibility id.
+ * @param doCopy True if shallow copy targetMap.
+ * @throws IllegalArgumentException if targetMap is empty or {@code null} in
+ * Regions or Views.
+ */
+ TouchDelegateInfo(@NonNull ArrayMap<Region, Long> targetMap, boolean doCopy) {
+ Preconditions.checkArgument(!targetMap.isEmpty()
+ && !targetMap.containsKey(null) && !targetMap.containsValue(null));
+ if (doCopy) {
+ mTargetMap = new ArrayMap<>(targetMap.size());
+ mTargetMap.putAll(targetMap);
+ } else {
+ mTargetMap = targetMap;
+ }
+ }
+
+ /**
+ * Set the connection ID.
+ *
+ * @param connectionId The connection id.
+ */
+ private void setConnectionId(int connectionId) {
+ mConnectionId = connectionId;
+ }
+
+ /**
+ * Set the window ID.
+ *
+ * @param windowId The window id.
+ */
+ private void setWindowId(int windowId) {
+ mWindowId = windowId;
+ }
+
+ /**
+ * Returns the number of touch delegate target region.
+ *
+ * @return Number of touch delegate target region.
+ */
+ public int getRegionCount() {
+ return mTargetMap.size();
+ }
+
+ /**
+ * Return the {@link Region} at the given index in the {@link TouchDelegateInfo}.
+ *
+ * @param index The desired index, must be between 0 and {@link #getRegionCount()}-1.
+ * @return Returns the {@link Region} stored at the given index.
+ */
+ @NonNull
+ public Region getRegionAt(int index) {
+ return mTargetMap.keyAt(index);
+ }
+
+ /**
+ * Return the target {@link AccessibilityNodeInfo} for the given {@link Region}.
+ * <p>
+ * <strong>Note:</strong> This api can only be called from {@link AccessibilityService}.
+ * </p>
+ * <p>
+ * <strong>Note:</strong> It is a client responsibility to recycle the
+ * received info by calling {@link AccessibilityNodeInfo#recycle()}
+ * to avoid creating of multiple instances.
+ * </p>
+ *
+ * @param region The region retrieved from {@link #getRegionAt(int)}.
+ * @return The target node associates with the given region.
+ */
+ @Nullable
+ public AccessibilityNodeInfo getTargetForRegion(@NonNull Region region) {
+ return getNodeForAccessibilityId(mConnectionId, mWindowId, mTargetMap.get(region));
+ }
+
+ /**
+ * Return the accessibility id of target node.
+ *
+ * @param region The region retrieved from {@link #getRegionAt(int)}.
+ * @return The accessibility id of target node.
+ *
+ * @hide
+ */
+ @TestApi
+ public long getAccessibilityIdForRegion(@NonNull Region region) {
+ return mTargetMap.get(region);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mTargetMap.size());
+ for (int i = 0; i < mTargetMap.size(); i++) {
+ final Region region = mTargetMap.keyAt(i);
+ final Long accessibilityId = mTargetMap.valueAt(i);
+ region.writeToParcel(dest, flags);
+ dest.writeLong(accessibilityId);
+ }
+ }
+
+ /**
+ * @see android.os.Parcelable.Creator
+ */
+ public static final Parcelable.Creator<TouchDelegateInfo> CREATOR =
+ new Parcelable.Creator<TouchDelegateInfo>() {
+ @Override
+ public TouchDelegateInfo createFromParcel(Parcel parcel) {
+ final int size = parcel.readInt();
+ if (size == 0) {
+ return null;
+ }
+ final ArrayMap<Region, Long> targetMap = new ArrayMap<>(size);
+ for (int i = 0; i < size; i++) {
+ final Region region = Region.CREATOR.createFromParcel(parcel);
+ final long accessibilityId = parcel.readLong();
+ targetMap.put(region, accessibilityId);
+ }
+ final TouchDelegateInfo touchDelegateInfo = new TouchDelegateInfo(
+ targetMap, false);
+ return touchDelegateInfo;
+ }
+
+ @Override
+ public TouchDelegateInfo[] newArray(int size) {
+ return new TouchDelegateInfo[size];
+ }
+ };
+ }
+
+ /**
* @see android.os.Parcelable.Creator
*/
public static final Parcelable.Creator<AccessibilityNodeInfo> CREATOR =
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 08ed9d17fb77..ca2ccaf224db 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -48,7 +48,6 @@ import android.util.Pools.SimplePool;
import android.util.PrintWriterPrinter;
import android.util.Printer;
import android.util.SparseArray;
-import android.view.Display;
import android.view.InputChannel;
import android.view.InputEvent;
import android.view.InputEventSender;
@@ -266,7 +265,7 @@ public final class InputMethodManager {
* @hide
*/
public static void ensureDefaultInstanceForDefaultDisplayIfNecessary() {
- forContextInternal(Display.DEFAULT_DISPLAY, Looper.getMainLooper());
+ getInstanceInternal();
}
private static final Object sLock = new Object();
@@ -280,17 +279,6 @@ public final class InputMethodManager {
static InputMethodManager sInstance;
/**
- * Global map between display to {@link InputMethodManager}.
- *
- * <p>Currently this map works like a so-called leaky singleton. Once an instance is registered
- * for the associated display ID, that instance will never be garbage collected.</p>
- *
- * <p>TODO(Bug 116699479): Implement instance clean up mechanism.</p>
- */
- @GuardedBy("sLock")
- private static final SparseArray<InputMethodManager> sInstanceMap = new SparseArray<>();
-
- /**
* @hide Flag for IInputMethodManager.windowGainedFocus: a view in
* the window has input focus.
*/
@@ -347,8 +335,6 @@ public final class InputMethodManager {
// Our generic input connection if the current target does not have its own.
final IInputContext mIInputContext;
- private final int mDisplayId;
-
/**
* True if this input method client is active, initially false.
*/
@@ -466,29 +452,6 @@ public final class InputMethodManager {
return afm != null && afm.isAutofillUiShowing();
}
- /**
- * Checks the consistency between {@link InputMethodManager} state and {@link View} state.
- *
- * @param view {@link View} to be checked
- * @return {@code true} if {@code view} is not {@code null} and there is a {@link Context}
- * mismatch between {@link InputMethodManager} and {@code view}
- */
- private boolean shouldDispatchToViewContext(@Nullable View view) {
- if (view == null) {
- return false;
- }
- final int viewDisplayId = getDisplayId(view.getContext());
- if (viewDisplayId != mDisplayId) {
- Log.w(TAG, "b/117267690: Context mismatch found. view=" + view + " belongs to"
- + " displayId=" + viewDisplayId
- + " but InputMethodManager belongs to displayId=" + mDisplayId
- + ". Use the right InputMethodManager instance to avoid performance overhead.",
- new Throwable());
- return true;
- }
- return false;
- }
-
private static boolean canStartInput(View servedView) {
// We can start input ether the servedView has window focus
// or the activity is showing autofill ui.
@@ -770,57 +733,33 @@ public final class InputMethodManager {
});
}
- InputMethodManager(int displayId, Looper looper) throws ServiceNotFoundException {
+ InputMethodManager(Looper looper) throws ServiceNotFoundException {
mService = getIInputMethodManager();
mMainLooper = looper;
mH = new H(looper);
- mDisplayId = displayId;
mIInputContext = new ControlledInputConnectionWrapper(looper,
mDummyInputConnection, this);
}
- private static int getDisplayId(Context context) {
- final Display display = context.getDisplay();
- return display != null ? display.getDisplayId() : Display.DEFAULT_DISPLAY;
- }
-
/**
- * Retrieve an instance for the given {@link Context}, creating it if it doesn't already exist.
+ * Retrieve the global {@link InputMethodManager} instance, creating it if it doesn't already
+ * exist.
*
- * @param context {@link Context} for which IME APIs need to work
- * @return {@link InputMethodManager} instance
+ * @return global {@link InputMethodManager} instance
* @hide
*/
- @Nullable
- public static InputMethodManager forContext(Context context) {
- final int displayId = getDisplayId(context);
- // For better backward compatibility, we always use Looper.getMainLooper() for the default
- // display case.
- final Looper looper = displayId == Display.DEFAULT_DISPLAY
- ? Looper.getMainLooper() : context.getMainLooper();
- return forContextInternal(displayId, looper);
- }
-
- @Nullable
- private static InputMethodManager forContextInternal(int displayId, Looper looper) {
- final boolean isDefaultDisplay = displayId == Display.DEFAULT_DISPLAY;
+ public static InputMethodManager getInstanceInternal() {
synchronized (sLock) {
- InputMethodManager instance = sInstanceMap.get(displayId);
- if (instance != null) {
- return instance;
- }
- try {
- instance = new InputMethodManager(displayId, looper);
- instance.mService.addClient(instance.mClient, instance.mIInputContext, displayId);
- } catch (ServiceNotFoundException | RemoteException e) {
- throw new IllegalStateException(e);
- }
- // For backward compatibility, store the instance also to sInstance for default display.
- if (sInstance == null && isDefaultDisplay) {
- sInstance = instance;
+ if (sInstance == null) {
+ try {
+ final InputMethodManager imm = new InputMethodManager(Looper.getMainLooper());
+ imm.mService.addClient(imm.mClient, imm.mIInputContext);
+ sInstance = imm;
+ } catch (ServiceNotFoundException | RemoteException e) {
+ throw new IllegalStateException(e);
+ }
}
- sInstanceMap.put(displayId, instance);
- return instance;
+ return sInstance;
}
}
@@ -977,11 +916,6 @@ public final class InputMethodManager {
* input method.
*/
public boolean isActive(View view) {
- // Re-dispatch if there is a context mismatch.
- if (shouldDispatchToViewContext(view)) {
- return view.getContext().getSystemService(InputMethodManager.class).isActive(view);
- }
-
checkFocus();
synchronized (mH) {
return (mServedView == view
@@ -1072,13 +1006,6 @@ public final class InputMethodManager {
}
public void displayCompletions(View view, CompletionInfo[] completions) {
- // Re-dispatch if there is a context mismatch.
- if (shouldDispatchToViewContext(view)) {
- view.getContext().getSystemService(InputMethodManager.class)
- .displayCompletions(view, completions);
- return;
- }
-
checkFocus();
synchronized (mH) {
if (mServedView != view && (mServedView == null
@@ -1097,13 +1024,6 @@ public final class InputMethodManager {
}
public void updateExtractedText(View view, int token, ExtractedText text) {
- // Re-dispatch if there is a context mismatch.
- if (shouldDispatchToViewContext(view)) {
- view.getContext().getSystemService(InputMethodManager.class)
- .updateExtractedText(view, token, text);
- return;
- }
-
checkFocus();
synchronized (mH) {
if (mServedView != view && (mServedView == null
@@ -1145,12 +1065,6 @@ public final class InputMethodManager {
* 0 or have the {@link #SHOW_IMPLICIT} bit set.
*/
public boolean showSoftInput(View view, int flags) {
- // Re-dispatch if there is a context mismatch.
- if (shouldDispatchToViewContext(view)) {
- return view.getContext().getSystemService(InputMethodManager.class)
- .showSoftInput(view, flags);
- }
-
return showSoftInput(view, flags, null);
}
@@ -1213,12 +1127,6 @@ public final class InputMethodManager {
* {@link #RESULT_HIDDEN}.
*/
public boolean showSoftInput(View view, int flags, ResultReceiver resultReceiver) {
- // Re-dispatch if there is a context mismatch.
- if (shouldDispatchToViewContext(view)) {
- return view.getContext().getSystemService(InputMethodManager.class)
- .showSoftInput(view, flags, resultReceiver);
- }
-
checkFocus();
synchronized (mH) {
if (mServedView != view && (mServedView == null
@@ -1382,12 +1290,6 @@ public final class InputMethodManager {
* @param view The view whose text has changed.
*/
public void restartInput(View view) {
- // Re-dispatch if there is a context mismatch.
- if (shouldDispatchToViewContext(view)) {
- view.getContext().getSystemService(InputMethodManager.class).restartInput(view);
- return;
- }
-
checkFocus();
synchronized (mH) {
if (mServedView != view && (mServedView == null
@@ -1812,13 +1714,6 @@ public final class InputMethodManager {
*/
public void updateSelection(View view, int selStart, int selEnd,
int candidatesStart, int candidatesEnd) {
- // Re-dispatch if there is a context mismatch.
- if (shouldDispatchToViewContext(view)) {
- view.getContext().getSystemService(InputMethodManager.class)
- .updateSelection(view, selStart, selEnd, candidatesStart, candidatesEnd);
- return;
- }
-
checkFocus();
synchronized (mH) {
if ((mServedView != view && (mServedView == null
@@ -1856,12 +1751,6 @@ public final class InputMethodManager {
* Notify the event when the user tapped or clicked the text view.
*/
public void viewClicked(View view) {
- // Re-dispatch if there is a context mismatch.
- if (shouldDispatchToViewContext(view)) {
- view.getContext().getSystemService(InputMethodManager.class).viewClicked(view);
- return;
- }
-
final boolean focusChanged = mServedView != mNextServedView;
checkFocus();
synchronized (mH) {
@@ -1926,13 +1815,6 @@ public final class InputMethodManager {
*/
@Deprecated
public void updateCursor(View view, int left, int top, int right, int bottom) {
- // Re-dispatch if there is a context mismatch.
- if (shouldDispatchToViewContext(view)) {
- view.getContext().getSystemService(InputMethodManager.class)
- .updateCursor(view, left, top, right, bottom);
- return;
- }
-
checkFocus();
synchronized (mH) {
if ((mServedView != view && (mServedView == null
@@ -1964,13 +1846,6 @@ public final class InputMethodManager {
if (view == null || cursorAnchorInfo == null) {
return;
}
- // Re-dispatch if there is a context mismatch.
- if (shouldDispatchToViewContext(view)) {
- view.getContext().getSystemService(InputMethodManager.class)
- .updateCursorAnchorInfo(view, cursorAnchorInfo);
- return;
- }
-
checkFocus();
synchronized (mH) {
if ((mServedView != view &&
@@ -2016,13 +1891,6 @@ public final class InputMethodManager {
* @param data Any data to include with the command.
*/
public void sendAppPrivateCommand(View view, String action, Bundle data) {
- // Re-dispatch if there is a context mismatch.
- if (shouldDispatchToViewContext(view)) {
- view.getContext().getSystemService(InputMethodManager.class)
- .sendAppPrivateCommand(view, action, data);
- return;
- }
-
checkFocus();
synchronized (mH) {
if ((mServedView != view && (mServedView == null
@@ -2194,13 +2062,6 @@ public final class InputMethodManager {
*/
public void dispatchKeyEventFromInputMethod(@Nullable View targetView,
@NonNull KeyEvent event) {
- // Re-dispatch if there is a context mismatch.
- if (shouldDispatchToViewContext(targetView)) {
- targetView.getContext().getSystemService(InputMethodManager.class)
- .dispatchKeyEventFromInputMethod(targetView, event);
- return;
- }
-
synchronized (mH) {
ViewRootImpl viewRootImpl = targetView != null ? targetView.getViewRootImpl() : null;
if (viewRootImpl == null) {
@@ -2690,7 +2551,6 @@ public final class InputMethodManager {
sb.append(",windowFocus=" + view.hasWindowFocus());
sb.append(",autofillUiShowing=" + isAutofillUIShowing(view));
sb.append(",window=" + view.getWindowToken());
- sb.append(",displayId=" + getDisplayId(view.getContext()));
sb.append(",temporaryDetach=" + view.isTemporarilyDetached());
return sb.toString();
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 9d06680c4c07..f74c2341d816 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -3521,7 +3521,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
Typeface mFontTypeface = null;
boolean mFontFamilyExplicit = false;
int mTypefaceIndex = -1;
- int mStyleIndex = -1;
+ int mTextStyle = 0;
int mFontWeight = -1;
boolean mAllCaps = false;
int mShadowColor = 0;
@@ -3547,7 +3547,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
+ " mFontTypeface:" + mFontTypeface + "\n"
+ " mFontFamilyExplicit:" + mFontFamilyExplicit + "\n"
+ " mTypefaceIndex:" + mTypefaceIndex + "\n"
- + " mStyleIndex:" + mStyleIndex + "\n"
+ + " mTextStyle:" + mTextStyle + "\n"
+ " mFontWeight:" + mFontWeight + "\n"
+ " mAllCaps:" + mAllCaps + "\n"
+ " mShadowColor:" + mShadowColor + "\n"
@@ -3672,7 +3672,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
attributes.mFontFamilyExplicit = true;
break;
case com.android.internal.R.styleable.TextAppearance_textStyle:
- attributes.mStyleIndex = appearance.getInt(attr, attributes.mStyleIndex);
+ attributes.mTextStyle = appearance.getInt(attr, attributes.mTextStyle);
break;
case com.android.internal.R.styleable.TextAppearance_textFontWeight:
attributes.mFontWeight = appearance.getInt(attr, attributes.mFontWeight);
@@ -3742,7 +3742,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
attributes.mFontFamily = null;
}
setTypefaceFromAttrs(attributes.mFontTypeface, attributes.mFontFamily,
- attributes.mTypefaceIndex, attributes.mStyleIndex, attributes.mFontWeight);
+ attributes.mTypefaceIndex, attributes.mTextStyle, attributes.mFontWeight);
if (attributes.mShadowColor != 0) {
setShadowLayer(attributes.mShadowRadius, attributes.mShadowDx, attributes.mShadowDy,
diff --git a/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java b/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java
index 0080ace230a2..d4c451e3ffff 100644
--- a/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java
+++ b/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java
@@ -72,7 +72,8 @@ public class AmbientDisplayConfiguration {
}
public boolean wakeLockScreenGestureAvailable() {
- return !TextUtils.isEmpty(wakeLockScreenSensorType());
+ return mContext.getResources()
+ .getBoolean(R.bool.config_dozeWakeLockScreenSensorAvailable);
}
public boolean wakeScreenGestureEnabled(int user) {
@@ -92,10 +93,6 @@ public class AmbientDisplayConfiguration {
return mContext.getResources().getString(R.string.config_dozeLongPressSensorType);
}
- public String wakeLockScreenSensorType() {
- return mContext.getResources().getString(R.string.config_dozeWakeLockScreenSensorType);
- }
-
public String wakeScreenSensorType() {
return mContext.getResources().getString(R.string.config_dozeWakeScreenSensorType);
}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 33b9ff7cee4f..017da550c9d3 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -5330,6 +5330,7 @@ public class BatteryStatsImpl extends BatteryStats {
if (DEBUG_HISTORY) Slog.v(TAG, "Phone started scanning to: "
+ Integer.toHexString(mHistoryCur.states));
mPhoneSignalScanningTimer.startRunningLocked(elapsedRealtime);
+ StatsLog.write(StatsLog.PHONE_SERVICE_STATE_CHANGED, state, simState, strengthBin);
}
}
@@ -5341,6 +5342,7 @@ public class BatteryStatsImpl extends BatteryStats {
+ Integer.toHexString(mHistoryCur.states));
newHistory = true;
mPhoneSignalScanningTimer.stopRunningLocked(elapsedRealtime);
+ StatsLog.write(StatsLog.PHONE_SERVICE_STATE_CHANGED, state, simState, strengthBin);
}
}
diff --git a/core/java/com/android/internal/os/LooperStats.java b/core/java/com/android/internal/os/LooperStats.java
index e4724ff45b9e..8dc97fe86eb3 100644
--- a/core/java/com/android/internal/os/LooperStats.java
+++ b/core/java/com/android/internal/os/LooperStats.java
@@ -66,6 +66,7 @@ public class LooperStats implements Looper.Observer {
session = session == null ? new DispatchSession() : session;
session.startTimeMicro = getElapsedRealtimeMicro();
session.cpuStartMicro = getThreadTimeMicro();
+ session.systemUptimeMillis = getSystemUptimeMillis();
return session;
}
@@ -85,12 +86,18 @@ public class LooperStats implements Looper.Observer {
entry.messageCount++;
if (session != DispatchSession.NOT_SAMPLED) {
entry.recordedMessageCount++;
- long latency = getElapsedRealtimeMicro() - session.startTimeMicro;
- long cpuUsage = getThreadTimeMicro() - session.cpuStartMicro;
+ final long latency = getElapsedRealtimeMicro() - session.startTimeMicro;
+ final long cpuUsage = getThreadTimeMicro() - session.cpuStartMicro;
entry.totalLatencyMicro += latency;
entry.maxLatencyMicro = Math.max(entry.maxLatencyMicro, latency);
entry.cpuUsageMicro += cpuUsage;
entry.maxCpuUsageMicro = Math.max(entry.maxCpuUsageMicro, cpuUsage);
+ if (msg.getWhen() > 0) {
+ final long delay = Math.max(0L, session.systemUptimeMillis - msg.getWhen());
+ entry.delayMillis += delay;
+ entry.maxDelayMillis = Math.max(entry.maxDelayMillis, delay);
+ entry.recordedDelayMessageCount++;
+ }
}
}
}
@@ -206,6 +213,10 @@ public class LooperStats implements Looper.Observer {
return SystemClock.elapsedRealtimeNanos() / 1000;
}
+ protected long getSystemUptimeMillis() {
+ return SystemClock.uptimeMillis();
+ }
+
protected boolean shouldCollectDetailedData() {
return ThreadLocalRandom.current().nextInt() % mSamplingInterval == 0;
}
@@ -214,6 +225,7 @@ public class LooperStats implements Looper.Observer {
static final DispatchSession NOT_SAMPLED = new DispatchSession();
public long startTimeMicro;
public long cpuStartMicro;
+ public long systemUptimeMillis;
}
private static class Entry {
@@ -228,6 +240,9 @@ public class LooperStats implements Looper.Observer {
public long maxLatencyMicro;
public long cpuUsageMicro;
public long maxCpuUsageMicro;
+ public long recordedDelayMessageCount;
+ public long delayMillis;
+ public long maxDelayMillis;
Entry(Message msg, boolean isInteractive) {
this.workSourceUid = msg.workSourceUid;
@@ -251,6 +266,9 @@ public class LooperStats implements Looper.Observer {
maxLatencyMicro = 0;
cpuUsageMicro = 0;
maxCpuUsageMicro = 0;
+ delayMillis = 0;
+ maxDelayMillis = 0;
+ recordedDelayMessageCount = 0;
}
static int idFor(Message msg, boolean isInteractive) {
@@ -281,6 +299,9 @@ public class LooperStats implements Looper.Observer {
public final long maxLatencyMicros;
public final long cpuUsageMicros;
public final long maxCpuUsageMicros;
+ public final long maxDelayMillis;
+ public final long delayMillis;
+ public final long recordedDelayMessageCount;
ExportedEntry(Entry entry) {
this.workSourceUid = entry.workSourceUid;
@@ -301,6 +322,9 @@ public class LooperStats implements Looper.Observer {
this.maxLatencyMicros = entry.maxLatencyMicro;
this.cpuUsageMicros = entry.cpuUsageMicro;
this.maxCpuUsageMicros = entry.maxCpuUsageMicro;
+ this.delayMillis = entry.delayMillis;
+ this.maxDelayMillis = entry.maxDelayMillis;
+ this.recordedDelayMessageCount = entry.recordedDelayMessageCount;
}
}
}
diff --git a/core/java/com/android/internal/os/ProcessCpuTracker.java b/core/java/com/android/internal/os/ProcessCpuTracker.java
index bf31c7d8ad85..1ee4269d974b 100644
--- a/core/java/com/android/internal/os/ProcessCpuTracker.java
+++ b/core/java/com/android/internal/os/ProcessCpuTracker.java
@@ -29,7 +29,6 @@ import android.util.Slog;
import com.android.internal.util.FastPrintWriter;
import libcore.io.IoUtils;
-import libcore.io.Libcore;
import java.io.File;
import java.io.FileInputStream;
diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
index dceacda5d4a3..5f1243f37542 100644
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
@@ -31,8 +31,7 @@ import com.android.internal.view.IInputMethodClient;
* applications.
*/
interface IInputMethodManager {
- void addClient(in IInputMethodClient client, in IInputContext inputContext,
- int untrustedDisplayId);
+ void addClient(in IInputMethodClient client, in IInputContext inputContext);
// TODO: Use ParceledListSlice instead
List<InputMethodInfo> getInputMethodList();
diff --git a/core/java/com/android/internal/view/InputBindResult.java b/core/java/com/android/internal/view/InputBindResult.java
index ec8e8dacb9db..101fd41f2925 100644
--- a/core/java/com/android/internal/view/InputBindResult.java
+++ b/core/java/com/android/internal/view/InputBindResult.java
@@ -51,9 +51,6 @@ public final class InputBindResult implements Parcelable {
ResultCode.ERROR_INVALID_USER,
ResultCode.ERROR_NULL_EDITOR_INFO,
ResultCode.ERROR_NOT_IME_TARGET_WINDOW,
- ResultCode.ERROR_NO_EDITOR,
- ResultCode.ERROR_DISPLAY_ID_MISMATCH,
- ResultCode.ERROR_INVALID_DISPLAY_ID,
})
public @interface ResultCode {
/**
@@ -142,22 +139,13 @@ public final class InputBindResult implements Parcelable {
* The client should try to restart input when its {@link android.view.Window} is focused
* again.</p>
*
- * @see com.android.server.wm.WindowManagerInternal#isInputMethodClientFocus(int, int, int)
+ * @see com.android.server.wm.WindowManagerInternal#isInputMethodClientFocus(int, int)
*/
int ERROR_NOT_IME_TARGET_WINDOW = 11;
/**
* Indicates that focused view in the current window is not an editor.
*/
int ERROR_NO_EDITOR = 12;
- /**
- * Indicates that there is a mismatch in display ID between IME client and focused Window.
- */
- int ERROR_DISPLAY_ID_MISMATCH = 13;
- /**
- * Indicates that current IME client is no longer allowed to access to the associated
- * display.
- */
- int ERROR_INVALID_DISPLAY_ID = 14;
}
@ResultCode
@@ -283,10 +271,6 @@ public final class InputBindResult implements Parcelable {
return "ERROR_NULL_EDITOR_INFO";
case ResultCode.ERROR_NOT_IME_TARGET_WINDOW:
return "ERROR_NOT_IME_TARGET_WINDOW";
- case ResultCode.ERROR_DISPLAY_ID_MISMATCH:
- return "ERROR_DISPLAY_ID_MISMATCH";
- case ResultCode.ERROR_INVALID_DISPLAY_ID:
- return "ERROR_INVALID_DISPLAY_ID";
default:
return "Unknown(" + result + ")";
}
@@ -332,15 +316,4 @@ public final class InputBindResult implements Parcelable {
*/
public static final InputBindResult INVALID_USER = error(ResultCode.ERROR_INVALID_USER);
- /**
- * Predefined error object for {@link ResultCode#ERROR_DISPLAY_ID_MISMATCH}.
- */
- public static final InputBindResult DISPLAY_ID_MISMATCH =
- error(ResultCode.ERROR_DISPLAY_ID_MISMATCH);
-
- /**
- * Predefined error object for {@link ResultCode#ERROR_INVALID_DISPLAY_ID}.
- */
- public static final InputBindResult INVALID_DISPLAY_ID =
- error(ResultCode.ERROR_INVALID_DISPLAY_ID);
}
diff --git a/core/java/com/android/internal/widget/AlertDialogLayout.java b/core/java/com/android/internal/widget/AlertDialogLayout.java
index 9bf094891f3b..7a0174946671 100644
--- a/core/java/com/android/internal/widget/AlertDialogLayout.java
+++ b/core/java/com/android/internal/widget/AlertDialogLayout.java
@@ -18,6 +18,7 @@ package com.android.internal.widget;
import android.annotation.AttrRes;
import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
import android.annotation.StyleRes;
import android.content.Context;
import android.graphics.drawable.Drawable;
@@ -50,6 +51,7 @@ public class AlertDialogLayout extends LinearLayout {
super(context);
}
+ @UnsupportedAppUsage
public AlertDialogLayout(@Nullable Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
diff --git a/core/java/com/android/internal/widget/ButtonBarLayout.java b/core/java/com/android/internal/widget/ButtonBarLayout.java
index ab8be33599fa..0ca67438c5c3 100644
--- a/core/java/com/android/internal/widget/ButtonBarLayout.java
+++ b/core/java/com/android/internal/widget/ButtonBarLayout.java
@@ -16,6 +16,7 @@
package com.android.internal.widget;
+import android.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
@@ -40,6 +41,7 @@ public class ButtonBarLayout extends LinearLayout {
private int mMinimumHeight = 0;
+ @UnsupportedAppUsage
public ButtonBarLayout(Context context, AttributeSet attrs) {
super(context, attrs);
diff --git a/core/java/com/android/internal/widget/DialogTitle.java b/core/java/com/android/internal/widget/DialogTitle.java
index 7ea3d6b5bff0..405436c53ff0 100644
--- a/core/java/com/android/internal/widget/DialogTitle.java
+++ b/core/java/com/android/internal/widget/DialogTitle.java
@@ -16,6 +16,7 @@
package com.android.internal.widget;
+import android.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.TypedArray;
import android.text.Layout;
@@ -37,6 +38,7 @@ public class DialogTitle extends TextView {
super(context, attrs, defStyleAttr);
}
+ @UnsupportedAppUsage
public DialogTitle(Context context, AttributeSet attrs) {
super(context, attrs);
}
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index 0a787b99c0ac..d68e8f88fc5a 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -331,13 +331,11 @@ public class SystemConfig {
readPermissions(Environment.buildPath(
Environment.getOemDirectory(), "etc", "permissions"), oemPermissionFlag);
- // Allow Product to customize system configs around libs, features, permissions and apps
- int productPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PERMISSIONS |
- ALLOW_APP_CONFIGS | ALLOW_PRIVAPP_PERMISSIONS;
+ // Allow Product to customize all system configs
readPermissions(Environment.buildPath(
- Environment.getProductDirectory(), "etc", "sysconfig"), productPermissionFlag);
+ Environment.getProductDirectory(), "etc", "sysconfig"), ALLOW_ALL);
readPermissions(Environment.buildPath(
- Environment.getProductDirectory(), "etc", "permissions"), productPermissionFlag);
+ Environment.getProductDirectory(), "etc", "permissions"), ALLOW_ALL);
// Allow /product_services to customize system configs around libs, features, permissions
// and apps.
diff --git a/core/proto/android/internal/powerprofile.proto b/core/proto/android/internal/powerprofile.proto
index 9dd5e7ee556c..b0c8b5638a72 100644
--- a/core/proto/android/internal/powerprofile.proto
+++ b/core/proto/android/internal/powerprofile.proto
@@ -35,7 +35,7 @@ message PowerProfileProto {
repeated double core_power = 5;
}
- repeated CpuCluster cpu_cluster = 41;
+ repeated CpuCluster cpu_cluster = 40;
optional double wifi_scan = 4;
@@ -85,27 +85,27 @@ message PowerProfileProto {
optional double ambient_display = 27;
- optional double screen_on = 29;
+ optional double screen_on = 28;
- optional double radio_on = 30;
+ optional double radio_on = 29;
- optional double radio_scanning = 31;
+ optional double radio_scanning = 30;
- optional double radio_active = 32;
+ optional double radio_active = 31;
- optional double screen_full = 33;
+ optional double screen_full = 32;
- optional double audio = 34;
+ optional double audio = 33;
- optional double video = 35;
+ optional double video = 34;
- optional double flashlight = 36;
+ optional double flashlight = 35;
- optional double memory = 37;
+ optional double memory = 36;
- optional double camera = 38;
+ optional double camera = 37;
- optional double wifi_batched_scan = 39;
+ optional double wifi_batched_scan = 38;
- optional double battery_capacity = 40;
+ optional double battery_capacity = 39;
}
diff --git a/proto/src/stats_enums.proto b/core/proto/android/stats/enums.proto
index 6c892cfeae6c..2320a01b324c 100644
--- a/proto/src/stats_enums.proto
+++ b/core/proto/android/stats/enums.proto
@@ -16,8 +16,7 @@
syntax = "proto2";
-package android.os.statsd;
-option java_package = "com.android.os";
+package android.stats;
option java_outer_classname = "StatsEnums";
enum EventType {
diff --git a/core/proto/android/telephony/enums.proto b/core/proto/android/telephony/enums.proto
index 32975a5550f1..fba2e51937b3 100644
--- a/core/proto/android/telephony/enums.proto
+++ b/core/proto/android/telephony/enums.proto
@@ -61,3 +61,64 @@ enum SignalStrengthEnum {
SIGNAL_STRENGTH_GOOD = 3;
SIGNAL_STRENGTH_GREAT = 4;
}
+
+
+enum ServiceStateEnum {
+ /**
+ * Normal operation condition, the phone is registered
+ * with an operator either in home network or in roaming.
+ */
+ SERVICE_STATE_IN_SERVICE = 0;
+
+ /**
+ * Phone is not registered with any operator, the phone
+ * can be currently searching a new operator to register to, or not
+ * searching to registration at all, or registration is denied, or radio
+ * signal is not available.
+ */
+ SERVICE_STATE_OUT_OF_SERVICE = 1;
+
+ /**
+ * The phone is registered and locked. Only emergency numbers are allowed. {@more}
+ */
+ SERVICE_STATE_EMERGENCY_ONLY = 2;
+
+ /**
+ * Radio of telephony is explicitly powered off.
+ */
+ SERVICE_STATE_POWER_OFF = 3;
+}
+
+enum SimStateEnum {
+ SIM_STATE_UNKNOWN = 0;
+ /** SIM card state: no SIM card is available in the device */
+ SIM_STATE_ABSENT = 1;
+ /** SIM card state: Locked: requires the user's SIM PIN to unlock */
+ SIM_STATE_PIN_REQUIRED = 2;
+ /** SIM card state: Locked: requires the user's SIM PUK to unlock */
+ SIM_STATE_PUK_REQUIRED = 3;
+ /** SIM card state: Locked: requires a network PIN to unlock */
+ SIM_STATE_NETWORK_LOCKED = 4;
+ /** SIM card state: Ready */
+ SIM_STATE_READY = 5;
+ /** SIM card state: SIM Card is NOT READY */
+ SIM_STATE_NOT_READY = 6;
+ /** SIM card state: SIM Card Error, permanently disabled */
+ SIM_STATE_PERM_DISABLED = 7;
+ /** SIM card state: SIM Card Error, present but faulty */
+ SIM_STATE_CARD_IO_ERROR = 8;
+ /** SIM card state: SIM Card restricted, present but not usable due to
+ * carrier restrictions.
+ */
+ SIM_STATE_CARD_RESTRICTED = 9;
+ /**
+ * SIM card state: Loaded: SIM card applications have been loaded
+ * @hide
+ */
+ SIM_STATE_LOADED = 10;
+ /**
+ * SIM card state: SIM Card is present
+ * @hide
+ */
+ SIM_STATE_PRESENT = 11;
+}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index f3f012de53be..1ae5f03a2f04 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -138,7 +138,6 @@
<protected-broadcast android:name="android.bluetooth.device.action.MAS_INSTANCE" />
<protected-broadcast android:name="android.bluetooth.device.action.ALIAS_CHANGED" />
<protected-broadcast android:name="android.bluetooth.device.action.FOUND" />
- <protected-broadcast android:name="android.bluetooth.device.action.DISAPPEARED" />
<protected-broadcast android:name="android.bluetooth.device.action.CLASS_CHANGED" />
<protected-broadcast android:name="android.bluetooth.device.action.ACL_CONNECTED" />
<protected-broadcast android:name="android.bluetooth.device.action.ACL_DISCONNECT_REQUESTED" />
@@ -1151,6 +1150,28 @@
android:protectionLevel="dangerous|instant"/>
<!-- ====================================================================== -->
+ <!-- Permissions for activity recognition -->
+ <!-- ====================================================================== -->
+ <eat-comment />
+
+ <!-- Used for permissions that are associated with activity recognition.
+ TODO(zezeozue). STOPSHIP: Add icon -->
+ <permission-group android:name="android.permission-group.ACTIVITY_RECOGNITION"
+ android:label="@string/permgrouplab_activityRecognition"
+ android:description="@string/permgroupdesc_activityRecognition"
+ android:request="@string/permgrouprequest_activityRecognition"
+ android:priority="1000" />
+
+ <!-- Allows an application to recognize physical activity.
+ <p>Protection level: dangerous
+ -->
+ <permission android:name="android.permission.ACTIVITY_RECOGNITION"
+ android:permissionGroup="android.permission-group.ACTIVITY_RECOGNITION"
+ android:label="@string/permlab_activityRecognition"
+ android:description="@string/permdesc_activityRecognition"
+ android:protectionLevel="dangerous|instant" />
+
+ <!-- ====================================================================== -->
<!-- Permissions for accessing the UCE Service -->
<!-- ====================================================================== -->
@@ -1546,6 +1567,7 @@
<!-- Allows SetupWizard to call methods in Networking services
<p>Not for use by any other third-party or privileged applications.
+ @SystemApi
@hide This should only be used by SetupWizard.
-->
<permission android:name="android.permission.NETWORK_SETUP_WIZARD"
@@ -2748,7 +2770,7 @@
android:protectionLevel="signature" />
<!-- @SystemApi Allows an application to use
- {@link android.view.WindowManager.LayoutsParams#PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS}
+ {@link android.view.WindowManager.LayoutsParams#SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS}
to hide non-system-overlay windows.
<p>Not for use by third-party applications.
@hide
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 8b73b6768479..aeeba59b694b 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2113,8 +2113,8 @@
<!-- Type of the long press sensor. Empty if long press is not supported. -->
<string name="config_dozeLongPressSensorType" translatable="false"></string>
- <!-- Type of sensor that wakes up the lock screen. Empty if not supported. -->
- <string name="config_dozeWakeLockScreenSensorType" translatable="false"></string>
+ <!-- If the sensor that wakes up the lock screen is available or not. -->
+ <bool name="config_dozeWakeLockScreenSensorAvailable">false</bool>
<!-- Type of the wake up sensor. Empty if not supported. -->
<string name="config_dozeWakeScreenSensorType" translatable="false"></string>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 6bf893d94ce5..fa4406185218 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -734,6 +734,14 @@
<string name="permgrouprequest_microphone">Allow
&lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to record audio?</string>
+ <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=40]-->
+ <string name="permgrouplab_activityRecognition">Activity recognition</string>
+ <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=40]-->
+ <string name="permgroupdesc_activityRecognition">recognize activity</string>
+ <!-- Message shown to the user when the apps requests permission from this group. If ever possible this should stay below 80 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 120 characters though. [CHAR LIMIT=120] -->
+ <string name="permgrouprequest_activityRecognition">Allow
+ &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to recognize your physical activity?</string>
+
<!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permgrouplab_camera">Camera</string>
<!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
@@ -1151,6 +1159,11 @@
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_sim_communication">Allows the app to send commands to the SIM. This is very dangerous.</string>
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=50]-->
+ <string name="permlab_activityRecognition">recognize physical activity</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=120]-->
+ <string name="permdesc_activityRecognition">This app can recognize your physical activity.</string>
+
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_camera">take pictures and videos</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 7e7c7b252e21..6f28b2c36e16 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3280,7 +3280,7 @@
<java-symbol type="array" name="config_hideWhenDisabled_packageNames" />
<java-symbol type="string" name="config_dozeLongPressSensorType" />
- <java-symbol type="string" name="config_dozeWakeLockScreenSensorType" />
+ <java-symbol type="bool" name="config_dozeWakeLockScreenSensorAvailable" />
<java-symbol type="array" name="config_allowedGlobalInstantAppSettings" />
<java-symbol type="array" name="config_allowedSystemInstantAppSettings" />
diff --git a/core/res/res/xml/sms_short_codes.xml b/core/res/res/xml/sms_short_codes.xml
index fb78b3b0533a..7b3d940b91f3 100644
--- a/core/res/res/xml/sms_short_codes.xml
+++ b/core/res/res/xml/sms_short_codes.xml
@@ -109,12 +109,12 @@
<!-- France: 5 digits, free: 3xxxx, premium [4-8]xxxx, plus EU:
http://clients.txtnation.com/entries/161972-france-premium-sms-short-code-requirements,
visual voicemail code for Orange: 21101 -->
- <shortcode country="fr" premium="[4-8]\\d{4}" free="3\\d{4}|116\\d{3}|21101|20366" />
+ <shortcode country="fr" premium="[4-8]\\d{4}" free="3\\d{4}|116\\d{3}|21101|20366|555|2051" />
<!-- United Kingdom (Great Britain): 4-6 digits, common codes [5-8]xxxx, plus EU:
http://www.short-codes.com/media/Co-regulatoryCodeofPracticeforcommonshortcodes170206.pdf,
visual voicemail code for EE: 887 -->
- <shortcode country="gb" pattern="\\d{4,6}" premium="[5-8]\\d{4}" free="116\\d{3}|2020|35890|61002|61202|887|83669|34664|40406|60174|7726|37726" />
+ <shortcode country="gb" pattern="\\d{4,6}" premium="[5-8]\\d{4}" free="116\\d{3}|2020|35890|61002|61202|887|83669|34664|40406|60174|7726|37726|88555|9017|9018" />
<!-- Georgia: 4 digits, known premium codes listed -->
<shortcode country="ge" pattern="\\d{4}" premium="801[234]|888[239]" />
@@ -189,11 +189,14 @@
<!-- The Netherlands, 4 digits, known premium codes listed, plus EU -->
<shortcode country="nl" pattern="\\d{4}" premium="4466|5040" free="116\\d{3}|2223|6225|2223" />
+ <!-- Nigeria -->
+ <shortcode country="ng" pattern="\\d{1,5}" free="2441" />
+
<!-- Norway: 4-5 digits (not confirmed), known premium codes listed -->
<shortcode country="no" pattern="\\d{4,5}" premium="2201|222[67]" free="2171" />
<!-- New Zealand: 3-4 digits, known premium codes listed -->
- <shortcode country="nz" pattern="\\d{3,4}" premium="3903|8995|4679" free="3067|3068|4053" />
+ <shortcode country="nz" pattern="\\d{3,4}" premium="3903|8995|4679" free="1737|2141|3067|3068|3110|4006|4053|4061|4062|4202|4300|4334|4412|4575|5626|8006|8681" />
<!-- Peru: 4-5 digits (not confirmed), known premium codes listed -->
<shortcode country="pe" pattern="\\d{4,5}" free="9963" />
@@ -209,7 +212,7 @@
<!-- Portugal: 5 digits, plus EU:
http://clients.txtnation.com/entries/158326-portugal-premium-sms-short-code-regulations -->
- <shortcode country="pt" premium="6[1289]\\d{3}" free="116\\d{3}|1262" />
+ <shortcode country="pt" premium="6[1289]\\d{3}" free="116\\d{3}|1262|12666" />
<!-- Qatar: 1-5 digits (standard system default, not country specific) -->
<shortcode country="qa" pattern="\\d{1,5}" free="92451" />
diff --git a/core/tests/coretests/Android.mk b/core/tests/coretests/Android.mk
index e0d53933b33b..307e2e8671b2 100644
--- a/core/tests/coretests/Android.mk
+++ b/core/tests/coretests/Android.mk
@@ -67,10 +67,6 @@ LOCAL_RESOURCE_DIR := $(FrameworkCoreTests_intermediates) $(LOCAL_PATH)/res
# Disable AAPT2 because the hacks below depend on the AAPT rules implementation
LOCAL_USE_AAPT2 := false
-# When AAPT2 is enabled it will need --warn-manifest-validation to fix:
-# frameworks/base/core/tests/coretests/AndroidManifest.xml:26: error: unknown element <meta-data> found.
-# TODO(b/79755007): Remove when AAPT2 recognizes the manifest elements.
-# LOCAL_AAPT_FLAGS += --warn-manifest-validation
include $(BUILD_PACKAGE)
# Rules to copy all the test apks to the intermediate raw resource directory
diff --git a/core/tests/coretests/apks/install_multi_package/Android.mk b/core/tests/coretests/apks/install_multi_package/Android.mk
index 97275931be4b..3f163def9ce0 100644
--- a/core/tests/coretests/apks/install_multi_package/Android.mk
+++ b/core/tests/coretests/apks/install_multi_package/Android.mk
@@ -8,10 +8,6 @@ LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_PACKAGE_NAME := install_multi_package
LOCAL_USE_AAPT2 := true
-# Disable AAPT2 manifest checks to fix:
-# frameworks/base/core/tests/coretests/apks/install_multi_package/AndroidManifest.xml:46: error: unexpected element <package> found in <manifest>.
-# TODO(b/79755007): Remove when AAPT2 recognizes the manifest elements.
-LOCAL_AAPT_FLAGS += --warn-manifest-validation
include $(FrameworkCoreTests_BUILD_PACKAGE)
#include $(BUILD_PACKAGE)
diff --git a/core/tests/coretests/apks/install_verifier_bad/Android.mk b/core/tests/coretests/apks/install_verifier_bad/Android.mk
index 679327c9b0df..745b4d32ccc4 100644
--- a/core/tests/coretests/apks/install_verifier_bad/Android.mk
+++ b/core/tests/coretests/apks/install_verifier_bad/Android.mk
@@ -6,9 +6,5 @@ LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_PACKAGE_NAME := install_verifier_bad
LOCAL_USE_AAPT2 := true
-# Disable AAPT2 manifest checks to fix:
-# frameworks/base/core/tests/coretests/apks/install_verifier_bad/AndroidManifest.xml:19: error: unexpected element <package-verifier> found in <manifest>.
-# TODO(b/79755007): Remove when AAPT2 recognizes the manifest elements.
-LOCAL_AAPT_FLAGS += --warn-manifest-validation
include $(FrameworkCoreTests_BUILD_PACKAGE)
diff --git a/core/tests/coretests/apks/install_verifier_good/Android.mk b/core/tests/coretests/apks/install_verifier_good/Android.mk
index 7d621b32900b..150fd8dd8701 100644
--- a/core/tests/coretests/apks/install_verifier_good/Android.mk
+++ b/core/tests/coretests/apks/install_verifier_good/Android.mk
@@ -6,9 +6,5 @@ LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_PACKAGE_NAME := install_verifier_good
LOCAL_USE_AAPT2 := true
-# Disable AAPT2 manifest checks to fix:
-# frameworks/base/core/tests/coretests/apks/install_verifier_good/AndroidManifest.xml:19: error: unexpected element <package-verifier> found in <manifest>.
-# TODO(b/79755007): Remove when AAPT2 recognizes the manifest elements.
-LOCAL_AAPT_FLAGS += --warn-manifest-validation
include $(FrameworkCoreTests_BUILD_PACKAGE)
diff --git a/core/tests/coretests/src/android/content/pm/dex/DexMetadataHelperTest.java b/core/tests/coretests/src/android/content/pm/dex/DexMetadataHelperTest.java
index 584257b1f6a9..e248a7771cab 100644
--- a/core/tests/coretests/src/android/content/pm/dex/DexMetadataHelperTest.java
+++ b/core/tests/coretests/src/android/content/pm/dex/DexMetadataHelperTest.java
@@ -45,7 +45,7 @@ import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
-import libcore.io.IoUtils;
+import libcore.testing.io.TestIoUtils;
import org.junit.After;
import org.junit.Assert;
@@ -63,7 +63,7 @@ public class DexMetadataHelperTest {
@Before
public void setUp() {
- mTmpDir = IoUtils.createTemporaryDirectory("DexMetadataHelperTest");
+ mTmpDir = TestIoUtils.createTemporaryDirectory("DexMetadataHelperTest");
}
@After
diff --git a/core/tests/coretests/src/android/os/FileUtilsTest.java b/core/tests/coretests/src/android/os/FileUtilsTest.java
index 20fe16251854..80281b63c4a1 100644
--- a/core/tests/coretests/src/android/os/FileUtilsTest.java
+++ b/core/tests/coretests/src/android/os/FileUtilsTest.java
@@ -48,7 +48,6 @@ import android.provider.DocumentsContract.Document;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
-import libcore.io.IoUtils;
import libcore.io.Streams;
import com.google.android.collect.Sets;
@@ -95,7 +94,7 @@ public class FileUtilsTest {
@After
public void tearDown() throws Exception {
- IoUtils.deleteContents(mDir);
+ FileUtils.deleteContents(mDir);
FileUtils.deleteContents(mTarget);
}
diff --git a/core/tests/coretests/src/android/text/format/DateUtilsTest.java b/core/tests/coretests/src/android/text/format/DateUtilsTest.java
index f8e3b4dfec56..872b71a5faa6 100644
--- a/core/tests/coretests/src/android/text/format/DateUtilsTest.java
+++ b/core/tests/coretests/src/android/text/format/DateUtilsTest.java
@@ -117,7 +117,7 @@ public class DateUtilsTest {
@Test
public void testFormatSameDayTime() {
// This test assumes a default DateFormat.is24Hour setting.
- DateFormat.is24Hour = null;
+ DateFormat.set24HourTimePref(null);
Date date = new Date(109, 0, 19, 3, 30, 15);
long fixedTime = date.getTime();
diff --git a/core/tests/coretests/src/android/view/DisplayCutoutTest.java b/core/tests/coretests/src/android/view/DisplayCutoutTest.java
index c8d994c4f6c1..8e4f2cd2fbff 100644
--- a/core/tests/coretests/src/android/view/DisplayCutoutTest.java
+++ b/core/tests/coretests/src/android/view/DisplayCutoutTest.java
@@ -103,6 +103,18 @@ public class DisplayCutoutTest {
equalTo(new Rect[]{ZERO_RECT, boundTop, ZERO_RECT, boundBottom}));
}
+ @Test
+ public void testExtractBoundsFromList_nullBoundingRects() {
+ Rect safeInsets = new Rect(0, 0, 0, 0);
+ assertThat(extractBoundsFromList(safeInsets, null /* boundingRects */),
+ equalTo(new Rect[]{ZERO_RECT, ZERO_RECT, ZERO_RECT, ZERO_RECT}));
+ }
+
+ @Test
+ public void testExtractBoundsFromList_nullSafeInsets() {
+ assertThat(extractBoundsFromList(null /* safeInsets */, Collections.emptyList()),
+ equalTo(new Rect[]{ZERO_RECT, ZERO_RECT, ZERO_RECT, ZERO_RECT}));
+ }
@Test
public void hasCutout() throws Exception {
diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java
index 69d2828f20bc..506e5447a239 100644
--- a/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java
+++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java
@@ -45,7 +45,7 @@ public class AccessibilityNodeInfoTest {
// The number of fields tested in the corresponding CTS AccessibilityNodeInfoTest:
// See fullyPopulateAccessibilityNodeInfo, assertEqualsAccessibilityNodeInfo,
// and assertAccessibilityNodeInfoCleared in that class.
- private static final int NUM_MARSHALLED_PROPERTIES = 33;
+ private static final int NUM_MARSHALLED_PROPERTIES = 34;
/**
* The number of properties that are purposely not marshalled
diff --git a/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java b/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java
index 0c8dd9d6ed59..f637b7c7ec32 100644
--- a/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java
@@ -77,9 +77,13 @@ public final class LooperStatsTest {
Message message = mHandlerFirst.obtainMessage(1000);
message.workSourceUid = 1000;
+ message.when = looperStats.getSystemUptimeMillis();
+
+ looperStats.tickUptime(30);
Object token = looperStats.messageDispatchStarting();
looperStats.tickRealtime(100);
looperStats.tickThreadTime(10);
+ looperStats.tickUptime(200);
looperStats.messageDispatched(token, message);
List<LooperStats.ExportedEntry> entries = looperStats.getEntries();
@@ -98,6 +102,10 @@ public final class LooperStatsTest {
assertThat(entry.maxLatencyMicros).isEqualTo(100);
assertThat(entry.cpuUsageMicros).isEqualTo(10);
assertThat(entry.maxCpuUsageMicros).isEqualTo(10);
+ assertThat(entry.recordedDelayMessageCount).isEqualTo(1);
+ assertThat(entry.delayMillis).isEqualTo(30);
+ assertThat(entry.maxDelayMillis).isEqualTo(30);
+
}
@Test
@@ -215,6 +223,56 @@ public final class LooperStatsTest {
}
@Test
+ public void testDispatchDelayIsRecorded() {
+ TestableLooperStats looperStats = new TestableLooperStats(1, 100);
+
+ // Dispatched right on time.
+ Message message1 = mHandlerFirst.obtainMessage(1000);
+ message1.when = looperStats.getSystemUptimeMillis();
+ Object token1 = looperStats.messageDispatchStarting();
+ looperStats.tickUptime(10);
+ looperStats.messageDispatched(token1, message1);
+
+ // Dispatched 100ms late.
+ Message message2 = mHandlerFirst.obtainMessage(1000);
+ message2.when = looperStats.getSystemUptimeMillis() - 100;
+ Object token2 = looperStats.messageDispatchStarting();
+ looperStats.tickUptime(10);
+ looperStats.messageDispatched(token2, message2);
+
+ // No target dispatching time.
+ Message message3 = mHandlerFirst.obtainMessage(1000);
+ message3.when = 0;
+ Object token3 = looperStats.messageDispatchStarting();
+ looperStats.tickUptime(10);
+ looperStats.messageDispatched(token3, message3);
+
+ // Dispatched too soon (should never happen).
+ Message message4 = mHandlerFirst.obtainMessage(1000);
+ message4.when = looperStats.getSystemUptimeMillis() + 200;
+ Object token4 = looperStats.messageDispatchStarting();
+ looperStats.tickUptime(10);
+ looperStats.messageDispatched(token4, message4);
+
+ // Dispatched 300ms late.
+ Message message5 = mHandlerFirst.obtainMessage(1000);
+ message5.when = looperStats.getSystemUptimeMillis() - 300;
+ Object token5 = looperStats.messageDispatchStarting();
+ looperStats.tickUptime(10);
+ looperStats.messageDispatched(token5, message5);
+
+ List<LooperStats.ExportedEntry> entries = looperStats.getEntries();
+ assertThat(entries).hasSize(1);
+
+ LooperStats.ExportedEntry entry = entries.get(0);
+ assertThat(entry.messageCount).isEqualTo(5);
+ assertThat(entry.recordedMessageCount).isEqualTo(5);
+ assertThat(entry.recordedDelayMessageCount).isEqualTo(4);
+ assertThat(entry.delayMillis).isEqualTo(400);
+ assertThat(entry.maxDelayMillis).isEqualTo(300);
+ }
+
+ @Test
public void testDataNotCollectedBeforeDeviceStateSet() {
TestableLooperStats looperStats = new TestableLooperStats(1, 100);
looperStats.setDeviceState(null);
@@ -385,6 +443,7 @@ public final class LooperStatsTest {
private int mCount;
private long mRealtimeMicros;
private long mThreadTimeMicros;
+ private long mUptimeMillis;
private int mSamplingInterval;
TestableLooperStats(int samplingInterval, int sizeCap) {
@@ -401,6 +460,10 @@ public final class LooperStatsTest {
mThreadTimeMicros += micros;
}
+ void tickUptime(long millis) {
+ mUptimeMillis += millis;
+ }
+
@Override
protected long getElapsedRealtimeMicro() {
return INITIAL_MICROS + mRealtimeMicros;
@@ -412,6 +475,11 @@ public final class LooperStatsTest {
}
@Override
+ protected long getSystemUptimeMillis() {
+ return INITIAL_MICROS / 1000 + mUptimeMillis;
+ }
+
+ @Override
protected boolean shouldCollectDetailedData() {
return mCount++ % mSamplingInterval == 0;
}
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index ed24543ed9bf..44f8737da2c1 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -325,6 +325,7 @@ applications that come with the platform
<permission name="android.permission.READ_LOWPAN_CREDENTIAL"/>
<permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
<permission name="android.permission.REAL_GET_TASKS"/>
+ <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
<permission name="android.permission.REGISTER_CALL_PROVIDER"/>
<permission name="android.permission.REGISTER_CONNECTION_MANAGER"/>
<permission name="android.permission.REGISTER_SIM_SUBSCRIPTION"/>
diff --git a/graphics/java/android/graphics/ColorSpace.java b/graphics/java/android/graphics/ColorSpace.java
index 8414d6a6b866..b65fb9cd24ec 100644
--- a/graphics/java/android/graphics/ColorSpace.java
+++ b/graphics/java/android/graphics/ColorSpace.java
@@ -2525,9 +2525,7 @@ public abstract class ColorSpace {
gamma == 1.0 ? DoubleUnaryOperator.identity() :
x -> Math.pow(x < 0.0 ? 0.0 : x, gamma),
min, max, id);
- mTransferParameters = gamma == 1.0 ?
- new TransferParameters(0.0, 0.0, 1.0, 1.0 + Math.ulp(1.0f), gamma) :
- new TransferParameters(1.0, 0.0, 0.0, 0.0, gamma);
+ mTransferParameters = new TransferParameters(1.0, 0.0, 0.0, 0.0, gamma);
}
/**
diff --git a/graphics/java/android/graphics/drawable/Icon.java b/graphics/java/android/graphics/drawable/Icon.java
index 7efe5220873e..f41cc7ee5095 100644
--- a/graphics/java/android/graphics/drawable/Icon.java
+++ b/graphics/java/android/graphics/drawable/Icon.java
@@ -21,7 +21,6 @@ import android.annotation.DrawableRes;
import android.annotation.IdRes;
import android.annotation.IntDef;
import android.annotation.NonNull;
-import android.annotation.SystemApi;
import android.annotation.UnsupportedAppUsage;
import android.content.ContentResolver;
import android.content.Context;
@@ -570,7 +569,7 @@ public final class Icon implements Parcelable {
* Version of createWithResource that takes Resources. Do not use.
* @hide
*/
- @SystemApi
+ @UnsupportedAppUsage
public static Icon createWithResource(Resources res, @DrawableRes int resId) {
if (res == null) {
throw new IllegalArgumentException("Resource must not be null.");
diff --git a/graphics/java/android/graphics/pdf/PdfEditor.java b/graphics/java/android/graphics/pdf/PdfEditor.java
index 3821bc7ab063..21ce1b8392d2 100644
--- a/graphics/java/android/graphics/pdf/PdfEditor.java
+++ b/graphics/java/android/graphics/pdf/PdfEditor.java
@@ -27,7 +27,6 @@ import android.system.Os;
import android.system.OsConstants;
import dalvik.system.CloseGuard;
import libcore.io.IoUtils;
-import libcore.io.Libcore;
import java.io.IOException;
diff --git a/keystore/OWNERS b/keystore/OWNERS
new file mode 100644
index 000000000000..a63ca46df2a6
--- /dev/null
+++ b/keystore/OWNERS
@@ -0,0 +1,4 @@
+jbires@google.com
+jdanis@google.com
+robbarnes@google.com
+swillden@google.com
diff --git a/libs/androidfw/Android.bp b/libs/androidfw/Android.bp
index 74cab920cf2d..98af3eb05391 100644
--- a/libs/androidfw/Android.bp
+++ b/libs/androidfw/Android.bp
@@ -50,6 +50,7 @@ cc_library {
"LocaleData.cpp",
"misc.cpp",
"ObbFile.cpp",
+ "PosixUtils.cpp",
"ResourceTypes.cpp",
"ResourceUtils.cpp",
"StreamingZipInflater.cpp",
@@ -157,6 +158,7 @@ cc_test {
srcs: [
"tests/BackupData_test.cpp",
"tests/ObbFile_test.cpp",
+ "tests/PosixUtils_test.cpp",
],
shared_libs: common_test_libs + ["libui"],
},
diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp
index 9c1629bc36f5..04cc5bb30ade 100644
--- a/libs/androidfw/AssetManager2.cpp
+++ b/libs/androidfw/AssetManager2.cpp
@@ -67,10 +67,10 @@ AssetManager2::AssetManager2() {
}
bool AssetManager2::SetApkAssets(const std::vector<const ApkAssets*>& apk_assets,
- bool invalidate_caches) {
+ bool invalidate_caches, bool filter_incompatible_configs) {
apk_assets_ = apk_assets;
BuildDynamicRefTable();
- RebuildFilterList();
+ RebuildFilterList(filter_incompatible_configs);
if (invalidate_caches) {
InvalidateCaches(static_cast<uint32_t>(-1));
}
@@ -825,7 +825,7 @@ uint32_t AssetManager2::GetResourceId(const std::string& resource_name,
return 0u;
}
-void AssetManager2::RebuildFilterList() {
+void AssetManager2::RebuildFilterList(bool filter_incompatible_configs) {
for (PackageGroup& group : package_groups_) {
for (ConfiguredPackage& impl : group.packages_) {
// Destroy it.
@@ -841,7 +841,7 @@ void AssetManager2::RebuildFilterList() {
for (auto iter = spec->types; iter != iter_end; ++iter) {
ResTable_config this_config;
this_config.copyFromDtoH((*iter)->config);
- if (this_config.match(configuration_)) {
+ if (!filter_incompatible_configs || this_config.match(configuration_)) {
group.configurations.push_back(this_config);
group.types.push_back(*iter);
}
diff --git a/libs/androidfw/LoadedArsc.cpp b/libs/androidfw/LoadedArsc.cpp
index c2740c9fbaa4..68d216d286cf 100644
--- a/libs/androidfw/LoadedArsc.cpp
+++ b/libs/androidfw/LoadedArsc.cpp
@@ -203,6 +203,39 @@ static bool VerifyResTableEntry(const ResTable_type* type, uint32_t entry_offset
return true;
}
+LoadedPackage::iterator::iterator(const LoadedPackage* lp, size_t ti, size_t ei)
+ : loadedPackage_(lp),
+ typeIndex_(ti),
+ entryIndex_(ei),
+ typeIndexEnd_(lp->resource_ids_.size() + 1) {
+ while (typeIndex_ < typeIndexEnd_ && loadedPackage_->resource_ids_[typeIndex_] == 0) {
+ typeIndex_++;
+ }
+}
+
+LoadedPackage::iterator& LoadedPackage::iterator::operator++() {
+ while (typeIndex_ < typeIndexEnd_) {
+ if (entryIndex_ + 1 < loadedPackage_->resource_ids_[typeIndex_]) {
+ entryIndex_++;
+ break;
+ }
+ entryIndex_ = 0;
+ typeIndex_++;
+ if (typeIndex_ < typeIndexEnd_ && loadedPackage_->resource_ids_[typeIndex_] != 0) {
+ break;
+ }
+ }
+ return *this;
+}
+
+uint32_t LoadedPackage::iterator::operator*() const {
+ if (typeIndex_ >= typeIndexEnd_) {
+ return 0;
+ }
+ return make_resid(loadedPackage_->package_id_, typeIndex_ + loadedPackage_->type_id_offset_,
+ entryIndex_);
+}
+
const ResTable_entry* LoadedPackage::GetEntry(const ResTable_type* type_chunk,
uint16_t entry_index) {
uint32_t entry_offset = GetEntryOffset(type_chunk, entry_index);
@@ -488,6 +521,7 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk,
std::unique_ptr<TypeSpecPtrBuilder>& builder_ptr = type_builder_map[type_spec->id - 1];
if (builder_ptr == nullptr) {
builder_ptr = util::make_unique<TypeSpecPtrBuilder>(type_spec, idmap_entry_header);
+ loaded_package->resource_ids_.set(type_spec->id, entry_count);
} else {
LOG(WARNING) << StringPrintf("RES_TABLE_TYPE_SPEC_TYPE already defined for ID %02x",
type_spec->id);
diff --git a/libs/androidfw/PosixUtils.cpp b/libs/androidfw/PosixUtils.cpp
new file mode 100644
index 000000000000..df0dd7ce463d
--- /dev/null
+++ b/libs/androidfw/PosixUtils.cpp
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#ifdef _WIN32
+// nothing to see here
+#else
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include "android-base/logging.h"
+
+#include "androidfw/PosixUtils.h"
+
+namespace {
+
+std::unique_ptr<std::string> ReadFile(int fd) {
+ std::unique_ptr<std::string> str(new std::string());
+ char buf[1024];
+ ssize_t r;
+ while ((r = read(fd, buf, sizeof(buf))) > 0) {
+ str->append(buf, r);
+ }
+ if (r != 0) {
+ return nullptr;
+ }
+ return str;
+}
+
+}
+
+namespace android {
+namespace util {
+
+std::unique_ptr<ProcResult> ExecuteBinary(const std::vector<std::string>& argv) {
+ int stdout[2]; // stdout[0] read, stdout[1] write
+ if (pipe(stdout) != 0) {
+ PLOG(ERROR) << "pipe";
+ return nullptr;
+ }
+
+ int stderr[2]; // stdout[0] read, stdout[1] write
+ if (pipe(stderr) != 0) {
+ PLOG(ERROR) << "pipe";
+ close(stdout[0]);
+ close(stdout[1]);
+ return nullptr;
+ }
+
+ char const** argv0 = (char const**)malloc(sizeof(char*) * (argv.size() + 1));
+ for (size_t i = 0; i < argv.size(); i++) {
+ argv0[i] = argv[i].c_str();
+ }
+ argv0[argv.size()] = nullptr;
+ switch (fork()) {
+ case -1: // error
+ free(argv0);
+ PLOG(ERROR) << "fork";
+ return nullptr;
+ case 0: // child
+ close(stdout[0]);
+ if (dup2(stdout[1], STDOUT_FILENO) == -1) {
+ abort();
+ }
+ close(stderr[0]);
+ if (dup2(stderr[1], STDERR_FILENO) == -1) {
+ abort();
+ }
+ execvp(argv0[0], const_cast<char* const*>(argv0));
+ PLOG(ERROR) << "execv";
+ abort();
+ default: // parent
+ free(argv0);
+ close(stdout[1]);
+ close(stderr[1]);
+ int status;
+ wait(&status);
+ if (!WIFEXITED(status)) {
+ return nullptr;
+ }
+ std::unique_ptr<ProcResult> result(new ProcResult());
+ result->status = status;
+ const auto out = ReadFile(stdout[0]);
+ result->stdout = out ? *out : "";
+ close(stdout[0]);
+ const auto err = ReadFile(stderr[0]);
+ result->stderr = err ? *err : "";
+ close(stderr[0]);
+ return result;
+ }
+}
+
+} // namespace util
+} // namespace android
+#endif
diff --git a/libs/androidfw/include/androidfw/AssetManager2.h b/libs/androidfw/include/androidfw/AssetManager2.h
index ad31f6940438..2f0ee01639fe 100644
--- a/libs/androidfw/include/androidfw/AssetManager2.h
+++ b/libs/androidfw/include/androidfw/AssetManager2.h
@@ -96,7 +96,12 @@ class AssetManager2 {
// Only pass invalidate_caches=false when it is known that the structure
// change in ApkAssets is due to a safe addition of resources with completely
// new resource IDs.
- bool SetApkAssets(const std::vector<const ApkAssets*>& apk_assets, bool invalidate_caches = true);
+ //
+ // Only pass in filter_incompatible_configs=false when you want to load all
+ // configurations (including incompatible ones) such as when constructing an
+ // idmap.
+ bool SetApkAssets(const std::vector<const ApkAssets*>& apk_assets, bool invalidate_caches = true,
+ bool filter_incompatible_configs = true);
inline const std::vector<const ApkAssets*> GetApkAssets() const {
return apk_assets_;
@@ -274,7 +279,7 @@ class AssetManager2 {
// Triggers the re-construction of lists of types that match the set configuration.
// This should always be called when mutating the AssetManager's configuration or ApkAssets set.
- void RebuildFilterList();
+ void RebuildFilterList(bool filter_incompatible_configs = true);
// AssetManager2::GetBag(resid) wraps this function to track which resource ids have already
// been seen while traversing bag parents.
diff --git a/libs/androidfw/include/androidfw/LoadedArsc.h b/libs/androidfw/include/androidfw/LoadedArsc.h
index 35ae5fcd9e7b..349b379778a6 100644
--- a/libs/androidfw/include/androidfw/LoadedArsc.h
+++ b/libs/androidfw/include/androidfw/LoadedArsc.h
@@ -78,6 +78,55 @@ using TypeSpecPtr = util::unique_cptr<TypeSpec>;
class LoadedPackage {
public:
+ class iterator {
+ public:
+ iterator& operator=(const iterator& rhs) {
+ loadedPackage_ = rhs.loadedPackage_;
+ typeIndex_ = rhs.typeIndex_;
+ entryIndex_ = rhs.entryIndex_;
+ return *this;
+ }
+
+ bool operator==(const iterator& rhs) const {
+ return loadedPackage_ == rhs.loadedPackage_ &&
+ typeIndex_ == rhs.typeIndex_ &&
+ entryIndex_ == rhs.entryIndex_;
+ }
+
+ bool operator!=(const iterator& rhs) const {
+ return !(*this == rhs);
+ }
+
+ iterator operator++(int) {
+ size_t prevTypeIndex_ = typeIndex_;
+ size_t prevEntryIndex_ = entryIndex_;
+ operator++();
+ return iterator(loadedPackage_, prevTypeIndex_, prevEntryIndex_);
+ }
+
+ iterator& operator++();
+
+ uint32_t operator*() const;
+
+ private:
+ friend class LoadedPackage;
+
+ iterator(const LoadedPackage* lp, size_t ti, size_t ei);
+
+ const LoadedPackage* loadedPackage_;
+ size_t typeIndex_;
+ size_t entryIndex_;
+ const size_t typeIndexEnd_; // STL style end, so one past the last element
+ };
+
+ iterator begin() const {
+ return iterator(this, 0, 0);
+ }
+
+ iterator end() const {
+ return iterator(this, resource_ids_.size() + 1, 0);
+ }
+
static std::unique_ptr<const LoadedPackage> Load(const Chunk& chunk,
const LoadedIdmap* loaded_idmap, bool system,
bool load_as_shared_library);
@@ -182,6 +231,7 @@ class LoadedPackage {
bool overlay_ = false;
ByteBucketArray<TypeSpecPtr> type_specs_;
+ ByteBucketArray<uint32_t> resource_ids_;
std::vector<DynamicPackageEntry> dynamic_package_map_;
};
diff --git a/libs/androidfw/include/androidfw/PosixUtils.h b/libs/androidfw/include/androidfw/PosixUtils.h
new file mode 100644
index 000000000000..8fc3ee2733c7
--- /dev/null
+++ b/libs/androidfw/include/androidfw/PosixUtils.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace android {
+namespace util {
+
+struct ProcResult {
+ int status;
+ std::string stdout;
+ std::string stderr;
+};
+
+// Fork, exec and wait for an external process. Return nullptr if the process could not be launched,
+// otherwise a ProcResult containing the external process' exit status and captured stdout and
+// stderr.
+std::unique_ptr<ProcResult> ExecuteBinary(const std::vector<std::string>& argv);
+
+} // namespace util
+} // namespace android
diff --git a/libs/androidfw/tests/LoadedArsc_test.cpp b/libs/androidfw/tests/LoadedArsc_test.cpp
index cae632ddea30..ffa48367c252 100644
--- a/libs/androidfw/tests/LoadedArsc_test.cpp
+++ b/libs/androidfw/tests/LoadedArsc_test.cpp
@@ -278,4 +278,52 @@ TEST(LoadedArscTest, LoadOverlay) {
// sizeof(Res_value) might not be backwards compatible.
TEST(LoadedArscTest, LoadingShouldBeForwardsAndBackwardsCompatible) { ASSERT_TRUE(false); }
+TEST(LoadedArscTest, ResourceIdentifierIterator) {
+ std::string contents;
+ ASSERT_TRUE(
+ ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk", "resources.arsc", &contents));
+
+ std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(StringPiece(contents));
+ ASSERT_NE(nullptr, loaded_arsc);
+
+ const std::vector<std::unique_ptr<const LoadedPackage>>& packages = loaded_arsc->GetPackages();
+ ASSERT_EQ(1u, packages.size());
+ EXPECT_EQ(std::string("com.android.basic"), packages[0]->GetPackageName());
+
+ const auto& loaded_package = packages[0];
+ auto iter = loaded_package->begin();
+ auto end = loaded_package->end();
+
+ ASSERT_NE(end, iter);
+ ASSERT_EQ(0x7f010000u, *iter++);
+ ASSERT_EQ(0x7f010001u, *iter++);
+ ASSERT_EQ(0x7f020000u, *iter++);
+ ASSERT_EQ(0x7f020001u, *iter++);
+ ASSERT_EQ(0x7f030000u, *iter++);
+ ASSERT_EQ(0x7f030001u, *iter++);
+ ASSERT_EQ(0x7f030002u, *iter++); // note: string without default, excluded by aapt2 dump
+ ASSERT_EQ(0x7f040000u, *iter++);
+ ASSERT_EQ(0x7f040001u, *iter++);
+ ASSERT_EQ(0x7f040002u, *iter++);
+ ASSERT_EQ(0x7f040003u, *iter++);
+ ASSERT_EQ(0x7f040004u, *iter++);
+ ASSERT_EQ(0x7f040005u, *iter++);
+ ASSERT_EQ(0x7f040006u, *iter++);
+ ASSERT_EQ(0x7f040007u, *iter++);
+ ASSERT_EQ(0x7f040008u, *iter++);
+ ASSERT_EQ(0x7f040009u, *iter++);
+ ASSERT_EQ(0x7f04000au, *iter++);
+ ASSERT_EQ(0x7f04000bu, *iter++);
+ ASSERT_EQ(0x7f04000cu, *iter++);
+ ASSERT_EQ(0x7f04000du, *iter++);
+ ASSERT_EQ(0x7f050000u, *iter++);
+ ASSERT_EQ(0x7f050001u, *iter++);
+ ASSERT_EQ(0x7f060000u, *iter++);
+ ASSERT_EQ(0x7f070000u, *iter++);
+ ASSERT_EQ(0x7f070001u, *iter++);
+ ASSERT_EQ(0x7f070002u, *iter++);
+ ASSERT_EQ(0x7f070003u, *iter++);
+ ASSERT_EQ(end, iter);
+}
+
} // namespace android
diff --git a/libs/androidfw/tests/PosixUtils_test.cpp b/libs/androidfw/tests/PosixUtils_test.cpp
new file mode 100644
index 000000000000..cf97f87a4163
--- /dev/null
+++ b/libs/androidfw/tests/PosixUtils_test.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <utility>
+
+#include "androidfw/PosixUtils.h"
+
+#include "TestHelpers.h"
+
+using ::testing::IsNull;
+using ::testing::NotNull;
+
+namespace android {
+namespace util {
+
+TEST(PosixUtilsTest, AbsolutePathToBinary) {
+ const auto result = ExecuteBinary({"/bin/date", "--help"});
+ ASSERT_THAT(result, NotNull());
+ ASSERT_EQ(result->status, 0);
+ ASSERT_EQ(result->stdout.find("usage: date "), 0);
+}
+
+TEST(PosixUtilsTest, RelativePathToBinary) {
+ const auto result = ExecuteBinary({"date", "--help"});
+ ASSERT_THAT(result, NotNull());
+ ASSERT_EQ(result->status, 0);
+ ASSERT_EQ(result->stdout.find("usage: date "), 0);
+}
+
+TEST(PosixUtilsTest, BadParameters) {
+ const auto result = ExecuteBinary({"/bin/date", "--this-parameter-is-not-supported"});
+ ASSERT_THAT(result, NotNull());
+ ASSERT_NE(result->status, 0);
+}
+
+TEST(PosixUtilsTest, NoSuchBinary) {
+ const auto result = ExecuteBinary({"/this/binary/does/not/exist"});
+ ASSERT_THAT(result, IsNull());
+}
+
+} // android
+} // util
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 6d10c2d692b1..b1968babe99f 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -2380,10 +2380,12 @@ public class LocationManager {
}
/**
+ * Return the package that implements the {@link #NETWORK_PROVIDER} functionality.
+ *
* @hide
*/
@SystemApi
- public String getNetworkProviderPackage() {
+ public @Nullable String getNetworkProviderPackage() {
try {
return mService.getNetworkProviderPackage();
} catch (RemoteException e) {
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index 2395b24f7136..b96a5853b9dc 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -3252,7 +3252,7 @@ public class ExifInterface {
int thumbnailLength = jpegInterchangeFormatLengthAttribute.getIntValue(mExifByteOrder);
// The following code limits the size of thumbnail size not to overflow EXIF data area.
- thumbnailLength = Math.min(thumbnailLength, in.available() - thumbnailOffset);
+ thumbnailLength = Math.min(thumbnailLength, in.getLength() - thumbnailOffset);
if (mMimeType == IMAGE_TYPE_JPEG || mMimeType == IMAGE_TYPE_RAF
|| mMimeType == IMAGE_TYPE_RW2) {
thumbnailOffset += mExifOffset;
@@ -3981,6 +3981,10 @@ public class ExifInterface {
public double readDouble() throws IOException {
return Double.longBitsToDouble(readLong());
}
+
+ public int getLength() {
+ return mLength;
+ }
}
// An output stream to write EXIF data area, which can be written in either little or big endian
diff --git a/media/java/android/media/MediaPlayer2Impl.java b/media/java/android/media/MediaPlayer2Impl.java
index 0e5cbe4e20b7..5604ffd83deb 100644
--- a/media/java/android/media/MediaPlayer2Impl.java
+++ b/media/java/android/media/MediaPlayer2Impl.java
@@ -3620,6 +3620,17 @@ public final class MediaPlayer2Impl extends MediaPlayer2 {
&& getState() == PLAYER_STATE_ERROR) {
status = CALL_STATUS_INVALID_OPERATION;
} else {
+ if (mMediaCallType == CALL_COMPLETED_SEEK_TO) {
+ synchronized (mTaskLock) {
+ if (!mPendingTasks.isEmpty()) {
+ Task nextTask = mPendingTasks.get(0);
+ if (nextTask.mMediaCallType == mMediaCallType) {
+ throw new CommandSkippedException(
+ "consecutive seekTo is skipped except last one");
+ }
+ }
+ }
+ }
process();
}
} catch (IllegalStateException e) {
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
index cdaabdcda20f..d0ca04bb07c2 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
@@ -184,7 +184,6 @@ public class DeviceDiscoveryService extends Service {
if (shouldScan(mBluetoothFilters)) {
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
- intentFilter.addAction(BluetoothDevice.ACTION_DISAPPEARED);
mBluetoothBroadcastReceiver = new BluetoothBroadcastReceiver();
registerReceiver(mBluetoothBroadcastReceiver, intentFilter);
diff --git a/packages/CtsShim/build/Android.mk b/packages/CtsShim/build/Android.mk
index e645adc60b7c..03eb0d9aad5a 100644
--- a/packages/CtsShim/build/Android.mk
+++ b/packages/CtsShim/build/Android.mk
@@ -67,10 +67,6 @@ LOCAL_MULTILIB := both
LOCAL_JNI_SHARED_LIBRARIES := libshim_jni
LOCAL_USE_AAPT2 := true
-# Disable AAPT2 manifest checks to fix:
-# out/target/common/obj/APPS/CtsShimPriv_intermediates/AndroidManifest.xml:25: error: unexpected element <restrict-update> found in <manifest>.
-# TODO(b/79755007): Remove when AAPT2 recognizes the manifest elements.
-LOCAL_AAPT_FLAGS += --warn-manifest-validation
include $(BUILD_PACKAGE)
@@ -113,10 +109,6 @@ LOCAL_PACKAGE_NAME := CtsShim
LOCAL_MANIFEST_FILE := shim/AndroidManifest.xml
LOCAL_USE_AAPT2 := true
-# Disable AAPT2 manifest checks to fix:
-# frameworks/base/packages/CtsShim/build/shim/AndroidManifest.xml:25: error: unexpected element <restrict-update> found in <manifest>.
-# TODO(b/79755007): Remove when AAPT2 recognizes the manifest elements.
-LOCAL_AAPT_FLAGS += --warn-manifest-validation
include $(BUILD_PACKAGE)
diff --git a/packages/EasterEgg/src/com/android/egg/paint/CutoutAvoidingToolbar.kt b/packages/EasterEgg/src/com/android/egg/paint/CutoutAvoidingToolbar.kt
index 164fc5a5af3d..9855565c1335 100644
--- a/packages/EasterEgg/src/com/android/egg/paint/CutoutAvoidingToolbar.kt
+++ b/packages/EasterEgg/src/com/android/egg/paint/CutoutAvoidingToolbar.kt
@@ -26,15 +26,16 @@ class CutoutAvoidingToolbar : LinearLayout {
private var _insets: WindowInsets? = null
constructor(context: Context) : super(context) {
- init(null, 0)
}
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
- init(attrs, 0)
}
- constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) {
- init(attrs, defStyle)
+ constructor(
+ context: Context,
+ attrs: AttributeSet,
+ defStyle: Int
+ ) : super(context, attrs, defStyle) {
}
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
@@ -81,8 +82,4 @@ class CutoutAvoidingToolbar : LinearLayout {
requestLayout()
}
}
-
- private fun init(attrs: AttributeSet?, defStyle: Int) {
- }
-
}
diff --git a/packages/EasterEgg/src/com/android/egg/paint/Painting.kt b/packages/EasterEgg/src/com/android/egg/paint/Painting.kt
index a4a3d3d835e0..fc7e8b008a54 100644
--- a/packages/EasterEgg/src/com/android/egg/paint/Painting.kt
+++ b/packages/EasterEgg/src/com/android/egg/paint/Painting.kt
@@ -17,7 +17,6 @@
package com.android.egg.paint
import android.content.Context
-import android.content.res.Resources
import android.graphics.*
import android.provider.Settings
import android.util.AttributeSet
@@ -26,7 +25,6 @@ import android.view.MotionEvent
import android.view.View
import android.view.WindowInsets
import java.util.concurrent.TimeUnit
-import android.util.Log
import android.provider.Settings.System
import org.json.JSONObject
@@ -86,11 +84,11 @@ public class Painting : View, SpotFilter.Plotter {
}
var bitmap: Bitmap? = null
- var paperColor : Int = 0xFFFFFFFF.toInt()
+ var paperColor: Int = 0xFFFFFFFF.toInt()
private var _paintCanvas: Canvas? = null
private val _bitmapLock = Object()
-
+
private var _drawPaint = Paint(Paint.ANTI_ALIAS_FLAG)
private var _lastX = 0f
private var _lastY = 0f
@@ -113,7 +111,9 @@ public class Painting : View, SpotFilter.Plotter {
FADE_TO_BLACK_CF
synchronized(_bitmapLock) {
- c.drawBitmap(bitmap, 0f, 0f, pt)
+ bitmap?.let {
+ c.drawBitmap(bitmap!!, 0f, 0f, pt)
+ }
}
invalidate()
}
@@ -122,18 +122,22 @@ public class Painting : View, SpotFilter.Plotter {
}
constructor(context: Context) : super(context) {
- init(null, 0)
+ init()
}
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
- init(attrs, 0)
+ init()
}
- constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) {
- init(attrs, defStyle)
+ constructor(
+ context: Context,
+ attrs: AttributeSet,
+ defStyle: Int
+ ) : super(context, attrs, defStyle) {
+ init()
}
- private fun init(attrs: AttributeSet?, defStyle: Int) {
+ private fun init() {
loadDevicePressureData()
}
@@ -264,7 +268,7 @@ public class Painting : View, SpotFilter.Plotter {
super.onDraw(canvas)
bitmap?.let {
- canvas.drawBitmap(bitmap, 0f, 0f, _drawPaint);
+ canvas.drawBitmap(bitmap!!, 0f, 0f, _drawPaint)
}
}
@@ -330,8 +334,8 @@ public class Painting : View, SpotFilter.Plotter {
}
if (bits.width != oldBits.height || bits.height != oldBits.width) {
matrix.postScale(
- bits.width.toFloat()/oldBits.height,
- bits.height.toFloat()/oldBits.width)
+ bits.width.toFloat() / oldBits.height,
+ bits.height.toFloat() / oldBits.width)
}
c.matrix = matrix
}
@@ -350,9 +354,10 @@ public class Painting : View, SpotFilter.Plotter {
val invertPaint = Paint()
invertPaint.colorFilter = INVERT_CF
synchronized(_bitmapLock) {
- _paintCanvas?.drawBitmap(bitmap, 0f, 0f, invertPaint)
+ bitmap?.let {
+ _paintCanvas?.drawBitmap(bitmap!!, 0f, 0f, invertPaint)
+ }
}
invalidate()
}
}
-
diff --git a/packages/EasterEgg/src/com/android/egg/paint/ToolbarView.kt b/packages/EasterEgg/src/com/android/egg/paint/ToolbarView.kt
index 86b11e7be81e..460fa3a7241f 100644
--- a/packages/EasterEgg/src/com/android/egg/paint/ToolbarView.kt
+++ b/packages/EasterEgg/src/com/android/egg/paint/ToolbarView.kt
@@ -17,19 +17,10 @@
package com.android.egg.paint
import android.content.Context
-import android.graphics.Canvas
-import android.graphics.Color
-import android.graphics.Paint
-import android.graphics.Rect
-import android.graphics.drawable.Drawable
-import android.text.TextPaint
-import android.transition.ChangeBounds
import android.transition.Transition
import android.transition.TransitionListenerAdapter
-import android.transition.TransitionManager
import android.util.AttributeSet
import android.view.*
-import android.view.animation.OvershootInterpolator
import android.widget.FrameLayout
class ToolbarView : FrameLayout {
@@ -44,15 +35,16 @@ class ToolbarView : FrameLayout {
}
constructor(context: Context) : super(context) {
- init(null, 0)
}
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
- init(attrs, 0)
}
- constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) {
- init(attrs, defStyle)
+ constructor(
+ context: Context,
+ attrs: AttributeSet,
+ defStyle: Int
+ ) : super(context, attrs, defStyle) {
}
override fun onApplyWindowInsets(insets: WindowInsets?): WindowInsets {
@@ -70,8 +62,4 @@ class ToolbarView : FrameLayout {
return super.onApplyWindowInsets(insets)
}
-
- private fun init(attrs: AttributeSet?, defStyle: Int) {
- }
-
}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
index 8c29a2520390..441dbac24928 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
@@ -16,7 +16,7 @@
*/
package com.android.packageinstaller;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
import android.Manifest;
import android.annotation.NonNull;
@@ -281,7 +281,7 @@ public class PackageInstallerActivity extends AlertActivity {
@Override
protected void onCreate(Bundle icicle) {
- getWindow().addPrivateFlags(PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
+ getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
super.onCreate(null);
diff --git a/packages/PrintSpooler/Android.bp b/packages/PrintSpooler/Android.bp
new file mode 100644
index 000000000000..c40a81791302
--- /dev/null
+++ b/packages/PrintSpooler/Android.bp
@@ -0,0 +1,38 @@
+// Copyright (C) 2013 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_app {
+ name: "PrintSpooler",
+
+ resource_dirs: ["res"],
+
+ srcs: [
+ "src/**/*.java",
+ "src/com/android/printspooler/renderer/IPdfRenderer.aidl",
+ "src/com/android/printspooler/renderer/IPdfEditor.aidl",
+ ],
+
+ platform_apis: true,
+
+ jni_libs: ["libprintspooler_jni"],
+ static_libs: [
+ "android-support-v7-recyclerview",
+ "android-support-compat",
+ "android-support-media-compat",
+ "android-support-core-utils",
+ "android-support-core-ui",
+ "android-support-fragment",
+ "android-support-annotations",
+ ],
+}
diff --git a/packages/PrintSpooler/Android.mk b/packages/PrintSpooler/Android.mk
deleted file mode 100644
index e356f38f10b3..000000000000
--- a/packages/PrintSpooler/Android.mk
+++ /dev/null
@@ -1,45 +0,0 @@
-# Copyright (C) 2013 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-LOCAL_USE_AAPT2 := true
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_SRC_FILES += \
- src/com/android/printspooler/renderer/IPdfRenderer.aidl \
- src/com/android/printspooler/renderer/IPdfEditor.aidl
-
-LOCAL_PACKAGE_NAME := PrintSpooler
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_JNI_SHARED_LIBRARIES := libprintspooler_jni
-LOCAL_STATIC_ANDROID_LIBRARIES := \
- android-support-v7-recyclerview \
- android-support-compat \
- android-support-media-compat \
- android-support-core-utils \
- android-support-core-ui \
- android-support-fragment
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- android-support-annotations
-
-include $(BUILD_PACKAGE)
-
-include $(call all-makefiles-under, $(LOCAL_PATH))
diff --git a/packages/PrintSpooler/tests/Android.mk b/packages/PrintSpooler/tests/Android.mk
deleted file mode 100644
index 83e00ce089d2..000000000000
--- a/packages/PrintSpooler/tests/Android.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright (C) 2016 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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-include $(call all-makefiles-under, $(LOCAL_PATH))
diff --git a/packages/PrintSpooler/tests/outofprocess/Android.bp b/packages/PrintSpooler/tests/outofprocess/Android.bp
new file mode 100644
index 000000000000..e88074ee4b9c
--- /dev/null
+++ b/packages/PrintSpooler/tests/outofprocess/Android.bp
@@ -0,0 +1,30 @@
+// Copyright (C) 2016 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.
+
+android_test {
+ name: "PrintSpoolerOutOfProcessTests",
+
+ srcs: ["src/**/*.java"],
+
+ libs: ["android.test.runner.stubs"],
+ static_libs: [
+ "android-support-test",
+ "ub-uiautomator",
+ "mockito-target-minus-junit4",
+ "print-test-util-lib",
+ ],
+
+ sdk_version: "test_current",
+ test_suites: ["device-tests"],
+}
diff --git a/packages/PrintSpooler/tests/outofprocess/Android.mk b/packages/PrintSpooler/tests/outofprocess/Android.mk
deleted file mode 100644
index 161a60021e65..000000000000
--- a/packages/PrintSpooler/tests/outofprocess/Android.mk
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright (C) 2016 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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_JAVA_LIBRARIES := android.test.runner.stubs
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-test ub-uiautomator mockito-target-minus-junit4 print-test-util-lib
-
-LOCAL_PACKAGE_NAME := PrintSpoolerOutOfProcessTests
-LOCAL_SDK_VERSION := current
-LOCAL_COMPATIBILITY_SUITE := device-tests
-
-include $(BUILD_PACKAGE)
diff --git a/packages/SettingsLib/RestrictedLockUtils/src/com/android/settingslib/RestrictedLockUtils.java b/packages/SettingsLib/RestrictedLockUtils/src/com/android/settingslib/RestrictedLockUtils.java
index b87c9e8de1b2..e278c10a2c59 100644
--- a/packages/SettingsLib/RestrictedLockUtils/src/com/android/settingslib/RestrictedLockUtils.java
+++ b/packages/SettingsLib/RestrictedLockUtils/src/com/android/settingslib/RestrictedLockUtils.java
@@ -91,13 +91,7 @@ public class RestrictedLockUtils {
public static boolean isCurrentUserOrProfile(Context context, int userId) {
UserManager um = context.getSystemService(UserManager.class);
- int[] userIds = um.getProfileIds(UserHandle.myUserId(), true);
- for (int i = 0; i < userIds.length; i++) {
- if (userIds[i] == userId) {
- return true;
- }
- }
- return false;
+ return um.getUserProfiles().contains(UserHandle.of(userId));
}
public static class EnforcedAdmin {
diff --git a/packages/SettingsLib/SettingsSpinner/src/com/android/settingslib/widget/settingsspinner/SettingsSpinnerAdapter.java b/packages/SettingsLib/SettingsSpinner/src/com/android/settingslib/widget/settingsspinner/SettingsSpinnerAdapter.java
index c26295ceaf59..8bf8fce4e36d 100644
--- a/packages/SettingsLib/SettingsSpinner/src/com/android/settingslib/widget/settingsspinner/SettingsSpinnerAdapter.java
+++ b/packages/SettingsLib/SettingsSpinner/src/com/android/settingslib/widget/settingsspinner/SettingsSpinnerAdapter.java
@@ -24,7 +24,7 @@ import android.widget.ArrayAdapter;
/**
* An ArrayAdapter which was used by {@link SettingsSpinner} with settings style.
*/
-public class SettingsSpinnerAdapter<CharSequence> extends ArrayAdapter {
+public class SettingsSpinnerAdapter<T> extends ArrayAdapter<T> {
/**
* Constructs a new SettingsSpinnerAdapter with the given context.
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
index 4aca2bb2c54d..7124096e31b8 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
@@ -267,8 +267,10 @@ public class BluetoothEventManager {
cachedDevice = mDeviceManager.addDevice(device);
Log.d(TAG, "DeviceFoundHandler created new CachedBluetoothDevice: "
+ cachedDevice);
- } else if (cachedDevice.getBondState() == BluetoothDevice.BOND_BONDED) {
- // Dispatch device add callback to show bonded BT device in discovery mode
+ } else if (cachedDevice.getBondState() == BluetoothDevice.BOND_BONDED
+ &&!cachedDevice.getDevice().isConnected()) {
+ // Dispatch device add callback to show bonded but
+ // not connected devices in discovery mode
dispatchDeviceAdded(cachedDevice);
}
cachedDevice.setRssi(rssi);
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index ce503b373dbe..dcc6cbafe41d 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -27,6 +27,7 @@
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
+ <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.READ_CALENDAR" />
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/SensorManagerPlugin.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/SensorManagerPlugin.java
index d1181445be43..ba4eb5f48528 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/SensorManagerPlugin.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/SensorManagerPlugin.java
@@ -16,6 +16,9 @@
package com.android.systemui.plugins;
+import android.hardware.Sensor;
+import android.hardware.TriggerEventListener;
+
import com.android.systemui.plugins.annotations.ProvidesInterface;
/**
@@ -28,10 +31,12 @@ public interface SensorManagerPlugin extends Plugin {
int VERSION = 1;
/**
- * Registers for trigger events from the sensor. The client will receive trigger events until
- * {@link #unregisterTriggerEvent(Sensor, TriggerEventListener)} is called.
+ * Registers for trigger events from the sensor. Trigger events are one-shot and need to
+ * re-registered in order for them to be fired again.
* @param sensor
* @param listener
+ * @see android.hardware.SensorManager#requestTriggerSensor(
+ * android.hardware.TriggerEventListener, android.hardware.Sensor)
*/
void registerTriggerEvent(Sensor sensor, TriggerEventListener listener);
@@ -62,9 +67,25 @@ public interface SensorManagerPlugin extends Plugin {
class TriggerEvent {
Sensor mSensor;
+ int mVendorType;
- public TriggerEvent(Sensor sensor) {
+ /**
+ * Creates a trigger event
+ * @param sensor The type of sensor, e.g. TYPE_WAKE_LOCK_SCREEN
+ * @param vendorType The vendor type, which should be unique for each type of sensor,
+ * e.g. SINGLE_TAP = 1, DOUBLE_TAP = 2, etc.
+ */
+ public TriggerEvent(Sensor sensor, int vendorType) {
mSensor = sensor;
+ mVendorType = vendorType;
+ }
+
+ public Sensor getSensor() {
+ return mSensor;
+ }
+
+ public int getVendorType() {
+ return mVendorType;
}
}
}
diff --git a/packages/SystemUI/res/layout/notification_info.xml b/packages/SystemUI/res/layout/notification_info.xml
index 7a38899f37f7..f138685e9810 100644
--- a/packages/SystemUI/res/layout/notification_info.xml
+++ b/packages/SystemUI/res/layout/notification_info.xml
@@ -24,8 +24,7 @@
android:clipChildren="false"
android:clipToPadding="false"
android:orientation="vertical"
- android:background="@color/notification_guts_bg_color"
- android:theme="@*android:style/Theme.DeviceDefault.Light">
+ android:background="@color/notification_guts_bg_color">
<!-- Package Info -->
<RelativeLayout
diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml
index f0436dea9207..d033057cdb78 100644
--- a/packages/SystemUI/res/layout/status_bar.xml
+++ b/packages/SystemUI/res/layout/status_bar.xml
@@ -49,11 +49,6 @@
android:paddingEnd="@dimen/status_bar_padding_end"
android:orientation="horizontal"
>
- <ViewStub
- android:id="@+id/operator_name"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout="@layout/operator_name" />
<FrameLayout
android:layout_height="match_parent"
android:layout_width="0dp"
@@ -70,6 +65,12 @@
android:layout_width="match_parent"
android:clipChildren="false"
>
+ <ViewStub
+ android:id="@+id/operator_name"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout="@layout/operator_name" />
+
<com.android.systemui.statusbar.policy.Clock
android:id="@+id/clock"
android:layout_width="wrap_content"
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index e1c71fae7559..42e19aace0c3 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -761,6 +761,8 @@
<string name="quick_settings_cast_device_default_description">Ready to cast</string>
<!-- QuickSettings: Cast detail panel, text when there are no items [CHAR LIMIT=NONE] -->
<string name="quick_settings_cast_detail_empty_text">No devices available</string>
+ <!-- QuickSettings: Cast unavailable, text when not connected to WiFi [CHAR LIMIT=NONE] -->
+ <string name="quick_settings_cast_no_wifi">Wi\u2011Fi not connected</string>
<!-- QuickSettings: Brightness dialog title [CHAR LIMIT=NONE] -->
<string name="quick_settings_brightness_dialog_title">Brightness</string>
<!-- QuickSettings: Brightness dialog auto brightness button [CHAR LIMIT=NONE] -->
@@ -1999,6 +2001,9 @@
<!-- accessibility label for quick settings items that open a details page [CHAR LIMIT=NONE] -->
<string name="accessibility_quick_settings_open_details">Open details.</string>
+ <!-- accessibility label for quick settings items that are currently disabled. Must have a reason [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_not_available">Unvailable due to <xliff:g name="reason" id="reason" example="Wifi not available">%s</xliff:g></string>
+
<!-- accessibility label for quick settings items that open a details page [CHAR LIMIT=NONE] -->
<string name="accessibility_quick_settings_open_settings">Open <xliff:g name="page" example="Bluetooth">%s</xliff:g> settings.</string>
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index 4d24d82bd7ee..3007b6e68b78 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -736,14 +736,19 @@ public class ScreenDecorations extends SystemUI implements Tunable {
switch (gravity) {
case Gravity.TOP:
out.set(displayCutout.getBoundingRectTop());
+ break;
case Gravity.LEFT:
out.set(displayCutout.getBoundingRectLeft());
+ break;
case Gravity.BOTTOM:
out.set(displayCutout.getBoundingRectBottom());
+ break;
case Gravity.RIGHT:
out.set(displayCutout.getBoundingRectRight());
+ break;
+ default:
+ out.setEmpty();
}
- out.setEmpty();
}
private void localBounds(Rect out) {
diff --git a/packages/SystemUI/src/com/android/systemui/SlicePermissionActivity.java b/packages/SystemUI/src/com/android/systemui/SlicePermissionActivity.java
index 6d790668995e..449ed8c3bcdb 100644
--- a/packages/SystemUI/src/com/android/systemui/SlicePermissionActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/SlicePermissionActivity.java
@@ -14,7 +14,7 @@
package com.android.systemui;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
import android.app.Activity;
import android.app.AlertDialog;
@@ -69,7 +69,7 @@ public class SlicePermissionActivity extends Activity implements OnClickListener
.setPositiveButton(R.string.slice_permission_allow, this)
.setOnDismissListener(this)
.create();
- dialog.getWindow().addPrivateFlags(PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
+ dialog.getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
dialog.show();
TextView t1 = dialog.getWindow().getDecorView().findViewById(R.id.text1);
t1.setText(getString(R.string.slice_permission_text_1, app2));
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index 701394763fbd..77f7ad4f3a9e 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -16,6 +16,8 @@
package com.android.systemui.doze;
+import static com.android.systemui.plugins.SensorManagerPlugin.Sensor.TYPE_WAKE_LOCK_SCREEN;
+
import android.annotation.AnyThread;
import android.app.ActivityManager;
import android.app.AlarmManager;
@@ -39,8 +41,10 @@ import android.util.Log;
import com.android.internal.hardware.AmbientDisplayConfiguration;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
+import com.android.systemui.plugins.SensorManagerPlugin;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.util.AlarmTimeout;
+import com.android.systemui.util.AsyncSensorManager;
import com.android.systemui.util.wakelock.WakeLock;
import java.io.PrintWriter;
@@ -112,8 +116,8 @@ public class DozeSensors {
DozeLog.PULSE_REASON_SENSOR_LONG_PRESS,
true /* reports touch coordinates */,
true /* touchscreen */),
- new TriggerSensor(
- findSensorWithType(config.wakeLockScreenSensorType()),
+ new PluginTriggerSensor(
+ new SensorManagerPlugin.Sensor(TYPE_WAKE_LOCK_SCREEN),
Settings.Secure.DOZE_WAKE_LOCK_SCREEN_GESTURE,
true /* configured */,
DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN,
@@ -375,7 +379,7 @@ public class DozeSensors {
mHandler.post(mWakeLock.wrap(() -> {
if (DEBUG) Log.d(TAG, "onTrigger: " + triggerEventToString(event));
boolean sensorPerformsProxCheck = false;
- if (mSensor.getType() == Sensor.TYPE_PICK_UP_GESTURE) {
+ if (mSensor != null && mSensor.getType() == Sensor.TYPE_PICK_UP_GESTURE) {
int subType = (int) event.values[0];
MetricsLogger.action(
mContext, MetricsProto.MetricsEvent.ACTION_AMBIENT_GESTURE,
@@ -418,6 +422,49 @@ public class DozeSensors {
}
}
+ /**
+ * A Sensor that is injected via plugin.
+ */
+ private class PluginTriggerSensor extends TriggerSensor {
+
+ private final SensorManagerPlugin.Sensor mPluginSensor;
+ private final SensorManagerPlugin.TriggerEventListener mTriggerEventListener = (event) -> {
+ onTrigger(null);
+ };
+
+ PluginTriggerSensor(SensorManagerPlugin.Sensor sensor, String setting, boolean configured,
+ int pulseReason, boolean reportsTouchCoordinates, boolean requiresTouchscreen) {
+ super(null, setting, configured, pulseReason, reportsTouchCoordinates,
+ requiresTouchscreen);
+ mPluginSensor = sensor;
+ }
+
+ @Override
+ public void updateListener() {
+ if (!mConfigured) return;
+ AsyncSensorManager asyncSensorManager = (AsyncSensorManager) mSensorManager;
+ if (mRequested && !mDisabled && enabledBySetting() && !mRegistered) {
+ asyncSensorManager.requestPluginTriggerSensor(mPluginSensor, mTriggerEventListener);
+ mRegistered = true;
+ if (DEBUG) Log.d(TAG, "requestPluginTriggerSensor");
+ } else if (mRegistered) {
+ asyncSensorManager.cancelPluginTriggerSensor(mPluginSensor, mTriggerEventListener);
+ mRegistered = false;
+ if (DEBUG) Log.d(TAG, "cancelPluginTriggerSensor");
+ }
+ }
+
+ @Override
+ public String toString() {
+ return new StringBuilder("{mRegistered=").append(mRegistered)
+ .append(", mRequested=").append(mRequested)
+ .append(", mDisabled=").append(mDisabled)
+ .append(", mConfigured=").append(mConfigured)
+ .append(", mSensor=").append(mPluginSensor).append("}").toString();
+ }
+
+ }
+
private class WakeScreenSensor extends TriggerSensor {
WakeScreenSensor() {
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
index 4a6786832df0..df763151cdd7 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
@@ -16,7 +16,7 @@
package com.android.systemui.media;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
import android.app.Activity;
import android.app.AlertDialog;
@@ -151,7 +151,7 @@ public class MediaProjectionPermissionActivity extends Activity
((CheckBox) mDialog.findViewById(R.id.remember)).setOnCheckedChangeListener(this);
final Window w = mDialog.getWindow();
w.setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
- w.addPrivateFlags(PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
+ w.addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
mDialog.show();
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
index ed78048c8746..921db6901626 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -46,6 +46,7 @@ import com.android.systemui.statusbar.phone.SystemUIDialog;
import com.android.systemui.statusbar.policy.CastController;
import com.android.systemui.statusbar.policy.CastController.CastDevice;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import com.android.systemui.statusbar.policy.NetworkController;
import java.util.LinkedHashMap;
import java.util.Set;
@@ -58,16 +59,18 @@ public class CastTile extends QSTileImpl<BooleanState> {
private final CastController mController;
private final CastDetailAdapter mDetailAdapter;
private final KeyguardMonitor mKeyguard;
+ private final NetworkController mNetworkController;
private final Callback mCallback = new Callback();
private final ActivityStarter mActivityStarter;
private Dialog mDialog;
- private boolean mRegistered;
+ private boolean mWifiConnected;
public CastTile(QSHost host) {
super(host);
mController = Dependency.get(CastController.class);
mDetailAdapter = new CastDetailAdapter();
mKeyguard = Dependency.get(KeyguardMonitor.class);
+ mNetworkController = Dependency.get(NetworkController.class);
mActivityStarter = Dependency.get(ActivityStarter.class);
}
@@ -87,10 +90,12 @@ public class CastTile extends QSTileImpl<BooleanState> {
if (listening) {
mController.addCallback(mCallback);
mKeyguard.addCallback(mCallback);
+ mNetworkController.addCallback(mSignalCallback);
} else {
mController.setDiscovering(false);
mController.removeCallback(mCallback);
mKeyguard.removeCallback(mCallback);
+ mNetworkController.removeCallback(mSignalCallback);
}
}
@@ -112,6 +117,9 @@ public class CastTile extends QSTileImpl<BooleanState> {
@Override
protected void handleClick() {
+ if (getState().state == Tile.STATE_UNAVAILABLE) {
+ return;
+ }
if (mKeyguard.isSecure() && !mKeyguard.canSkipBouncer()) {
mActivityStarter.postQSRunnableDismissingKeyguard(() -> {
showDetail(true);
@@ -164,13 +172,22 @@ public class CastTile extends QSTileImpl<BooleanState> {
if (!state.value && connecting) {
state.label = mContext.getString(R.string.quick_settings_connecting);
}
- state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
state.icon = ResourceIcon.get(state.value ? R.drawable.ic_qs_cast_on
: R.drawable.ic_qs_cast_off);
+ if (mWifiConnected) {
+ state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
+ state.secondaryLabel = "";
+ state.contentDescription = state.contentDescription + ","
+ + mContext.getString(R.string.accessibility_quick_settings_open_details);
+ state.expandedAccessibilityClassName = Button.class.getName();
+ } else {
+ state.state = Tile.STATE_UNAVAILABLE;
+ String noWifi = mContext.getString(R.string.quick_settings_cast_no_wifi);
+ state.secondaryLabel = noWifi;
+ state.contentDescription = state.contentDescription + ", " + mContext.getString(
+ R.string.accessibility_quick_settings_not_available, noWifi);
+ }
mDetailAdapter.updateItems(devices);
- state.expandedAccessibilityClassName = Button.class.getName();
- state.contentDescription = state.contentDescription + ","
- + mContext.getString(R.string.accessibility_quick_settings_open_details);
}
@Override
@@ -192,6 +209,22 @@ public class CastTile extends QSTileImpl<BooleanState> {
: mContext.getString(R.string.quick_settings_cast_device_default_name);
}
+ private final NetworkController.SignalCallback mSignalCallback =
+ new NetworkController.SignalCallback() {
+ @Override
+ public void setWifiIndicators(boolean enabled,
+ NetworkController.IconState statusIcon,
+ NetworkController.IconState qsIcon, boolean activityIn, boolean activityOut,
+ String description, boolean isTransient, String statusLabel) {
+ // statusIcon.visible has the connected status information
+ boolean enabledAndConnected = enabled && qsIcon.visible;
+ if (enabledAndConnected != mWifiConnected) {
+ mWifiConnected = enabledAndConnected;
+ refreshState();
+ }
+ }
+ };
+
private final class Callback implements CastController.Callback, KeyguardMonitor.Callback {
@Override
public void onCastDevicesChanged() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index 2450e448c4f7..24665eac76a7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -491,6 +491,10 @@ public class CarStatusBar extends StatusBar implements
@Override
public void onStateChanged(int newState) {
super.onStateChanged(newState);
+ if (mFullscreenUserSwitcher == null) {
+ return; // Not using the full screen user switcher.
+ }
+
if (newState == StatusBarState.FULLSCREEN_USER_SWITCHER) {
if (!mFullscreenUserSwitcher.isVisible()) {
// Current execution path continues to set state after this, thus we deffer the
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 9ddab7cc0b2f..33ac390de29f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -4849,7 +4849,7 @@ public class NotificationStackScrollLayout extends ViewGroup
activatedChild.makeInactive(false /* animate */);
}
updateFooter();
- updateChildren();
+ requestChildrenUpdate();
onUpdateRowStates();
mEntryManager.updateNotifications();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
index 9acaf21c41f5..c66bbb1696ac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
@@ -48,6 +48,7 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener,
private final NotificationStackScrollLayout mStackScroller;
private final HeadsUpStatusBarView mHeadsUpStatusBarView;
private final View mClockView;
+ private final View mOperatorNameView;
private final DarkIconDispatcher mDarkIconDispatcher;
private final NotificationPanelView mPanelView;
private final Consumer<ExpandableNotificationRow>
@@ -65,8 +66,10 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener,
private final View.OnLayoutChangeListener mStackScrollLayoutChangeListener =
(v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom)
-> updatePanelTranslation();
+ private boolean mAnimationsEnabled = true;
Point mPoint;
+
public HeadsUpAppearanceController(
NotificationIconAreaController notificationIconAreaController,
HeadsUpManagerPhone headsUpManager,
@@ -75,7 +78,8 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener,
statusbarView.findViewById(R.id.heads_up_status_bar_view),
statusbarView.findViewById(R.id.notification_stack_scroller),
statusbarView.findViewById(R.id.notification_panel),
- statusbarView.findViewById(R.id.clock));
+ statusbarView.findViewById(R.id.clock),
+ statusbarView.findViewById(R.id.operator_name_frame));
}
@VisibleForTesting
@@ -85,7 +89,8 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener,
HeadsUpStatusBarView headsUpStatusBarView,
NotificationStackScrollLayout stackScroller,
NotificationPanelView panelView,
- View clockView) {
+ View clockView,
+ View operatorNameView) {
mNotificationIconAreaController = notificationIconAreaController;
mHeadsUpManager = headsUpManager;
mHeadsUpManager.addListener(this);
@@ -101,6 +106,7 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener,
mStackScroller.addOnLayoutChangeListener(mStackScrollLayoutChangeListener);
mStackScroller.setHeadsUpAppearanceController(this);
mClockView = clockView;
+ mOperatorNameView = operatorNameView;
mDarkIconDispatcher = Dependency.get(DarkIconDispatcher.class);
mDarkIconDispatcher.addDarkReceiver(this);
@@ -230,20 +236,52 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener,
mShown = isShown;
if (isShown) {
mHeadsUpStatusBarView.setVisibility(View.VISIBLE);
- CrossFadeHelper.fadeIn(mHeadsUpStatusBarView, CONTENT_FADE_DURATION /* duration */,
- CONTENT_FADE_DELAY /* delay */);
- CrossFadeHelper.fadeOut(mClockView, CONTENT_FADE_DURATION/* duration */,
- 0 /* delay */, () -> mClockView.setVisibility(View.INVISIBLE));
+ show(mHeadsUpStatusBarView);
+ hide(mClockView, View.INVISIBLE);
+ if (mOperatorNameView != null) {
+ hide(mOperatorNameView, View.INVISIBLE);
+ }
} else {
- CrossFadeHelper.fadeIn(mClockView, CONTENT_FADE_DURATION /* duration */,
- CONTENT_FADE_DELAY /* delay */);
- CrossFadeHelper.fadeOut(mHeadsUpStatusBarView, CONTENT_FADE_DURATION/* duration */,
- 0 /* delay */, () -> mHeadsUpStatusBarView.setVisibility(View.GONE));
-
+ show(mClockView);
+ if (mOperatorNameView != null) {
+ show(mOperatorNameView);
+ }
+ hide(mHeadsUpStatusBarView, View.GONE);
}
}
}
+ /**
+ * Hides the view and sets the state to endState when finished.
+ *
+ * @param view The view to hide.
+ * @param endState One of {@link View#INVISIBLE} or {@link View#GONE}.
+ * @see View#setVisibility(int)
+ *
+ */
+ private void hide(View view, int endState) {
+ if (mAnimationsEnabled) {
+ CrossFadeHelper.fadeOut(view, CONTENT_FADE_DURATION /* duration */,
+ 0 /* delay */, () -> view.setVisibility(endState));
+ } else {
+ view.setVisibility(endState);
+ }
+ }
+
+ private void show(View view) {
+ if (mAnimationsEnabled) {
+ CrossFadeHelper.fadeIn(view, CONTENT_FADE_DURATION /* duration */,
+ CONTENT_FADE_DELAY /* delay */);
+ } else {
+ view.setVisibility(View.VISIBLE);
+ }
+ }
+
+ @VisibleForTesting
+ void setAnimationsEnabled(boolean enabled) {
+ mAnimationsEnabled = enabled;
+ }
+
@VisibleForTesting
public boolean isShown() {
return mShown;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index 2a4595b980ac..8ac867727e65 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -361,6 +361,8 @@ public class KeyguardBouncer {
} else if (fraction == EXPANSION_HIDDEN && oldExpansion != EXPANSION_HIDDEN) {
onFullyHidden();
mExpansionCallback.onFullyHidden();
+ } else if (fraction != EXPANSION_VISIBLE && oldExpansion == EXPANSION_VISIBLE) {
+ mExpansionCallback.onStartingToHide();
}
}
@@ -481,6 +483,7 @@ public class KeyguardBouncer {
public interface BouncerExpansionCallback {
void onFullyShown();
+ void onStartingToHide();
void onFullyHidden();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
index 7c84df91fffa..e85ff8ef22c0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
@@ -519,7 +519,14 @@ public class KeyguardStatusBarView extends RelativeLayout
mStatusIconContainer.setAlpha(alpha);
mStatusIconContainer.setVisibility(visibility);
- mSystemIconsContainer.setTranslationX(-mCurrentBurnInOffsetX * mDarkAmount);
+ float iconsX = -mCurrentBurnInOffsetX;
+ if (mMultiUserSwitch.getVisibility() == VISIBLE) {
+ // Squared alpha to add a nice easing curve and avoid overlap during animation.
+ mMultiUserAvatar.setAlpha(alpha * alpha);
+ iconsX += mMultiUserAvatar.getPaddingLeft() + mMultiUserAvatar.getWidth()
+ + mMultiUserAvatar.getPaddingRight();
+ }
+ mSystemIconsContainer.setTranslationX(iconsX * mDarkAmount);
mSystemIconsContainer.setTranslationY(mCurrentBurnInOffsetY * mDarkAmount);
updateIconsAndTextColors();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 3db1456446a0..ac3608bc622a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -84,6 +84,11 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
}
@Override
+ public void onStartingToHide() {
+ updateStates();
+ }
+
+ @Override
public void onFullyHidden() {
updateStates();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
index 57c7e285e29f..0d37b550d4e0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
@@ -173,9 +173,9 @@ public class StatusBarWindowController implements Callback, Dumpable, Configurat
}
if (state.dozing) {
- mLpChanged.privateFlags |= LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+ mLpChanged.privateFlags |= LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
} else {
- mLpChanged.privateFlags &= ~LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+ mLpChanged.privateFlags &= ~LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunablePadding.java b/packages/SystemUI/src/com/android/systemui/tuner/TunablePadding.java
index af99236cc393..e85dee841715 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunablePadding.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunablePadding.java
@@ -51,7 +51,9 @@ public class TunablePadding implements Tunable {
public void onTuningChanged(String key, String newValue) {
int dimen = mDefaultSize;
if (newValue != null) {
- dimen = (int) (Integer.parseInt(newValue) * mDensity);
+ try {
+ dimen = (int) (Integer.parseInt(newValue) * mDensity);
+ } catch (NumberFormatException ex) {}
}
int left = mView.isLayoutRtl() ? FLAG_END : FLAG_START;
int right = mView.isLayoutRtl() ? FLAG_START : FLAG_END;
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java
index 66d5ee1a276f..4102e63f7330 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java
@@ -54,7 +54,7 @@ public class UsbDebuggingActivity extends AlertActivity
@Override
public void onCreate(Bundle icicle) {
Window window = getWindow();
- window.addPrivateFlags(WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
+ window.addSystemFlags(WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
window.setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
super.onCreate(icicle);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java
new file mode 100644
index 000000000000..d9412ecd9a3a
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertTrue;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.service.quicksettings.Tile;
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import com.android.systemui.Dependency;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.statusbar.policy.CastController;
+import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import com.android.systemui.statusbar.policy.NetworkController;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.HashSet;
+import java.util.Set;
+
+
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+@SmallTest
+public class CastTileTest extends SysuiTestCase {
+
+ @Mock
+ private CastController mController;
+ @Mock
+ private ActivityStarter mActivityStarter;
+ @Mock
+ private KeyguardMonitor mKeyguard;
+ @Mock
+ private NetworkController mNetworkController;
+ @Mock
+ private QSTileHost mHost;
+ @Mock
+ NetworkController.SignalCallback mCallback;
+
+ private TestableLooper mTestableLooper;
+ private CastTile mCastTile;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ mTestableLooper = TestableLooper.get(this);
+
+ mDependency.injectTestDependency(Dependency.BG_LOOPER, mTestableLooper.getLooper());
+ mController = mDependency.injectMockDependency(CastController.class);
+ mActivityStarter = mDependency.injectMockDependency(ActivityStarter.class);
+ mKeyguard = mDependency.injectMockDependency(KeyguardMonitor.class);
+ mNetworkController = mDependency.injectMockDependency(NetworkController.class);
+
+ when(mHost.getContext()).thenReturn(mContext);
+
+ mCastTile = new CastTile(mHost);
+
+ // We are not setting the mocks to listening, so we trigger a first refresh state to
+ // set the initial state
+ mCastTile.refreshState();
+
+ mCastTile.handleSetListening(true);
+ ArgumentCaptor<NetworkController.SignalCallback> signalCallbackArgumentCaptor =
+ ArgumentCaptor.forClass(NetworkController.SignalCallback.class);
+ verify(mNetworkController).addCallback(signalCallbackArgumentCaptor.capture());
+ mCallback = signalCallbackArgumentCaptor.getValue();
+
+ }
+
+ @Test
+ public void testStateUnavailable_wifiDisabled() {
+ NetworkController.IconState qsIcon =
+ new NetworkController.IconState(false, 0, "");
+ mCallback.setWifiIndicators(false, mock(NetworkController.IconState.class),
+ qsIcon, false,false, "",
+ false, "");
+ mTestableLooper.processAllMessages();
+
+ assertEquals(Tile.STATE_UNAVAILABLE, mCastTile.getState().state);
+ }
+
+ @Test
+ public void testStateUnavailable_wifiNotConnected() {
+ NetworkController.IconState qsIcon =
+ new NetworkController.IconState(false, 0, "");
+ mCallback.setWifiIndicators(true, mock(NetworkController.IconState.class),
+ qsIcon, false,false, "",
+ false, "");
+ mTestableLooper.processAllMessages();
+
+ assertEquals(Tile.STATE_UNAVAILABLE, mCastTile.getState().state);
+ }
+
+ @Test
+ public void testStateActive_wifiEnabledAndCasting() {
+ CastController.CastDevice device = mock(CastController.CastDevice.class);
+ device.state = CastController.CastDevice.STATE_CONNECTED;
+ Set<CastController.CastDevice> devices = new HashSet<>();
+ devices.add(device);
+ when(mController.getCastDevices()).thenReturn(devices);
+
+ NetworkController.IconState qsIcon =
+ new NetworkController.IconState(true, 0, "");
+ mCallback.setWifiIndicators(true, mock(NetworkController.IconState.class),
+ qsIcon, false,false, "",
+ false, "");
+ mTestableLooper.processAllMessages();
+
+ assertEquals(Tile.STATE_ACTIVE, mCastTile.getState().state);
+ }
+
+ @Test
+ public void testStateInactive_wifiEnabledNotCasting() {
+ NetworkController.IconState qsIcon =
+ new NetworkController.IconState(true, 0, "");
+ mCallback.setWifiIndicators(true, mock(NetworkController.IconState.class),
+ qsIcon, false,false, "",
+ false, "");
+ mTestableLooper.processAllMessages();
+
+ assertEquals(Tile.STATE_INACTIVE, mCastTile.getState().state);
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
index a4004ae2d7cc..10b0d834b36b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
@@ -54,6 +54,7 @@ public class HeadsUpAppearanceControllerTest extends SysuiTestCase {
private ExpandableNotificationRow mFirst;
private HeadsUpStatusBarView mHeadsUpStatusBarView;
private HeadsUpManagerPhone mHeadsUpManager;
+ private View mOperatorNameView;
@Before
public void setUp() throws Exception {
@@ -63,13 +64,15 @@ public class HeadsUpAppearanceControllerTest extends SysuiTestCase {
mHeadsUpStatusBarView = new HeadsUpStatusBarView(mContext, mock(View.class),
mock(TextView.class));
mHeadsUpManager = mock(HeadsUpManagerPhone.class);
+ mOperatorNameView = new View(mContext);
mHeadsUpAppearanceController = new HeadsUpAppearanceController(
mock(NotificationIconAreaController.class),
mHeadsUpManager,
mHeadsUpStatusBarView,
mStackScroller,
mPanelView,
- new View(mContext));
+ new View(mContext),
+ mOperatorNameView);
mHeadsUpAppearanceController.setExpandedHeight(0.0f, 0.0f);
}
@@ -116,6 +119,22 @@ public class HeadsUpAppearanceControllerTest extends SysuiTestCase {
}
@Test
+ public void testOperatorNameViewUpdated() {
+ mHeadsUpAppearanceController.setAnimationsEnabled(false);
+
+ mFirst.setPinned(true);
+ when(mHeadsUpManager.hasPinnedHeadsUp()).thenReturn(true);
+ when(mHeadsUpManager.getTopEntry()).thenReturn(mFirst.getEntry());
+ mHeadsUpAppearanceController.onHeadsUpPinned(mFirst);
+ Assert.assertEquals(View.INVISIBLE, mOperatorNameView.getVisibility());
+
+ mFirst.setPinned(false);
+ when(mHeadsUpManager.hasPinnedHeadsUp()).thenReturn(false);
+ mHeadsUpAppearanceController.onHeadsUpUnPinned(mFirst);
+ Assert.assertEquals(View.VISIBLE, mOperatorNameView.getVisibility());
+ }
+
+ @Test
public void testHeaderReadFromOldController() {
mHeadsUpAppearanceController.setExpandedHeight(1.0f, 1.0f);
@@ -125,6 +144,7 @@ public class HeadsUpAppearanceControllerTest extends SysuiTestCase {
mHeadsUpStatusBarView,
mStackScroller,
mPanelView,
+ new View(mContext),
new View(mContext));
newController.readFrom(mHeadsUpAppearanceController);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java
index a7954f2aa199..020682b6b4e8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java
@@ -170,13 +170,17 @@ public class KeyguardBouncerTest extends SysuiTestCase {
mBouncer.ensureView();
mBouncer.setExpansion(0.5f);
- mBouncer.setExpansion(1);
+ mBouncer.setExpansion(KeyguardBouncer.EXPANSION_HIDDEN);
verify(mFalsingManager).onBouncerHidden();
verify(mExpansionCallback).onFullyHidden();
- mBouncer.setExpansion(0);
+ mBouncer.setExpansion(KeyguardBouncer.EXPANSION_VISIBLE);
verify(mFalsingManager).onBouncerShown();
verify(mExpansionCallback).onFullyShown();
+
+ verify(mExpansionCallback, never()).onStartingToHide();
+ mBouncer.setExpansion(0.9f);
+ verify(mExpansionCallback).onStartingToHide();
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java
index f7a7e0430977..de26c709922d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java
@@ -74,14 +74,14 @@ public class StatusBarWindowControllerTest extends SysuiTestCase {
ArgumentCaptor.forClass(WindowManager.LayoutParams.class);
verify(mWindowManager).updateViewLayout(any(), captor.capture());
int flag = captor.getValue().privateFlags
- & WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+ & WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
assertThat(flag).isNotEqualTo(0);
reset(mWindowManager);
mStatusBarWindowController.setDozing(false);
verify(mWindowManager).updateViewLayout(any(), captor.capture());
flag = captor.getValue().privateFlags
- & WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+ & WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
assertThat(flag).isEqualTo(0);
}
diff --git a/proto/src/metrics_constants/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto
index 5e87707c39e6..d86de5dfd799 100644
--- a/proto/src/metrics_constants/metrics_constants.proto
+++ b/proto/src/metrics_constants/metrics_constants.proto
@@ -6549,6 +6549,21 @@ message MetricsEvent {
// Subtype: The importance of a notification has been changed
ADJUSTMENT_KEY_IMPORTANCE = 1580;
+ // OPEN: Settings > Network & internet > Mobile network > Choose network
+ // CATEGORY: SETTINGS
+ // OS: Q
+ MOBILE_NETWORK_SELECT = 1581;
+
+ // OPEN: Settings > Network & internet > Mobile network > Mobile Data > Dialog
+ // CATEGORY: SETTINGS
+ // OS: Q
+ MOBILE_DATA_DIALOG = 1582;
+
+ // OPEN: Settings > Network & internet > Mobile network > Data roaming > Dialog
+ // CATEGORY: SETTINGS
+ // OS: Q
+ MOBILE_ROAMING_DIALOG = 1583;
+
// ---- End Q Constants, all Q constants go above this line ----
// Add new aosp constants above this line.
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 6918275dd8c0..fbceade2341f 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -2630,7 +2630,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
final List<Integer> outsideWindowsIds;
final List<RemoteAccessibilityConnection> connectionList = new ArrayList<>();
synchronized (mLock) {
- outsideWindowsIds = mSecurityPolicy.getWatchOutsideTouchWindowId(targetWindowId);
+ outsideWindowsIds = mSecurityPolicy.getWatchOutsideTouchWindowIdLocked(targetWindowId);
for (int i = 0; i < outsideWindowsIds.size(); i++) {
connectionList.add(getConnectionLocked(outsideWindowsIds.get(i)));
}
@@ -3684,13 +3684,13 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
return mWindowInfoById.get(windowId);
}
- private List<Integer> getWatchOutsideTouchWindowId(int targetWindowId) {
- if (mWindowInfoById != null && mHasWatchOutsideTouchWindow) {
+ private List<Integer> getWatchOutsideTouchWindowIdLocked(int targetWindowId) {
+ final WindowInfo targetWindow = mWindowInfoById.get(targetWindowId);
+ if (targetWindow != null && mWindowInfoById != null && mHasWatchOutsideTouchWindow) {
final List<Integer> outsideWindowsId = new ArrayList<>();
- final WindowInfo targetWindow = mWindowInfoById.get(targetWindowId);
for (int i = 0; i < mWindowInfoById.size(); i++) {
WindowInfo window = mWindowInfoById.valueAt(i);
- if (window.layer < targetWindow.layer
+ if (window != null && window.layer < targetWindow.layer
&& window.hasFlagWatchOutsideTouch) {
outsideWindowsId.add(mWindowInfoById.keyAt(i));
}
diff --git a/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
index 6904b3fc6b9c..3a5232a6b97a 100644
--- a/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
+++ b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
@@ -708,8 +708,6 @@ public class KeyValueBackupTask implements BackupRestoreTask, Runnable {
} else {
throw TaskException.create();
}
- } finally {
- mBlankStateFile.delete();
}
checkAgentResult(packageInfo, agentResult);
}
@@ -1037,8 +1035,13 @@ public class KeyValueBackupTask implements BackupRestoreTask, Runnable {
private void cleanUpAgent(@StateTransaction int stateTransaction) {
applyStateTransaction(stateTransaction);
- mBackupDataFile.delete();
+ if (mBackupDataFile != null) {
+ mBackupDataFile.delete();
+ }
mBlankStateFile.delete();
+ mSavedStateFile = null;
+ mBackupDataFile = null;
+ mNewStateFile = null;
tryCloseFileDescriptor(mSavedState, "old state");
tryCloseFileDescriptor(mBackupData, "backup data");
tryCloseFileDescriptor(mNewState, "new state");
@@ -1059,7 +1062,9 @@ public class KeyValueBackupTask implements BackupRestoreTask, Runnable {
mNewStateFile.renameTo(mSavedStateFile);
break;
case StateTransaction.DISCARD_NEW:
- mNewStateFile.delete();
+ if (mNewStateFile != null) {
+ mNewStateFile.delete();
+ }
break;
case StateTransaction.DISCARD_ALL:
mSavedStateFile.delete();
diff --git a/services/core/Android.bp b/services/core/Android.bp
index d9519e015f67..2fa2941efe7f 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -4,6 +4,7 @@ java_library_static {
aidl: {
include_dirs: [
"frameworks/native/aidl/binder",
+ "frameworks/native/cmds/dumpstate/binder",
"system/core/storaged/binder",
"system/netd/server/binder",
"system/vold/binder",
@@ -11,6 +12,7 @@ java_library_static {
},
srcs: [
"java/**/*.java",
+ ":dumpstate_aidl",
":netd_aidl",
":netd_metrics_aidl",
":installd_aidl",
@@ -44,6 +46,7 @@ java_library_static {
"android.hardware.configstore-V1.0-java",
"android.hardware.contexthub-V1.0-java",
"android.hidl.manager-V1.0-java",
+ "netd_aidl_interface-java",
],
}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 5e8ffb79c493..bc6254a76327 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -1679,6 +1679,16 @@ public class ConnectivityService extends IConnectivityManager.Stub
"ConnectivityService");
}
+ private void enforceAnyPermissionOf(String... permissions) {
+ for (String permission : permissions) {
+ if (mContext.checkCallingOrSelfPermission(permission) == PERMISSION_GRANTED) {
+ return;
+ }
+ }
+ throw new SecurityException(
+ "Requires one of the following permissions: " + String.join(", ", permissions) + ".");
+ }
+
private void enforceInternetPermission() {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.INTERNET,
@@ -1723,6 +1733,13 @@ public class ConnectivityService extends IConnectivityManager.Stub
"ConnectivityService");
}
+ private void enforceNetworkStackSettingsOrSetup() {
+ enforceAnyPermissionOf(
+ android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD,
+ android.Manifest.permission.NETWORK_STACK);
+ }
+
private boolean checkNetworkStackPermission() {
return PERMISSION_GRANTED == mContext.checkCallingOrSelfPermission(
android.Manifest.permission.NETWORK_STACK);
@@ -1798,7 +1815,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
private void sendStickyBroadcast(Intent intent) {
synchronized (this) {
- if (!mSystemReady) {
+ if (!mSystemReady
+ && intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
mInitialBroadcast = new Intent(intent);
}
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
@@ -1847,8 +1865,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
mInitialBroadcast = null;
}
}
- // load the global proxy at startup
- mHandler.sendMessage(mHandler.obtainMessage(EVENT_APPLY_GLOBAL_HTTP_PROXY));
// Try bringing up tracker, but KeyStore won't be ready yet for secondary users so wait
// for user to unlock device too.
@@ -3089,7 +3105,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
break;
}
case EVENT_APPLY_GLOBAL_HTTP_PROXY: {
- handleDeprecatedGlobalHttpProxy();
+ mProxyTracker.loadDeprecatedGlobalHttpProxy();
break;
}
case EVENT_PROXY_HAS_CHANGED: {
@@ -3483,29 +3499,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
}
- private void handleDeprecatedGlobalHttpProxy() {
- final String proxy = Settings.Global.getString(mContext.getContentResolver(),
- Settings.Global.HTTP_PROXY);
- if (!TextUtils.isEmpty(proxy)) {
- String data[] = proxy.split(":");
- if (data.length == 0) {
- return;
- }
-
- final String proxyHost = data[0];
- int proxyPort = 8080;
- if (data.length > 1) {
- try {
- proxyPort = Integer.parseInt(data[1]);
- } catch (NumberFormatException e) {
- return;
- }
- }
- final ProxyInfo p = new ProxyInfo(proxyHost, proxyPort, "");
- setGlobalProxy(p);
- }
- }
-
private static class SettingsObserver extends ContentObserver {
final private HashMap<Uri, Integer> mUriEventMap;
final private Context mContext;
@@ -4008,7 +4001,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
@Override
public void setAirplaneMode(boolean enable) {
- enforceConnectivityInternalPermission();
+ enforceNetworkStackSettingsOrSetup();
final long ident = Binder.clearCallingIdentity();
try {
final ContentResolver cr = mContext.getContentResolver();
@@ -5537,15 +5530,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (networkAgent.isVPN()) {
// Temporarily disable the default proxy (not global).
- synchronized (mProxyTracker.mProxyLock) {
- if (!mProxyTracker.mDefaultProxyDisabled) {
- mProxyTracker.mDefaultProxyDisabled = true;
- if (mProxyTracker.mGlobalProxy == null
- && mProxyTracker.mDefaultProxy != null) {
- mProxyTracker.sendProxyBroadcast(null);
- }
- }
- }
+ mProxyTracker.setDefaultProxyEnabled(false);
// TODO: support proxy per network.
}
@@ -5567,15 +5552,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
} else if (state == NetworkInfo.State.DISCONNECTED) {
networkAgent.asyncChannel.disconnect();
if (networkAgent.isVPN()) {
- synchronized (mProxyTracker.mProxyLock) {
- if (mProxyTracker.mDefaultProxyDisabled) {
- mProxyTracker.mDefaultProxyDisabled = false;
- if (mProxyTracker.mGlobalProxy == null
- && mProxyTracker.mDefaultProxy != null) {
- mProxyTracker.sendProxyBroadcast(mProxyTracker.mDefaultProxy);
- }
- }
- }
+ mProxyTracker.setDefaultProxyEnabled(true);
updateUids(networkAgent, networkAgent.networkCapabilities, null);
}
disconnectAndDestroyNetwork(networkAgent);
diff --git a/services/core/java/com/android/server/LooperStatsService.java b/services/core/java/com/android/server/LooperStatsService.java
index 96ce6a4ee6a4..6677541b1b32 100644
--- a/services/core/java/com/android/server/LooperStatsService.java
+++ b/services/core/java/com/android/server/LooperStatsService.java
@@ -109,14 +109,28 @@ public class LooperStatsService extends Binder {
"max_latency_micros",
"total_cpu_micros",
"max_cpu_micros",
+ "recorded_delay_message_count",
+ "total_delay_millis",
+ "max_delay_millis",
"exception_count"));
pw.println(header);
for (LooperStats.ExportedEntry entry : entries) {
- pw.printf("%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n", entry.workSourceUid,
- entry.threadName, entry.handlerClassName, entry.messageName,
- entry.isInteractive, entry.messageCount, entry.recordedMessageCount,
- entry.totalLatencyMicros, entry.maxLatencyMicros, entry.cpuUsageMicros,
- entry.maxCpuUsageMicros, entry.exceptionCount);
+ pw.printf("%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n",
+ entry.workSourceUid,
+ entry.threadName,
+ entry.handlerClassName,
+ entry.messageName,
+ entry.isInteractive,
+ entry.messageCount,
+ entry.recordedMessageCount,
+ entry.totalLatencyMicros,
+ entry.maxLatencyMicros,
+ entry.cpuUsageMicros,
+ entry.maxCpuUsageMicros,
+ entry.recordedDelayMessageCount,
+ entry.delayMillis,
+ entry.maxDelayMillis,
+ entry.exceptionCount);
}
}
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index de930f794e50..cf39e95fd735 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -57,6 +57,7 @@ import android.content.ContentResolver;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.INetd;
+import android.net.TetherStatsParcel;
import android.net.INetworkManagementEventObserver;
import android.net.ITetheringStatsProvider;
import android.net.InterfaceConfiguration;
@@ -1844,31 +1845,30 @@ public class NetworkManagementService extends INetworkManagementService.Stub
return new NetworkStats(SystemClock.elapsedRealtime(), 0);
}
- final PersistableBundle bundle;
+ final TetherStatsParcel[] tetherStatsVec;
try {
- bundle = mNetdService.tetherGetStats();
+ tetherStatsVec = mNetdService.tetherGetStats();
} catch (RemoteException | ServiceSpecificException e) {
throw new IllegalStateException("problem parsing tethering stats: ", e);
}
final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(),
- bundle.size());
+ tetherStatsVec.length);
final NetworkStats.Entry entry = new NetworkStats.Entry();
- for (String iface : bundle.keySet()) {
- long[] statsArray = bundle.getLongArray(iface);
+ for (TetherStatsParcel tetherStats : tetherStatsVec) {
try {
- entry.iface = iface;
+ entry.iface = tetherStats.iface;
entry.uid = UID_TETHERING;
entry.set = SET_DEFAULT;
entry.tag = TAG_NONE;
- entry.rxBytes = statsArray[INetd.TETHER_STATS_RX_BYTES];
- entry.rxPackets = statsArray[INetd.TETHER_STATS_RX_PACKETS];
- entry.txBytes = statsArray[INetd.TETHER_STATS_TX_BYTES];
- entry.txPackets = statsArray[INetd.TETHER_STATS_TX_PACKETS];
+ entry.rxBytes = tetherStats.rxBytes;
+ entry.rxPackets = tetherStats.rxPackets;
+ entry.txBytes = tetherStats.txBytes;
+ entry.txPackets = tetherStats.txPackets;
stats.combineValues(entry);
} catch (ArrayIndexOutOfBoundsException e) {
- throw new IllegalStateException("invalid tethering stats for " + iface, e);
+ throw new IllegalStateException("invalid tethering stats " + e);
}
}
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index fb8894b48411..591ec0070ea5 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -49,6 +49,7 @@ import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.VoLteServiceState;
import android.util.LocalLog;
+import android.util.StatsLog;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IBatteryStats;
@@ -1719,8 +1720,12 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
try {
if (state == TelephonyManager.CALL_STATE_IDLE) {
mBatteryStats.notePhoneOff();
+ StatsLog.write(StatsLog.PHONE_STATE_CHANGED,
+ StatsLog.PHONE_STATE_CHANGED__STATE__OFF);
} else {
mBatteryStats.notePhoneOn();
+ StatsLog.write(StatsLog.PHONE_STATE_CHANGED,
+ StatsLog.PHONE_STATE_CHANGED__STATE__ON);
}
} catch (RemoteException e) {
/* The remote entity disappeared, we can safely ignore the exception. */
diff --git a/services/core/java/com/android/server/am/ActivityDisplay.java b/services/core/java/com/android/server/am/ActivityDisplay.java
index a648b09abda5..95a8e2a0aade 100644
--- a/services/core/java/com/android/server/am/ActivityDisplay.java
+++ b/services/core/java/com/android/server/am/ActivityDisplay.java
@@ -1087,7 +1087,7 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack>
if (top == null) {
return false;
}
- mSupervisor.moveFocusableActivityToTop(top, reason);
+ top.moveFocusableActivityToTop(reason);
return true;
}
diff --git a/services/core/java/com/android/server/am/ActivityLaunchParamsModifier.java b/services/core/java/com/android/server/am/ActivityLaunchParamsModifier.java
deleted file mode 100644
index f44ee7a234ca..000000000000
--- a/services/core/java/com/android/server/am/ActivityLaunchParamsModifier.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * 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.am;
-
-import android.app.ActivityOptions;
-import android.content.pm.ActivityInfo;
-import android.graphics.Rect;
-
-import com.android.server.am.LaunchParamsController.LaunchParams;
-import com.android.server.am.LaunchParamsController.LaunchParamsModifier;
-
-/**
- * An implementation of {@link LaunchParamsModifier}, which applies the launch bounds specified
- * inside {@link ActivityOptions#getLaunchBounds()}.
- */
-public class ActivityLaunchParamsModifier implements LaunchParamsModifier {
- private final ActivityStackSupervisor mSupervisor;
-
- ActivityLaunchParamsModifier(ActivityStackSupervisor activityStackSupervisor) {
- mSupervisor = activityStackSupervisor;
- }
-
- @Override
- public int onCalculate(TaskRecord task, ActivityInfo.WindowLayout layout,
- ActivityRecord activity, ActivityRecord source, ActivityOptions options,
- LaunchParams currentParams, LaunchParams outParams) {
- // We only care about figuring out bounds for activities.
- if (activity == null) {
- return RESULT_SKIP;
- }
-
- // Activity must be resizeable in the specified task.
- if (!(mSupervisor.canUseActivityOptionsLaunchBounds(options)
- && (activity.isResizeable() || (task != null && task.isResizeable())))) {
- return RESULT_SKIP;
- }
-
- final Rect bounds = options.getLaunchBounds();
-
- // Bounds weren't valid.
- if (bounds == null || bounds.isEmpty()) {
- return RESULT_SKIP;
- }
-
- outParams.mBounds.set(bounds);
-
- // When this is the most explicit position specification so we should not allow further
- // modification of the position.
- return RESULT_DONE;
- }
-}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 37167c688d87..acf7a73332b7 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -10184,6 +10184,7 @@ public class ActivityManagerService extends IActivityManager.Stub
synchronized (this) {
sb.append("Process: ").append(processName).append("\n");
sb.append("PID: ").append(process.pid).append("\n");
+ sb.append("UID: ").append(process.uid).append("\n");
int flags = process.info.flags;
IPackageManager pm = AppGlobals.getPackageManager();
sb.append("Flags: 0x").append(Integer.toHexString(flags)).append("\n");
diff --git a/services/core/java/com/android/server/am/ActivityMetricsLogger.java b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
index 18cdb054e648..7080e2bd58fd 100644
--- a/services/core/java/com/android/server/am/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
@@ -110,7 +110,7 @@ import com.android.server.LocalServices;
* data for Tron, logcat, event logs and {@link android.app.WaitResult}.
*
* Tests:
- * atest SystemMetricsFunctionalTests
+ * atest CtsActivityManagerDeviceTestCases:ActivityMetricsLoggerTests
*/
class ActivityMetricsLogger {
@@ -351,18 +351,24 @@ class ActivityMetricsLogger {
+ " processRunning=" + processRunning
+ " processSwitch=" + processSwitch);
- // If we are already in an existing transition, only update the activity name, but not the
- // other attributes.
final int windowingMode = launchedActivity != null
? launchedActivity.getWindowingMode()
: WINDOWING_MODE_UNDEFINED;
-
+ final WindowingModeTransitionInfo info = mWindowingModeTransitionInfo.get(windowingMode);
if (mCurrentTransitionStartTime == INVALID_START_TIME) {
+ // No transition is active ignore this launch.
+ return;
+ }
+
+ if (launchedActivity != null && launchedActivity.nowVisible) {
+ // Launched activity is already visible. We cannot measure windows drawn delay.
+ reset(true /* abort */, info);
return;
}
- final WindowingModeTransitionInfo info = mWindowingModeTransitionInfo.get(windowingMode);
if (launchedActivity != null && info != null) {
+ // If we are already in an existing transition, only update the activity name, but not
+ // the other attributes.
info.launchedActivity = launchedActivity;
return;
}
@@ -371,7 +377,6 @@ class ActivityMetricsLogger {
mWindowingModeTransitionInfo.size() > 0 && info == null;
if ((!isLoggableResultCode(resultCode) || launchedActivity == null || !processSwitch
|| windowingMode == WINDOWING_MODE_UNDEFINED) && !otherWindowModesLaunching) {
-
// Failed to launch or it was not a process switch, so we don't care about the timing.
reset(true /* abort */, info);
return;
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index fe10baf33354..6bdceb22d866 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -84,11 +84,13 @@ import static android.os.Process.SYSTEM_UID;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_LEFT;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOCUS;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SAVED_STATE;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STATES;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SWITCH;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_VISIBILITY;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONFIGURATION;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_FOCUS;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SAVED_STATE;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_STATES;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SWITCH;
@@ -215,6 +217,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
private static final String TAG_STATES = TAG + POSTFIX_STATES;
private static final String TAG_SWITCH = TAG + POSTFIX_SWITCH;
private static final String TAG_VISIBILITY = TAG + POSTFIX_VISIBILITY;
+ private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
// TODO(b/67864419): Remove once recents component is overridden
private static final String LEGACY_RECENTS_PACKAGE_NAME = "com.android.systemui.recents";
@@ -1348,6 +1351,42 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
return (info.flags & FLAG_ALWAYS_FOCUSABLE) != 0;
}
+ /** Move activity with its stack to front and make the stack focused. */
+ boolean moveFocusableActivityToTop(String reason) {
+ if (!isFocusable()) {
+ if (DEBUG_FOCUS) {
+ Slog.d(TAG_FOCUS, "moveActivityStackToFront: unfocusable activity=" + this);
+ }
+ return false;
+ }
+
+ final TaskRecord task = getTask();
+ final ActivityStack stack = getStack();
+ if (stack == null) {
+ Slog.w(TAG, "moveActivityStackToFront: invalid task or stack: activity="
+ + this + " task=" + task);
+ return false;
+ }
+
+ if (mStackSupervisor.getTopResumedActivity() == this) {
+ if (DEBUG_FOCUS) {
+ Slog.d(TAG_FOCUS, "moveActivityStackToFront: already on top, activity=" + this);
+ }
+ return false;
+ }
+
+ if (DEBUG_FOCUS) {
+ Slog.d(TAG_FOCUS, "moveActivityStackToFront: activity=" + this);
+ }
+
+ stack.moveToFront(reason, task);
+ // Report top activity change to tracking services and WM
+ if (mStackSupervisor.getTopResumedActivity() == this) {
+ // TODO(b/111361570): Support multiple focused apps in WM
+ service.setResumedActivityUncheckLocked(this, reason);
+ }
+ return true;
+ }
/**
* @return true if the activity contains windows that have
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 6388423d04b4..864bf2d77b59 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -227,7 +227,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
}
@Override
- protected ConfigurationContainer getChildAt(int index) {
+ protected TaskRecord getChildAt(int index) {
return mTaskHistory.get(index);
}
@@ -3450,8 +3450,10 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
final String myReason = reason + " adjustFocus";
if (next == r) {
- mStackSupervisor.moveFocusableActivityToTop(mStackSupervisor.topRunningActivityLocked(),
- myReason);
+ final ActivityRecord top = mStackSupervisor.topRunningActivityLocked();
+ if (top != null) {
+ top.moveFocusableActivityToTop(myReason);
+ }
return;
}
@@ -4662,7 +4664,9 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
// Set focus to the top running activity of this stack.
final ActivityRecord r = topRunningActivityLocked();
- mStackSupervisor.moveFocusableActivityToTop(r, reason);
+ if (r != null) {
+ r.moveFocusableActivityToTop(reason);
+ }
if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare to front transition: task=" + tr);
if (noAnimation) {
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 0477d73301f1..8c8146c54d9f 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -53,8 +53,8 @@ import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.Display.TYPE_VIRTUAL;
import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
+
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL;
-import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOCUS;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_IDLE;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PAUSE;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RECENTS;
@@ -63,7 +63,6 @@ import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STATES;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SWITCH;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS;
-import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_FOCUS;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_IDLE;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_PAUSE;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RECENTS;
@@ -99,6 +98,7 @@ import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_WHITELISTED;
import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
import static com.android.server.am.TaskRecord.REPARENT_LEAVE_STACK_IN_PLACE;
import static com.android.server.am.TaskRecord.REPARENT_MOVE_STACK_TO_FRONT;
+
import static java.lang.Integer.MAX_VALUE;
import android.Manifest;
@@ -199,7 +199,6 @@ import java.util.Set;
public class ActivityStackSupervisor extends ConfigurationContainer implements DisplayListener,
RecentTasks.Callbacks, RootWindowContainerListener {
private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStackSupervisor" : TAG_AM;
- private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
private static final String TAG_IDLE = TAG + POSTFIX_IDLE;
private static final String TAG_PAUSE = TAG + POSTFIX_PAUSE;
private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS;
@@ -783,7 +782,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
// Only resume home activity if isn't finishing.
if (r != null && !r.finishing) {
- moveFocusableActivityToTop(r, myReason);
+ r.moveFocusableActivityToTop(myReason);
return resumeFocusedStacksTopActivitiesLocked(r.getStack(), prev, null);
}
return mService.startHomeActivityLocked(mCurrentUser, myReason, displayId);
@@ -3359,41 +3358,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
mService.getTaskChangeNotificationController().notifyActivityPinned(r);
}
- /** Move activity with its stack to front and make the stack focused. */
- // TODO(b/111363427): Move this method to ActivityRecord.
- boolean moveFocusableActivityToTop(ActivityRecord r, String reason) {
- if (r == null || !r.isFocusable()) {
- if (DEBUG_FOCUS) Slog.d(TAG_FOCUS,
- "moveActivityStackToFront: unfocusable r=" + r);
- return false;
- }
-
- final TaskRecord task = r.getTask();
- final ActivityStack stack = r.getStack();
- if (stack == null) {
- Slog.w(TAG, "moveActivityStackToFront: invalid task or stack: r="
- + r + " task=" + task);
- return false;
- }
-
- if (r == getTopResumedActivity()) {
- if (DEBUG_FOCUS) Slog.d(TAG_FOCUS,
- "moveActivityStackToFront: already on top, r=" + r);
- return false;
- }
-
- if (DEBUG_FOCUS) Slog.d(TAG_FOCUS,
- "moveActivityStackToFront: r=" + r);
-
- stack.moveToFront(reason, task);
- // Report top activity change to tracking services and WM
- if (r == getTopResumedActivity()) {
- // TODO(b/111361570): Support multiple focused apps in WM
- mService.setResumedActivityUncheckLocked(r, reason);
- }
- return true;
- }
-
ActivityRecord findTaskLocked(ActivityRecord r, int preferredDisplayId) {
if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Looking for task of " + r);
mTmpFindTaskResult.clear();
@@ -4456,10 +4420,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
if (!task.canBeLaunchedOnDisplay(actualDisplayId)) {
throw new IllegalStateException("Task resolved to incompatible display");
}
- // The task might have landed on a display different from requested.
- // TODO(multi-display): Find proper stack for the task on the default display.
- mService.setTaskWindowingMode(task.taskId,
- WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY, true /* toTop */);
if (preferredDisplayId != actualDisplayId) {
Slog.w(TAG, "Failed to put " + task + " on display " + preferredDisplayId);
// Display a warning toast that we failed to put a task on a secondary display.
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 2bd22e8601d6..33f949fccfb0 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -1477,7 +1477,7 @@ class ActivityStarter {
if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
&& (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
newTask = true;
- result = setTaskFromReuseOrCreateNewTask(taskToAffiliate, topStack);
+ result = setTaskFromReuseOrCreateNewTask(taskToAffiliate);
} else if (mSourceRecord != null) {
result = setTaskFromSourceRecord();
} else if (mInTask != null) {
@@ -1606,13 +1606,18 @@ class ActivityStarter {
mVoiceSession = voiceSession;
mVoiceInteractor = voiceInteractor;
- mPreferredDisplayId = getPreferedDisplayId(mSourceRecord, mStartActivity, options);
-
mLaunchParams.reset();
mSupervisor.getLaunchParamsController().calculate(inTask, null /*layout*/, r, sourceRecord,
options, mLaunchParams);
+ if (mLaunchParams.hasPreferredDisplay()) {
+ mPreferredDisplayId = mLaunchParams.mPreferredDisplayId;
+ } else {
+ mPreferredDisplayId = DEFAULT_DISPLAY;
+ }
+ ensureValidPreferredDisplayId(r);
+
mLaunchMode = r.launchMode;
mLaunchFlags = adjustLaunchFlagsToDocumentMode(
@@ -1704,6 +1709,24 @@ class ActivityStarter {
mNoAnimation = (mLaunchFlags & FLAG_ACTIVITY_NO_ANIMATION) != 0;
}
+ /**
+ * Ensure preferred display ID matches the starting activity.
+ */
+ private void ensureValidPreferredDisplayId(ActivityRecord startingActivity) {
+ // Check if the Activity is a VR activity. If so, the activity should be launched in
+ // main display.
+ if (startingActivity != null && startingActivity.requestedVrComponent != null) {
+ mPreferredDisplayId = DEFAULT_DISPLAY;
+ }
+
+ // Get the virtual display ID from ActivityStackManagerService. If that's set we should
+ // always use that.
+ final int displayId = mService.mVr2dDisplayId;
+ if (displayId != INVALID_DISPLAY) {
+ mPreferredDisplayId = displayId;
+ }
+ }
+
private void sendNewTaskResultRequestIfNeeded() {
final ActivityStack sourceStack = mStartActivity.resultTo != null
? mStartActivity.resultTo.getStack() : null;
@@ -1883,44 +1906,6 @@ class ActivityStarter {
}
/**
- * Returns the ID of the display to use for a new activity. If the device is in VR mode,
- * then return the Vr mode's virtual display ID. If not, if the activity was started with
- * a launchDisplayId, use that. Otherwise, if the source activity has a explicit display ID
- * set, use that to launch the activity.
- */
- private int getPreferedDisplayId(
- ActivityRecord sourceRecord, ActivityRecord startingActivity, ActivityOptions options) {
- // Check if the Activity is a VR activity. If so, the activity should be launched in
- // main display.
- if (startingActivity != null && startingActivity.requestedVrComponent != null) {
- return DEFAULT_DISPLAY;
- }
-
- // Get the virtual display id from ActivityManagerService.
- int displayId = mService.mVr2dDisplayId;
- if (displayId != INVALID_DISPLAY) {
- if (DEBUG_STACK) {
- Slog.d(TAG, "getSourceDisplayId :" + displayId);
- }
- return displayId;
- }
-
- // If the caller requested a display, prefer that display.
- final int launchDisplayId =
- (options != null) ? options.getLaunchDisplayId() : INVALID_DISPLAY;
- if (launchDisplayId != INVALID_DISPLAY) {
- return launchDisplayId;
- }
-
- displayId = sourceRecord != null ? sourceRecord.getDisplayId() : INVALID_DISPLAY;
- // If the activity has a displayId set explicitly, launch it on the same displayId.
- if (displayId != INVALID_DISPLAY) {
- return displayId;
- }
- return DEFAULT_DISPLAY;
- }
-
- /**
* Figure out which task and activity to bring to front when we have found an existing matching
* activity record in history. May also clear the task if needed.
* @param intentActivity Existing matching activity.
@@ -2125,8 +2110,7 @@ class ActivityStarter {
mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
}
- private int setTaskFromReuseOrCreateNewTask(
- TaskRecord taskToAffiliate, ActivityStack topStack) {
+ private int setTaskFromReuseOrCreateNewTask(TaskRecord taskToAffiliate) {
mTargetStack = computeStackFocus(mStartActivity, true, mLaunchFlags, mOptions);
// Do no move the target stack to front yet, as we might bail if
@@ -2431,17 +2415,6 @@ class ActivityStarter {
}
}
if (stack == null) {
- // We first try to put the task in the first dynamic stack on home display.
- final ActivityDisplay display = mSupervisor.getDefaultDisplay();
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- stack = display.getChildAt(stackNdx);
- if (!stack.isOnHomeDisplay()) {
- if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
- "computeStackFocus: Setting focused stack=" + stack);
- return stack;
- }
- }
- // If there is no suitable dynamic stack then we figure out which static stack to use.
stack = mSupervisor.getLaunchStack(r, aOptions, task, ON_TOP);
}
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
diff --git a/services/core/java/com/android/server/am/ActivityTaskManagerService.java b/services/core/java/com/android/server/am/ActivityTaskManagerService.java
index 8e3eeae5d569..b369b7135b4e 100644
--- a/services/core/java/com/android/server/am/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityTaskManagerService.java
@@ -141,7 +141,6 @@ import android.app.WindowConfiguration;
import android.app.admin.DevicePolicyCache;
import android.app.assist.AssistContent;
import android.app.assist.AssistStructure;
-import android.app.servertransaction.ConfigurationChangeItem;
import android.app.usage.UsageEvents;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
@@ -1707,7 +1706,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
return;
}
final ActivityRecord r = stack.topRunningActivityLocked();
- if (mStackSupervisor.moveFocusableActivityToTop(r, "setFocusedStack")) {
+ if (r != null && r.moveFocusableActivityToTop("setFocusedStack")) {
mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
}
}
@@ -1728,7 +1727,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
return;
}
final ActivityRecord r = task.topRunningActivityLocked();
- if (mStackSupervisor.moveFocusableActivityToTop(r, "setFocusedTask")) {
+ if (r != null && r.moveFocusableActivityToTop("setFocusedTask")) {
mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
}
}
@@ -4525,19 +4524,13 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
mAm.mHandler.sendMessage(msg);
}
- // TODO: Consider using mPidMap to update configurations for processes.
- for (int i = mAm.mLruProcesses.size() - 1; i >= 0; i--) {
- ProcessRecord app = mAm.mLruProcesses.get(i);
- try {
- if (app.thread != null) {
- if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, "Sending to proc "
- + app.processName + " new config " + configCopy);
- getLifecycleManager().scheduleTransaction(app.thread,
- ConfigurationChangeItem.obtain(configCopy));
- }
- } catch (Exception e) {
- Slog.e(TAG_CONFIGURATION, "Failed to schedule configuration change", e);
+ for (int i = mPidMap.size() - 1; i >= 0; i--) {
+ WindowProcessController app = mPidMap.get(mPidMap.keyAt(i));
+ if (DEBUG_CONFIGURATION) {
+ Slog.v(TAG_CONFIGURATION, "Update process config of "
+ + app.mName + " to new config " + configCopy);
}
+ app.onConfigurationChanged(configCopy);
}
Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
@@ -5554,7 +5547,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
throw new IllegalArgumentException(
"setFocusedActivity: No activity record matching token=" + token);
}
- if (mStackSupervisor.moveFocusableActivityToTop(r, "setFocusedActivity")) {
+ if (r.moveFocusableActivityToTop("setFocusedActivity")) {
mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
}
}
diff --git a/services/core/java/com/android/server/am/LaunchParamsController.java b/services/core/java/com/android/server/am/LaunchParamsController.java
index 6415c3ee7f72..218d9080c2c0 100644
--- a/services/core/java/com/android/server/am/LaunchParamsController.java
+++ b/services/core/java/com/android/server/am/LaunchParamsController.java
@@ -16,6 +16,13 @@
package com.android.server.am;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.view.Display.INVALID_DISPLAY;
+
+import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_CONTINUE;
+import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_DONE;
+import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_SKIP;
+
import android.annotation.IntDef;
import android.app.ActivityOptions;
import android.content.pm.ActivityInfo.WindowLayout;
@@ -26,13 +33,6 @@ import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
-import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
-import static android.view.Display.INVALID_DISPLAY;
-
-import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_CONTINUE;
-import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_DONE;
-import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_SKIP;
-
/**
* {@link LaunchParamsController} calculates the {@link LaunchParams} by coordinating between
* registered {@link LaunchParamsModifier}s.
@@ -58,11 +58,7 @@ class LaunchParamsController {
*/
void registerDefaultModifiers(ActivityStackSupervisor supervisor) {
// {@link TaskLaunchParamsModifier} handles window layout preferences.
- registerModifier(new TaskLaunchParamsModifier());
-
- // {@link ActivityLaunchParamsModifier} is the most specific modifier and thus should be
- // registered last (applied first) out of the defaults.
- registerModifier(new ActivityLaunchParamsModifier(supervisor));
+ registerModifier(new TaskLaunchParamsModifier(supervisor));
}
/**
@@ -226,27 +222,41 @@ class LaunchParamsController {
@IntDef({RESULT_SKIP, RESULT_DONE, RESULT_CONTINUE})
@interface Result {}
- // Returned when the modifier does not want to influence the bounds calculation
+ /** Returned when the modifier does not want to influence the bounds calculation */
int RESULT_SKIP = 0;
- // Returned when the modifier has changed the bounds and would like its results to be the
- // final bounds applied.
+ /**
+ * Returned when the modifier has changed the bounds and would like its results to be the
+ * final bounds applied.
+ */
int RESULT_DONE = 1;
- // Returned when the modifier has changed the bounds but is okay with other modifiers
- // influencing the bounds.
+ /**
+ * Returned when the modifier has changed the bounds but is okay with other modifiers
+ * influencing the bounds.
+ */
int RESULT_CONTINUE = 2;
/**
- * Called when asked to calculate {@link LaunchParams}.
- * @param task The {@link TaskRecord} currently being positioned.
- * @param layout The specified {@link WindowLayout}.
- * @param activity The {@link ActivityRecord} currently being positioned.
- * @param source The {@link ActivityRecord} activity was started from.
- * @param options The {@link ActivityOptions} specified for the activity.
- * @param currentParams The current {@link LaunchParams}. This can differ from the initial
- * params as it represents the modified params up to this point.
- * @param outParams The resulting {@link LaunchParams} after all calculations.
- * @return A {@link Result} representing the result of the
- * {@link LaunchParams} calculation.
+ * Returns the launch params that the provided activity launch params should be overridden
+ * to. {@link LaunchParamsModifier} can use this for various purposes, including: 1)
+ * Providing default bounds if the launch bounds have not been provided. 2) Repositioning
+ * the task so it doesn't get placed over an existing task. 3) Resizing the task so that its
+ * dimensions match the activity's requested orientation.
+ *
+ * @param task Can be: 1) the target task in which the source activity wants to
+ * launch the target activity; 2) a newly created task that Android
+ * gives a chance to override its launching bounds; 3) {@code null} if
+ * this is called to override an activity's launching bounds.
+ * @param layout Desired layout when activity is first launched.
+ * @param activity Activity that is being started. This can be {@code null} on
+ * re-parenting an activity to a new task (e.g. for
+ * Picture-In-Picture). Tasks being created because an activity was
+ * launched should have this be non-null.
+ * @param source the Activity that launched a new task. Could be {@code null}.
+ * @param options {@link ActivityOptions} used to start the activity with.
+ * @param currentParams launching params after the process of last {@link
+ * LaunchParamsModifier}.
+ * @param outParams the result params to be set.
+ * @return see {@link LaunchParamsModifier.Result}
*/
@Result
int onCalculate(TaskRecord task, WindowLayout layout, ActivityRecord activity,
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 3ac7885eba37..9e7ce3204444 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -162,9 +162,11 @@ public final class ProcessList {
// LMK_TARGET <minfree> <minkillprio> ... (up to 6 pairs)
// LMK_PROCPRIO <pid> <uid> <prio>
// LMK_PROCREMOVE <pid>
+ // LMK_PROCPURGE
static final byte LMK_TARGET = 0;
static final byte LMK_PROCPRIO = 1;
static final byte LMK_PROCREMOVE = 2;
+ static final byte LMK_PROCPURGE = 3;
// These are the various interesting memory levels that we will give to
// the OOM killer. Note that the OOM killer only supports 6 slots, so we
@@ -813,31 +815,46 @@ public final class ProcessList {
return true;
}
+ // Never call directly, use writeLmkd() instead
+ private static boolean writeLmkdCommand(ByteBuffer buf) {
+ try {
+ sLmkdOutputStream.write(buf.array(), 0, buf.position());
+ } catch (IOException ex) {
+ Slog.w(TAG, "Error writing to lowmemorykiller socket");
+
+ try {
+ sLmkdSocket.close();
+ } catch (IOException ex2) {
+ }
+
+ sLmkdSocket = null;
+ return false;
+ }
+ return true;
+ }
+
private static void writeLmkd(ByteBuffer buf) {
for (int i = 0; i < 3; i++) {
if (sLmkdSocket == null) {
- if (openLmkdSocket() == false) {
- try {
- Thread.sleep(1000);
- } catch (InterruptedException ie) {
- }
- continue;
+ if (openLmkdSocket() == false) {
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException ie) {
}
- }
-
- try {
- sLmkdOutputStream.write(buf.array(), 0, buf.position());
- return;
- } catch (IOException ex) {
- Slog.w(TAG, "Error writing to lowmemorykiller socket");
-
- try {
- sLmkdSocket.close();
- } catch (IOException ex2) {
+ continue;
}
- sLmkdSocket = null;
+ // Purge any previously registered pids
+ ByteBuffer purge_buf = ByteBuffer.allocate(4);
+ purge_buf.putInt(LMK_PROCPURGE);
+ if (writeLmkdCommand(purge_buf) == false) {
+ // Write failed, skip the rest and retry
+ continue;
+ }
+ }
+ if (writeLmkdCommand(buf)) {
+ return;
}
}
}
diff --git a/services/core/java/com/android/server/am/TaskLaunchParamsModifier.java b/services/core/java/com/android/server/am/TaskLaunchParamsModifier.java
index 92f1cc34be92..fd34d180ebc0 100644
--- a/services/core/java/com/android/server/am/TaskLaunchParamsModifier.java
+++ b/services/core/java/com/android/server/am/TaskLaunchParamsModifier.java
@@ -16,304 +16,770 @@
package com.android.server.am;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LOCKED;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT;
+import static android.util.DisplayMetrics.DENSITY_DEFAULT;
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.Display.INVALID_DISPLAY;
+
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.ActivityOptions;
+import android.app.WindowConfiguration;
import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
import android.graphics.Rect;
+import android.os.Build;
import android.util.Slog;
import android.view.Gravity;
-import com.android.internal.annotations.VisibleForTesting;
+
import com.android.server.am.LaunchParamsController.LaunchParams;
import com.android.server.am.LaunchParamsController.LaunchParamsModifier;
import java.util.ArrayList;
+import java.util.List;
/**
- * Determines where a launching task should be positioned and sized on the display.
- *
- * The modifier is fairly simple. For the new task it tries default position based on the gravity
- * and compares corners of the task with corners of existing tasks. If some two pairs of corners are
- * sufficiently close enough, it shifts the bounds of the new task and tries again. When it exhausts
- * all possible shifts, it gives up and puts the task in the original position.
- *
- * Note that the only gravities of concern are the corners and the center.
+ * The class that defines the default launch params for tasks.
*/
class TaskLaunchParamsModifier implements LaunchParamsModifier {
private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskLaunchParamsModifier" : TAG_AM;
+ private static final boolean DEBUG = false;
- // Determines how close window frames/corners have to be to call them colliding.
- private static final int BOUNDS_CONFLICT_MIN_DISTANCE = 4;
+ // A mask for SUPPORTS_SCREEN that indicates the activity supports resize.
+ private static final int SUPPORTS_SCREEN_RESIZEABLE_MASK =
+ ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES
+ | ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS
+ | ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS
+ | ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS
+ | ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES
+ | ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS;
- // Task will receive dimensions based on available dimensions divided by this.
- private static final int WINDOW_SIZE_DENOMINATOR = 2;
+ // Screen size of Nexus 5x
+ private static final int DEFAULT_PORTRAIT_PHONE_WIDTH_DP = 412;
+ private static final int DEFAULT_PORTRAIT_PHONE_HEIGHT_DP = 732;
- // Task will receive margins based on available dimensions divided by this.
- private static final int MARGIN_SIZE_DENOMINATOR = 4;
+ // Allowance of size matching.
+ private static final int EPSILON = 2;
- // If task bounds collide with some other, we will step and try again until we find a good
- // position. The step will be determined by using dimensions and dividing it by this.
+ // Cascade window offset.
+ private static final int CASCADING_OFFSET_DP = 75;
+
+ // Threshold how close window corners have to be to call them colliding.
+ private static final int BOUNDS_CONFLICT_THRESHOLD = 4;
+
+ // Divide display size by this number to get each step to adjust bounds to avoid conflict.
private static final int STEP_DENOMINATOR = 16;
// We always want to step by at least this.
private static final int MINIMAL_STEP = 1;
- // Used to indicate if positioning algorithm is allowed to restart from the beginning, when it
- // reaches the end of stack bounds.
- private static final boolean ALLOW_RESTART = true;
+ private final ActivityStackSupervisor mSupervisor;
+ private final Rect mTmpBounds = new Rect();
+ private final int[] mTmpDirections = new int[2];
- private static final int SHIFT_POLICY_DIAGONAL_DOWN = 1;
- private static final int SHIFT_POLICY_HORIZONTAL_RIGHT = 2;
- private static final int SHIFT_POLICY_HORIZONTAL_LEFT = 3;
+ private StringBuilder mLogBuilder;
- private final Rect mAvailableRect = new Rect();
- private final Rect mTmpProposal = new Rect();
- private final Rect mTmpOriginal = new Rect();
+ TaskLaunchParamsModifier(ActivityStackSupervisor supervisor) {
+ mSupervisor = supervisor;
+ }
- /**
- * Tries to set task's bound in a way that it won't collide with any other task. By colliding
- * we mean that two tasks have left-top corner very close to each other, so one might get
- * obfuscated by the other one.
- */
@Override
public int onCalculate(TaskRecord task, ActivityInfo.WindowLayout layout,
ActivityRecord activity, ActivityRecord source, ActivityOptions options,
LaunchParams currentParams, LaunchParams outParams) {
- // We can only apply positioning if we're in a freeform stack.
- if (task == null || task.getStack() == null || !task.inFreeformWindowingMode()) {
- return RESULT_SKIP;
- }
+ initLogBuilder(task, activity);
+ final int result = calculate(task, layout, activity, source, options, currentParams,
+ outParams);
+ outputLog();
+ return result;
+ }
- final ArrayList<TaskRecord> tasks = task.getStack().getAllTasks();
+ private int calculate(TaskRecord task, ActivityInfo.WindowLayout layout,
+ ActivityRecord activity, ActivityRecord source, ActivityOptions options,
+ LaunchParams currentParams, LaunchParams outParams) {
+ // STEP 1: Determine the display to launch the activity/task.
+ final int displayId = getPreferredLaunchDisplay(options, source, currentParams);
+ outParams.mPreferredDisplayId = displayId;
+ ActivityDisplay display = mSupervisor.getActivityDisplay(displayId);
+ if (DEBUG) {
+ appendLog("display-id=" + outParams.mPreferredDisplayId + " display-windowing-mode="
+ + display.getWindowingMode());
+ }
- mAvailableRect.set(task.getParent().getBounds());
+ final ActivityRecord root;
+ if (task != null) {
+ root = (task.getRootActivity() == null ? activity : task.getRootActivity());
+ } else {
+ root = activity;
+ }
+ // STEP 2: Resolve launch windowing mode.
+ // STEP 2.1: Determine if any parameter has specified initial bounds. That might be the
+ // launch bounds from activity options, or size/gravity passed in layout. It also treat the
+ // launch windowing mode in options as a suggestion for future resolution.
+ int launchMode = options != null ? options.getLaunchWindowingMode()
+ : WINDOWING_MODE_UNDEFINED;
+ // hasInitialBounds is set if either activity options or layout has specified bounds. If
+ // that's set we'll skip some adjustments later to avoid overriding the initial bounds.
+ boolean hasInitialBounds = false;
+ final boolean canApplyFreeformPolicy =
+ canApplyFreeformWindowPolicy(display, root, launchMode);
+ if (mSupervisor.canUseActivityOptionsLaunchBounds(options) && canApplyFreeformPolicy) {
+ hasInitialBounds = true;
+ launchMode = launchMode == WINDOWING_MODE_UNDEFINED
+ ? WINDOWING_MODE_FREEFORM
+ : launchMode;
+ outParams.mBounds.set(options.getLaunchBounds());
+ if (DEBUG) appendLog("activity-options-bounds=" + outParams.mBounds);
+ } else if (launchMode == WINDOWING_MODE_PINNED) {
+ // System controls PIP window's bounds, so don't apply launch bounds.
+ if (DEBUG) appendLog("empty-window-layout-for-pip");
+ } else if (launchMode == WINDOWING_MODE_FULLSCREEN) {
+ if (DEBUG) appendLog("activity-options-fullscreen=" + outParams.mBounds);
+ } else if (layout != null && canApplyFreeformPolicy) {
+ getLayoutBounds(display, root, layout, mTmpBounds);
+ if (!mTmpBounds.isEmpty()) {
+ launchMode = WINDOWING_MODE_FREEFORM;
+ outParams.mBounds.set(mTmpBounds);
+ hasInitialBounds = true;
+ if (DEBUG) appendLog("bounds-from-layout=" + outParams.mBounds);
+ } else {
+ if (DEBUG) appendLog("empty-window-layout");
+ }
+ }
- final Rect resultBounds = outParams.mBounds;
+ // STEP 2.2: Check if previous modifier or the controller (referred as "callers" below) has
+ // some opinions on launch mode and launch bounds. If they have opinions and there is no
+ // initial bounds set in parameters. Note the check on display ID is also input param
+ // related because we always defer to callers' suggestion if there is no specific display ID
+ // in options or from source activity.
+ //
+ // If opinions from callers don't need any further resolution, we try to honor that as is as
+ // much as possible later.
+
+ // Flag to indicate if current param needs no further resolution. It's true it current
+ // param isn't freeform mode, or it already has launch bounds.
+ boolean fullyResolvedCurrentParam = false;
+ // We inherit launch params from previous modifiers or LaunchParamsController if options,
+ // layout and display conditions are not contradictory to their suggestions. It's important
+ // to carry over their values because LaunchParamsController doesn't automatically do that.
+ if (!currentParams.isEmpty() && !hasInitialBounds
+ && (!currentParams.hasPreferredDisplay()
+ || displayId == currentParams.mPreferredDisplayId)) {
+ if (currentParams.hasWindowingMode()) {
+ launchMode = currentParams.mWindowingMode;
+ fullyResolvedCurrentParam = (launchMode != WINDOWING_MODE_FREEFORM);
+ if (DEBUG) {
+ appendLog("inherit-" + WindowConfiguration.windowingModeToString(launchMode));
+ }
+ }
- if (layout == null) {
- positionCenter(tasks, mAvailableRect, getFreeformWidth(mAvailableRect),
- getFreeformHeight(mAvailableRect), resultBounds);
- return RESULT_CONTINUE;
+ if (!currentParams.mBounds.isEmpty()) {
+ outParams.mBounds.set(currentParams.mBounds);
+ fullyResolvedCurrentParam = true;
+ if (DEBUG) appendLog("inherit-bounds=" + outParams.mBounds);
+ }
}
- int width = getFinalWidth(layout, mAvailableRect);
- int height = getFinalHeight(layout, mAvailableRect);
- int verticalGravity = layout.gravity & Gravity.VERTICAL_GRAVITY_MASK;
- int horizontalGravity = layout.gravity & Gravity.HORIZONTAL_GRAVITY_MASK;
- if (verticalGravity == Gravity.TOP) {
- if (horizontalGravity == Gravity.RIGHT) {
- positionTopRight(tasks, mAvailableRect, width, height, resultBounds);
- } else {
- positionTopLeft(tasks, mAvailableRect, width, height, resultBounds);
- }
- } else if (verticalGravity == Gravity.BOTTOM) {
- if (horizontalGravity == Gravity.RIGHT) {
- positionBottomRight(tasks, mAvailableRect, width, height, resultBounds);
- } else {
- positionBottomLeft(tasks, mAvailableRect, width, height, resultBounds);
+ // STEP 2.3: Adjust launch parameters as needed for freeform display. We enforce the policy
+ // that legacy (pre-D) apps and those apps that can't handle multiple screen density well
+ // are forced to be maximized. The rest of this step is to define the default policy when
+ // there is no initial bounds or a fully resolved current params from callers. Right now we
+ // launch all possible tasks/activities that can handle freeform into freeform mode.
+ if (display.inFreeformWindowingMode()) {
+ if (launchMode == WINDOWING_MODE_PINNED) {
+ if (DEBUG) appendLog("picture-in-picture");
+ } else if (isTaskForcedMaximized(root)) {
+ // We're launching an activity that probably can't handle resizing nicely, so force
+ // it to be maximized even someone suggests launching it in freeform using launch
+ // options.
+ launchMode = WINDOWING_MODE_FULLSCREEN;
+ outParams.mBounds.setEmpty();
+ if (DEBUG) appendLog("forced-maximize");
+ } else if (fullyResolvedCurrentParam) {
+ // Don't adjust launch mode if that's inherited, except when we're launching an
+ // activity that should be forced to maximize.
+ if (DEBUG) appendLog("skip-adjustment-fully-resolved-params");
+ } else if (launchMode != WINDOWING_MODE_FREEFORM
+ && (isNOrGreater(root) || isPreNResizeable(root))) {
+ // We're launching a pre-N and post-D activity that supports resizing, or a post-N
+ // activity. They can handle freeform nicely so launch them in freeform.
+ // Use undefined because we know we're in a freeform display.
+ launchMode = WINDOWING_MODE_UNDEFINED;
+ if (DEBUG) appendLog("should-be-freeform");
}
} else {
- // Some fancy gravity setting that we don't support yet. We just put the activity in the
- // center.
- Slog.w(TAG, "Received unsupported gravity: " + layout.gravity
- + ", positioning in the center instead.");
- positionCenter(tasks, mAvailableRect, width, height, resultBounds);
+ if (DEBUG) appendLog("non-freeform-display");
+ }
+ // If launch mode matches display windowing mode, let it inherit from display.
+ outParams.mWindowingMode = launchMode == display.getWindowingMode()
+ ? WINDOWING_MODE_UNDEFINED : launchMode;
+
+ // STEP 3: Determine final launch bounds based on resolved windowing mode and activity
+ // requested orientation. We set bounds to empty for fullscreen mode and keep bounds as is
+ // for all other windowing modes that's not freeform mode. One can read comments in
+ // relevant methods to further understand this step.
+ //
+ // We skip making adjustments if the params are fully resolved from previous results and
+ // trust that they are valid.
+ if (!fullyResolvedCurrentParam) {
+ final int resolvedMode = (launchMode != WINDOWING_MODE_UNDEFINED) ? launchMode
+ : display.getWindowingMode();
+ if (source != null && source.inFreeformWindowingMode()
+ && resolvedMode == WINDOWING_MODE_FREEFORM
+ && outParams.mBounds.isEmpty()
+ && source.getDisplayId() == display.mDisplayId) {
+ // Set bounds to be not very far from source activity.
+ cascadeBounds(source.getBounds(), display, outParams.mBounds);
+ }
+ getTaskBounds(root, display, layout, resolvedMode, hasInitialBounds, outParams.mBounds);
}
return RESULT_CONTINUE;
}
- @VisibleForTesting
- static int getFreeformStartLeft(Rect bounds) {
- return bounds.left + bounds.width() / MARGIN_SIZE_DENOMINATOR;
+ private int getPreferredLaunchDisplay(@Nullable ActivityOptions options,
+ ActivityRecord source, LaunchParams currentParams) {
+ int displayId = INVALID_DISPLAY;
+ final int optionLaunchId = options != null ? options.getLaunchDisplayId() : INVALID_DISPLAY;
+ if (optionLaunchId != INVALID_DISPLAY) {
+ if (DEBUG) appendLog("display-from-option=" + optionLaunchId);
+ displayId = optionLaunchId;
+ }
+
+ if (displayId == INVALID_DISPLAY && source != null) {
+ final int sourceDisplayId = source.getDisplayId();
+ if (DEBUG) appendLog("display-from-source=" + sourceDisplayId);
+ displayId = sourceDisplayId;
+ }
+
+ if (displayId != INVALID_DISPLAY && mSupervisor.getActivityDisplay(displayId) == null) {
+ displayId = INVALID_DISPLAY;
+ }
+ displayId = (displayId == INVALID_DISPLAY) ? currentParams.mPreferredDisplayId : displayId;
+
+ displayId = (displayId == INVALID_DISPLAY) ? DEFAULT_DISPLAY : displayId;
+
+ return displayId;
+ }
+
+ private boolean canApplyFreeformWindowPolicy(@NonNull ActivityDisplay display,
+ @NonNull ActivityRecord root, int launchMode) {
+ return display.inFreeformWindowingMode() || launchMode == WINDOWING_MODE_FREEFORM
+ || root.isResizeable();
}
- @VisibleForTesting
- static int getFreeformStartTop(Rect bounds) {
- return bounds.top + bounds.height() / MARGIN_SIZE_DENOMINATOR;
+ private void getLayoutBounds(@NonNull ActivityDisplay display, @NonNull ActivityRecord root,
+ @NonNull ActivityInfo.WindowLayout windowLayout, @NonNull Rect outBounds) {
+ final int verticalGravity = windowLayout.gravity & Gravity.VERTICAL_GRAVITY_MASK;
+ final int horizontalGravity = windowLayout.gravity & Gravity.HORIZONTAL_GRAVITY_MASK;
+ if (!windowLayout.hasSpecifiedSize() && verticalGravity == 0 && horizontalGravity == 0) {
+ outBounds.setEmpty();
+ return;
+ }
+
+ final Rect bounds = display.getBounds();
+ final int defaultWidth = bounds.width();
+ final int defaultHeight = bounds.height();
+
+ int width;
+ int height;
+ if (!windowLayout.hasSpecifiedSize()) {
+ outBounds.setEmpty();
+ getTaskBounds(root, display, windowLayout, WINDOWING_MODE_FREEFORM,
+ /* hasInitialBounds */ false, outBounds);
+ width = outBounds.width();
+ height = outBounds.height();
+ } else {
+ width = defaultWidth;
+ if (windowLayout.width > 0 && windowLayout.width < defaultWidth) {
+ width = windowLayout.width;
+ } else if (windowLayout.widthFraction > 0 && windowLayout.widthFraction < 1.0f) {
+ width = (int) (width * windowLayout.widthFraction);
+ }
+
+ height = defaultHeight;
+ if (windowLayout.height > 0 && windowLayout.height < defaultHeight) {
+ height = windowLayout.height;
+ } else if (windowLayout.heightFraction > 0 && windowLayout.heightFraction < 1.0f) {
+ height = (int) (height * windowLayout.heightFraction);
+ }
+ }
+
+ final float fractionOfHorizontalOffset;
+ switch (horizontalGravity) {
+ case Gravity.LEFT:
+ fractionOfHorizontalOffset = 0f;
+ break;
+ case Gravity.RIGHT:
+ fractionOfHorizontalOffset = 1f;
+ break;
+ default:
+ fractionOfHorizontalOffset = 0.5f;
+ }
+
+ final float fractionOfVerticalOffset;
+ switch (verticalGravity) {
+ case Gravity.TOP:
+ fractionOfVerticalOffset = 0f;
+ break;
+ case Gravity.BOTTOM:
+ fractionOfVerticalOffset = 1f;
+ break;
+ default:
+ fractionOfVerticalOffset = 0.5f;
+ }
+
+ outBounds.set(0, 0, width, height);
+ final int xOffset = (int) (fractionOfHorizontalOffset * (defaultWidth - width));
+ final int yOffset = (int) (fractionOfVerticalOffset * (defaultHeight - height));
+ outBounds.offset(xOffset, yOffset);
}
- @VisibleForTesting
- static int getFreeformWidth(Rect bounds) {
- return bounds.width() / WINDOW_SIZE_DENOMINATOR;
+ /**
+ * Returns if task is forced to maximize.
+ *
+ * There are several cases where we force a task to maximize:
+ * 1) Root activity is targeting pre-Donut, which by default can't handle multiple screen
+ * densities, so resizing will likely cause issues;
+ * 2) Root activity doesn't declare any flag that it supports any screen density, so resizing
+ * may also cause issues;
+ * 3) Root activity is not resizeable, for which we shouldn't allow user resize it.
+ *
+ * @param root the root activity to check against.
+ * @return {@code true} if it should be forced to maximize; {@code false} otherwise.
+ */
+ private boolean isTaskForcedMaximized(@NonNull ActivityRecord root) {
+ if (root.appInfo.targetSdkVersion < Build.VERSION_CODES.DONUT
+ || (root.appInfo.flags & SUPPORTS_SCREEN_RESIZEABLE_MASK) == 0) {
+ return true;
+ }
+
+ return !root.isResizeable();
}
- @VisibleForTesting
- static int getFreeformHeight(Rect bounds) {
- return bounds.height() / WINDOW_SIZE_DENOMINATOR;
+ private boolean isNOrGreater(@NonNull ActivityRecord root) {
+ return root.appInfo.targetSdkVersion >= Build.VERSION_CODES.N;
+ }
+
+ /**
+ * Resolves activity requested orientation to 4 categories:
+ * 1) {@link ActivityInfo#SCREEN_ORIENTATION_LOCKED} indicating app wants to lock down
+ * orientation;
+ * 2) {@link ActivityInfo#SCREEN_ORIENTATION_LANDSCAPE} indicating app wants to be in landscape;
+ * 3) {@link ActivityInfo#SCREEN_ORIENTATION_PORTRAIT} indicating app wants to be in portrait;
+ * 4) {@link ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED} indicating app can handle any
+ * orientation.
+ *
+ * @param activity the activity to check
+ * @return corresponding resolved orientation value.
+ */
+ private int resolveOrientation(@NonNull ActivityRecord activity) {
+ int orientation = activity.info.screenOrientation;
+ switch (orientation) {
+ case SCREEN_ORIENTATION_NOSENSOR:
+ case SCREEN_ORIENTATION_LOCKED:
+ orientation = SCREEN_ORIENTATION_LOCKED;
+ break;
+ case SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
+ case SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
+ case SCREEN_ORIENTATION_USER_LANDSCAPE:
+ case SCREEN_ORIENTATION_LANDSCAPE:
+ if (DEBUG) appendLog("activity-requested-landscape");
+ orientation = SCREEN_ORIENTATION_LANDSCAPE;
+ break;
+ case SCREEN_ORIENTATION_SENSOR_PORTRAIT:
+ case SCREEN_ORIENTATION_REVERSE_PORTRAIT:
+ case SCREEN_ORIENTATION_USER_PORTRAIT:
+ case SCREEN_ORIENTATION_PORTRAIT:
+ if (DEBUG) appendLog("activity-requested-portrait");
+ orientation = SCREEN_ORIENTATION_PORTRAIT;
+ break;
+ default:
+ orientation = SCREEN_ORIENTATION_UNSPECIFIED;
+ }
+
+ return orientation;
}
- @VisibleForTesting
- static int getHorizontalStep(Rect bounds) {
- return Math.max(bounds.width() / STEP_DENOMINATOR, MINIMAL_STEP);
+ private boolean isPreNResizeable(ActivityRecord root) {
+ return root.appInfo.targetSdkVersion < Build.VERSION_CODES.N && root.isResizeable();
}
- @VisibleForTesting
- static int getVerticalStep(Rect bounds) {
- return Math.max(bounds.height() / STEP_DENOMINATOR, MINIMAL_STEP);
+ private void cascadeBounds(@NonNull Rect srcBounds, @NonNull ActivityDisplay display,
+ @NonNull Rect outBounds) {
+ outBounds.set(srcBounds);
+ float density = (float) display.getConfiguration().densityDpi / DENSITY_DEFAULT;
+ final int defaultOffset = (int) (CASCADING_OFFSET_DP * density + 0.5f);
+
+ display.getBounds(mTmpBounds);
+ final int dx = Math.min(defaultOffset, Math.max(0, mTmpBounds.right - srcBounds.right));
+ final int dy = Math.min(defaultOffset, Math.max(0, mTmpBounds.bottom - srcBounds.bottom));
+ outBounds.offset(dx, dy);
}
+ private void getTaskBounds(@NonNull ActivityRecord root, @NonNull ActivityDisplay display,
+ @NonNull ActivityInfo.WindowLayout layout, int resolvedMode, boolean hasInitialBounds,
+ @NonNull Rect inOutBounds) {
+ if (resolvedMode == WINDOWING_MODE_FULLSCREEN) {
+ // We don't handle letterboxing here. Letterboxing will be handled by valid checks
+ // later.
+ inOutBounds.setEmpty();
+ if (DEBUG) appendLog("maximized-bounds");
+ return;
+ }
+ if (resolvedMode != WINDOWING_MODE_FREEFORM) {
+ // We don't apply freeform bounds adjustment to other windowing modes.
+ if (DEBUG) {
+ appendLog("skip-bounds-" + WindowConfiguration.windowingModeToString(resolvedMode));
+ }
+ return;
+ }
- private int getFinalWidth(ActivityInfo.WindowLayout windowLayout, Rect availableRect) {
- int width = getFreeformWidth(availableRect);
- if (windowLayout.width > 0) {
- width = windowLayout.width;
+ final int orientation = resolveOrientation(root, display, inOutBounds);
+ if (orientation != SCREEN_ORIENTATION_PORTRAIT
+ && orientation != SCREEN_ORIENTATION_LANDSCAPE) {
+ throw new IllegalStateException(
+ "Orientation must be one of portrait or landscape, but it's "
+ + ActivityInfo.screenOrientationToString(orientation));
}
- if (windowLayout.widthFraction > 0) {
- width = (int) (availableRect.width() * windowLayout.widthFraction);
+
+ // First we get the default size we want.
+ getDefaultFreeformSize(display, layout, orientation, mTmpBounds);
+ if (hasInitialBounds || sizeMatches(inOutBounds, mTmpBounds)) {
+ // We're here because either input parameters specified initial bounds, or the suggested
+ // bounds have the same size of the default freeform size. We should use the suggested
+ // bounds if possible -- so if app can handle the orientation we just use it, and if not
+ // we transpose the suggested bounds in-place.
+ if (orientation == orientationFromBounds(inOutBounds)) {
+ if (DEBUG) appendLog("freeform-size-orientation-match=" + inOutBounds);
+ } else {
+ // Meh, orientation doesn't match. Let's rotate inOutBounds in-place.
+ centerBounds(display, inOutBounds.height(), inOutBounds.width(), inOutBounds);
+ if (DEBUG) appendLog("freeform-orientation-mismatch=" + inOutBounds);
+ }
+ } else {
+ // We are here either because there is no suggested bounds, or the suggested bounds is
+ // a cascade from source activity. We should use the default freeform size and center it
+ // to the center of suggested bounds (or the display if no suggested bounds). The
+ // default size might be too big to center to source activity bounds in display, so we
+ // may need to move it back to the display.
+ centerBounds(display, mTmpBounds.width(), mTmpBounds.height(), inOutBounds);
+ adjustBoundsToFitInDisplay(display, inOutBounds);
+ if (DEBUG) appendLog("freeform-size-mismatch=" + inOutBounds);
}
- return width;
+
+ // Lastly we adjust bounds to avoid conflicts with other tasks as much as possible.
+ adjustBoundsToAvoidConflict(display, inOutBounds);
}
- private int getFinalHeight(ActivityInfo.WindowLayout windowLayout, Rect availableRect) {
- int height = getFreeformHeight(availableRect);
- if (windowLayout.height > 0) {
- height = windowLayout.height;
+ private int resolveOrientation(@NonNull ActivityRecord root, @NonNull ActivityDisplay display,
+ @NonNull Rect bounds) {
+ int orientation = resolveOrientation(root);
+
+ if (orientation == SCREEN_ORIENTATION_LOCKED) {
+ orientation = bounds.isEmpty() ? display.getConfiguration().orientation
+ : orientationFromBounds(bounds);
+ if (DEBUG) {
+ appendLog(bounds.isEmpty() ? "locked-orientation-from-display=" + orientation
+ : "locked-orientation-from-bounds=" + bounds);
+ }
}
- if (windowLayout.heightFraction > 0) {
- height = (int) (availableRect.height() * windowLayout.heightFraction);
+
+ if (orientation == SCREEN_ORIENTATION_UNSPECIFIED) {
+ orientation = bounds.isEmpty() ? SCREEN_ORIENTATION_PORTRAIT
+ : orientationFromBounds(bounds);
+ if (DEBUG) {
+ appendLog(bounds.isEmpty() ? "default-portrait"
+ : "orientation-from-bounds=" + bounds);
+ }
}
- return height;
- }
- private void positionBottomLeft(ArrayList<TaskRecord> tasks, Rect availableRect, int width,
- int height, Rect result) {
- mTmpProposal.set(availableRect.left, availableRect.bottom - height,
- availableRect.left + width, availableRect.bottom);
- position(tasks, availableRect, mTmpProposal, !ALLOW_RESTART, SHIFT_POLICY_HORIZONTAL_RIGHT,
- result);
+ return orientation;
}
- private void positionBottomRight(ArrayList<TaskRecord> tasks, Rect availableRect, int width,
- int height, Rect result) {
- mTmpProposal.set(availableRect.right - width, availableRect.bottom - height,
- availableRect.right, availableRect.bottom);
- position(tasks, availableRect, mTmpProposal, !ALLOW_RESTART, SHIFT_POLICY_HORIZONTAL_LEFT,
- result);
+ private void getDefaultFreeformSize(@NonNull ActivityDisplay display,
+ @NonNull ActivityInfo.WindowLayout layout, int orientation, @NonNull Rect bounds) {
+ // Default size, which is letterboxing/pillarboxing in display. That's to say the large
+ // dimension of default size is the small dimension of display size, and the small dimension
+ // of default size is calculated to keep the same aspect ratio as the display's.
+ Rect displayBounds = display.getBounds();
+ final int portraitHeight = Math.min(displayBounds.width(), displayBounds.height());
+ final int otherDimension = Math.max(displayBounds.width(), displayBounds.height());
+ final int portraitWidth = (portraitHeight * portraitHeight) / otherDimension;
+ final int defaultWidth = (orientation == SCREEN_ORIENTATION_LANDSCAPE) ? portraitHeight
+ : portraitWidth;
+ final int defaultHeight = (orientation == SCREEN_ORIENTATION_LANDSCAPE) ? portraitWidth
+ : portraitHeight;
+
+ // Get window size based on Nexus 5x screen, we assume that this is enough to show content
+ // of activities.
+ final float density = (float) display.getConfiguration().densityDpi / DENSITY_DEFAULT;
+ final int phonePortraitWidth = (int) (DEFAULT_PORTRAIT_PHONE_WIDTH_DP * density + 0.5f);
+ final int phonePortraitHeight = (int) (DEFAULT_PORTRAIT_PHONE_HEIGHT_DP * density + 0.5f);
+ final int phoneWidth = (orientation == SCREEN_ORIENTATION_LANDSCAPE) ? phonePortraitHeight
+ : phonePortraitWidth;
+ final int phoneHeight = (orientation == SCREEN_ORIENTATION_LANDSCAPE) ? phonePortraitWidth
+ : phonePortraitHeight;
+
+ // Minimum layout requirements.
+ final int layoutMinWidth = (layout == null) ? -1 : layout.minWidth;
+ final int layoutMinHeight = (layout == null) ? -1 : layout.minHeight;
+
+ // Final result.
+ final int width = Math.min(defaultWidth, Math.max(phoneWidth, layoutMinWidth));
+ final int height = Math.min(defaultHeight, Math.max(phoneHeight, layoutMinHeight));
+
+ bounds.set(0, 0, width, height);
}
- private void positionTopLeft(ArrayList<TaskRecord> tasks, Rect availableRect, int width,
- int height, Rect result) {
- mTmpProposal.set(availableRect.left, availableRect.top,
- availableRect.left + width, availableRect.top + height);
- position(tasks, availableRect, mTmpProposal, !ALLOW_RESTART, SHIFT_POLICY_HORIZONTAL_RIGHT,
- result);
+ /**
+ * Gets centered bounds of width x height. If inOutBounds is not empty, the result bounds
+ * centers at its center or display's center if inOutBounds is empty.
+ */
+ private void centerBounds(@NonNull ActivityDisplay display, int width, int height,
+ @NonNull Rect inOutBounds) {
+ if (inOutBounds.isEmpty()) {
+ display.getBounds(inOutBounds);
+ }
+ final int left = inOutBounds.centerX() - width / 2;
+ final int top = inOutBounds.centerY() - height / 2;
+ inOutBounds.set(left, top, left + width, top + height);
}
- private void positionTopRight(ArrayList<TaskRecord> tasks, Rect availableRect, int width,
- int height, Rect result) {
- mTmpProposal.set(availableRect.right - width, availableRect.top,
- availableRect.right, availableRect.top + height);
- position(tasks, availableRect, mTmpProposal, !ALLOW_RESTART, SHIFT_POLICY_HORIZONTAL_LEFT,
- result);
- }
+ private void adjustBoundsToFitInDisplay(@NonNull ActivityDisplay display,
+ @NonNull Rect inOutBounds) {
+ final Rect displayBounds = display.getBounds();
+
+ if (displayBounds.width() < inOutBounds.width()
+ || displayBounds.height() < inOutBounds.height()) {
+ // There is no way for us to fit the bounds in the display without changing width
+ // or height. Don't even try it.
+ return;
+ }
+
+ final int dx;
+ if (inOutBounds.right > displayBounds.right) {
+ // Right edge is out of display.
+ dx = displayBounds.right - inOutBounds.right;
+ } else if (inOutBounds.left < displayBounds.left) {
+ // Left edge is out of display.
+ dx = displayBounds.left - inOutBounds.left;
+ } else {
+ // Vertical edges are all in display.
+ dx = 0;
+ }
- private void positionCenter(ArrayList<TaskRecord> tasks, Rect availableRect, int width,
- int height, Rect result) {
- final int defaultFreeformLeft = getFreeformStartLeft(availableRect);
- final int defaultFreeformTop = getFreeformStartTop(availableRect);
- mTmpProposal.set(defaultFreeformLeft, defaultFreeformTop,
- defaultFreeformLeft + width, defaultFreeformTop + height);
- position(tasks, availableRect, mTmpProposal, ALLOW_RESTART, SHIFT_POLICY_DIAGONAL_DOWN,
- result);
+ final int dy;
+ if (inOutBounds.top < displayBounds.top) {
+ // Top edge is out of display.
+ dy = displayBounds.top - inOutBounds.top;
+ } else if (inOutBounds.bottom > displayBounds.bottom) {
+ // Bottom edge is out of display.
+ dy = displayBounds.bottom - inOutBounds.bottom;
+ } else {
+ // Horizontal edges are all in display.
+ dy = 0;
+ }
+ inOutBounds.offset(dx, dy);
}
- private void position(ArrayList<TaskRecord> tasks, Rect availableRect,
- Rect proposal, boolean allowRestart, int shiftPolicy, Rect result) {
- mTmpOriginal.set(proposal);
- boolean restarted = false;
- while (boundsConflict(proposal, tasks)) {
- // Unfortunately there is already a task at that spot, so we need to look for some
- // other place.
- shiftStartingPoint(proposal, availableRect, shiftPolicy);
- if (shiftedTooFar(proposal, availableRect, shiftPolicy)) {
- // We don't want the task to go outside of the stack, because it won't look
- // nice. Depending on the starting point we either restart, or immediately give up.
- if (!allowRestart) {
- proposal.set(mTmpOriginal);
- break;
- }
- // We must have started not from the top. Let's restart from there because there
- // might be some space there.
- proposal.set(availableRect.left, availableRect.top,
- availableRect.left + proposal.width(),
- availableRect.top + proposal.height());
- restarted = true;
+ /**
+ * Adjusts input bounds to avoid conflict with existing tasks in the display.
+ *
+ * If the input bounds conflict with existing tasks, this method scans the bounds in a series of
+ * directions to find a location where the we can put the bounds in display without conflict
+ * with any other tasks.
+ *
+ * It doesn't try to adjust bounds that's not fully in the given display.
+ *
+ * @param display the display which tasks are to check
+ * @param inOutBounds the bounds used to input initial bounds and output result bounds
+ */
+ private void adjustBoundsToAvoidConflict(@NonNull ActivityDisplay display,
+ @NonNull Rect inOutBounds) {
+ final Rect displayBounds = display.getBounds();
+ if (!displayBounds.contains(inOutBounds)) {
+ // The initial bounds are already out of display. The scanning algorithm below doesn't
+ // work so well with them.
+ return;
+ }
+
+ final List<TaskRecord> tasksToCheck = new ArrayList<>();
+ for (int i = 0; i < display.getChildCount(); ++i) {
+ ActivityStack<?> stack = display.getChildAt(i);
+ if (!stack.inFreeformWindowingMode()) {
+ continue;
}
- if (restarted && (proposal.left > getFreeformStartLeft(availableRect)
- || proposal.top > getFreeformStartTop(availableRect))) {
- // If we restarted and crossed the initial position, let's not struggle anymore.
- // The user already must have ton of tasks visible, we can just smack the new
- // one in the center.
- proposal.set(mTmpOriginal);
+
+ for (int j = 0; j < stack.getChildCount(); ++j) {
+ tasksToCheck.add(stack.getChildAt(j));
+ }
+ }
+
+ if (!boundsConflict(tasksToCheck, inOutBounds)) {
+ // Current proposal doesn't conflict with any task. Early return to avoid unnecessary
+ // calculation.
+ return;
+ }
+
+ calculateCandidateShiftDirections(displayBounds, inOutBounds);
+ for (int direction : mTmpDirections) {
+ if (direction == Gravity.NO_GRAVITY) {
+ // We exhausted candidate directions, give up.
break;
}
+
+ mTmpBounds.set(inOutBounds);
+ while (boundsConflict(tasksToCheck, mTmpBounds) && displayBounds.contains(mTmpBounds)) {
+ shiftBounds(direction, displayBounds, mTmpBounds);
+ }
+
+ if (!boundsConflict(tasksToCheck, mTmpBounds) && displayBounds.contains(mTmpBounds)) {
+ // Found a candidate. Just use this.
+ inOutBounds.set(mTmpBounds);
+ if (DEBUG) appendLog("avoid-bounds-conflict=" + inOutBounds);
+ return;
+ }
+
+ // Didn't find a conflict free bounds here. Try the next candidate direction.
}
- result.set(proposal);
+
+ // We failed to find a conflict free location. Just keep the original result.
}
- private boolean shiftedTooFar(Rect start, Rect availableRect, int shiftPolicy) {
- switch (shiftPolicy) {
- case SHIFT_POLICY_HORIZONTAL_LEFT:
- return start.left < availableRect.left;
- case SHIFT_POLICY_HORIZONTAL_RIGHT:
- return start.right > availableRect.right;
- default: // SHIFT_POLICY_DIAGONAL_DOWN
- return start.right > availableRect.right || start.bottom > availableRect.bottom;
+ /**
+ * Determines scanning directions and their priorities to avoid bounds conflict.
+ *
+ * @param availableBounds bounds that the result must be in
+ * @param initialBounds initial bounds when start scanning
+ */
+ private void calculateCandidateShiftDirections(@NonNull Rect availableBounds,
+ @NonNull Rect initialBounds) {
+ for (int i = 0; i < mTmpDirections.length; ++i) {
+ mTmpDirections[i] = Gravity.NO_GRAVITY;
+ }
+
+ final int oneThirdWidth = (2 * availableBounds.left + availableBounds.right) / 3;
+ final int twoThirdWidth = (availableBounds.left + 2 * availableBounds.right) / 3;
+ final int centerX = initialBounds.centerX();
+ if (centerX < oneThirdWidth) {
+ // Too close to left, just scan to the right.
+ mTmpDirections[0] = Gravity.RIGHT;
+ return;
+ } else if (centerX > twoThirdWidth) {
+ // Too close to right, just scan to the left.
+ mTmpDirections[0] = Gravity.LEFT;
+ return;
}
+
+ final int oneThirdHeight = (2 * availableBounds.top + availableBounds.bottom) / 3;
+ final int twoThirdHeight = (availableBounds.top + 2 * availableBounds.bottom) / 3;
+ final int centerY = initialBounds.centerY();
+ if (centerY < oneThirdHeight || centerY > twoThirdHeight) {
+ // Too close to top or bottom boundary and we're in the middle horizontally, scan
+ // horizontally in both directions.
+ mTmpDirections[0] = Gravity.RIGHT;
+ mTmpDirections[1] = Gravity.LEFT;
+ return;
+ }
+
+ // We're in the center region both horizontally and vertically. Scan in both directions of
+ // primary diagonal.
+ mTmpDirections[0] = Gravity.BOTTOM | Gravity.RIGHT;
+ mTmpDirections[1] = Gravity.TOP | Gravity.LEFT;
}
- private void shiftStartingPoint(Rect posposal, Rect availableRect, int shiftPolicy) {
- final int defaultFreeformStepHorizontal = getHorizontalStep(availableRect);
- final int defaultFreeformStepVertical = getVerticalStep(availableRect);
+ private boolean boundsConflict(@NonNull List<TaskRecord> tasks, @NonNull Rect bounds) {
+ for (TaskRecord task : tasks) {
+ final Rect taskBounds = task.getBounds();
+ final boolean leftClose = Math.abs(taskBounds.left - bounds.left)
+ < BOUNDS_CONFLICT_THRESHOLD;
+ final boolean topClose = Math.abs(taskBounds.top - bounds.top)
+ < BOUNDS_CONFLICT_THRESHOLD;
+ final boolean rightClose = Math.abs(taskBounds.right - bounds.right)
+ < BOUNDS_CONFLICT_THRESHOLD;
+ final boolean bottomClose = Math.abs(taskBounds.bottom - bounds.bottom)
+ < BOUNDS_CONFLICT_THRESHOLD;
+
+ if ((leftClose && topClose) || (leftClose && bottomClose) || (rightClose && topClose)
+ || (rightClose && bottomClose)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
- switch (shiftPolicy) {
- case SHIFT_POLICY_HORIZONTAL_LEFT:
- posposal.offset(-defaultFreeformStepHorizontal, 0);
+ private void shiftBounds(int direction, @NonNull Rect availableRect,
+ @NonNull Rect inOutBounds) {
+ final int horizontalOffset;
+ switch (direction & Gravity.HORIZONTAL_GRAVITY_MASK) {
+ case Gravity.LEFT:
+ horizontalOffset = -Math.max(MINIMAL_STEP,
+ availableRect.width() / STEP_DENOMINATOR);
break;
- case SHIFT_POLICY_HORIZONTAL_RIGHT:
- posposal.offset(defaultFreeformStepHorizontal, 0);
+ case Gravity.RIGHT:
+ horizontalOffset = Math.max(MINIMAL_STEP, availableRect.width() / STEP_DENOMINATOR);
break;
- default: // SHIFT_POLICY_DIAGONAL_DOWN:
- posposal.offset(defaultFreeformStepHorizontal, defaultFreeformStepVertical);
+ default:
+ horizontalOffset = 0;
+ }
+
+ final int verticalOffset;
+ switch (direction & Gravity.VERTICAL_GRAVITY_MASK) {
+ case Gravity.TOP:
+ verticalOffset = -Math.max(MINIMAL_STEP, availableRect.height() / STEP_DENOMINATOR);
break;
+ case Gravity.BOTTOM:
+ verticalOffset = Math.max(MINIMAL_STEP, availableRect.height() / STEP_DENOMINATOR);
+ break;
+ default:
+ verticalOffset = 0;
}
+
+ inOutBounds.offset(horizontalOffset, verticalOffset);
}
- private static boolean boundsConflict(Rect proposal, ArrayList<TaskRecord> tasks) {
- for (int i = tasks.size() - 1; i >= 0; i--) {
- final TaskRecord task = tasks.get(i);
- if (!task.mActivities.isEmpty() && !task.matchParentBounds()) {
- final Rect bounds = task.getOverrideBounds();
- if (closeLeftTopCorner(proposal, bounds) || closeRightTopCorner(proposal, bounds)
- || closeLeftBottomCorner(proposal, bounds)
- || closeRightBottomCorner(proposal, bounds)) {
- return true;
- }
- }
+ private void initLogBuilder(TaskRecord task, ActivityRecord activity) {
+ if (DEBUG) {
+ mLogBuilder = new StringBuilder("TaskLaunchParamsModifier:task=" + task
+ + " activity=" + activity);
}
- return false;
}
- private static final boolean closeLeftTopCorner(Rect first, Rect second) {
- return Math.abs(first.left - second.left) < BOUNDS_CONFLICT_MIN_DISTANCE
- && Math.abs(first.top - second.top) < BOUNDS_CONFLICT_MIN_DISTANCE;
+ private void appendLog(String log) {
+ if (DEBUG) mLogBuilder.append(" ").append(log);
}
- private static final boolean closeRightTopCorner(Rect first, Rect second) {
- return Math.abs(first.right - second.right) < BOUNDS_CONFLICT_MIN_DISTANCE
- && Math.abs(first.top - second.top) < BOUNDS_CONFLICT_MIN_DISTANCE;
+ private void outputLog() {
+ if (DEBUG) Slog.d(TAG, mLogBuilder.toString());
}
- private static final boolean closeLeftBottomCorner(Rect first, Rect second) {
- return Math.abs(first.left - second.left) < BOUNDS_CONFLICT_MIN_DISTANCE
- && Math.abs(first.bottom - second.bottom) < BOUNDS_CONFLICT_MIN_DISTANCE;
+ private static int orientationFromBounds(Rect bounds) {
+ return bounds.width() > bounds.height() ? SCREEN_ORIENTATION_LANDSCAPE
+ : SCREEN_ORIENTATION_PORTRAIT;
}
- private static final boolean closeRightBottomCorner(Rect first, Rect second) {
- return Math.abs(first.right - second.right) < BOUNDS_CONFLICT_MIN_DISTANCE
- && Math.abs(first.bottom - second.bottom) < BOUNDS_CONFLICT_MIN_DISTANCE;
+ private static boolean sizeMatches(Rect left, Rect right) {
+ return (Math.abs(right.width() - left.width()) < EPSILON)
+ && (Math.abs(right.height() - left.height()) < EPSILON);
}
}
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index ca9b25699c1c..30659c1e77a3 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -1031,6 +1031,11 @@ public class NetworkMonitor extends StateMachine {
result.isPortal() /* isCaptivePortal */,
startTime, endTime);
+ log("isCaptivePortal: isSuccessful()=" + result.isSuccessful() +
+ " isPortal()=" + result.isPortal() +
+ " RedirectUrl=" + result.redirectUrl +
+ " StartTime=" + startTime + " EndTime=" + endTime);
+
return result;
}
diff --git a/services/core/java/com/android/server/connectivity/ProxyTracker.java b/services/core/java/com/android/server/connectivity/ProxyTracker.java
index b7bbd422458f..47e85b5fd3ab 100644
--- a/services/core/java/com/android/server/connectivity/ProxyTracker.java
+++ b/services/core/java/com/android/server/connectivity/ProxyTracker.java
@@ -16,6 +16,12 @@
package com.android.server.connectivity;
+import static android.provider.Settings.Global.GLOBAL_HTTP_PROXY_EXCLUSION_LIST;
+import static android.provider.Settings.Global.GLOBAL_HTTP_PROXY_HOST;
+import static android.provider.Settings.Global.GLOBAL_HTTP_PROXY_PAC;
+import static android.provider.Settings.Global.GLOBAL_HTTP_PROXY_PORT;
+import static android.provider.Settings.Global.HTTP_PROXY;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ContentResolver;
@@ -47,16 +53,14 @@ public class ProxyTracker {
@NonNull
private final Context mContext;
- // TODO : make this private and import as much managing logic from ConnectivityService as
- // possible
@NonNull
- public final Object mProxyLock = new Object();
+ private final Object mProxyLock = new Object();
// The global proxy is the proxy that is set device-wide, overriding any network-specific
// proxy. Note however that proxies are hints ; the system does not enforce their use. Hence
// this value is only for querying.
@Nullable
@GuardedBy("mProxyLock")
- public ProxyInfo mGlobalProxy = null;
+ private ProxyInfo mGlobalProxy = null;
// The default proxy is the proxy that applies to no particular network if the global proxy
// is not set. Individual networks have their own settings that override this. This member
// is set through setDefaultProxy, which is called when the default network changes proxies
@@ -64,10 +68,10 @@ public class ProxyTracker {
// when PacManager resolves the proxy.
@Nullable
@GuardedBy("mProxyLock")
- public volatile ProxyInfo mDefaultProxy = null;
- // Whether the default proxy is disabled. TODO : make this mDefaultProxyEnabled
+ private volatile ProxyInfo mDefaultProxy = null;
+ // Whether the default proxy is enabled.
@GuardedBy("mProxyLock")
- public boolean mDefaultProxyDisabled = false;
+ private boolean mDefaultProxyEnabled = true;
// The object responsible for Proxy Auto Configuration (PAC).
@NonNull
@@ -85,7 +89,7 @@ public class ProxyTracker {
@Nullable
private static ProxyInfo canonicalizeProxyInfo(@Nullable final ProxyInfo proxy) {
if (proxy != null && TextUtils.isEmpty(proxy.getHost())
- && (proxy.getPacFileUrl() == null || Uri.EMPTY.equals(proxy.getPacFileUrl()))) {
+ && Uri.EMPTY.equals(proxy.getPacFileUrl())) {
return null;
}
return proxy;
@@ -123,7 +127,7 @@ public class ProxyTracker {
// This information is already available as a world read/writable jvm property.
synchronized (mProxyLock) {
final ProxyInfo ret = mGlobalProxy;
- if ((ret == null) && !mDefaultProxyDisabled) return mDefaultProxy;
+ if ((ret == null) && mDefaultProxyEnabled) return mDefaultProxy;
return ret;
}
}
@@ -146,11 +150,10 @@ public class ProxyTracker {
*/
public void loadGlobalProxy() {
ContentResolver res = mContext.getContentResolver();
- String host = Settings.Global.getString(res, Settings.Global.GLOBAL_HTTP_PROXY_HOST);
- int port = Settings.Global.getInt(res, Settings.Global.GLOBAL_HTTP_PROXY_PORT, 0);
- String exclList = Settings.Global.getString(res,
- Settings.Global.GLOBAL_HTTP_PROXY_EXCLUSION_LIST);
- String pacFileUrl = Settings.Global.getString(res, Settings.Global.GLOBAL_HTTP_PROXY_PAC);
+ String host = Settings.Global.getString(res, GLOBAL_HTTP_PROXY_HOST);
+ int port = Settings.Global.getInt(res, GLOBAL_HTTP_PROXY_PORT, 0);
+ String exclList = Settings.Global.getString(res, GLOBAL_HTTP_PROXY_EXCLUSION_LIST);
+ String pacFileUrl = Settings.Global.getString(res, GLOBAL_HTTP_PROXY_PAC);
if (!TextUtils.isEmpty(host) || !TextUtils.isEmpty(pacFileUrl)) {
ProxyInfo proxyProperties;
if (!TextUtils.isEmpty(pacFileUrl)) {
@@ -167,10 +170,36 @@ public class ProxyTracker {
mGlobalProxy = proxyProperties;
}
}
+ loadDeprecatedGlobalHttpProxy();
// TODO : shouldn't this function call mPacManager.setCurrentProxyScriptUrl ?
}
/**
+ * Read the global proxy from the deprecated Settings.Global.HTTP_PROXY setting and apply it.
+ */
+ public void loadDeprecatedGlobalHttpProxy() {
+ final String proxy = Settings.Global.getString(mContext.getContentResolver(), HTTP_PROXY);
+ if (!TextUtils.isEmpty(proxy)) {
+ String data[] = proxy.split(":");
+ if (data.length == 0) {
+ return;
+ }
+
+ final String proxyHost = data[0];
+ int proxyPort = 8080;
+ if (data.length > 1) {
+ try {
+ proxyPort = Integer.parseInt(data[1]);
+ } catch (NumberFormatException e) {
+ return;
+ }
+ }
+ final ProxyInfo p = new ProxyInfo(proxyHost, proxyPort, "");
+ setGlobalProxy(p);
+ }
+ }
+
+ /**
* Sends the system broadcast informing apps about a new proxy configuration.
*
* Confusingly this method also sets the PAC file URL. TODO : separate this, it has nothing
@@ -232,11 +261,10 @@ public class ProxyTracker {
final ContentResolver res = mContext.getContentResolver();
final long token = Binder.clearCallingIdentity();
try {
- Settings.Global.putString(res, Settings.Global.GLOBAL_HTTP_PROXY_HOST, host);
- Settings.Global.putInt(res, Settings.Global.GLOBAL_HTTP_PROXY_PORT, port);
- Settings.Global.putString(res, Settings.Global.GLOBAL_HTTP_PROXY_EXCLUSION_LIST,
- exclList);
- Settings.Global.putString(res, Settings.Global.GLOBAL_HTTP_PROXY_PAC, pacFileUrl);
+ Settings.Global.putString(res, GLOBAL_HTTP_PROXY_HOST, host);
+ Settings.Global.putInt(res, GLOBAL_HTTP_PROXY_PORT, port);
+ Settings.Global.putString(res, GLOBAL_HTTP_PROXY_EXCLUSION_LIST, exclList);
+ Settings.Global.putString(res, GLOBAL_HTTP_PROXY_PAC, pacFileUrl);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -253,10 +281,7 @@ public class ProxyTracker {
*/
public void setDefaultProxy(@Nullable ProxyInfo proxyInfo) {
synchronized (mProxyLock) {
- if (mDefaultProxy != null && mDefaultProxy.equals(proxyInfo)) {
- return;
- }
- if (mDefaultProxy == proxyInfo) return; // catches repeated nulls
+ if (Objects.equals(mDefaultProxy, proxyInfo)) return;
if (proxyInfo != null && !proxyInfo.isValid()) {
if (DBG) Slog.d(TAG, "Invalid proxy properties, ignoring: " + proxyInfo);
return;
@@ -277,9 +302,27 @@ public class ProxyTracker {
mDefaultProxy = proxyInfo;
if (mGlobalProxy != null) return;
- if (!mDefaultProxyDisabled) {
+ if (mDefaultProxyEnabled) {
sendProxyBroadcast(proxyInfo);
}
}
}
+
+ /**
+ * Enable or disable the default proxy.
+ *
+ * This sets the flag for enabling/disabling the default proxy and sends the broadcast
+ * if applicable.
+ * @param enabled whether the default proxy should be enabled.
+ */
+ public void setDefaultProxyEnabled(final boolean enabled) {
+ synchronized (mProxyLock) {
+ if (mDefaultProxyEnabled != enabled) {
+ mDefaultProxyEnabled = enabled;
+ if (mGlobalProxy == null && mDefaultProxy != null) {
+ sendProxyBroadcast(enabled ? mDefaultProxy : null);
+ }
+ }
+ }
+ }
}
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 71c419f50790..a9b0d5c42f73 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -421,7 +421,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
final IInputContext inputContext;
final int uid;
final int pid;
- final int selfReportedDisplayId;
final InputBinding binding;
final ClientDeathRecipient clientDeathRecipient;
@@ -431,18 +430,16 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
@Override
public String toString() {
return "ClientState{" + Integer.toHexString(
- System.identityHashCode(this)) + " uid=" + uid
- + " pid=" + pid + " displayId=" + selfReportedDisplayId + "}";
+ System.identityHashCode(this)) + " uid " + uid
+ + " pid " + pid + "}";
}
ClientState(IInputMethodClient _client, IInputContext _inputContext,
- int _uid, int _pid, int _selfReportedDisplayId,
- ClientDeathRecipient _clientDeathRecipient) {
+ int _uid, int _pid, ClientDeathRecipient _clientDeathRecipient) {
client = _client;
inputContext = _inputContext;
uid = _uid;
pid = _pid;
- selfReportedDisplayId = _selfReportedDisplayId;
binding = new InputBinding(null, inputContext.asBinder(), uid, pid);
clientDeathRecipient = _clientDeathRecipient;
}
@@ -1748,21 +1745,15 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
* process
* @param inputContext communication channel for the dummy
* {@link android.view.inputmethod.InputConnection}
- * @param selfReportedDisplayId self-reported display ID to which the client is associated.
- * Whether the client is still allowed to access to this display
- * or not needs to be evaluated every time the client interacts
- * with the display
*/
@Override
- public void addClient(IInputMethodClient client, IInputContext inputContext,
- int selfReportedDisplayId) {
+ public void addClient(IInputMethodClient client, IInputContext inputContext) {
final int callerUid = Binder.getCallingUid();
final int callerPid = Binder.getCallingPid();
synchronized (mMethodMap) {
// TODO: Optimize this linear search.
for (ClientState state : mClients.values()) {
- if (state.uid == callerUid && state.pid == callerPid
- && state.selfReportedDisplayId == selfReportedDisplayId) {
+ if (state.uid == callerUid && state.pid == callerPid) {
throw new SecurityException("uid=" + callerUid + "/pid=" + callerPid
+ " is already registered");
}
@@ -1773,25 +1764,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
} catch (RemoteException e) {
throw new IllegalStateException(e);
}
- // We cannot fully avoid race conditions where the client UID already lost the access to
- // the given self-reported display ID, even if the client is not maliciously reporting
- // a fake display ID. Unconditionally returning SecurityException just because the
- // client doesn't pass display ID verification can cause many test failures hence not an
- // option right now. At the same time
- // context.getSystemService(InputMethodManager.class)
- // is expected to return a valid non-null instance at any time if we do not choose to
- // have the client crash. Thus we do not verify the display ID at all here. Instead we
- // later check the display ID every time the client needs to interact with the specified
- // display.
- mClients.put(client.asBinder(), new ClientState(client, inputContext, callerUid,
- callerPid, selfReportedDisplayId, deathRecipient));
+ mClients.put(client.asBinder(),
+ new ClientState(client, inputContext, callerUid, callerPid, deathRecipient));
}
}
- private boolean verifyDisplayId(ClientState cs) {
- return mWindowManagerInternal.isUidAllowedOnDisplay(cs.selfReportedDisplayId, cs.uid);
- }
-
void removeClient(IInputMethodClient client) {
synchronized (mMethodMap) {
ClientState cs = mClients.remove(client.asBinder());
@@ -1941,9 +1918,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
mCurAttribute = attribute;
// Check if the input method is changing.
- // We expect the caller has already verified that the client is allowed to access this
- // display ID.
- final int displayId = mCurFocusedWindowClient.selfReportedDisplayId;
+ final int displayId = mWindowManagerInternal.getDisplayIdForWindow(
+ mCurFocusedWindow);
if (mCurId != null && mCurId.equals(mCurMethodId) && displayId == mCurTokenDisplayId) {
if (cs.curSession != null) {
// Fast case: if we are already connected to the input method,
@@ -2008,11 +1984,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
com.android.internal.R.string.input_method_binding_label);
mCurIntent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
mContext, 0, new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS), 0));
- if (!verifyDisplayId(mCurFocusedWindowClient)) {
- // Wait, the client no longer has access to the display.
- return InputBindResult.INVALID_DISPLAY_ID;
- }
- final int displayId = mCurFocusedWindowClient.selfReportedDisplayId;
+ final int displayId = mWindowManagerInternal.getDisplayIdForWindow(mCurFocusedWindow);
mCurTokenDisplayId = (displayId != INVALID_DISPLAY) ? displayId : DEFAULT_DISPLAY;
if (bindCurrentInputMethodServiceLocked(mCurIntent, this, IME_CONNECTION_BIND_FLAGS)) {
@@ -2612,8 +2584,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
if (cs == null) {
throw new IllegalArgumentException("unknown client " + client.asBinder());
}
- if (!mWindowManagerInternal.isInputMethodClientFocus(cs.uid, cs.pid,
- cs.selfReportedDisplayId)) {
+ if (!mWindowManagerInternal.isInputMethodClientFocus(cs.uid, cs.pid)) {
Slog.w(TAG, "Ignoring showSoftInput of uid " + uid + ": " + client);
return false;
}
@@ -2697,8 +2668,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
if (cs == null) {
throw new IllegalArgumentException("unknown client " + client.asBinder());
}
- if (!mWindowManagerInternal.isInputMethodClientFocus(cs.uid, cs.pid,
- cs.selfReportedDisplayId)) {
+ if (!mWindowManagerInternal.isInputMethodClientFocus(cs.uid, cs.pid)) {
if (DEBUG) {
Slog.w(TAG, "Ignoring hideSoftInput of uid " + uid + ": " + client);
}
@@ -2797,8 +2767,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
InputBindResult res = null;
long ident = Binder.clearCallingIdentity();
try {
- final int windowDisplayId =
- mWindowManagerInternal.getDisplayIdForWindow(windowToken);
synchronized (mMethodMap) {
if (DEBUG) Slog.v(TAG, "startInputOrWindowGainedFocusInternal: reason="
+ InputMethodClient.getStartInputReason(startInputReason)
@@ -2817,15 +2785,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
throw new IllegalArgumentException("unknown client "
+ client.asBinder());
}
- if (cs.selfReportedDisplayId != windowDisplayId) {
- Slog.e(TAG, "startInputOrWindowGainedFocusInternal: display ID mismatch."
- + " from client:" + cs.selfReportedDisplayId
- + " from window:" + windowDisplayId);
- return InputBindResult.DISPLAY_ID_MISMATCH;
- }
- if (!mWindowManagerInternal.isInputMethodClientFocus(cs.uid, cs.pid,
- cs.selfReportedDisplayId)) {
+ if (!mWindowManagerInternal.isInputMethodClientFocus(cs.uid, cs.pid)) {
// Check with the window manager to make sure this client actually
// has a window with focus. If not, reject. This is thread safe
// because if the focus changes some time before or after, the
@@ -2897,9 +2858,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
// If focused display changed, we should unbind current method
// to make app window in previous display relayout after Ime
// window token removed.
- // Note that we can trust client's display ID as long as it matches
- // to the display ID obtained from the window.
- if (cs.selfReportedDisplayId != mCurTokenDisplayId) {
+ final int newFocusDisplayId =
+ mWindowManagerInternal.getDisplayIdForWindow(windowToken);
+ if (newFocusDisplayId != mCurTokenDisplayId) {
unbindCurrentMethodLocked();
}
}
@@ -2997,7 +2958,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
private boolean canShowInputMethodPickerLocked(IInputMethodClient client) {
- // TODO(yukawa): multi-display support.
final int uid = Binder.getCallingUid();
if (UserHandle.getAppId(uid) == Process.SYSTEM_UID) {
return true;
@@ -3074,7 +3034,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
@Override
public void showInputMethodAndSubtypeEnablerFromClient(
IInputMethodClient client, String inputMethodId) {
- // TODO(yukawa): Should we verify the display ID?
if (!calledFromValidUser()) {
return;
}
@@ -3270,7 +3229,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
*/
@Override
public int getInputMethodWindowVisibleHeight() {
- // TODO(yukawa): Should we verify the display ID?
return mWindowManagerInternal.getInputMethodWindowVisibleHeight(mCurTokenDisplayId);
}
diff --git a/services/core/java/com/android/server/location/ContextHubClientBroker.java b/services/core/java/com/android/server/location/ContextHubClientBroker.java
index 9640e042fe6a..b29b7cf5a712 100644
--- a/services/core/java/com/android/server/location/ContextHubClientBroker.java
+++ b/services/core/java/com/android/server/location/ContextHubClientBroker.java
@@ -76,6 +76,13 @@ public class ContextHubClientBroker extends IContextHubClient.Stub
*/
private final AtomicBoolean mConnectionOpen = new AtomicBoolean(true);
+ /*
+ * Internal interface used to invoke client callbacks.
+ */
+ private interface CallbackConsumer {
+ void accept(IContextHubClientCallback callback) throws RemoteException;
+ }
+
/* package */ ContextHubClientBroker(
Context context, IContexthub contextHubProxy, ContextHubClientManager clientManager,
int contextHubId, short hostEndPointId, IContextHubClientCallback callback) {
@@ -140,12 +147,9 @@ public class ContextHubClientBroker extends IContextHubClient.Stub
/**
* Invoked when the underlying binder of this broker has died at the client process.
*/
+ @Override
public void binderDied() {
- try {
- IContextHubClient.Stub.asInterface(this).close();
- } catch (RemoteException e) {
- Log.e(TAG, "RemoteException while closing client on death", e);
- }
+ close();
}
/**
@@ -168,14 +172,7 @@ public class ContextHubClientBroker extends IContextHubClient.Stub
* @param message the message that came from a nanoapp
*/
/* package */ void sendMessageToClient(NanoAppMessage message) {
- if (mConnectionOpen.get()) {
- try {
- mCallbackInterface.onMessageFromNanoApp(message);
- } catch (RemoteException e) {
- Log.e(TAG, "RemoteException while sending message to client (host endpoint ID = "
- + mHostEndPointId + ")", e);
- }
- }
+ invokeCallbackConcurrent(callback -> callback.onMessageFromNanoApp(message));
}
/**
@@ -184,14 +181,7 @@ public class ContextHubClientBroker extends IContextHubClient.Stub
* @param nanoAppId the ID of the nanoapp that was loaded.
*/
/* package */ void onNanoAppLoaded(long nanoAppId) {
- if (mConnectionOpen.get()) {
- try {
- mCallbackInterface.onNanoAppLoaded(nanoAppId);
- } catch (RemoteException e) {
- Log.e(TAG, "RemoteException while calling onNanoAppLoaded on client"
- + " (host endpoint ID = " + mHostEndPointId + ")", e);
- }
- }
+ invokeCallbackConcurrent(callback -> callback.onNanoAppLoaded(nanoAppId));
}
/**
@@ -200,28 +190,14 @@ public class ContextHubClientBroker extends IContextHubClient.Stub
* @param nanoAppId the ID of the nanoapp that was unloaded.
*/
/* package */ void onNanoAppUnloaded(long nanoAppId) {
- if (mConnectionOpen.get()) {
- try {
- mCallbackInterface.onNanoAppUnloaded(nanoAppId);
- } catch (RemoteException e) {
- Log.e(TAG, "RemoteException while calling onNanoAppUnloaded on client"
- + " (host endpoint ID = " + mHostEndPointId + ")", e);
- }
- }
+ invokeCallbackConcurrent(callback -> callback.onNanoAppUnloaded(nanoAppId));
}
/**
* Notifies the client of a hub reset event if the connection is open.
*/
/* package */ void onHubReset() {
- if (mConnectionOpen.get()) {
- try {
- mCallbackInterface.onHubReset();
- } catch (RemoteException e) {
- Log.e(TAG, "RemoteException while calling onHubReset on client" +
- " (host endpoint ID = " + mHostEndPointId + ")", e);
- }
- }
+ invokeCallbackConcurrent(callback -> callback.onHubReset());
}
/**
@@ -231,12 +207,21 @@ public class ContextHubClientBroker extends IContextHubClient.Stub
* @param abortCode the nanoapp specific abort code
*/
/* package */ void onNanoAppAborted(long nanoAppId, int abortCode) {
+ invokeCallbackConcurrent(callback -> callback.onNanoAppAborted(nanoAppId, abortCode));
+ }
+
+ /**
+ * Helper function to invoke a specified client callback, if the connection is open.
+ *
+ * @param consumer the consumer specifying the callback to invoke
+ */
+ private void invokeCallbackConcurrent(CallbackConsumer consumer) {
if (mConnectionOpen.get()) {
try {
- mCallbackInterface.onNanoAppAborted(nanoAppId, abortCode);
+ consumer.accept(mCallbackInterface);
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException while calling onNanoAppAborted on client"
- + " (host endpoint ID = " + mHostEndPointId + ")", e);
+ Log.e(TAG, "RemoteException while invoking client callback (host endpoint ID = "
+ + mHostEndPointId + ")", e);
}
}
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index f9d49d7ce0d1..506cc441c868 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -4282,14 +4282,16 @@ public class NotificationManagerService extends SystemService {
}
private void doChannelWarningToast(CharSequence toastText) {
- final int defaultWarningEnabled = Build.IS_DEBUGGABLE ? 1 : 0;
- final boolean warningEnabled = Settings.Global.getInt(getContext().getContentResolver(),
- Settings.Global.SHOW_NOTIFICATION_CHANNEL_WARNINGS, defaultWarningEnabled) != 0;
- if (warningEnabled) {
- Toast toast = Toast.makeText(getContext(), mHandler.getLooper(), toastText,
- Toast.LENGTH_SHORT);
- toast.show();
- }
+ Binder.withCleanCallingIdentity(() -> {
+ final int defaultWarningEnabled = Build.IS_DEBUGGABLE ? 1 : 0;
+ final boolean warningEnabled = Settings.Global.getInt(getContext().getContentResolver(),
+ Settings.Global.SHOW_NOTIFICATION_CHANNEL_WARNINGS, defaultWarningEnabled) != 0;
+ if (warningEnabled) {
+ Toast toast = Toast.makeText(getContext(), mHandler.getLooper(), toastText,
+ Toast.LENGTH_SHORT);
+ toast.show();
+ }
+ });
}
@VisibleForTesting
diff --git a/services/core/java/com/android/server/os/DeviceIdentifiersPolicyService.java b/services/core/java/com/android/server/os/DeviceIdentifiersPolicyService.java
index 3ffc5c53eab6..9c1ac346ce32 100644
--- a/services/core/java/com/android/server/os/DeviceIdentifiersPolicyService.java
+++ b/services/core/java/com/android/server/os/DeviceIdentifiersPolicyService.java
@@ -57,7 +57,7 @@ public final class DeviceIdentifiersPolicyService extends SystemService {
// should use the getSerialForPackage method with the calling package specified.
if (!TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mContext,
/* callingPackage */ null, "getSerial")) {
- return null;
+ return Build.UNKNOWN;
}
return SystemProperties.get("ro.serialno", Build.UNKNOWN);
}
@@ -66,7 +66,7 @@ public final class DeviceIdentifiersPolicyService extends SystemService {
public @Nullable String getSerialForPackage(String callingPackage) throws RemoteException {
if (!TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mContext,
callingPackage, "getSerial")) {
- return null;
+ return Build.UNKNOWN;
}
return SystemProperties.get("ro.serialno", Build.UNKNOWN);
}
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 93230401eb20..a08c189cb125 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -20,6 +20,7 @@ import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
+import android.app.AppDetailsActivity;
import android.app.AppGlobals;
import android.app.IApplicationThread;
import android.app.PendingIntent;
@@ -65,7 +66,9 @@ import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.wm.ActivityTaskManagerInternal;
+import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
/**
@@ -74,6 +77,7 @@ import java.util.List;
*/
public class LauncherAppsService extends SystemService {
+ private static final boolean SHOW_HIDDEN_APP_ENABLED = false;
private final LauncherAppsImpl mLauncherAppsImpl;
public LauncherAppsService(Context context) {
@@ -281,15 +285,84 @@ public class LauncherAppsService extends SystemService {
}
}
+ private ResolveInfo getHiddenAppActivityInfo(String packageName, int callingUid,
+ UserHandle user) {
+ Intent intent = new Intent();
+ intent.setComponent(new ComponentName(packageName, AppDetailsActivity.class.getName()));
+ final PackageManagerInternal pmInt =
+ LocalServices.getService(PackageManagerInternal.class);
+ List<ResolveInfo> apps = pmInt.queryIntentActivities(intent,
+ PackageManager.MATCH_DIRECT_BOOT_AWARE
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
+ callingUid, user.getIdentifier());
+ if (apps.size() > 0) {
+ return apps.get(0);
+ }
+ return null;
+ }
+
@Override
public ParceledListSlice<ResolveInfo> getLauncherActivities(String callingPackage,
- String packageName, UserHandle user)
- throws RemoteException {
- return queryActivitiesForUser(callingPackage,
+ String packageName, UserHandle user) throws RemoteException {
+ ParceledListSlice<ResolveInfo> launcherActivities = queryActivitiesForUser(
+ callingPackage,
new Intent(Intent.ACTION_MAIN)
.addCategory(Intent.CATEGORY_LAUNCHER)
.setPackage(packageName),
user);
+ if (!SHOW_HIDDEN_APP_ENABLED) {
+ return launcherActivities;
+ }
+
+ final int callingUid = injectBinderCallingUid();
+ final ArrayList<ResolveInfo> result = new ArrayList<>(launcherActivities.getList());
+ if (packageName != null) {
+ // If target package has launcher activities, then return those launcher
+ // activities. Otherwise, return hidden activity that forwards user to app
+ // details page.
+ if (result.size() > 0) {
+ return launcherActivities;
+ }
+ ResolveInfo info = getHiddenAppActivityInfo(packageName, callingUid, user);
+ if (info != null) {
+ result.add(info);
+ }
+ return new ParceledListSlice<>(result);
+ }
+
+ long ident = injectClearCallingIdentity();
+ try {
+ final HashSet<String> visiblePackages = new HashSet<>();
+ for (ResolveInfo info : result) {
+ visiblePackages.add(info.activityInfo.packageName);
+ }
+ final PackageManagerInternal pmInt =
+ LocalServices.getService(PackageManagerInternal.class);
+ List<ApplicationInfo> installedPackages = pmInt.getInstalledApplications(0,
+ user.getIdentifier(), callingUid);
+ for (ApplicationInfo applicationInfo : installedPackages) {
+ if (!visiblePackages.contains(applicationInfo.packageName)) {
+ if (!shouldShowHiddenApp(applicationInfo)) {
+ continue;
+ }
+ ResolveInfo info = getHiddenAppActivityInfo(applicationInfo.packageName,
+ callingUid, user);
+ if (info != null) {
+ result.add(info);
+ }
+ }
+ }
+ return new ParceledListSlice<>(result);
+ } finally {
+ injectRestoreCallingIdentity(ident);
+ }
+ }
+
+ private static boolean shouldShowHiddenApp(ApplicationInfo appInfo) {
+ if (appInfo.isSystemApp() || appInfo.isUpdatedSystemApp()) {
+ return false;
+ }
+ return true;
}
@Override
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 13f084e67494..3528b86b05f4 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -121,6 +121,7 @@ import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
+import android.app.AppDetailsActivity;
import android.app.AppOpsManager;
import android.app.IActivityManager;
import android.app.ResourcesManager;
@@ -2920,7 +2921,7 @@ public class PackageManagerService extends IPackageManager.Stub
for (int splitPermNum = 0; splitPermNum < numSplitPerms; splitPermNum++) {
final PermissionManager.SplitPermissionInfo splitPerm =
splitPermissions.get(splitPermNum);
- final String rootPerm = splitPerm.getRootPermission();
+ final String rootPerm = splitPerm.getSplitPermission();
if (preUpgradeSdkVersion >= splitPerm.getTargetSdk()) {
continue;
@@ -2942,11 +2943,11 @@ public class PackageManagerService extends IPackageManager.Stub
continue;
}
- final String[] newPerms = splitPerm.getNewPermissions();
+ final List<String> newPerms = splitPerm.getNewPermissions();
- final int numNewPerms = newPerms.length;
+ final int numNewPerms = newPerms.size();
for (int newPermNum = 0; newPermNum < numNewPerms; newPermNum++) {
- final String newPerm = newPerms[newPermNum];
+ final String newPerm = newPerms.get(newPermNum);
if (checkPermission(newPerm, pkgName, userId) == PERMISSION_GRANTED) {
continue;
}
@@ -7869,10 +7870,16 @@ public class PackageManagerService extends IPackageManager.Stub
@Override
public ParceledListSlice<ApplicationInfo> getInstalledApplications(int flags, int userId) {
final int callingUid = Binder.getCallingUid();
+ return new ParceledListSlice<>(
+ getInstalledApplicationsListInternal(flags, userId, callingUid));
+ }
+
+ private List<ApplicationInfo> getInstalledApplicationsListInternal(int flags, int userId,
+ int callingUid) {
if (getInstantAppPackageName(callingUid) != null) {
- return ParceledListSlice.emptyList();
+ return Collections.emptyList();
}
- if (!sUserManager.exists(userId)) return ParceledListSlice.emptyList();
+ if (!sUserManager.exists(userId)) return Collections.emptyList();
flags = updateFlagsForApplication(flags, userId, null);
final boolean listUninstalled = (flags & MATCH_KNOWN_PACKAGES) != 0;
@@ -7937,7 +7944,7 @@ public class PackageManagerService extends IPackageManager.Stub
}
}
- return new ParceledListSlice<>(list);
+ return list;
}
}
@@ -12150,7 +12157,9 @@ public class PackageManagerService extends IPackageManager.Stub
if (mPackageListObservers.size() == 0) {
return;
}
- observers = (PackageListObserver[]) mPackageListObservers.toArray();
+ final PackageListObserver[] observerArray =
+ new PackageListObserver[mPackageListObservers.size()];
+ observers = mPackageListObservers.toArray(observerArray);
}
for (int i = observers.length - 1; i >= 0; --i) {
observers[i].onPackageAdded(packageName);
@@ -12170,7 +12179,9 @@ public class PackageManagerService extends IPackageManager.Stub
if (mPackageListObservers.size() == 0) {
return;
}
- observers = (PackageListObserver[]) mPackageListObservers.toArray();
+ final PackageListObserver[] observerArray =
+ new PackageListObserver[mPackageListObservers.size()];
+ observers = mPackageListObservers.toArray(observerArray);
}
for (int i = observers.length - 1; i >= 0; --i) {
observers[i].onPackageRemoved(packageName);
@@ -19388,6 +19399,16 @@ public class PackageManagerService extends IPackageManager.Stub
throw new SecurityException("Cannot disable a protected package: " + packageName);
}
}
+ // Only allow apps with CHANGE_COMPONENT_ENABLED_STATE permission to change hidden
+ // app details activity
+ if (AppDetailsActivity.class.getName().equals(className)) {
+ if (mContext.checkCallingOrSelfPermission(
+ android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE)
+ != PackageManager.PERMISSION_GRANTED) {
+ Slog.e(TAG, "Cannot disable a protected component: " + packageName);
+ return;
+ }
+ }
synchronized (mPackages) {
if (callingUid == Process.SHELL_UID
@@ -22283,6 +22304,14 @@ public class PackageManagerService extends IPackageManager.Stub
}
@Override
+ public List<ApplicationInfo> getInstalledApplications(int flags, int userId,
+ int callingUid) {
+ return PackageManagerService.this.getInstalledApplicationsListInternal(flags, userId,
+ callingUid);
+ }
+
+
+ @Override
public boolean isPlatformSigned(String packageName) {
PackageSetting packageSetting = mSettings.mPackages.get(packageName);
if (packageSetting == null) {
diff --git a/services/core/java/com/android/server/pm/dex/TEST_MAPPING b/services/core/java/com/android/server/pm/dex/TEST_MAPPING
index ad5255904d20..c93af2a5ba41 100644
--- a/services/core/java/com/android/server/pm/dex/TEST_MAPPING
+++ b/services/core/java/com/android/server/pm/dex/TEST_MAPPING
@@ -1,19 +1,12 @@
{
"presubmit": [
{
- "name": "DexLoggerTests"
- },
- {
- "name": "DexManagerTests"
- },
- {
- "name": "DexoptOptionsTests"
- },
- {
- "name": "DexoptUtilsTest"
- },
- {
- "name": "PackageDexUsageTests"
+ "name": "FrameworksServicesTests",
+ "options": [
+ {
+ "include-filter": "com.android.server.pm.dex"
+ }
+ ]
},
{
"name": "DexLoggerIntegrationTests"
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index 6f644dd70339..0a93653ede56 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -1033,8 +1033,8 @@ public final class DefaultPermissionGrantPolicy {
if (applicationInfo != null
&& applicationInfo.targetSdkVersion < splitPerm.getTargetSdk()
- && permissionsWithoutSplits.contains(splitPerm.getRootPermission())) {
- Collections.addAll(permissions, splitPerm.getNewPermissions());
+ && permissionsWithoutSplits.contains(splitPerm.getSplitPermission())) {
+ permissions.addAll(splitPerm.getNewPermissions());
}
}
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 21bf488f828c..06ee935818b3 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -6046,6 +6046,19 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
+ // Intercept the Accessibility keychord (CTRL + ALT + Z) for keyboard users.
+ if (mAccessibilityShortcutController.isAccessibilityShortcutAvailable(isKeyguardLocked())) {
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_Z: {
+ if (down && event.isCtrlPressed() && event.isAltPressed()) {
+ mHandler.sendMessage(mHandler.obtainMessage(MSG_ACCESSIBILITY_SHORTCUT));
+ result &= ~ACTION_PASS_TO_USER;
+ }
+ break;
+ }
+ }
+ }
+
if (useHapticFeedback) {
performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false,
"Virtual Key - Press");
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java b/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
index 1cba1c7bed1b..a55b49fe028d 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
@@ -95,10 +95,22 @@ public class KeyguardStateMonitor extends IKeyguardStateCallback.Stub {
mIsShowing = showing;
mCallback.onShowingChanged();
- try {
- mKeystoreService.onKeyguardVisibilityChanged(showing, mCurrentUserId);
- } catch (RemoteException e) {
- Slog.e(TAG, "Error informing keystore of screen lock", e);
+ int retry = 2;
+ while (retry > 0) {
+ try {
+ mKeystoreService.onKeyguardVisibilityChanged(showing, mCurrentUserId);
+ break;
+ } catch (RemoteException e) {
+ if (retry == 2) {
+ Slog.w(TAG, "Error informing keystore of screen lock. Keystore may have died"
+ + " -> refreshing service token and retrying");
+ mKeystoreService = IKeystoreService.Stub.asInterface(ServiceManager
+ .getService("android.security.keystore"));
+ } else {
+ Slog.e(TAG, "Error informing keystore of screen lock after retrying once", e);
+ }
+ --retry;
+ }
}
}
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index 1abaaf2412bf..6ca4f2e49d0a 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -1056,6 +1056,11 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
e.writeLong(entry.totalLatencyMicros);
e.writeLong(entry.cpuUsageMicros);
e.writeBoolean(entry.isInteractive);
+ e.writeLong(entry.maxCpuUsageMicros);
+ e.writeLong(entry.maxLatencyMicros);
+ e.writeLong(entry.recordedDelayMessageCount);
+ e.writeLong(entry.delayMillis);
+ e.writeLong(entry.maxDelayMillis);
pulledData.add(e);
}
}
diff --git a/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java b/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
index d36ab3f09399..5ce8145fa00e 100644
--- a/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
+++ b/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
@@ -28,7 +28,6 @@ import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.UserHandle;
-import android.provider.Settings;
import android.service.textclassifier.ITextClassificationCallback;
import android.service.textclassifier.ITextClassifierService;
import android.service.textclassifier.ITextLinksCallback;
@@ -41,7 +40,6 @@ import android.view.textclassifier.TextClassification;
import android.view.textclassifier.TextClassificationContext;
import android.view.textclassifier.TextClassificationManager;
import android.view.textclassifier.TextClassificationSessionId;
-import android.view.textclassifier.TextClassifier;
import android.view.textclassifier.TextLinks;
import android.view.textclassifier.TextSelection;
@@ -275,6 +273,20 @@ public final class TextClassificationManagerService extends ITextClassifierServi
IndentingPrintWriter pw = new IndentingPrintWriter(fout, " ");
TextClassificationManager tcm = mContext.getSystemService(TextClassificationManager.class);
tcm.dump(pw);
+
+ pw.printPair("context", mContext); pw.println();
+ synchronized (mLock) {
+ int size = mUserStates.size();
+ pw.print("Number user states: "); pw.println(size);
+ if (size > 0) {
+ for (int i = 0; i < size; i++) {
+ pw.increaseIndent();
+ UserState userState = mUserStates.valueAt(i);
+ pw.print(i); pw.print(":"); userState.dump(pw); pw.println();
+ pw.decreaseIndent();
+ }
+ }
+ }
}
private static final class PendingRequest implements IBinder.DeathRecipient {
@@ -431,6 +443,15 @@ public final class TextClassificationManagerService extends ITextClassifierServi
return willBind;
}
+ private void dump(IndentingPrintWriter pw) {
+ pw.printPair("context", mContext);
+ pw.printPair("userId", mUserId);
+ synchronized (mLock) {
+ pw.printPair("binding", mBinding);
+ pw.printPair("numberRequests", mPendingRequests.size());
+ }
+ }
+
private final class TextClassifierServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index e57fea31f1a8..e38e22909957 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -102,6 +102,7 @@ import android.view.WindowManager.LayoutParams;
import android.view.animation.Animation;
import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ToBooleanFunction;
import com.android.server.input.InputApplicationHandle;
import com.android.server.policy.WindowManagerPolicy.StartingSurface;
@@ -1741,6 +1742,30 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
return boundsLayer;
}
+ /** Get position and crop region of animation. */
+ @VisibleForTesting
+ void getAnimationBounds(Point outPosition, Rect outBounds) {
+ outPosition.set(0, 0);
+ outBounds.setEmpty();
+
+ final TaskStack stack = getStack();
+ final Task task = getTask();
+ if (task != null && task.inFreeformWindowingMode()) {
+ task.getRelativePosition(outPosition);
+ } else if (stack != null) {
+ stack.getRelativePosition(outPosition);
+ }
+
+ // Always use stack bounds in order to have the ability to animate outside the task region.
+ // It also needs to be consistent when {@link #mNeedsAnimationBoundsLayer} is set that crops
+ // according to the bounds.
+ if (stack != null) {
+ stack.getBounds(outBounds);
+ }
+ // We have the relative position so the local position can be removed from bounds.
+ outBounds.offsetTo(0, 0);
+ }
+
boolean applyAnimationLocked(WindowManager.LayoutParams lp, int transit, boolean enter,
boolean isVoiceInteraction) {
@@ -1759,14 +1784,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AWT#applyAnimationLocked");
if (okToAnimate()) {
final AnimationAdapter adapter;
- final TaskStack stack = getStack();
- mTmpPoint.set(0, 0);
- mTmpRect.setEmpty();
- if (stack != null) {
- stack.getRelativePosition(mTmpPoint);
- stack.getBounds(mTmpRect);
- mTmpRect.offsetTo(0, 0);
- }
+ getAnimationBounds(mTmpPoint, mTmpRect);
// Delaying animation start isn't compatible with remote animations at all.
if (mService.mAppTransition.getRemoteAnimationController() != null
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 6f728fcf1f00..642f57814c61 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -92,7 +92,6 @@ import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREENSHOT;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREEN_ON;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_STACK_CRAWLS;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
@@ -119,7 +118,6 @@ import static com.android.server.wm.WindowManagerService.logSurface;
import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP;
import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING;
import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW;
-import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE;
import android.annotation.CallSuper;
import android.annotation.NonNull;
@@ -2065,9 +2063,25 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
layoutAndAssignWindowLayersIfNeeded();
}
- int taskIdFromPoint(int x, int y) {
+ /**
+ * Used to obtain task ID when user taps on coordinate (x, y) in this display, and outside
+ * current task in focus.
+ *
+ * This returns the task ID of the foremost task at (x, y) if the task is not home. Otherwise it
+ * returns -1.
+ *
+ * @param x horizontal coordinate of the tap position
+ * @param y vertical coordinate of the tap position
+ * @return the task ID if a non-home task is found; -1 if not
+ */
+ int taskForTapOutside(int x, int y) {
for (int stackNdx = mTaskStackContainers.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
final TaskStack stack = mTaskStackContainers.getChildAt(stackNdx);
+ if (stack.isActivityTypeHome()) {
+ // We skip not only home stack, but also everything behind home because user can't
+ // see them.
+ break;
+ }
final int taskId = stack.taskIdFromPoint(x, y);
if (taskId != -1) {
return taskId;
diff --git a/services/core/java/com/android/server/wm/TaskPositioningController.java b/services/core/java/com/android/server/wm/TaskPositioningController.java
index b7e37b2fd47a..25148d15343a 100644
--- a/services/core/java/com/android/server/wm/TaskPositioningController.java
+++ b/services/core/java/com/android/server/wm/TaskPositioningController.java
@@ -88,7 +88,7 @@ class TaskPositioningController {
}
taskId = task.mTaskId;
} else {
- taskId = displayContent.taskIdFromPoint(x, y);
+ taskId = displayContent.taskForTapOutside(x, y);
}
}
if (taskId >= 0) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java
index b096bf2d0738..5410676a49fc 100644
--- a/services/core/java/com/android/server/wm/WindowManagerInternal.java
+++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java
@@ -430,25 +430,14 @@ public abstract class WindowManagerInternal {
public abstract boolean isUidFocused(int uid);
/**
- * Checks whether the specified IME client has IME focus or not.
+ * Checks whether the specified process has IME focus or not.
*
* @param uid UID of the process to be queried
* @param pid PID of the process to be queried
- * @param displayId Display ID reported from the client. Note that this method also verifies
- * whether the specified process is allowed to access to this display or not
- * @return {@code true} if the IME client specified with {@code uid}, {@code pid}, and
- * {@code displayId} has IME focus
+ * @return {@code true} if a process that is identified by {@code uid} and {@code pid} has IME
+ * focus
*/
- public abstract boolean isInputMethodClientFocus(int uid, int pid, int displayId);
-
- /**
- * Checks whether the given {@code uid} is allowed to use the given {@code displayId} or not.
- *
- * @param displayId Display ID to be checked
- * @param uid UID to be checked.
- * @return {@code true} if the given {@code uid} is allowed to use the given {@code displayId}
- */
- public abstract boolean isUidAllowedOnDisplay(int displayId, int uid);
+ public abstract boolean isInputMethodClientFocus(int uid, int pid);
/**
* Return the display Id for given window.
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index e153a1d6594e..14ea04073c66 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -45,8 +45,8 @@ import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHA
import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY;
+import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
@@ -1928,7 +1928,7 @@ public class WindowManagerService extends IWindowManager.Stub
mAccessibilityController.onSomeWindowResizedOrMovedLocked();
}
- if ((flagChanges & PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) != 0) {
+ if ((flagChanges & SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) != 0) {
updateNonSystemOverlayWindowsVisibilityIfNeeded(
win, win.mWinAnimator.getShown());
}
@@ -7201,20 +7201,16 @@ public class WindowManagerService extends IWindowManager.Stub
}
@Override
- public boolean isInputMethodClientFocus(int uid, int pid, int displayId) {
- if (displayId == Display.INVALID_DISPLAY) {
- return false;
- }
+ public boolean isInputMethodClientFocus(int uid, int pid) {
synchronized (mWindowMap) {
- final DisplayContent displayContent = mRoot.getTopFocusedDisplayContent();
- if (displayContent == null
- || displayContent.getDisplayId() != displayId
- || !displayContent.hasAccess(uid)) {
- return false;
- }
- if (displayContent.isInputMethodClientFocus(uid, pid)) {
- return true;
+ // Check all displays if any input method window has focus.
+ for (int i = mRoot.mChildren.size() - 1; i >= 0; --i) {
+ final DisplayContent displayContent = mRoot.mChildren.get(i);
+ if (displayContent.isInputMethodClientFocus(uid, pid)) {
+ return true;
+ }
}
+
// Okay, how about this... what is the current focus?
// It seems in some cases we may not have moved the IM
// target window, such as when it was in a pop-up window,
@@ -7223,7 +7219,7 @@ public class WindowManagerService extends IWindowManager.Stub
// press home. Sometimes the IME won't go down.)
// Would be nice to fix this more correctly, but it's
// way at the end of a release, and this should be good enough.
- final WindowState currentFocus = displayContent.mCurrentFocus;
+ final WindowState currentFocus = mRoot.getTopFocusedDisplayContent().mCurrentFocus;
if (currentFocus != null && currentFocus.mSession.mUid == uid
&& currentFocus.mSession.mPid == pid) {
return true;
@@ -7233,20 +7229,6 @@ public class WindowManagerService extends IWindowManager.Stub
}
@Override
- public boolean isUidAllowedOnDisplay(int displayId, int uid) {
- if (displayId == Display.DEFAULT_DISPLAY) {
- return true;
- }
- if (displayId == Display.INVALID_DISPLAY) {
- return false;
- }
- synchronized (mWindowMap) {
- final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
- return displayContent != null && displayContent.hasAccess(uid);
- }
- }
-
- @Override
public int getDisplayIdForWindow(IBinder windowToken) {
synchronized (mWindowMap) {
final WindowState window = mWindowMap.get(windowToken);
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 8276952d8a6c..eacbda198aba 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -46,12 +46,12 @@ import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import static android.view.WindowManager.LayoutParams.MATCH_PARENT;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
+import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
@@ -3470,7 +3470,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
* this window is visible.
*/
boolean hideNonSystemOverlayWindowsWhenVisible() {
- return (mAttrs.privateFlags & PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) != 0
+ return (mAttrs.privateFlags & SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) != 0
&& mSession.mCanHideNonSystemOverlayWindows;
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 52b849f93553..bbc4f4441294 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -468,6 +468,12 @@ public final class SystemServer {
}
}
+ // Diagnostic to ensure that the system is in a base healthy state. Done here as a common
+ // non-zygote process.
+ if (!VMRuntime.hasBootImageSpaces()) {
+ Slog.wtf(TAG, "Runtime is not running with a boot image!");
+ }
+
// Loop forever.
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
diff --git a/services/net/java/android/net/ip/IpNeighborMonitor.java b/services/net/java/android/net/ip/IpNeighborMonitor.java
index fc07aa1ecd17..9512f1be66ef 100644
--- a/services/net/java/android/net/ip/IpNeighborMonitor.java
+++ b/services/net/java/android/net/ip/IpNeighborMonitor.java
@@ -40,7 +40,6 @@ import android.util.Log;
import com.android.internal.util.BitUtils;
import libcore.io.IoUtils;
-import libcore.io.Libcore;
import java.io.FileDescriptor;
import java.net.InetAddress;
diff --git a/services/net/java/android/net/ip/RouterAdvertisementDaemon.java b/services/net/java/android/net/ip/RouterAdvertisementDaemon.java
index 9d686efcb2ab..d197d017acce 100644
--- a/services/net/java/android/net/ip/RouterAdvertisementDaemon.java
+++ b/services/net/java/android/net/ip/RouterAdvertisementDaemon.java
@@ -28,7 +28,6 @@ import android.net.TrafficStats;
import android.net.util.InterfaceParams;
import android.system.ErrnoException;
import android.system.Os;
-import android.system.StructGroupReq;
import android.system.StructTimeval;
import android.util.Log;
diff --git a/services/net/java/android/net/netlink/NetlinkSocket.java b/services/net/java/android/net/netlink/NetlinkSocket.java
index cfcba3a84f51..40098c1532b1 100644
--- a/services/net/java/android/net/netlink/NetlinkSocket.java
+++ b/services/net/java/android/net/netlink/NetlinkSocket.java
@@ -32,7 +32,6 @@ import android.system.Os;
import android.system.StructTimeval;
import android.util.Log;
import libcore.io.IoUtils;
-import libcore.io.Libcore;
import java.io.FileDescriptor;
import java.io.InterruptedIOException;
diff --git a/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java b/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
index fb57d68082a2..7a847f3284d2 100644
--- a/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
+++ b/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
@@ -726,6 +726,39 @@ public class KeyValueBackupTaskTest {
}
@Test
+ public void testRunTask_whenSecondAgentUnavailable_commitsFirstAgentState() throws Exception {
+ TransportMock transportMock = setUpInitializedTransport(mTransport);
+ AgentMock agentMock = setUpAgent(PACKAGE_1);
+ setUpAgent(PACKAGE_2.unavailable());
+ agentOnBackupDo(
+ agentMock,
+ (oldState, dataOutput, newState) -> {
+ writeData(dataOutput, "key", "data".getBytes());
+ writeState(newState, "newState".getBytes());
+ });
+ KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1, PACKAGE_2);
+
+ runTask(task);
+
+ assertThat(Files.readAllBytes(getStateFile(mTransport, PACKAGE_1))).isEqualTo(
+ "newState".getBytes());
+ }
+
+ @Test
+ public void testRunTask_whenNonIncrementalAndAgentUnavailable() throws Exception {
+ TransportMock transportMock = setUpInitializedTransport(mTransport);
+ setUpAgent(PACKAGE_1.unavailable());
+ KeyValueBackupTask task = createKeyValueBackupTask(transportMock, true, PACKAGE_1);
+
+ runTask(task);
+
+ verify(mBackupManagerService).setWorkSource(null);
+ verify(mObserver).onResult(PACKAGE_1.packageName, ERROR_AGENT_FAILURE);
+ verify(mObserver).backupFinished(BackupManager.SUCCESS);
+ assertBackupPendingFor(PACKAGE_1);
+ }
+
+ @Test
public void testRunTask_whenBindToAgentThrowsSecurityException() throws Exception {
TransportMock transportMock = setUpInitializedTransport(mTransport);
setUpAgent(PACKAGE_1);
@@ -743,6 +776,23 @@ public class KeyValueBackupTaskTest {
}
@Test
+ public void testRunTask_whenNonIncrementalAndBindToAgentThrowsSecurityException() throws Exception {
+ TransportMock transportMock = setUpInitializedTransport(mTransport);
+ setUpAgent(PACKAGE_1);
+ doThrow(SecurityException.class)
+ .when(mBackupManagerService)
+ .bindToAgentSynchronous(argThat(applicationInfo(PACKAGE_1)), anyInt());
+ KeyValueBackupTask task = createKeyValueBackupTask(transportMock, true, PACKAGE_1);
+
+ runTask(task);
+
+ verify(mBackupManagerService).setWorkSource(null);
+ verify(mObserver).onResult(PACKAGE_1.packageName, ERROR_AGENT_FAILURE);
+ verify(mObserver).backupFinished(BackupManager.SUCCESS);
+ assertBackupPendingFor(PACKAGE_1);
+ }
+
+ @Test
public void testRunTask_whenTransportGetBackupQuotaThrows_notifiesCorrectly() throws Exception {
TransportMock transportMock = setUpInitializedTransport(mTransport);
when(transportMock.transport.getBackupQuota(PACKAGE_1.packageName, false))
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityLaunchParamsModifierTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityLaunchParamsModifierTests.java
deleted file mode 100644
index 9de64f2cf211..000000000000
--- a/services/tests/servicestests/src/com/android/server/am/ActivityLaunchParamsModifierTests.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * 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.am;
-
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-
-import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_DONE;
-import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_SKIP;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import android.app.ActivityOptions;
-import android.content.pm.ActivityInfo;
-import android.graphics.Rect;
-import android.platform.test.annotations.Presubmit;
-
-import androidx.test.filters.MediumTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.server.am.LaunchParamsController.LaunchParams;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Tests for exercising resizing bounds due to activity options.
- *
- * Build/Install/Run:
- * atest FrameworksServicesTests:ActivityLaunchParamsModifierTests
- */
-@MediumTest
-@Presubmit
-@RunWith(AndroidJUnit4.class)
-public class ActivityLaunchParamsModifierTests extends ActivityTestsBase {
- private ActivityLaunchParamsModifier mModifier;
- private ActivityTaskManagerService mService;
- private ActivityStack mStack;
- private TaskRecord mTask;
- private ActivityRecord mActivity;
-
- private LaunchParams mCurrent;
- private LaunchParams mResult;
-
- @Before
- @Override
- public void setUp() throws Exception {
- super.setUp();
- mService = createActivityTaskManagerService();
- mModifier = new ActivityLaunchParamsModifier(mService.mStackSupervisor);
- mCurrent = new LaunchParams();
- mResult = new LaunchParams();
-
-
- mStack = mService.mStackSupervisor.getDefaultDisplay().createStack(
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
- mTask = new TaskBuilder(mService.mStackSupervisor).setStack(mStack).build();
- mActivity = new ActivityBuilder(mService).setTask(mTask).build();
- }
-
-
- @Test
- public void testSkippedInvocations() throws Exception {
- // No specified activity should be ignored
- assertEquals(RESULT_SKIP, mModifier.onCalculate(null /*task*/, null /*layout*/,
- null /*activity*/, null /*source*/, null /*options*/, mCurrent, mResult));
-
- // No specified activity options should be ignored
- assertEquals(RESULT_SKIP, mModifier.onCalculate(null /*task*/, null /*layout*/,
- mActivity, null /*source*/, null /*options*/, mCurrent, mResult));
-
- // launch bounds specified should be ignored.
- final ActivityOptions options = ActivityOptions.makeBasic();
- assertEquals(RESULT_SKIP, mModifier.onCalculate(null /*task*/, null /*layout*/,
- mActivity, null /*source*/, options /*options*/, mCurrent, mResult));
-
- // Non-resizeable records should be ignored
- mActivity.info.resizeMode = ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
- assertFalse(mActivity.isResizeable());
- assertEquals(RESULT_SKIP, mModifier.onCalculate(null /*task*/, null /*layout*/,
- mActivity, null /*source*/, options /*options*/, mCurrent, mResult));
-
- // make record resizeable
- mActivity.info.resizeMode = ActivityInfo.RESIZE_MODE_RESIZEABLE;
- assertTrue(mActivity.isResizeable());
-
- assertEquals(RESULT_SKIP, mModifier.onCalculate(null /*task*/, null /*layout*/,
- mActivity, null /*source*/, options /*options*/, mCurrent, mResult));
-
- // Does not support freeform
- mService.mSupportsFreeformWindowManagement = false;
- assertFalse(mService.mStackSupervisor.canUseActivityOptionsLaunchBounds(options));
- assertEquals(RESULT_SKIP, mModifier.onCalculate(null /*task*/, null /*layout*/,
- mActivity, null /*source*/, options /*options*/, mCurrent, mResult));
-
- mService.mSupportsFreeformWindowManagement = true;
- options.setLaunchBounds(new Rect());
- assertTrue(mService.mStackSupervisor.canUseActivityOptionsLaunchBounds(options));
-
- // Invalid bounds
- assertEquals(RESULT_SKIP, mModifier.onCalculate(null /*task*/, null /*layout*/,
- mActivity, null /*source*/, options /*options*/, mCurrent, mResult));
- options.setLaunchBounds(new Rect(0, 0, -1, -1));
- assertEquals(RESULT_SKIP, mModifier.onCalculate(null /*task*/, null /*layout*/,
- mActivity, null /*source*/, options /*options*/, mCurrent, mResult));
-
- // Valid bounds should cause the positioner to be applied.
- options.setLaunchBounds(new Rect(0, 0, 100, 100));
- assertEquals(RESULT_DONE, mModifier.onCalculate(null /*task*/, null /*layout*/,
- mActivity, null /*source*/, options /*options*/, mCurrent, mResult));
- }
-
- @Test
- public void testBoundsExtraction() throws Exception {
- // Make activity resizeable and enable freeform mode.
- mActivity.info.resizeMode = ActivityInfo.RESIZE_MODE_RESIZEABLE;
- mService.mSupportsFreeformWindowManagement = true;
-
- ActivityOptions options = ActivityOptions.makeBasic();
- final Rect proposedBounds = new Rect(20, 30, 45, 40);
- options.setLaunchBounds(proposedBounds);
-
- assertEquals(RESULT_DONE, mModifier.onCalculate(null /*task*/, null /*layout*/,
- mActivity, null /*source*/, options /*options*/, mCurrent, mResult));
- assertEquals(mResult.mBounds, proposedBounds);
- }
-}
diff --git a/services/tests/servicestests/src/com/android/server/am/TaskLaunchParamsModifierTests.java b/services/tests/servicestests/src/com/android/server/am/TaskLaunchParamsModifierTests.java
index f5b8f78cfd53..0d1302f78316 100644
--- a/services/tests/servicestests/src/com/android/server/am/TaskLaunchParamsModifierTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/TaskLaunchParamsModifierTests.java
@@ -11,239 +11,1098 @@
* 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
+ * limitations under the License.
*/
package com.android.server.am;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LOCKED;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
+import static android.util.DisplayMetrics.DENSITY_DEFAULT;
+import static android.view.Display.DEFAULT_DISPLAY;
import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_CONTINUE;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
-import android.content.pm.ActivityInfo.WindowLayout;
+import android.app.ActivityOptions;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.res.Configuration;
import android.graphics.Rect;
+import android.os.Build;
import android.platform.test.annotations.Presubmit;
import android.view.Gravity;
-import androidx.test.filters.MediumTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.filters.FlakyTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.server.am.LaunchParamsController.LaunchParams;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.Locale;
+
/**
- * Tests for exercising resizing task bounds.
+ * Tests for default task bounds.
*
* Build/Install/Run:
* atest FrameworksServicesTests:TaskLaunchParamsModifierTests
*/
-@MediumTest
+@SmallTest
@Presubmit
@RunWith(AndroidJUnit4.class)
+@FlakyTest(detail = "Confirm stable in post-submit before removing")
public class TaskLaunchParamsModifierTests extends ActivityTestsBase {
- private final static int STACK_WIDTH = 100;
- private final static int STACK_HEIGHT = 200;
-
- private final static Rect STACK_BOUNDS = new Rect(0, 0, STACK_WIDTH, STACK_HEIGHT);
- private ActivityTaskManagerService mService;
- private ActivityStack mStack;
- private TaskRecord mTask;
+ private ActivityRecord mActivity;
- private TaskLaunchParamsModifier mPositioner;
+ private TaskLaunchParamsModifier mTarget;
- private LaunchParamsController.LaunchParams mCurrent;
- private LaunchParamsController.LaunchParams mResult;
+ private LaunchParams mCurrent;
+ private LaunchParams mResult;
@Before
@Override
public void setUp() throws Exception {
super.setUp();
- mService = createActivityTaskManagerService();
- mStack = mService.mStackSupervisor.getDefaultDisplay().createStack(
- WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD, true /* onTop */);
- mStack.requestResize(STACK_BOUNDS);
+ setupActivityTaskManagerService();
+ mService.mSupportsFreeformWindowManagement = true;
+ when(mSupervisor.canUseActivityOptionsLaunchBounds(any())).thenCallRealMethod();
+
+ mActivity = new ActivityBuilder(mService).build();
+ mActivity.appInfo.targetSdkVersion = Build.VERSION_CODES.N_MR1;
+ mActivity.info.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES;
+
+ mTarget = new TaskLaunchParamsModifier(mSupervisor);
+
+ mCurrent = new LaunchParams();
+ mCurrent.reset();
+ mResult = new LaunchParams();
+ mResult.reset();
+ }
- // We must create the task after resizing to make sure it does not inherit the stack
- // dimensions on resize.
- mTask = new TaskBuilder(mService.mStackSupervisor).setStack(mStack).build();
+ // =============================
+ // Display ID Related Tests
+ // =============================
+ @Test
+ public void testDefaultToPrimaryDisplay() {
+ createNewActivityDisplay(WINDOWING_MODE_FREEFORM);
- mPositioner = new TaskLaunchParamsModifier();
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+ mActivity, /* source */ null, /* options */ null, mCurrent, mResult));
- mResult = new LaunchParamsController.LaunchParams();
- mCurrent = new LaunchParamsController.LaunchParams();
+ assertEquals(DEFAULT_DISPLAY, mResult.mPreferredDisplayId);
}
- /**
- * Ensures that the setup bounds are set as expected with the stack bounds set and the task
- * bounds still {@code null}.
- * @throws Exception
- */
@Test
- public void testInitialBounds() throws Exception {
- assertEquals(mStack.getOverrideBounds(), STACK_BOUNDS);
- assertEquals(mTask.getOverrideBounds(), new Rect());
+ public void testUsesPreviousDisplayIdIfSet() {
+ createNewActivityDisplay(WINDOWING_MODE_FREEFORM);
+ final TestActivityDisplay display = createNewActivityDisplay(WINDOWING_MODE_FULLSCREEN);
+
+ mCurrent.mPreferredDisplayId = display.mDisplayId;
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+ mActivity, /* source */ null, /* options */ null, mCurrent, mResult));
+
+ assertEquals(display.mDisplayId, mResult.mPreferredDisplayId);
}
- /**
- * Ensures that a task positioned with no {@link WindowLayout} receives the default launch
- * position.
- * @throws Exception
- */
@Test
- public void testLaunchNoWindowLayout() throws Exception {
- assertEquals(RESULT_CONTINUE, mPositioner.onCalculate(mTask, null /*layout*/,
- null /*record*/, null /*source*/, null /*options*/, mCurrent, mResult));
- assertEquals(getDefaultBounds(Gravity.NO_GRAVITY), mResult.mBounds);
+ public void testUsesSourcesDisplayIdIfSet() {
+ final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+ WINDOWING_MODE_FREEFORM);
+ final TestActivityDisplay fullscreenDisplay = createNewActivityDisplay(
+ WINDOWING_MODE_FULLSCREEN);
+
+ mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+
+ ActivityRecord source = createSourceActivity(fullscreenDisplay);
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+ mActivity, source, /* options */ null, mCurrent, mResult));
+
+ assertEquals(fullscreenDisplay.mDisplayId, mResult.mPreferredDisplayId);
}
- /**
- * Ensures that a task positioned with an empty {@link WindowLayout} receives the default launch
- * position.
- * @throws Exception
- */
@Test
- public void testlaunchEmptyWindowLayout() throws Exception {
- assertEquals(RESULT_CONTINUE, mPositioner.onCalculate(mTask,
- new WindowLayout(0, 0, 0, 0, Gravity.NO_GRAVITY, 0, 0), null /*activity*/,
- null /*source*/, null /*options*/, mCurrent, mResult));
- assertEquals(mResult.mBounds, getDefaultBounds(Gravity.NO_GRAVITY));
+ public void testUsesOptionsDisplayIdIfSet() {
+ final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+ WINDOWING_MODE_FREEFORM);
+ final TestActivityDisplay fullscreenDisplay = createNewActivityDisplay(
+ WINDOWING_MODE_FULLSCREEN);
+
+ mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+ ActivityRecord source = createSourceActivity(freeformDisplay);
+
+ ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchDisplayId(fullscreenDisplay.mDisplayId);
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+ mActivity, source, options, mCurrent, mResult));
+
+ assertEquals(fullscreenDisplay.mDisplayId, mResult.mPreferredDisplayId);
}
- /**
- * Ensures that a task positioned with a {@link WindowLayout} gravity specified is positioned
- * according to specification.
- * @throws Exception
- */
+ // =====================================
+ // Launch Windowing Mode Related Tests
+ // =====================================
@Test
- public void testlaunchWindowLayoutGravity() throws Exception {
- // Unspecified gravity should be ignored
- testGravity(Gravity.NO_GRAVITY);
+ public void testBoundsInOptionsInfersFreeformOnFreeformDisplay() {
+ final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+ WINDOWING_MODE_FREEFORM);
+
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchBounds(new Rect(0, 0, 100, 100));
- // Unsupported gravity should be ignored
- testGravity(Gravity.LEFT);
- testGravity(Gravity.RIGHT);
+ mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
- // Test defaults for vertical gravities
- testGravity(Gravity.TOP);
- testGravity(Gravity.BOTTOM);
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+ mActivity, /* source */ null, options, mCurrent, mResult));
- // Test corners
- testGravity(Gravity.TOP | Gravity.LEFT);
- testGravity(Gravity.TOP | Gravity.RIGHT);
- testGravity(Gravity.BOTTOM | Gravity.LEFT);
- testGravity(Gravity.BOTTOM | Gravity.RIGHT);
+ assertEquivalentWindowingMode(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode,
+ WINDOWING_MODE_FREEFORM);
}
- private void testGravity(int gravity) {
- try {
- assertEquals(RESULT_CONTINUE, mPositioner.onCalculate(mTask,
- new WindowLayout(0, 0, 0, 0, gravity, 0, 0), null /*activity*/,
- null /*source*/, null /*options*/, mCurrent, mResult));
- assertEquals(mResult.mBounds, getDefaultBounds(gravity));
- } finally {
- mCurrent.reset();
- mResult.reset();
- }
+ @Test
+ public void testBoundsInOptionsInfersFreeformWithResizeableActivity() {
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchBounds(new Rect(0, 0, 100, 100));
+
+ mCurrent.mPreferredDisplayId = DEFAULT_DISPLAY;
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+ mActivity, /* source */ null, options, mCurrent, mResult));
+
+ assertEquivalentWindowingMode(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode,
+ WINDOWING_MODE_FULLSCREEN);
+ }
+
+ @Test
+ public void testKeepsPictureInPictureLaunchModeInOptions() {
+ final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+ WINDOWING_MODE_FREEFORM);
+
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchWindowingMode(WINDOWING_MODE_PINNED);
+
+ mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+ mActivity, /* source */ null, options, mCurrent, mResult));
+
+ assertEquivalentWindowingMode(WINDOWING_MODE_PINNED, mResult.mWindowingMode,
+ WINDOWING_MODE_FREEFORM);
+ }
+
+ @Test
+ public void testKeepsPictureInPictureLaunchModeWithBoundsInOptions() {
+ final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+ WINDOWING_MODE_FREEFORM);
+
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchWindowingMode(WINDOWING_MODE_PINNED);
+ options.setLaunchBounds(new Rect(0, 0, 100, 100));
+
+ mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+ mActivity, /* source */ null, options, mCurrent, mResult));
+
+ assertEquivalentWindowingMode(WINDOWING_MODE_PINNED, mResult.mWindowingMode,
+ WINDOWING_MODE_FREEFORM);
+ }
+
+ @Test
+ public void testKeepsFullscreenLaunchModeInOptionsOnNonFreeformDisplay() {
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN);
+
+ mCurrent.mPreferredDisplayId = DEFAULT_DISPLAY;
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+ mActivity, /* source */ null, options, mCurrent, mResult));
+
+ assertEquivalentWindowingMode(WINDOWING_MODE_FULLSCREEN, mResult.mWindowingMode,
+ WINDOWING_MODE_FULLSCREEN);
+ }
+
+ @Test
+ public void testNonEmptyLayoutInfersFreeformOnFreeformDisplay() {
+ final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+ WINDOWING_MODE_FREEFORM);
+
+ mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+
+ final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
+ .setWidth(120).setHeight(80).build();
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
+ /* source */ null, /* options */ null, mCurrent, mResult));
+
+ assertEquivalentWindowingMode(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode,
+ WINDOWING_MODE_FREEFORM);
+ }
+
+ @Test
+ public void testNonEmptyLayoutInfersFreeformWithEmptySize() {
+ final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+ WINDOWING_MODE_FREEFORM);
+
+ mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+
+ final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
+ .setGravity(Gravity.LEFT).build();
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
+ /* source */ null, /* options */ null, mCurrent, mResult));
+
+ assertEquivalentWindowingMode(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode,
+ WINDOWING_MODE_FREEFORM);
+ }
+
+ @Test
+ public void testNonEmptyLayoutInfersFreeformWithResizeableActivity() {
+ final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
+ .setWidth(120).setHeight(80).build();
+
+ mCurrent.mPreferredDisplayId = DEFAULT_DISPLAY;
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
+ /* source */ null, /* options */ null, mCurrent, mResult));
+
+ assertEquivalentWindowingMode(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode,
+ WINDOWING_MODE_FULLSCREEN);
+ }
+
+ @Test
+ public void testRespectsFullyResolvedCurrentParam_Fullscreen() {
+ final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+ WINDOWING_MODE_FREEFORM);
+
+ mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+ mCurrent.mWindowingMode = WINDOWING_MODE_FULLSCREEN;
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+ mActivity, /* source */ null, /* options */ null, mCurrent, mResult));
+
+ assertEquivalentWindowingMode(WINDOWING_MODE_FULLSCREEN, mResult.mWindowingMode,
+ WINDOWING_MODE_FREEFORM);
+ }
+
+ @Test
+ public void testRespectsModeFromFullyResolvedCurrentParam_NonEmptyBounds() {
+ final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+ WINDOWING_MODE_FREEFORM);
+
+ mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+ mCurrent.mWindowingMode = WINDOWING_MODE_FREEFORM;
+ mCurrent.mBounds.set(0, 0, 200, 100);
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+ mActivity, /* source */ null, /* options */ null, mCurrent, mResult));
+
+ assertEquivalentWindowingMode(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode,
+ WINDOWING_MODE_FREEFORM);
+ }
+
+ @Test
+ public void testForceMaximizesPreDApp() {
+ final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+ WINDOWING_MODE_FREEFORM);
+
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchWindowingMode(WINDOWING_MODE_FREEFORM);
+ options.setLaunchBounds(new Rect(0, 0, 200, 100));
+
+ mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+ mCurrent.mWindowingMode = WINDOWING_MODE_FREEFORM;
+ mCurrent.mBounds.set(0, 0, 200, 100);
+
+ mActivity.appInfo.targetSdkVersion = Build.VERSION_CODES.CUPCAKE;
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+ mActivity, /* source */ null, options, mCurrent, mResult));
+
+ assertEquivalentWindowingMode(WINDOWING_MODE_FULLSCREEN, mResult.mWindowingMode,
+ WINDOWING_MODE_FREEFORM);
+ }
+
+ @Test
+ public void testForceMaximizesAppWithoutMultipleDensitySupport() {
+ final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+ WINDOWING_MODE_FREEFORM);
+
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchWindowingMode(WINDOWING_MODE_FREEFORM);
+ options.setLaunchBounds(new Rect(0, 0, 200, 100));
+
+ mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+ mCurrent.mWindowingMode = WINDOWING_MODE_FREEFORM;
+ mCurrent.mBounds.set(0, 0, 200, 100);
+
+ mActivity.appInfo.flags = 0;
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+ mActivity, /* source */ null, options, mCurrent, mResult));
+
+ assertEquivalentWindowingMode(WINDOWING_MODE_FULLSCREEN, mResult.mWindowingMode,
+ WINDOWING_MODE_FREEFORM);
+ }
+
+ @Test
+ public void testForceMaximizesUnresizeableApp() {
+ final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+ WINDOWING_MODE_FREEFORM);
+
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchWindowingMode(WINDOWING_MODE_FREEFORM);
+ options.setLaunchBounds(new Rect(0, 0, 200, 100));
+
+ mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+ mCurrent.mWindowingMode = WINDOWING_MODE_FREEFORM;
+ mCurrent.mBounds.set(0, 0, 200, 100);
+
+ mActivity.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+ mActivity, /* source */ null, options, mCurrent, mResult));
+
+ assertEquivalentWindowingMode(WINDOWING_MODE_FULLSCREEN, mResult.mWindowingMode,
+ WINDOWING_MODE_FREEFORM);
+ }
+
+ @Test
+ public void testSkipsForceMaximizingAppsOnNonFreeformDisplay() {
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchWindowingMode(WINDOWING_MODE_FREEFORM);
+ options.setLaunchBounds(new Rect(0, 0, 200, 100));
+
+ mCurrent.mPreferredDisplayId = DEFAULT_DISPLAY;
+ mCurrent.mWindowingMode = WINDOWING_MODE_FREEFORM;
+ mCurrent.mBounds.set(0, 0, 200, 100);
+
+ mActivity.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+ mActivity, /* source */ null, options, mCurrent, mResult));
+
+ assertEquivalentWindowingMode(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode,
+ WINDOWING_MODE_FULLSCREEN);
+ }
+
+ @Test
+ public void testUsesFullscreenOnNonFreeformDisplay() {
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchDisplayId(DEFAULT_DISPLAY);
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+ mActivity, /* source */ null, options, mCurrent, mResult));
+
+ assertEquivalentWindowingMode(WINDOWING_MODE_FULLSCREEN, mResult.mWindowingMode,
+ WINDOWING_MODE_FULLSCREEN);
+ }
+
+ @Test
+ public void testUsesFreeformByDefaultForPostNApp() {
+ final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+ WINDOWING_MODE_FREEFORM);
+
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchDisplayId(freeformDisplay.mDisplayId);
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+ mActivity, /* source */ null, options, mCurrent, mResult));
+
+ assertEquivalentWindowingMode(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode,
+ WINDOWING_MODE_FREEFORM);
+ }
+
+ @Test
+ public void testUsesFreeformByDefaultForPreNResizeableAppWithoutOrientationRequest() {
+ final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+ WINDOWING_MODE_FREEFORM);
+
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchDisplayId(freeformDisplay.mDisplayId);
+
+ mActivity.appInfo.targetSdkVersion = Build.VERSION_CODES.LOLLIPOP;
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+ mActivity, /* source */ null, options, mCurrent, mResult));
+
+ assertEquivalentWindowingMode(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode,
+ WINDOWING_MODE_FREEFORM);
+ }
+
+ @Test
+ public void testSkipsFreeformForPreNResizeableAppOnNonFullscreenDisplay() {
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchDisplayId(DEFAULT_DISPLAY);
+
+ mActivity.appInfo.targetSdkVersion = Build.VERSION_CODES.LOLLIPOP;
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+ mActivity, /* source */ null, options, mCurrent, mResult));
+
+ assertEquivalentWindowingMode(WINDOWING_MODE_FULLSCREEN, mResult.mWindowingMode,
+ WINDOWING_MODE_FULLSCREEN);
+ }
+
+ // ================================
+ // Launching Bounds Related Tests
+ // ===============================
+ @Test
+ public void testKeepsBoundsWithPictureInPictureLaunchModeInOptions() {
+ final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+ WINDOWING_MODE_FREEFORM);
+
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchWindowingMode(WINDOWING_MODE_PINNED);
+
+ final Rect expected = new Rect(0, 0, 100, 100);
+ options.setLaunchBounds(expected);
+
+ mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+ mActivity, /* source */ null, options, mCurrent, mResult));
+
+ assertEquals(expected, mResult.mBounds);
+ }
+
+ @Test
+ public void testNonEmptyLayoutBoundsRespectsGravityWithEmptySize_LeftGravity() {
+ final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+ WINDOWING_MODE_FREEFORM);
+
+ mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+
+ final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
+ .setGravity(Gravity.LEFT).build();
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
+ /* source */ null, /* options */ null, mCurrent, mResult));
+
+ assertEquals(0, mResult.mBounds.left);
+ }
+
+ @Test
+ public void testNonEmptyLayoutBoundsRespectsGravityWithEmptySize_TopGravity() {
+ final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+ WINDOWING_MODE_FREEFORM);
+
+ mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+
+ final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
+ .setGravity(Gravity.TOP).build();
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
+ /* source */ null, /* options */ null, mCurrent, mResult));
+
+ assertEquals(0, mResult.mBounds.top);
+ }
+
+ @Test
+ public void testNonEmptyLayoutBoundsRespectsGravityWithEmptySize_TopLeftGravity() {
+ final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+ WINDOWING_MODE_FREEFORM);
+
+ mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+
+ final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
+ .setGravity(Gravity.TOP | Gravity.LEFT).build();
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
+ /* source */ null, /* options */ null, mCurrent, mResult));
+
+ assertEquals(0, mResult.mBounds.left);
+ assertEquals(0, mResult.mBounds.top);
+ }
+
+ @Test
+ public void testNonEmptyLayoutBoundsRespectsGravityWithEmptySize_RightGravity() {
+ final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+ WINDOWING_MODE_FREEFORM);
+
+ mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+
+ final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
+ .setGravity(Gravity.RIGHT).build();
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
+ /* source */ null, /* options */ null, mCurrent, mResult));
+
+ assertEquals(1920, mResult.mBounds.right);
+ }
+
+ @Test
+ public void testNonEmptyLayoutBoundsRespectsGravityWithEmptySize_BottomGravity() {
+ final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+ WINDOWING_MODE_FREEFORM);
+
+ mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+
+ final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
+ .setGravity(Gravity.BOTTOM).build();
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
+ /* source */ null, /* options */ null, mCurrent, mResult));
+
+ assertEquals(1080, mResult.mBounds.bottom);
+ }
+
+ @Test
+ public void testNonEmptyLayoutBoundsRespectsGravityWithEmptySize_BottomRightGravity() {
+ final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+ WINDOWING_MODE_FREEFORM);
+
+ mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+
+ final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
+ .setGravity(Gravity.BOTTOM | Gravity.RIGHT).build();
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
+ /* source */ null, /* options */ null, mCurrent, mResult));
+
+ assertEquals(1920, mResult.mBounds.right);
+ assertEquals(1080, mResult.mBounds.bottom);
+ }
+
+ @Test
+ public void testNonEmptyLayoutBoundsOnFreeformDisplay_CenterToDisplay() {
+ final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+ WINDOWING_MODE_FREEFORM);
+
+ mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+
+ final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
+ .setWidth(120).setHeight(80).build();
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
+ /* source */ null, /* options */ null, mCurrent, mResult));
+
+ assertEquals(new Rect(900, 500, 1020, 580), mResult.mBounds);
+ }
+
+ @Test
+ public void testNonEmptyLayoutBoundsOnFreeformDisplay_LeftGravity() {
+ final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+ WINDOWING_MODE_FREEFORM);
+
+ mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+
+ final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
+ .setWidth(120).setHeight(80).setGravity(Gravity.LEFT).build();
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
+ /* source */ null, /* options */ null, mCurrent, mResult));
+
+ assertEquals(new Rect(0, 500, 120, 580), mResult.mBounds);
+ }
+
+ @Test
+ public void testNonEmptyLayoutBoundsOnFreeformDisplay_TopGravity() {
+ final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+ WINDOWING_MODE_FREEFORM);
+
+ mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+
+ final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
+ .setWidth(120).setHeight(80).setGravity(Gravity.TOP).build();
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
+ /* source */ null, /* options */ null, mCurrent, mResult));
+
+ assertEquals(new Rect(900, 0, 1020, 80), mResult.mBounds);
+ }
+
+ @Test
+ public void testNonEmptyLayoutBoundsOnFreeformDisplay_TopLeftGravity() {
+ final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+ WINDOWING_MODE_FREEFORM);
+
+ mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+
+ final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
+ .setWidth(120).setHeight(80).setGravity(Gravity.TOP | Gravity.LEFT).build();
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
+ /* source */ null, /* options */ null, mCurrent, mResult));
+
+ assertEquals(new Rect(0, 0, 120, 80), mResult.mBounds);
+ }
+
+ @Test
+ public void testNonEmptyLayoutBoundsOnFreeformDisplay_RightGravity() {
+ final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+ WINDOWING_MODE_FREEFORM);
+
+ mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+
+ final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
+ .setWidth(120).setHeight(80).setGravity(Gravity.RIGHT).build();
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
+ /* source */ null, /* options */ null, mCurrent, mResult));
+
+ assertEquals(new Rect(1800, 500, 1920, 580), mResult.mBounds);
+ }
+
+ @Test
+ public void testNonEmptyLayoutBoundsOnFreeformDisplay_BottomGravity() {
+ final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+ WINDOWING_MODE_FREEFORM);
+
+ mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+
+ final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
+ .setWidth(120).setHeight(80).setGravity(Gravity.BOTTOM).build();
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
+ /* source */ null, /* options */ null, mCurrent, mResult));
+
+ assertEquals(new Rect(900, 1000, 1020, 1080), mResult.mBounds);
+ }
+
+ @Test
+ public void testNonEmptyLayoutBoundsOnFreeformDisplay_RightBottomGravity() {
+ final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+ WINDOWING_MODE_FREEFORM);
+
+ mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+
+ final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
+ .setWidth(120).setHeight(80).setGravity(Gravity.BOTTOM | Gravity.RIGHT).build();
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
+ /* source */ null, /* options */ null, mCurrent, mResult));
+
+ assertEquals(new Rect(1800, 1000, 1920, 1080), mResult.mBounds);
+ }
+
+ @Test
+ public void testNonEmptyLayoutFractionBoundsOnFreeformDisplay() {
+ final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+ WINDOWING_MODE_FREEFORM);
+
+ mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+
+ final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
+ .setWidthFraction(0.0625f).setHeightFraction(0.1f).build();
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
+ /* source */ null, /* options */ null, mCurrent, mResult));
+
+ assertEquals(new Rect(900, 486, 1020, 594), mResult.mBounds);
+ }
+
+ @Test
+ public void testNonEmptyLayoutBoundsWithResizeableActivity() {
+ final ActivityDisplay display = mSupervisor.getActivityDisplay(DEFAULT_DISPLAY);
+ display.setBounds(new Rect(0, 0, 1920, 1080));
+ final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
+ .setWidth(120).setHeight(80).build();
+
+ mCurrent.mPreferredDisplayId = DEFAULT_DISPLAY;
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
+ /* source */ null, /* options */ null, mCurrent, mResult));
+
+ assertEquals(new Rect(900, 500, 1020, 580), mResult.mBounds);
+ }
+
+ @Test
+ public void testRespectBoundsFromFullyResolvedCurrentParam_NonEmptyBounds() {
+ final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+ WINDOWING_MODE_FREEFORM);
+
+ mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+ mCurrent.mWindowingMode = WINDOWING_MODE_FREEFORM;
+ mCurrent.mBounds.set(0, 0, 200, 100);
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+ mActivity, /* source */ null, /* options */ null, mCurrent, mResult));
+
+ assertEquals(new Rect(0, 0, 200, 100), mResult.mBounds);
+ }
+
+ @Test
+ public void testDefaultSizeSmallerThanBigScreen() {
+ final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+ WINDOWING_MODE_FREEFORM);
+
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchDisplayId(freeformDisplay.mDisplayId);
+
+ mActivity.appInfo.targetSdkVersion = Build.VERSION_CODES.LOLLIPOP;
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+ mActivity, /* source */ null, options, mCurrent, mResult));
+
+ final int resultWidth = mResult.mBounds.width();
+ final int displayWidth = freeformDisplay.getBounds().width();
+ assertTrue("Result width " + resultWidth + " is not smaller than " + displayWidth,
+ resultWidth < displayWidth);
+
+ final int resultHeight = mResult.mBounds.height();
+ final int displayHeight = freeformDisplay.getBounds().height();
+ assertTrue("Result width " + resultHeight + " is not smaller than "
+ + displayHeight, resultHeight < displayHeight);
+ }
+
+ @Test
+ public void testDefaultFreeformSizeCenteredToDisplay() {
+ final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+ WINDOWING_MODE_FREEFORM);
+
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchDisplayId(freeformDisplay.mDisplayId);
+
+ mActivity.appInfo.targetSdkVersion = Build.VERSION_CODES.LOLLIPOP;
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+ mActivity, /* source */ null, options, mCurrent, mResult));
+
+ final Rect displayBounds = freeformDisplay.getBounds();
+ assertEquals("Distance to left and right should be equal.",
+ mResult.mBounds.left - displayBounds.left,
+ displayBounds.right - mResult.mBounds.right);
+ assertEquals("Distance to top and bottom should be equal.",
+ mResult.mBounds.top - displayBounds.top,
+ displayBounds.bottom - mResult.mBounds.bottom);
+ }
+
+ @Test
+ public void testCascadesToSourceSizeForFreeform() {
+ final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+ WINDOWING_MODE_FREEFORM);
+
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchDisplayId(freeformDisplay.mDisplayId);
+
+ final ActivityRecord source = createSourceActivity(freeformDisplay);
+ source.setBounds(0, 0, 412, 732);
+
+ mActivity.appInfo.targetSdkVersion = Build.VERSION_CODES.LOLLIPOP;
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+ mActivity, source, options, mCurrent, mResult));
+
+ final Rect displayBounds = freeformDisplay.getBounds();
+ assertTrue("Left bounds should be larger than 0.", mResult.mBounds.left > 0);
+ assertTrue("Top bounds should be larger than 0.", mResult.mBounds.top > 0);
+ assertTrue("Bounds should be centered at somewhere in the left half, but it's "
+ + "centerX is " + mResult.mBounds.centerX(),
+ mResult.mBounds.centerX() < displayBounds.centerX());
+ assertTrue("Bounds should be centered at somewhere in the top half, but it's "
+ + "centerY is " + mResult.mBounds.centerY(),
+ mResult.mBounds.centerY() < displayBounds.centerY());
+ }
+
+ @Test
+ public void testAdjustBoundsToFitDisplay_TopLeftOutOfDisplay() {
+ final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+ WINDOWING_MODE_FREEFORM);
+
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchDisplayId(freeformDisplay.mDisplayId);
+
+ final ActivityRecord source = createSourceActivity(freeformDisplay);
+ source.setBounds(0, 0, 200, 400);
+
+ mActivity.appInfo.targetSdkVersion = Build.VERSION_CODES.LOLLIPOP;
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+ mActivity, source, options, mCurrent, mResult));
+
+ final Rect displayBounds = freeformDisplay.getBounds();
+ assertTrue("display bounds doesn't contain result. display bounds: "
+ + displayBounds + " result: " + mResult.mBounds,
+ displayBounds.contains(mResult.mBounds));
+ }
+
+ @Test
+ public void testAdjustBoundsToFitDisplay_BottomRightOutOfDisplay() {
+ final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+ WINDOWING_MODE_FREEFORM);
+
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchDisplayId(freeformDisplay.mDisplayId);
+
+ final ActivityRecord source = createSourceActivity(freeformDisplay);
+ source.setBounds(1720, 680, 1920, 1080);
+
+ mActivity.appInfo.targetSdkVersion = Build.VERSION_CODES.LOLLIPOP;
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+ mActivity, source, options, mCurrent, mResult));
+
+ final Rect displayBounds = freeformDisplay.getBounds();
+ assertTrue("display bounds doesn't contain result. display bounds: "
+ + displayBounds + " result: " + mResult.mBounds,
+ displayBounds.contains(mResult.mBounds));
+ }
+
+ @Test
+ public void testAdjustBoundsToFitDisplay_LargerThanDisplay() {
+ final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+ WINDOWING_MODE_FREEFORM);
+
+ Configuration overrideConfig = new Configuration();
+ overrideConfig.setTo(mSupervisor.getOverrideConfiguration());
+ overrideConfig.setLayoutDirection(new Locale("ar"));
+ mSupervisor.onConfigurationChanged(overrideConfig);
+
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchDisplayId(freeformDisplay.mDisplayId);
+
+ final ActivityRecord source = createSourceActivity(freeformDisplay);
+ source.setBounds(1720, 680, 1920, 1080);
+
+ mActivity.appInfo.targetSdkVersion = Build.VERSION_CODES.LOLLIPOP;
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+ mActivity, source, options, mCurrent, mResult));
+
+ final Rect displayBounds = freeformDisplay.getBounds();
+ assertTrue("display bounds doesn't contain result. display bounds: "
+ + displayBounds + " result: " + mResult.mBounds,
+ displayBounds.contains(mResult.mBounds));
}
- /**
- * Ensures that a task which causes a conflict with another task when positioned is adjusted as
- * expected.
- * @throws Exception
- */
- @Test
- public void testLaunchWindowCenterConflict() throws Exception {
- testConflict(Gravity.NO_GRAVITY);
- testConflict(Gravity.TOP);
- testConflict(Gravity.BOTTOM);
- testConflict(Gravity.TOP | Gravity.LEFT);
- testConflict(Gravity.TOP | Gravity.RIGHT);
- testConflict(Gravity.BOTTOM | Gravity.LEFT);
- testConflict(Gravity.BOTTOM | Gravity.RIGHT);
- }
-
- private void testConflict(int gravity) {
- final WindowLayout layout = new WindowLayout(0, 0, 0, 0, gravity, 0, 0);
-
- // layout first task
- mService.mStackSupervisor.getLaunchParamsController().layoutTask(mTask, layout);
-
- // Second task will be laid out on top of the first so starting bounds is the same.
- final Rect expectedBounds = new Rect(mTask.getOverrideBounds());
-
- ActivityRecord activity = null;
- TaskRecord secondTask = null;
-
- // wrap with try/finally to ensure cleanup of activity/stack.
- try {
- // empty tasks are ignored in conflicts
- activity = new ActivityBuilder(mService).setTask(mTask).build();
-
- // Create secondary task
- secondTask = new TaskBuilder(mService.mStackSupervisor).setStack(mStack).build();
-
- // layout second task
- assertEquals(RESULT_CONTINUE,
- mPositioner.onCalculate(secondTask, layout, null /*activity*/,
- null /*source*/, null /*options*/, mCurrent, mResult));
-
- if ((gravity & (Gravity.TOP | Gravity.RIGHT)) == (Gravity.TOP | Gravity.RIGHT)
- || (gravity & (Gravity.BOTTOM | Gravity.RIGHT))
- == (Gravity.BOTTOM | Gravity.RIGHT)) {
- expectedBounds.offset(-TaskLaunchParamsModifier.getHorizontalStep(
- mStack.getOverrideBounds()), 0);
- } else if ((gravity & Gravity.TOP) == Gravity.TOP
- || (gravity & Gravity.BOTTOM) == Gravity.BOTTOM) {
- expectedBounds.offset(
- TaskLaunchParamsModifier.getHorizontalStep(mStack.getOverrideBounds()), 0);
- } else {
- expectedBounds.offset(
- TaskLaunchParamsModifier.getHorizontalStep(mStack.getOverrideBounds()),
- TaskLaunchParamsModifier.getVerticalStep(mStack.getOverrideBounds()));
- }
-
- assertEquals(mResult.mBounds, expectedBounds);
- } finally {
- // Remove task and activity to prevent influencing future tests
- if (activity != null) {
- mTask.removeActivity(activity);
- }
-
- if (secondTask != null) {
- mStack.removeTask(secondTask, "cleanup", ActivityStack.REMOVE_TASK_MODE_DESTROYING);
- }
+ @Test
+ public void testRespectsLayoutMinDimensions() {
+ final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+ WINDOWING_MODE_FREEFORM);
+
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchDisplayId(freeformDisplay.mDisplayId);
+
+ final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
+ .setMinWidth(500).setMinHeight(800).build();
+
+ mActivity.appInfo.targetSdkVersion = Build.VERSION_CODES.LOLLIPOP;
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
+ /* source */ null, options, mCurrent, mResult));
+
+ assertEquals(500, mResult.mBounds.width());
+ assertEquals(800, mResult.mBounds.height());
+ }
+
+ @Test
+ public void testRotatesInPlaceInitialBoundsMismatchOrientation() {
+ final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+ WINDOWING_MODE_FREEFORM);
+
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchDisplayId(freeformDisplay.mDisplayId);
+ options.setLaunchBounds(new Rect(100, 100, 500, 300));
+
+ mActivity.info.screenOrientation = SCREEN_ORIENTATION_PORTRAIT;
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+ mActivity, /* source */ null, options, mCurrent, mResult));
+
+ assertEquals(new Rect(200, 0, 400, 400), mResult.mBounds);
+ }
+
+ @Test
+ public void testShiftsToRightForCloseToLeftBoundsWhenConflict() {
+ final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+ WINDOWING_MODE_FREEFORM);
+
+ addFreeformTaskTo(freeformDisplay, new Rect(50, 50, 100, 150));
+
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchDisplayId(freeformDisplay.mDisplayId);
+ options.setLaunchBounds(new Rect(50, 50, 500, 300));
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+ mActivity, /* source */ null, options, mCurrent, mResult));
+
+ assertEquals(new Rect(170, 50, 620, 300), mResult.mBounds);
+ }
+
+ @Test
+ public void testShiftsToLeftForCloseToRightBoundsWhenConflict() {
+ final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+ WINDOWING_MODE_FREEFORM);
+
+ addFreeformTaskTo(freeformDisplay, new Rect(1720, 50, 1830, 150));
+
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchDisplayId(freeformDisplay.mDisplayId);
+ options.setLaunchBounds(new Rect(1720, 50, 1850, 300));
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+ mActivity, /* source */ null, options, mCurrent, mResult));
+
+ assertEquals(new Rect(1600, 50, 1730, 300), mResult.mBounds);
+ }
+
+ @Test
+ public void testShiftsToRightFirstForHorizontallyCenteredAndCloseToTopWhenConflict() {
+ final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+ WINDOWING_MODE_FREEFORM);
+
+ addFreeformTaskTo(freeformDisplay, new Rect(0, 0, 100, 300));
+
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchDisplayId(freeformDisplay.mDisplayId);
+ options.setLaunchBounds(new Rect(0, 0, 1800, 200));
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+ mActivity, /* source */ null, options, mCurrent, mResult));
+
+ assertEquals(new Rect(120, 0, 1920, 200), mResult.mBounds);
+ }
+
+ @Test
+ public void testShiftsToLeftNoSpaceOnRightForHorizontallyCenteredAndCloseToTopWhenConflict() {
+ final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+ WINDOWING_MODE_FREEFORM);
+
+ addFreeformTaskTo(freeformDisplay, new Rect(120, 0, 240, 300));
+
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchDisplayId(freeformDisplay.mDisplayId);
+ options.setLaunchBounds(new Rect(120, 0, 1860, 200));
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+ mActivity, /* source */ null, options, mCurrent, mResult));
+
+ assertEquals(new Rect(0, 0, 1740, 200), mResult.mBounds);
+ }
+
+ @Test
+ public void testShiftsToBottomRightFirstForCenteredBoundsWhenConflict() {
+ final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+ WINDOWING_MODE_FREEFORM);
+
+ addFreeformTaskTo(freeformDisplay, new Rect(120, 0, 240, 100));
+
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchDisplayId(freeformDisplay.mDisplayId);
+ options.setLaunchBounds(new Rect(120, 0, 1800, 1013));
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+ mActivity, /* source */ null, options, mCurrent, mResult));
+
+ assertEquals(new Rect(240, 67, 1920, 1080), mResult.mBounds);
+ }
+
+ @Test
+ public void testShiftsToTopLeftIfNoSpaceOnBottomRightForCenteredBoundsWhenConflict() {
+ final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+ WINDOWING_MODE_FREEFORM);
+
+ addFreeformTaskTo(freeformDisplay, new Rect(120, 67, 240, 100));
+
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchDisplayId(freeformDisplay.mDisplayId);
+ options.setLaunchBounds(new Rect(120, 67, 1800, 1020));
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+ mActivity, /* source */ null, options, mCurrent, mResult));
+
+ assertEquals(new Rect(0, 0, 1680,
+ 953), mResult.mBounds);
+ }
+
+ private TestActivityDisplay createNewActivityDisplay(int windowingMode) {
+ final TestActivityDisplay display = addNewActivityDisplayAt(ActivityDisplay.POSITION_TOP);
+ display.setWindowingMode(windowingMode);
+ display.setBounds(/* left */ 0, /* top */ 0, /* right */ 1920, /* bottom */ 1080);
+ display.getConfiguration().densityDpi = DENSITY_DEFAULT;
+ return display;
+ }
+
+ private ActivityRecord createSourceActivity(TestActivityDisplay display) {
+ final TestActivityStack stack = display.createStack(display.getWindowingMode(),
+ ACTIVITY_TYPE_STANDARD, true);
+ return new ActivityBuilder(mService).setStack(stack).setCreateTask(true).build();
+ }
+
+ private void addFreeformTaskTo(TestActivityDisplay display, Rect bounds) {
+ final TestActivityStack stack = display.createStack(display.getWindowingMode(),
+ ACTIVITY_TYPE_STANDARD, true);
+ stack.setWindowingMode(WINDOWING_MODE_FREEFORM);
+ final TaskRecord task = new TaskBuilder(mSupervisor).setStack(stack).build();
+ task.setBounds(bounds);
+ }
+
+ private void assertEquivalentWindowingMode(int expected, int actual, int parentWindowingMode) {
+ if (expected != parentWindowingMode) {
+ assertEquals(expected, actual);
+ } else {
+ assertEquals(WINDOWING_MODE_UNDEFINED, actual);
}
}
- private Rect getDefaultBounds(int gravity) {
- final Rect bounds = new Rect();
- bounds.set(mStack.getOverrideBounds());
+ private static class WindowLayoutBuilder {
+ private int mWidth = -1;
+ private int mHeight = -1;
+ private float mWidthFraction = -1f;
+ private float mHeightFraction = -1f;
+ private int mGravity = Gravity.NO_GRAVITY;
+ private int mMinWidth = -1;
+ private int mMinHeight = -1;
- final int verticalInset =
- TaskLaunchParamsModifier.getFreeformStartTop(mStack.getOverrideBounds());
- final int horizontalInset =
- TaskLaunchParamsModifier.getFreeformStartLeft(mStack.getOverrideBounds());
+ private WindowLayoutBuilder setWidth(int width) {
+ mWidth = width;
+ return this;
+ }
+
+ private WindowLayoutBuilder setHeight(int height) {
+ mHeight = height;
+ return this;
+ }
- bounds.inset(horizontalInset, verticalInset);
+ private WindowLayoutBuilder setWidthFraction(float widthFraction) {
+ mWidthFraction = widthFraction;
+ return this;
+ }
+
+ private WindowLayoutBuilder setHeightFraction(float heightFraction) {
+ mHeightFraction = heightFraction;
+ return this;
+ }
- if ((gravity & (Gravity.TOP | Gravity.RIGHT)) == (Gravity.TOP | Gravity.RIGHT)) {
- bounds.offsetTo(horizontalInset * 2, 0);
- } else if ((gravity & Gravity.TOP) == Gravity.TOP) {
- bounds.offsetTo(0, 0);
- } else if ((gravity & (Gravity.BOTTOM | Gravity.RIGHT))
- == (Gravity.BOTTOM | Gravity.RIGHT)) {
- bounds.offsetTo(horizontalInset * 2, verticalInset * 2);
- } else if ((gravity & Gravity.BOTTOM) == Gravity.BOTTOM) {
- bounds.offsetTo(0, verticalInset * 2);
+ private WindowLayoutBuilder setGravity(int gravity) {
+ mGravity = gravity;
+ return this;
}
- return bounds;
+ private WindowLayoutBuilder setMinWidth(int minWidth) {
+ mMinWidth = minWidth;
+ return this;
+ }
+
+ private WindowLayoutBuilder setMinHeight(int minHeight) {
+ mMinHeight = minHeight;
+ return this;
+ }
+
+ private ActivityInfo.WindowLayout build() {
+ return new ActivityInfo.WindowLayout(mWidth, mWidthFraction, mHeight, mHeightFraction,
+ mGravity, mMinWidth, mMinHeight);
+ }
}
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
index 6d31dfbb8186..7935ec168142 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -16,6 +16,8 @@
package com.android.server.wm;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
@@ -33,10 +35,12 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.anyInt;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
+import android.graphics.Point;
+import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
import android.view.Surface;
import android.view.WindowManager;
@@ -255,4 +259,30 @@ public class AppWindowTokenTests extends WindowTestsBase {
closingWindow.removeIfPossible();
assertTrue(closingWindow.mRemoved);
}
+
+ @Test
+ public void testTransitionAnimationPositionAndBounds() {
+ final Rect stackBounds = new Rect(
+ 0/* left */, 0 /* top */, 1000 /* right */, 1000 /* bottom */);
+ final Rect taskBounds = new Rect(
+ 100/* left */, 200 /* top */, 600 /* right */, 600 /* bottom */);
+ mStack.setBounds(stackBounds);
+ mTask.setBounds(taskBounds);
+
+ mTask.setWindowingMode(WINDOWING_MODE_FREEFORM);
+ assertTransitionAnimationPositionAndBounds(taskBounds.left, taskBounds.top, stackBounds);
+
+ mTask.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
+ assertTransitionAnimationPositionAndBounds(stackBounds.left, stackBounds.top, stackBounds);
+ }
+
+ private void assertTransitionAnimationPositionAndBounds(int expectedX, int expectedY,
+ Rect expectedBounds) {
+ final Point outPosition = new Point();
+ final Rect outBounds = new Rect();
+ mToken.getAnimationBounds(outPosition, outBounds);
+ assertEquals(expectedX, outPosition.x);
+ assertEquals(expectedY, outPosition.y);
+ assertEquals(expectedBounds, outBounds);
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/DragDropControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/DragDropControllerTests.java
index 7125246b6a29..3c8b2a036c9b 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DragDropControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DragDropControllerTests.java
@@ -40,27 +40,25 @@ import android.view.SurfaceControl;
import android.view.SurfaceSession;
import android.view.View;
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
import com.android.internal.annotations.GuardedBy;
import com.android.server.LocalServices;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
-import org.junit.runner.RunWith;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
+import androidx.test.filters.SmallTest;
+
/**
* Tests for the {@link DragDropController} class.
*
- * atest FrameworksServicesTests:com.android.server.wm.DragDropControllerTests
+ * Build/Install/Run:
+ * atest FrameworksServicesTests:com.android.server.wm.DragDropControllerTests
*/
@SmallTest
-@RunWith(AndroidJUnit4.class)
@Presubmit
public class DragDropControllerTests extends WindowTestsBase {
private static final int TIMEOUT_MS = 3000;
@@ -109,6 +107,7 @@ public class DragDropControllerTests extends WindowTestsBase {
return window;
}
+ @Override
@Before
public void setUp() throws Exception {
final UserManagerInternal userManager = mock(UserManagerInternal.class);
@@ -127,6 +126,7 @@ public class DragDropControllerTests extends WindowTestsBase {
}
}
+ @Override
@After
public void tearDown() throws Exception {
LocalServices.removeServiceForTest(UserManagerInternal.class);
@@ -139,25 +139,25 @@ public class DragDropControllerTests extends WindowTestsBase {
mTarget.cancelDragAndDrop(mToken);
}
latch = new CountDownLatch(1);
- mTarget.setOnClosedCallbackLocked(() -> {
- latch.countDown();
- });
+ mTarget.setOnClosedCallbackLocked(latch::countDown);
}
assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+
+ super.tearDown();
}
@Test
- public void testDragFlow() throws Exception {
+ public void testDragFlow() {
dragFlow(0, ClipData.newPlainText("label", "Test"), 0, 0);
}
@Test
- public void testPerformDrag_NullDataWithGrantUri() throws Exception {
+ public void testPerformDrag_NullDataWithGrantUri() {
dragFlow(View.DRAG_FLAG_GLOBAL | View.DRAG_FLAG_GLOBAL_URI_READ, null, 0, 0);
}
@Test
- public void testPerformDrag_NullDataToOtherUser() throws Exception {
+ public void testPerformDrag_NullDataToOtherUser() {
final WindowState otherUsersWindow =
createDropTargetWindow("Other user's window", 1 * UserHandle.PER_USER_RANGE);
doReturn(otherUsersWindow).when(mDisplayContent).getTouchableWinAtPointLocked(10, 10);
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
index 6f4f17380e3f..33b137ef33e2 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
@@ -29,14 +29,14 @@ import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.os.UserManager;
-import androidx.test.InstrumentationRegistry;
-
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import java.io.File;
+import androidx.test.InstrumentationRegistry;
+
/**
* Base class for tests that use a {@link TaskSnapshotPersister}.
*/
@@ -54,9 +54,11 @@ class TaskSnapshotPersisterTestBase extends WindowTestsBase {
sFilesDir = InstrumentationRegistry.getContext().getFilesDir();
}
+ @Override
@Before
public void setUp() throws Exception {
super.setUp();
+
final UserManager um = UserManager.get(InstrumentationRegistry.getContext());
mTestUserId = um.getUserHandle();
mPersister = new TaskSnapshotPersister(userId -> sFilesDir);
@@ -64,9 +66,12 @@ class TaskSnapshotPersisterTestBase extends WindowTestsBase {
mPersister.start();
}
+ @Override
@After
public void tearDown() throws Exception {
cleanDirectory();
+
+ super.tearDown();
}
private void cleanDirectory() {
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java b/services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java
index ea44279b46a9..0e9a63ce728b 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java
@@ -19,36 +19,37 @@ package com.android.server.wm;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import android.platform.test.annotations.Presubmit;
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
-import org.junit.runner.RunWith;
+
+import androidx.test.filters.SmallTest;
/**
* Tests for the {@link DisplayContent.TaskStackContainers} container in {@link DisplayContent}.
*
* Build/Install/Run:
- * bit FrameworksServicesTests:com.android.server.wm.TaskStackContainersTests
+ * atest FrameworksServicesTests:com.android.server.wm.TaskStackContainersTests
*/
@SmallTest
@Presubmit
-@RunWith(AndroidJUnit4.class)
public class TaskStackContainersTests extends WindowTestsBase {
private TaskStack mPinnedStack;
+ @Override
@Before
public void setUp() throws Exception {
super.setUp();
+
mPinnedStack = createStackControllerOnStackOnDisplay(
WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, mDisplayContent).mContainer;
// Stack should contain visible app window to be considered visible.
@@ -60,13 +61,16 @@ public class TaskStackContainersTests extends WindowTestsBase {
assertTrue(mPinnedStack.isVisible());
}
+ @Override
@After
public void tearDown() throws Exception {
mPinnedStack.removeImmediately();
+
+ super.tearDown();
}
@Test
- public void testStackPositionChildAt() throws Exception {
+ public void testStackPositionChildAt() {
// Test that always-on-top stack can't be moved to position other than top.
final TaskStack stack1 = createTaskStackOnDisplay(mDisplayContent);
final TaskStack stack2 = createTaskStackOnDisplay(mDisplayContent);
@@ -76,8 +80,8 @@ public class TaskStackContainersTests extends WindowTestsBase {
final int stack1Pos = taskStackContainer.mChildren.indexOf(stack1);
final int stack2Pos = taskStackContainer.mChildren.indexOf(stack2);
final int pinnedStackPos = taskStackContainer.mChildren.indexOf(mPinnedStack);
- assertGreaterThan(pinnedStackPos, stack2Pos);
- assertGreaterThan(stack2Pos, stack1Pos);
+ assertThat(pinnedStackPos).isGreaterThan(stack2Pos);
+ assertThat(stack2Pos).isGreaterThan(stack1Pos);
taskStackContainer.positionChildAt(WindowContainer.POSITION_BOTTOM, mPinnedStack, false);
assertEquals(taskStackContainer.mChildren.get(stack1Pos), stack1);
@@ -91,7 +95,7 @@ public class TaskStackContainersTests extends WindowTestsBase {
}
@Test
- public void testStackPositionBelowPinnedStack() throws Exception {
+ public void testStackPositionBelowPinnedStack() {
// Test that no stack can be above pinned stack.
final TaskStack stack1 = createTaskStackOnDisplay(mDisplayContent);
@@ -99,7 +103,7 @@ public class TaskStackContainersTests extends WindowTestsBase {
final int stackPos = taskStackContainer.mChildren.indexOf(stack1);
final int pinnedStackPos = taskStackContainer.mChildren.indexOf(mPinnedStack);
- assertGreaterThan(pinnedStackPos, stackPos);
+ assertThat(pinnedStackPos).isGreaterThan(stackPos);
taskStackContainer.positionChildAt(WindowContainer.POSITION_TOP, stack1, false);
assertEquals(taskStackContainer.mChildren.get(stackPos), stack1);
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
index 70e4ce419e0a..cf67d786056c 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
@@ -48,18 +48,17 @@ import android.view.DisplayInfo;
import android.view.IWindow;
import android.view.WindowManager;
-import androidx.test.InstrumentationRegistry;
-
import com.android.server.AttributeCache;
import org.junit.After;
-import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import java.util.HashSet;
import java.util.LinkedList;
+import androidx.test.InstrumentationRegistry;
+
/**
* Common base class for window manager unit test classes.
*
@@ -194,14 +193,6 @@ class WindowTestsBase {
}
}
- /**
- * @return A SurfaceBuilderFactory to inject in to the WindowManagerService during
- * set-up (or null).
- */
- SurfaceBuilderFactory getSurfaceBuilderFactory() {
- return null;
- }
-
private WindowState createCommonWindow(WindowState parent, int type, String name) {
synchronized (sWm.mWindowMap) {
final WindowState win = createWindow(parent, type, name);
@@ -212,16 +203,6 @@ class WindowTestsBase {
}
}
- /** Asserts that the first entry is greater than the second entry. */
- void assertGreaterThan(int first, int second) throws Exception {
- Assert.assertTrue("Excepted " + first + " to be greater than " + second, first > second);
- }
-
- /** Asserts that the first entry is greater than the second entry. */
- void assertLessThan(int first, int second) throws Exception {
- Assert.assertTrue("Excepted " + first + " to be less than " + second, first < second);
- }
-
/**
* Waits until the main handler for WM has processed all messages.
*/
diff --git a/services/tests/servicestests/src/com/android/server/wm/ZOrderingTests.java b/services/tests/servicestests/src/com/android/server/wm/ZOrderingTests.java
index 8f9fb1b7d5ec..a610e6efda8c 100644
--- a/services/tests/servicestests/src/com/android/server/wm/ZOrderingTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/ZOrderingTests.java
@@ -32,36 +32,35 @@ import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
+import static com.google.common.truth.Truth.assertThat;
+
import android.platform.test.annotations.Presubmit;
import android.view.SurfaceControl;
import android.view.SurfaceSession;
-import androidx.test.filters.FlakyTest;
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
import org.junit.After;
import org.junit.Test;
-import org.junit.runner.RunWith;
import java.util.HashMap;
import java.util.LinkedList;
+import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SmallTest;
+
/**
* Tests for the {@link WindowLayersController} class.
*
* Build/Install/Run:
- * bit FrameworksServicesTests:com.android.server.wm.ZOrderingTests
+ * atest FrameworksServicesTests:com.android.server.wm.ZOrderingTests
*/
@SmallTest
@FlakyTest(bugId = 74078662)
@Presubmit
-@RunWith(AndroidJUnit4.class)
public class ZOrderingTests extends WindowTestsBase {
private class LayerRecordingTransaction extends SurfaceControl.Transaction {
- HashMap<SurfaceControl, Integer> mLayersForControl = new HashMap();
- HashMap<SurfaceControl, SurfaceControl> mRelativeLayersForControl = new HashMap();
+ HashMap<SurfaceControl, Integer> mLayersForControl = new HashMap<>();
+ HashMap<SurfaceControl, SurfaceControl> mRelativeLayersForControl = new HashMap<>();
@Override
public SurfaceControl.Transaction setLayer(SurfaceControl sc, int layer) {
@@ -86,11 +85,11 @@ public class ZOrderingTests extends WindowTestsBase {
private SurfaceControl getRelativeLayer(SurfaceControl sc) {
return mRelativeLayersForControl.get(sc);
}
- };
+ }
// We have WM use our Hierarchy recording subclass of SurfaceControl.Builder
// such that we can keep track of the parents of Surfaces as they are constructed.
- private HashMap<SurfaceControl, SurfaceControl> mParentFor = new HashMap();
+ private HashMap<SurfaceControl, SurfaceControl> mParentFor = new HashMap<>();
private class HierarchyRecorder extends SurfaceControl.Builder {
SurfaceControl mPendingParent;
@@ -109,13 +108,13 @@ public class ZOrderingTests extends WindowTestsBase {
mPendingParent = null;
return sc;
}
- };
+ }
class HierarchyRecordingBuilderFactory implements SurfaceBuilderFactory {
public SurfaceControl.Builder make(SurfaceSession s) {
return new HierarchyRecorder(s);
}
- };
+ }
private LayerRecordingTransaction mTransaction;
@@ -136,7 +135,7 @@ public class ZOrderingTests extends WindowTestsBase {
}
LinkedList<SurfaceControl> getAncestors(LayerRecordingTransaction t, SurfaceControl sc) {
- LinkedList<SurfaceControl> p = new LinkedList();
+ LinkedList<SurfaceControl> p = new LinkedList<>();
SurfaceControl current = sc;
do {
p.addLast(current);
@@ -153,7 +152,7 @@ public class ZOrderingTests extends WindowTestsBase {
void assertZOrderGreaterThan(LayerRecordingTransaction t, SurfaceControl left,
- SurfaceControl right) throws Exception {
+ SurfaceControl right) {
final LinkedList<SurfaceControl> leftParentChain = getAncestors(t, left);
final LinkedList<SurfaceControl> rightParentChain = getAncestors(t, right);
@@ -168,16 +167,15 @@ public class ZOrderingTests extends WindowTestsBase {
}
if (rightTop == null) { // right is the parent of left.
- assertGreaterThan(t.getLayer(leftTop), 0);
+ assertThat(t.getLayer(leftTop)).isGreaterThan(0);
} else if (leftTop == null) { // left is the parent of right.
- assertGreaterThan(0, t.getLayer(rightTop));
+ assertThat(t.getLayer(rightTop)).isLessThan(0);
} else {
- assertGreaterThan(t.getLayer(leftTop),
- t.getLayer(rightTop));
+ assertThat(t.getLayer(leftTop)).isGreaterThan(t.getLayer(rightTop));
}
}
- void assertWindowHigher(WindowState left, WindowState right) throws Exception {
+ void assertWindowHigher(WindowState left, WindowState right) {
assertZOrderGreaterThan(mTransaction, left.getSurfaceControl(), right.getSurfaceControl());
}
@@ -186,7 +184,7 @@ public class ZOrderingTests extends WindowTestsBase {
}
@Test
- public void testAssignWindowLayers_ForImeWithNoTarget() throws Exception {
+ public void testAssignWindowLayers_ForImeWithNoTarget() {
sWm.mInputMethodTarget = null;
mDisplayContent.assignChildLayers(mTransaction);
@@ -203,7 +201,7 @@ public class ZOrderingTests extends WindowTestsBase {
}
@Test
- public void testAssignWindowLayers_ForImeWithAppTarget() throws Exception {
+ public void testAssignWindowLayers_ForImeWithAppTarget() {
final WindowState imeAppTarget = createWindow("imeAppTarget");
sWm.mInputMethodTarget = imeAppTarget;
@@ -222,7 +220,7 @@ public class ZOrderingTests extends WindowTestsBase {
}
@Test
- public void testAssignWindowLayers_ForImeWithAppTargetWithChildWindows() throws Exception {
+ public void testAssignWindowLayers_ForImeWithAppTargetWithChildWindows() {
final WindowState imeAppTarget = createWindow("imeAppTarget");
final WindowState imeAppTargetChildAboveWindow = createWindow(imeAppTarget,
TYPE_APPLICATION_ATTACHED_DIALOG, imeAppTarget.mToken,
@@ -248,7 +246,7 @@ public class ZOrderingTests extends WindowTestsBase {
}
@Test
- public void testAssignWindowLayers_ForImeWithAppTargetAndAppAbove() throws Exception {
+ public void testAssignWindowLayers_ForImeWithAppTargetAndAppAbove() {
final WindowState appBelowImeTarget = createWindow("appBelowImeTarget");
final WindowState imeAppTarget = createWindow("imeAppTarget");
final WindowState appAboveImeTarget = createWindow("appAboveImeTarget");
@@ -271,7 +269,7 @@ public class ZOrderingTests extends WindowTestsBase {
}
@Test
- public void testAssignWindowLayers_ForImeNonAppImeTarget() throws Exception {
+ public void testAssignWindowLayers_ForImeNonAppImeTarget() {
final WindowState imeSystemOverlayTarget = createWindow(null, TYPE_SYSTEM_OVERLAY,
mDisplayContent, "imeSystemOverlayTarget",
true /* ownerCanAddInternalSystemWindow */);
@@ -298,7 +296,7 @@ public class ZOrderingTests extends WindowTestsBase {
}
@Test
- public void testAssignWindowLayers_ForStatusBarImeTarget() throws Exception {
+ public void testAssignWindowLayers_ForStatusBarImeTarget() {
sWm.mInputMethodTarget = mStatusBarWindow;
mDisplayContent.assignChildLayers(mTransaction);
@@ -312,7 +310,7 @@ public class ZOrderingTests extends WindowTestsBase {
}
@Test
- public void testStackLayers() throws Exception {
+ public void testStackLayers() {
final WindowState anyWindow1 = createWindow("anyWindow");
final WindowState pinnedStackWindow = createWindowOnStack(null, WINDOWING_MODE_PINNED,
ACTIVITY_TYPE_STANDARD, TYPE_BASE_APPLICATION, mDisplayContent,
@@ -342,7 +340,7 @@ public class ZOrderingTests extends WindowTestsBase {
}
@Test
- public void testAssignWindowLayers_ForSysUiPanels() throws Exception {
+ public void testAssignWindowLayers_ForSysUiPanels() {
final WindowState navBarPanel =
createWindow(null, TYPE_NAVIGATION_BAR_PANEL, mDisplayContent, "NavBarPanel");
final WindowState statusBarPanel =
@@ -359,7 +357,7 @@ public class ZOrderingTests extends WindowTestsBase {
}
@Test
- public void testAssignWindowLayers_ForNegativelyZOrderedSubtype() throws Exception {
+ public void testAssignWindowLayers_ForNegativelyZOrderedSubtype() {
// TODO(b/70040778): We should aim to eliminate the last user of TYPE_APPLICATION_MEDIA
// then we can drop all negative layering on the windowing side.
@@ -376,7 +374,7 @@ public class ZOrderingTests extends WindowTestsBase {
}
@Test
- public void testDockedDividerPosition() throws Exception {
+ public void testDockedDividerPosition() {
final WindowState pinnedStackWindow = createWindowOnStack(null, WINDOWING_MODE_PINNED,
ACTIVITY_TYPE_STANDARD, TYPE_BASE_APPLICATION, mDisplayContent,
"pinnedStackWindow");
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index 08bc9bcc4003..daa09f574651 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -397,7 +397,19 @@ public final class Call {
public static final int PROPERTY_WIFI = 0x00000008;
/**
- * Call is using high definition audio.
+ * When set, the UI should indicate to the user that a call is using high definition
+ * audio.
+ * <p>
+ * The underlying {@link ConnectionService} is responsible for reporting this
+ * property. It is important to note that this property is not intended to report the
+ * actual audio codec being used for a Call, but whether the call should be indicated
+ * to the user as high definition.
+ * <p>
+ * The Android Telephony stack reports this property for calls based on a number
+ * of factors, including which audio codec is used and whether a call is using an HD
+ * codec end-to-end. Some mobile operators choose to suppress display of an HD indication,
+ * and in these cases this property will not be set for a call even if the underlying audio
+ * codec is in fact "high definition".
*/
public static final int PROPERTY_HIGH_DEF_AUDIO = 0x00000010;
diff --git a/telephony/java/android/provider/Telephony.java b/telephony/java/android/provider/Telephony.java
index 4846092286ba..8454d12ac317 100644
--- a/telephony/java/android/provider/Telephony.java
+++ b/telephony/java/android/provider/Telephony.java
@@ -3289,7 +3289,6 @@ public final class Telephony {
values.put(CDMA_ERI_ICON_INDEX, state.getCdmaEriIconIndex());
values.put(CDMA_ERI_ICON_MODE, state.getCdmaEriIconMode());
values.put(IS_EMERGENCY_ONLY, state.isEmergencyOnly());
- values.put(IS_DATA_ROAMING_FROM_REGISTRATION, state.getDataRoamingFromRegistration());
values.put(IS_USING_CARRIER_AGGREGATION, state.isUsingCarrierAggregation());
return values;
}
diff --git a/telephony/java/android/telephony/NeighboringCellInfo.java b/telephony/java/android/telephony/NeighboringCellInfo.java
index 79298fd54c50..ac38efb4d029 100644
--- a/telephony/java/android/telephony/NeighboringCellInfo.java
+++ b/telephony/java/android/telephony/NeighboringCellInfo.java
@@ -34,8 +34,8 @@ import android.os.Parcelable;
* Received Signal Strength and Cell ID location.
*
* @deprecated This class should not be used by any app targeting
- * {@link Build.VERSION_CODES.Q Android Q} or higher. Instead callers should use
- * {@Link android.telephony.CellInfo CellInfo}.
+ * {@link android.os.Build.VERSION_CODES#Q Android Q} or higher. Instead callers should use
+ * {@link android.telephony.CellInfo CellInfo}.
*/
@Deprecated
public class NeighboringCellInfo implements Parcelable
diff --git a/telephony/java/android/telephony/NetworkRegistrationState.java b/telephony/java/android/telephony/NetworkRegistrationState.java
index c3931557feb3..b312f8478413 100644
--- a/telephony/java/android/telephony/NetworkRegistrationState.java
+++ b/telephony/java/android/telephony/NetworkRegistrationState.java
@@ -95,6 +95,13 @@ public class NetworkRegistrationState implements Parcelable {
@RegState
private final int mRegState;
+ /**
+ * Save the {@link ServiceState.RoamingType roaming type}. it can be overridden roaming type
+ * from resource overlay or carrier config.
+ */
+ @ServiceState.RoamingType
+ private int mRoamingType;
+
private final int mAccessNetworkTechnology;
private final int mRejectCause;
@@ -140,6 +147,8 @@ public class NetworkRegistrationState implements Parcelable {
mDomain = domain;
mTransportType = transportType;
mRegState = regState;
+ mRoamingType = (regState == REG_STATE_ROAMING)
+ ? ServiceState.ROAMING_TYPE_UNKNOWN : ServiceState.ROAMING_TYPE_NOT_ROAMING;
mAccessNetworkTechnology = accessNetworkTechnology;
mRejectCause = rejectCause;
mAvailableServices = availableServices;
@@ -182,6 +191,7 @@ public class NetworkRegistrationState implements Parcelable {
mDomain = source.readInt();
mTransportType = source.readInt();
mRegState = source.readInt();
+ mRoamingType = source.readInt();
mAccessNetworkTechnology = source.readInt();
mRejectCause = source.readInt();
mEmergencyOnly = source.readBoolean();
@@ -211,6 +221,31 @@ public class NetworkRegistrationState implements Parcelable {
}
/**
+ * @return {@code true} if registered on roaming network, {@code false} otherwise.
+ */
+ public boolean isRoaming() {
+ return mRoamingType != ServiceState.ROAMING_TYPE_NOT_ROAMING;
+ }
+
+ /**
+ * Set {@link ServiceState.RoamingType roaming type}. This could override
+ * roaming type based on resource overlay or carrier config.
+ * @hide
+ */
+ public void setRoamingType(@ServiceState.RoamingType int roamingType) {
+ mRoamingType = roamingType;
+ }
+
+ /**
+ * @return {@link ServiceState.RoamingType roaming type}. This could return
+ * overridden roaming type based on resource overlay or carrier config.
+ * @hide
+ */
+ public @ServiceState.RoamingType int getRoamingType() {
+ return mRoamingType;
+ }
+
+ /**
* @return Whether emergency is enabled.
*/
public boolean isEmergencyEnabled() { return mEmergencyOnly; }
@@ -280,6 +315,7 @@ public class NetworkRegistrationState implements Parcelable {
.append(" domain=").append((mDomain == DOMAIN_CS) ? "CS" : "PS")
.append("transportType=").append(mTransportType)
.append(" regState=").append(regStateToString(mRegState))
+ .append(" roamingType=").append(mRoamingType)
.append(" accessNetworkTechnology=")
.append(TelephonyManager.getNetworkTypeName(mAccessNetworkTechnology))
.append(" rejectCause=").append(mRejectCause)
@@ -293,9 +329,9 @@ public class NetworkRegistrationState implements Parcelable {
@Override
public int hashCode() {
- return Objects.hash(mDomain, mTransportType, mRegState, mAccessNetworkTechnology,
- mRejectCause, mEmergencyOnly, mAvailableServices, mCellIdentity,
- mVoiceSpecificStates, mDataSpecificStates);
+ return Objects.hash(mDomain, mTransportType, mRegState, mRoamingType,
+ mAccessNetworkTechnology, mRejectCause, mEmergencyOnly, mAvailableServices,
+ mCellIdentity, mVoiceSpecificStates, mDataSpecificStates);
}
@Override
@@ -310,6 +346,7 @@ public class NetworkRegistrationState implements Parcelable {
return mDomain == other.mDomain
&& mTransportType == other.mTransportType
&& mRegState == other.mRegState
+ && mRoamingType == other.mRoamingType
&& mAccessNetworkTechnology == other.mAccessNetworkTechnology
&& mRejectCause == other.mRejectCause
&& mEmergencyOnly == other.mEmergencyOnly
@@ -325,6 +362,7 @@ public class NetworkRegistrationState implements Parcelable {
dest.writeInt(mDomain);
dest.writeInt(mTransportType);
dest.writeInt(mRegState);
+ dest.writeInt(mRoamingType);
dest.writeInt(mAccessNetworkTechnology);
dest.writeInt(mRejectCause);
dest.writeBoolean(mEmergencyOnly);
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 7469186a5d51..e0ec2c50ab5b 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -20,6 +20,7 @@ import android.annotation.IntDef;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
+import android.content.Intent;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -57,7 +58,7 @@ public class ServiceState implements Parcelable {
* Normal operation condition, the phone is registered
* with an operator either in home network or in roaming.
*/
- public static final int STATE_IN_SERVICE = 0;
+ public static final int STATE_IN_SERVICE = TelephonyProtoEnums.SERVICE_STATE_IN_SERVICE; // 0
/**
* Phone is not registered with any operator, the phone
@@ -65,17 +66,19 @@ public class ServiceState implements Parcelable {
* searching to registration at all, or registration is denied, or radio
* signal is not available.
*/
- public static final int STATE_OUT_OF_SERVICE = 1;
+ public static final int STATE_OUT_OF_SERVICE =
+ TelephonyProtoEnums.SERVICE_STATE_OUT_OF_SERVICE; // 1
/**
* The phone is registered and locked. Only emergency numbers are allowed. {@more}
*/
- public static final int STATE_EMERGENCY_ONLY = 2;
+ public static final int STATE_EMERGENCY_ONLY =
+ TelephonyProtoEnums.SERVICE_STATE_EMERGENCY_ONLY; // 2
/**
* Radio of telephony is explicitly powered off.
*/
- public static final int STATE_POWER_OFF = 3;
+ public static final int STATE_POWER_OFF = TelephonyProtoEnums.SERVICE_STATE_POWER_OFF; // 3
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@@ -198,6 +201,15 @@ public class ServiceState implements Parcelable {
private int mVoiceRegState = STATE_OUT_OF_SERVICE;
private int mDataRegState = STATE_OUT_OF_SERVICE;
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "ROAMING_TYPE_" }, value = {
+ ROAMING_TYPE_NOT_ROAMING,
+ ROAMING_TYPE_UNKNOWN,
+ ROAMING_TYPE_DOMESTIC,
+ ROAMING_TYPE_INTERNATIONAL
+ })
+ public @interface RoamingType {}
/**
* Roaming type
* HOME : in home network
@@ -228,8 +240,6 @@ public class ServiceState implements Parcelable {
*/
public static final int UNKNOWN_ID = -1;
- private int mVoiceRoamingType;
- private int mDataRoamingType;
private String mVoiceOperatorAlphaLong;
private String mVoiceOperatorAlphaShort;
private String mVoiceOperatorNumeric;
@@ -259,8 +269,6 @@ public class ServiceState implements Parcelable {
@UnsupportedAppUsage
private int mCdmaEriIconMode;
- private boolean mIsDataRoamingFromRegistration;
-
@UnsupportedAppUsage
private boolean mIsUsingCarrierAggregation;
@@ -332,8 +340,6 @@ public class ServiceState implements Parcelable {
protected void copyFrom(ServiceState s) {
mVoiceRegState = s.mVoiceRegState;
mDataRegState = s.mDataRegState;
- mVoiceRoamingType = s.mVoiceRoamingType;
- mDataRoamingType = s.mDataRoamingType;
mVoiceOperatorAlphaLong = s.mVoiceOperatorAlphaLong;
mVoiceOperatorAlphaShort = s.mVoiceOperatorAlphaShort;
mVoiceOperatorNumeric = s.mVoiceOperatorNumeric;
@@ -351,7 +357,6 @@ public class ServiceState implements Parcelable {
mCdmaEriIconIndex = s.mCdmaEriIconIndex;
mCdmaEriIconMode = s.mCdmaEriIconMode;
mIsEmergencyOnly = s.mIsEmergencyOnly;
- mIsDataRoamingFromRegistration = s.mIsDataRoamingFromRegistration;
mIsUsingCarrierAggregation = s.mIsUsingCarrierAggregation;
mChannelNumber = s.mChannelNumber;
mCellBandwidths = s.mCellBandwidths == null ? null :
@@ -367,8 +372,6 @@ public class ServiceState implements Parcelable {
public ServiceState(Parcel in) {
mVoiceRegState = in.readInt();
mDataRegState = in.readInt();
- mVoiceRoamingType = in.readInt();
- mDataRoamingType = in.readInt();
mVoiceOperatorAlphaLong = in.readString();
mVoiceOperatorAlphaShort = in.readString();
mVoiceOperatorNumeric = in.readString();
@@ -386,7 +389,6 @@ public class ServiceState implements Parcelable {
mCdmaEriIconIndex = in.readInt();
mCdmaEriIconMode = in.readInt();
mIsEmergencyOnly = in.readInt() != 0;
- mIsDataRoamingFromRegistration = in.readInt() != 0;
mIsUsingCarrierAggregation = in.readInt() != 0;
mLteEarfcnRsrpBoost = in.readInt();
mNetworkRegistrationStates = new ArrayList<>();
@@ -398,8 +400,6 @@ public class ServiceState implements Parcelable {
public void writeToParcel(Parcel out, int flags) {
out.writeInt(mVoiceRegState);
out.writeInt(mDataRegState);
- out.writeInt(mVoiceRoamingType);
- out.writeInt(mDataRoamingType);
out.writeString(mVoiceOperatorAlphaLong);
out.writeString(mVoiceOperatorAlphaShort);
out.writeString(mVoiceOperatorNumeric);
@@ -417,7 +417,6 @@ public class ServiceState implements Parcelable {
out.writeInt(mCdmaEriIconIndex);
out.writeInt(mCdmaEriIconMode);
out.writeInt(mIsEmergencyOnly ? 1 : 0);
- out.writeInt(mIsDataRoamingFromRegistration ? 1 : 0);
out.writeInt(mIsUsingCarrierAggregation ? 1 : 0);
out.writeInt(mLteEarfcnRsrpBoost);
out.writeList(mNetworkRegistrationStates);
@@ -535,17 +534,21 @@ public class ServiceState implements Parcelable {
*/
@UnsupportedAppUsage
public boolean getVoiceRoaming() {
- return mVoiceRoamingType != ROAMING_TYPE_NOT_ROAMING;
+ return getVoiceRoamingType() != ROAMING_TYPE_NOT_ROAMING;
}
-
/**
* Get current voice network roaming type
* @return roaming type
* @hide
*/
@UnsupportedAppUsage
- public int getVoiceRoamingType() {
- return mVoiceRoamingType;
+ public @RoamingType int getVoiceRoamingType() {
+ final NetworkRegistrationState regState = getNetworkRegistrationState(
+ NetworkRegistrationState.DOMAIN_CS, AccessNetworkConstants.TransportType.WWAN);
+ if (regState != null) {
+ return regState.getRoamingType();
+ }
+ return ROAMING_TYPE_NOT_ROAMING;
}
/**
@@ -555,19 +558,7 @@ public class ServiceState implements Parcelable {
*/
@UnsupportedAppUsage
public boolean getDataRoaming() {
- return mDataRoamingType != ROAMING_TYPE_NOT_ROAMING;
- }
-
- /**
- * Set whether data network registration state is roaming
- *
- * This should only be set to the roaming value received
- * once the data registration phase has completed.
- * @hide
- */
- @UnsupportedAppUsage
- public void setDataRoamingFromRegistration(boolean dataRoaming) {
- mIsDataRoamingFromRegistration = dataRoaming;
+ return getDataRoamingType() != ROAMING_TYPE_NOT_ROAMING;
}
/**
@@ -576,7 +567,12 @@ public class ServiceState implements Parcelable {
* @hide
*/
public boolean getDataRoamingFromRegistration() {
- return mIsDataRoamingFromRegistration;
+ final NetworkRegistrationState regState = getNetworkRegistrationState(
+ NetworkRegistrationState.DOMAIN_PS, AccessNetworkConstants.TransportType.WWAN);
+ if (regState != null) {
+ return (regState.getRegState() == NetworkRegistrationState.REG_STATE_ROAMING);
+ }
+ return false;
}
/**
@@ -585,8 +581,13 @@ public class ServiceState implements Parcelable {
* @hide
*/
@UnsupportedAppUsage
- public int getDataRoamingType() {
- return mDataRoamingType;
+ public @RoamingType int getDataRoamingType() {
+ final NetworkRegistrationState regState = getNetworkRegistrationState(
+ NetworkRegistrationState.DOMAIN_PS, AccessNetworkConstants.TransportType.WWAN);
+ if (regState != null) {
+ return regState.getRoamingType();
+ }
+ return ROAMING_TYPE_NOT_ROAMING;
}
/**
@@ -759,8 +760,6 @@ public class ServiceState implements Parcelable {
return Objects.hash(
mVoiceRegState,
mDataRegState,
- mVoiceRoamingType,
- mDataRoamingType,
mChannelNumber,
mCellBandwidths,
mVoiceOperatorAlphaLong,
@@ -780,7 +779,6 @@ public class ServiceState implements Parcelable {
mCdmaEriIconIndex,
mCdmaEriIconMode,
mIsEmergencyOnly,
- mIsDataRoamingFromRegistration,
mIsUsingCarrierAggregation,
mLteEarfcnRsrpBoost,
mNetworkRegistrationStates);
@@ -794,8 +792,6 @@ public class ServiceState implements Parcelable {
return (mVoiceRegState == s.mVoiceRegState
&& mDataRegState == s.mDataRegState
&& mIsManualNetworkSelection == s.mIsManualNetworkSelection
- && mVoiceRoamingType == s.mVoiceRoamingType
- && mDataRoamingType == s.mDataRoamingType
&& mChannelNumber == s.mChannelNumber
&& Arrays.equals(mCellBandwidths, s.mCellBandwidths)
&& equalsHandlesNulls(mVoiceOperatorAlphaLong, s.mVoiceOperatorAlphaLong)
@@ -813,7 +809,6 @@ public class ServiceState implements Parcelable {
&& equalsHandlesNulls(mCdmaDefaultRoamingIndicator,
s.mCdmaDefaultRoamingIndicator)
&& mIsEmergencyOnly == s.mIsEmergencyOnly
- && mIsDataRoamingFromRegistration == s.mIsDataRoamingFromRegistration
&& mIsUsingCarrierAggregation == s.mIsUsingCarrierAggregation)
&& (mNetworkRegistrationStates == null ? s.mNetworkRegistrationStates == null :
s.mNetworkRegistrationStates != null &&
@@ -933,8 +928,6 @@ public class ServiceState implements Parcelable {
.append(", mChannelNumber=").append(mChannelNumber)
.append(", duplexMode()=").append(getDuplexMode())
.append(", mCellBandwidths=").append(Arrays.toString(mCellBandwidths))
- .append(", mVoiceRoamingType=").append(getRoamingLogString(mVoiceRoamingType))
- .append(", mDataRoamingType=").append(getRoamingLogString(mDataRoamingType))
.append(", mVoiceOperatorAlphaLong=").append(mVoiceOperatorAlphaLong)
.append(", mVoiceOperatorAlphaShort=").append(mVoiceOperatorAlphaShort)
.append(", mDataOperatorAlphaLong=").append(mDataOperatorAlphaLong)
@@ -951,7 +944,6 @@ public class ServiceState implements Parcelable {
.append(", mCdmaRoamingIndicator=").append(mCdmaRoamingIndicator)
.append(", mCdmaDefaultRoamingIndicator=").append(mCdmaDefaultRoamingIndicator)
.append(", mIsEmergencyOnly=").append(mIsEmergencyOnly)
- .append(", mIsDataRoamingFromRegistration=").append(mIsDataRoamingFromRegistration)
.append(", mIsUsingCarrierAggregation=").append(mIsUsingCarrierAggregation)
.append(", mLteEarfcnRsrpBoost=").append(mLteEarfcnRsrpBoost)
.append(", mNetworkRegistrationStates=").append(mNetworkRegistrationStates)
@@ -962,8 +954,6 @@ public class ServiceState implements Parcelable {
if (DBG) Rlog.d(LOG_TAG, "[ServiceState] setNullState=" + state);
mVoiceRegState = state;
mDataRegState = state;
- mVoiceRoamingType = ROAMING_TYPE_NOT_ROAMING;
- mDataRoamingType = ROAMING_TYPE_NOT_ROAMING;
mChannelNumber = -1;
mCellBandwidths = new int[0];
mVoiceOperatorAlphaLong = null;
@@ -983,7 +973,6 @@ public class ServiceState implements Parcelable {
mCdmaEriIconIndex = -1;
mCdmaEriIconMode = -1;
mIsEmergencyOnly = false;
- mIsDataRoamingFromRegistration = false;
mIsUsingCarrierAggregation = false;
mLteEarfcnRsrpBoost = 0;
mNetworkRegistrationStates = new ArrayList<>();
@@ -1029,32 +1018,50 @@ public class ServiceState implements Parcelable {
}
public void setRoaming(boolean roaming) {
- mVoiceRoamingType = (roaming ? ROAMING_TYPE_UNKNOWN : ROAMING_TYPE_NOT_ROAMING);
- mDataRoamingType = mVoiceRoamingType;
+ setVoiceRoaming(roaming);
+ setDataRoaming(roaming);
}
/** @hide */
@UnsupportedAppUsage
public void setVoiceRoaming(boolean roaming) {
- mVoiceRoamingType = (roaming ? ROAMING_TYPE_UNKNOWN : ROAMING_TYPE_NOT_ROAMING);
+ setVoiceRoamingType(roaming ? ROAMING_TYPE_UNKNOWN : ROAMING_TYPE_NOT_ROAMING);
}
/** @hide */
@UnsupportedAppUsage
- public void setVoiceRoamingType(int type) {
- mVoiceRoamingType = type;
+ public void setVoiceRoamingType(@RoamingType int type) {
+ NetworkRegistrationState regState = getNetworkRegistrationState(
+ NetworkRegistrationState.DOMAIN_CS, AccessNetworkConstants.TransportType.WWAN);
+ if (regState == null) {
+ regState = new NetworkRegistrationState(
+ NetworkRegistrationState.DOMAIN_CS, AccessNetworkConstants.TransportType.WWAN,
+ ServiceState.ROAMING_TYPE_NOT_ROAMING, TelephonyManager.NETWORK_TYPE_UNKNOWN, 0,
+ false, null, null);
+ addNetworkRegistrationState(regState);
+ }
+ regState.setRoamingType(type);
}
/** @hide */
@UnsupportedAppUsage
public void setDataRoaming(boolean dataRoaming) {
- mDataRoamingType = (dataRoaming ? ROAMING_TYPE_UNKNOWN : ROAMING_TYPE_NOT_ROAMING);
+ setDataRoamingType(dataRoaming ? ROAMING_TYPE_UNKNOWN : ROAMING_TYPE_NOT_ROAMING);
}
/** @hide */
@UnsupportedAppUsage
- public void setDataRoamingType(int type) {
- mDataRoamingType = type;
+ public void setDataRoamingType(@RoamingType int type) {
+ NetworkRegistrationState regState = getNetworkRegistrationState(
+ NetworkRegistrationState.DOMAIN_PS, AccessNetworkConstants.TransportType.WWAN);
+ if (regState == null) {
+ regState = new NetworkRegistrationState(
+ NetworkRegistrationState.DOMAIN_PS, AccessNetworkConstants.TransportType.WWAN,
+ ServiceState.ROAMING_TYPE_NOT_ROAMING, TelephonyManager.NETWORK_TYPE_UNKNOWN, 0,
+ false, null, null);
+ addNetworkRegistrationState(regState);
+ }
+ regState.setRoamingType(type);
}
/**
@@ -1166,30 +1173,10 @@ public class ServiceState implements Parcelable {
*/
@UnsupportedAppUsage
private void setFromNotifierBundle(Bundle m) {
- mVoiceRegState = m.getInt("voiceRegState");
- mDataRegState = m.getInt("dataRegState");
- mVoiceRoamingType = m.getInt("voiceRoamingType");
- mDataRoamingType = m.getInt("dataRoamingType");
- mVoiceOperatorAlphaLong = m.getString("operator-alpha-long");
- mVoiceOperatorAlphaShort = m.getString("operator-alpha-short");
- mVoiceOperatorNumeric = m.getString("operator-numeric");
- mDataOperatorAlphaLong = m.getString("data-operator-alpha-long");
- mDataOperatorAlphaShort = m.getString("data-operator-alpha-short");
- mDataOperatorNumeric = m.getString("data-operator-numeric");
- mIsManualNetworkSelection = m.getBoolean("manual");
- mRilVoiceRadioTechnology = m.getInt("radioTechnology");
- mRilDataRadioTechnology = m.getInt("dataRadioTechnology");
- mCssIndicator = m.getBoolean("cssIndicator");
- mNetworkId = m.getInt("networkId");
- mSystemId = m.getInt("systemId");
- mCdmaRoamingIndicator = m.getInt("cdmaRoamingIndicator");
- mCdmaDefaultRoamingIndicator = m.getInt("cdmaDefaultRoamingIndicator");
- mIsEmergencyOnly = m.getBoolean("emergencyOnly");
- mIsDataRoamingFromRegistration = m.getBoolean("isDataRoamingFromRegistration");
- mIsUsingCarrierAggregation = m.getBoolean("isUsingCarrierAggregation");
- mLteEarfcnRsrpBoost = m.getInt("LteEarfcnRsrpBoost");
- mChannelNumber = m.getInt("ChannelNumber");
- mCellBandwidths = m.getIntArray("CellBandwidths");
+ ServiceState ssFromBundle = m.getParcelable(Intent.EXTRA_SERVICE_STATE);
+ if (ssFromBundle != null) {
+ copyFrom(ssFromBundle);
+ }
}
/**
@@ -1200,10 +1187,13 @@ public class ServiceState implements Parcelable {
*/
@UnsupportedAppUsage
public void fillInNotifierBundle(Bundle m) {
+ m.putParcelable(Intent.EXTRA_SERVICE_STATE, this);
+ // serviceState already consists of below entries.
+ // for backward compatibility, we continue fill in below entries.
m.putInt("voiceRegState", mVoiceRegState);
m.putInt("dataRegState", mDataRegState);
- m.putInt("voiceRoamingType", mVoiceRoamingType);
- m.putInt("dataRoamingType", mDataRoamingType);
+ m.putInt("dataRoamingType", getDataRoamingType());
+ m.putInt("voiceRoamingType", getVoiceRoamingType());
m.putString("operator-alpha-long", mVoiceOperatorAlphaLong);
m.putString("operator-alpha-short", mVoiceOperatorAlphaShort);
m.putString("operator-numeric", mVoiceOperatorNumeric);
@@ -1219,7 +1209,7 @@ public class ServiceState implements Parcelable {
m.putInt("cdmaRoamingIndicator", mCdmaRoamingIndicator);
m.putInt("cdmaDefaultRoamingIndicator", mCdmaDefaultRoamingIndicator);
m.putBoolean("emergencyOnly", mIsEmergencyOnly);
- m.putBoolean("isDataRoamingFromRegistration", mIsDataRoamingFromRegistration);
+ m.putBoolean("isDataRoamingFromRegistration", getDataRoamingFromRegistration());
m.putBoolean("isUsingCarrierAggregation", mIsUsingCarrierAggregation);
m.putInt("LteEarfcnRsrpBoost", mLteEarfcnRsrpBoost);
m.putInt("ChannelNumber", mChannelNumber);
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 76e6afddcf12..f85069385f3c 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -32,12 +32,14 @@ import android.annotation.SystemService;
import android.annotation.UnsupportedAppUsage;
import android.app.BroadcastOptions;
import android.app.PendingIntent;
+import android.app.job.JobService;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.database.ContentObserver;
import android.net.INetworkPolicyManager;
import android.net.NetworkCapabilities;
import android.net.Uri;
@@ -116,6 +118,52 @@ public class SubscriptionManager {
@UnsupportedAppUsage
public static final Uri CONTENT_URI = Uri.parse("content://telephony/siminfo");
+
+ /**
+ * Generates a content {@link Uri} used to receive updates on simInfo change
+ * on the given subscriptionId
+ * @param subscriptionId the subscriptionId to receive updates on
+ * @return the Uri used to observe carrier identity changes
+ * @hide
+ */
+ public static Uri getUriForSubscriptionId(int subscriptionId) {
+ return Uri.withAppendedPath(CONTENT_URI, String.valueOf(subscriptionId));
+ }
+
+ /**
+ * A content {@link Uri} used to receive updates on wfc enabled user setting.
+ * <p>
+ * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
+ * subscription wfc enabled {@link SubscriptionManager#WFC_IMS_ENABLED}
+ * while your app is running. You can also use a {@link JobService} to ensure your app
+ * is notified of changes to the {@link Uri} even when it is not running.
+ * Note, however, that using a {@link JobService} does not guarantee timely delivery of
+ * updates to the {@link Uri}.
+ * To be notified of changes to a specific subId, append subId to the URI
+ * {@link Uri#withAppendedPath(Uri, String)}.
+ * @hide
+ */
+ @SystemApi
+ public static final Uri WFC_ENABLED_CONTENT_URI = Uri.withAppendedPath(CONTENT_URI, "wfc");
+
+ /**
+ * A content {@link Uri} used to receive updates on enhanced 4g user setting.
+ * <p>
+ * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
+ * subscription enhanced 4G enabled {@link SubscriptionManager#ENHANCED_4G_MODE_ENABLED}
+ * while your app is running. You can also use a {@link JobService} to ensure your app
+ * is notified of changes to the {@link Uri} even when it is not running.
+ * Note, however, that using a {@link JobService} does not guarantee timely delivery of
+ * updates to the {@link Uri}.
+ * To be notified of changes to a specific subId, append subId to the URI
+ * {@link Uri#withAppendedPath(Uri, String)}.
+ * @hide
+ */
+ @SystemApi
+ public static final Uri ENHANCED_4G_ENABLED_CONTENT_URI = Uri.withAppendedPath(
+ CONTENT_URI, "enhanced_4g");
+
+
/**
* TelephonyProvider unique key column name is the subscription id.
* <P>Type: TEXT (String)</P>
@@ -1603,7 +1651,7 @@ public class SubscriptionManager {
* Check if the subscription ID is usable.
*
* A usable subscription ID has a valid value except some special values such as
- * {@link DEFAULT_SUBSCRIPTION_ID}. It can be used for subscription functions.
+ * {@link #DEFAULT_SUBSCRIPTION_ID}. It can be used for subscription functions.
*
* @param subscriptionId the subscription ID
* @return {@code true} if the subscription ID is usable; {@code false} otherwise.
@@ -2185,9 +2233,10 @@ public class SubscriptionManager {
* Provide all available user downloaded profiles on phone which are used only for
* opportunistic data.
* @param slotIndex slot on which the profiles are queried from.
+ * @return the list of opportunistic subscription info. If none exists, an empty list.
*/
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
- public List<SubscriptionInfo> getOpportunisticSubscriptions(int slotIndex) {
+ public @NonNull List<SubscriptionInfo> getOpportunisticSubscriptions(int slotIndex) {
String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
List<SubscriptionInfo> subInfoList = null;
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index c5e47077e680..fca14c823751 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -60,6 +60,7 @@ import android.telephony.ims.aidl.IImsMmTelFeature;
import android.telephony.ims.aidl.IImsRcsFeature;
import android.telephony.ims.aidl.IImsRegistration;
import android.telephony.ims.stub.ImsRegistrationImplBase;
+import android.text.TextUtils;
import android.util.Log;
import com.android.ims.internal.IImsServiceFeatureCallback;
@@ -2446,39 +2447,46 @@ public class TelephonyManager {
*
* These are the ordinal value of IccCardConstants.State.
*/
- public static final int SIM_STATE_UNKNOWN = 0;
+
+ public static final int SIM_STATE_UNKNOWN = TelephonyProtoEnums.SIM_STATE_UNKNOWN; // 0
/** SIM card state: no SIM card is available in the device */
- public static final int SIM_STATE_ABSENT = 1;
+ public static final int SIM_STATE_ABSENT = TelephonyProtoEnums.SIM_STATE_ABSENT; // 1
/** SIM card state: Locked: requires the user's SIM PIN to unlock */
- public static final int SIM_STATE_PIN_REQUIRED = 2;
+ public static final int SIM_STATE_PIN_REQUIRED =
+ TelephonyProtoEnums.SIM_STATE_PIN_REQUIRED; // 2
/** SIM card state: Locked: requires the user's SIM PUK to unlock */
- public static final int SIM_STATE_PUK_REQUIRED = 3;
+ public static final int SIM_STATE_PUK_REQUIRED =
+ TelephonyProtoEnums.SIM_STATE_PUK_REQUIRED; // 3
/** SIM card state: Locked: requires a network PIN to unlock */
- public static final int SIM_STATE_NETWORK_LOCKED = 4;
+ public static final int SIM_STATE_NETWORK_LOCKED =
+ TelephonyProtoEnums.SIM_STATE_NETWORK_LOCKED; // 4
/** SIM card state: Ready */
- public static final int SIM_STATE_READY = 5;
+ public static final int SIM_STATE_READY = TelephonyProtoEnums.SIM_STATE_READY; // 5
/** SIM card state: SIM Card is NOT READY */
- public static final int SIM_STATE_NOT_READY = 6;
+ public static final int SIM_STATE_NOT_READY = TelephonyProtoEnums.SIM_STATE_NOT_READY; // 6
/** SIM card state: SIM Card Error, permanently disabled */
- public static final int SIM_STATE_PERM_DISABLED = 7;
+ public static final int SIM_STATE_PERM_DISABLED =
+ TelephonyProtoEnums.SIM_STATE_PERM_DISABLED; // 7
/** SIM card state: SIM Card Error, present but faulty */
- public static final int SIM_STATE_CARD_IO_ERROR = 8;
+ public static final int SIM_STATE_CARD_IO_ERROR =
+ TelephonyProtoEnums.SIM_STATE_CARD_IO_ERROR; // 8
/** SIM card state: SIM Card restricted, present but not usable due to
* carrier restrictions.
*/
- public static final int SIM_STATE_CARD_RESTRICTED = 9;
+ public static final int SIM_STATE_CARD_RESTRICTED =
+ TelephonyProtoEnums.SIM_STATE_CARD_RESTRICTED; // 9
/**
* SIM card state: Loaded: SIM card applications have been loaded
* @hide
*/
@SystemApi
- public static final int SIM_STATE_LOADED = 10;
+ public static final int SIM_STATE_LOADED = TelephonyProtoEnums.SIM_STATE_LOADED; // 10
/**
* SIM card state: SIM Card is present
* @hide
*/
@SystemApi
- public static final int SIM_STATE_PRESENT = 11;
+ public static final int SIM_STATE_PRESENT = TelephonyProtoEnums.SIM_STATE_PRESENT; // 11
/**
* Extra included in {@link #ACTION_SIM_CARD_STATE_CHANGED} and
@@ -5395,7 +5403,7 @@ public class TelephonyManager {
@UnsupportedAppUsage
public static String getTelephonyProperty(String property, String defaultVal) {
String propVal = SystemProperties.get(property);
- return propVal == null ? defaultVal : propVal;
+ return TextUtils.isEmpty(propVal) ? defaultVal : propVal;
}
/** @hide */
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index 8379f8cefda0..eb144f9053be 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -80,7 +80,7 @@ public class ApnSetting implements Parcelable {
*/
public static final int TYPE_ALL = ApnTypes.ALL;
/** APN type for default data traffic. */
- public static final int TYPE_DEFAULT = ApnTypes.DEFAULT;
+ public static final int TYPE_DEFAULT = ApnTypes.DEFAULT | ApnTypes.HIPRI;
/** APN type for MMS traffic. */
public static final int TYPE_MMS = ApnTypes.MMS;
/** APN type for SUPL assisted GPS. */
@@ -979,7 +979,7 @@ public class ApnSetting implements Parcelable {
return false;
}
// DEFAULT can handle HIPRI.
- if (hasApnType(type) || (type == TYPE_HIPRI && hasApnType(TYPE_DEFAULT))) {
+ if (hasApnType(type)) {
return true;
}
return false;
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index 3a263504a2ec..cb8269efe443 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -420,6 +420,7 @@ public interface RILConstants {
int RIL_REQUEST_SET_LOGICAL_TO_PHYSICAL_SLOT_MAPPING = 201;
int RIL_REQUEST_SET_SIGNAL_STRENGTH_REPORTING_CRITERIA = 202;
int RIL_REQUEST_SET_LINK_CAPACITY_REPORTING_CRITERIA = 203;
+ int RIL_REQUEST_SET_PREFERRED_DATA_MODEM = 204;
/* Responses begin */
int RIL_RESPONSE_ACKNOWLEDGEMENT = 800;
diff --git a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
index dac7e04be07a..9730ebc57fcf 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
@@ -32,6 +32,7 @@ import android.os.UserHandle;
import android.telephony.Rlog;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
+import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
@@ -43,6 +44,10 @@ public final class TelephonyPermissions {
private static final boolean DBG = false;
+ // When set to true this flag will treat all apps that fail the device identifier check as
+ // though they are targeting pre-Q and return dummy data instead of throwing a SecurityException
+ private static final boolean RELAX_DEVICE_IDENTIFIER_CHECK = true;
+
private static final Supplier<ITelephony> TELEPHONY_SUPPLIER = () ->
ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE));
@@ -275,31 +280,41 @@ public final class TelephonyPermissions {
*/
private static boolean reportAccessDeniedToReadIdentifiers(Context context, int subId, int pid,
int uid, String callingPackage, String message) {
- if (callingPackage != null) {
- try {
- // if the target SDK is pre-Q then check if the calling package would have
- // previously had access to device identifiers.
- ApplicationInfo callingPackageInfo = context.getPackageManager().getApplicationInfo(
- callingPackage, 0);
- if (callingPackageInfo != null
- && callingPackageInfo.targetSdkVersion < Build.VERSION_CODES.Q) {
- if (context.checkPermission(android.Manifest.permission.READ_PHONE_STATE, pid,
- uid) == PackageManager.PERMISSION_GRANTED) {
- return false;
- }
- if (SubscriptionManager.isValidSubscriptionId(subId)
- && getCarrierPrivilegeStatus(TELEPHONY_SUPPLIER, subId, uid)
- == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
- return false;
+ // if the device identifier check is relaxed then just return false to return dummy data to
+ // the caller instead of throwing a SecurityException for apps targeting Q+.
+ if (RELAX_DEVICE_IDENTIFIER_CHECK) {
+ Log.wtf(LOG_TAG,
+ "reportAccessDeniedToReadIdentifiers:" + callingPackage + ":" + message);
+ return false;
+ } else {
+ if (callingPackage != null) {
+ try {
+ // if the target SDK is pre-Q then check if the calling package would have
+ // previously had access to device identifiers.
+ ApplicationInfo callingPackageInfo =
+ context.getPackageManager().getApplicationInfo(
+ callingPackage, 0);
+ if (callingPackageInfo != null
+ && callingPackageInfo.targetSdkVersion < Build.VERSION_CODES.Q) {
+ if (context.checkPermission(android.Manifest.permission.READ_PHONE_STATE,
+ pid,
+ uid) == PackageManager.PERMISSION_GRANTED) {
+ return false;
+ }
+ if (SubscriptionManager.isValidSubscriptionId(subId)
+ && getCarrierPrivilegeStatus(TELEPHONY_SUPPLIER, subId, uid)
+ == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
+ return false;
+ }
}
+ } catch (PackageManager.NameNotFoundException e) {
+ // If the application info for the calling package could not be found then
+ // default to throwing the SecurityException.
}
- } catch (PackageManager.NameNotFoundException e) {
- // If the application info for the calling package could not be found then default
- // to throwing the SecurityException.
}
+ throw new SecurityException(message + ": The user " + uid + " does not have the "
+ + "READ_PRIVILEGED_PHONE_STATE permission to access the device identifiers");
}
- throw new SecurityException(message + ": The user " + uid + " does not have the "
- + "READ_PRIVILEGED_PHONE_STATE permission to access the device identifiers");
}
/**
diff --git a/tests/ActivityTests/Android.mk b/tests/ActivityTests/Android.mk
index 4c68c8bb40c2..94294f6b062a 100644
--- a/tests/ActivityTests/Android.mk
+++ b/tests/ActivityTests/Android.mk
@@ -10,9 +10,5 @@ LOCAL_MODULE_TAGS := tests
LOCAL_CERTIFICATE := platform
LOCAL_USE_AAPT2 := true
-# Disable AAPT2 manifest checks to fix:
-# frameworks/base/tests/ActivityTests/AndroidManifest.xml:42: error: unexpected element <preferred> found in <manifest><application><activity>.
-# TODO(b/79755007): Remove when AAPT2 recognizes the manifest elements.
-LOCAL_AAPT_FLAGS += --warn-manifest-validation
include $(BUILD_PACKAGE)
diff --git a/tests/NetworkSecurityConfigTest/Android.mk b/tests/NetworkSecurityConfigTest/Android.mk
index c225e170c377..a6c21db16846 100644
--- a/tests/NetworkSecurityConfigTest/Android.mk
+++ b/tests/NetworkSecurityConfigTest/Android.mk
@@ -7,7 +7,6 @@ LOCAL_CERTIFICATE := platform
LOCAL_JAVA_LIBRARIES := \
android.test.runner \
- conscrypt \
android.test.base \
LOCAL_STATIC_JAVA_LIBRARIES := junit
diff --git a/tests/net/Android.mk b/tests/net/Android.mk
index 750e2fb6f6b4..132135dc89bc 100644
--- a/tests/net/Android.mk
+++ b/tests/net/Android.mk
@@ -63,7 +63,8 @@ LOCAL_JNI_SHARED_LIBRARIES := \
libunwindstack \
libutilscallstack \
libziparchive \
- libz
+ libz \
+ netd_aidl_interface-cpp
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
@@ -92,7 +93,8 @@ LOCAL_SHARED_LIBRARIES := \
liblog \
libcutils \
libnativehelper \
- libnetdaidl
+ libnetdaidl \
+ netd_aidl_interface-cpp
LOCAL_STATIC_LIBRARIES := \
libpcap \
diff --git a/tools/aapt2/cmd/Convert.cpp b/tools/aapt2/cmd/Convert.cpp
index 954f1ed3fb72..3ea17552ea7c 100644
--- a/tools/aapt2/cmd/Convert.cpp
+++ b/tools/aapt2/cmd/Convert.cpp
@@ -46,7 +46,7 @@ class IApkSerializer {
IApkSerializer(IAaptContext* context, const Source& source) : context_(context), source_(source) {}
virtual bool SerializeXml(const xml::XmlResource* xml, const std::string& path, bool utf16,
- IArchiveWriter* writer) = 0;
+ IArchiveWriter* writer, uint32_t compression_flags) = 0;
virtual bool SerializeTable(ResourceTable* table, IArchiveWriter* writer) = 0;
virtual bool SerializeFile(FileReference* file, IArchiveWriter* writer) = 0;
@@ -59,7 +59,10 @@ class IApkSerializer {
bool ConvertApk(IAaptContext* context, unique_ptr<LoadedApk> apk, IApkSerializer* serializer,
IArchiveWriter* writer) {
- if (!serializer->SerializeXml(apk->GetManifest(), kAndroidManifestPath, true /*utf16*/, writer)) {
+ io::IFile* manifest = apk->GetFileCollection()->FindFile(kAndroidManifestPath);
+ if (!serializer->SerializeXml(apk->GetManifest(), kAndroidManifestPath, true /*utf16*/, writer,
+ (manifest != nullptr && manifest->WasCompressed())
+ ? ArchiveEntry::kCompress : 0u)) {
context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
<< "failed to serialize AndroidManifest.xml");
return false;
@@ -133,7 +136,7 @@ class BinaryApkSerializer : public IApkSerializer {
: IApkSerializer(context, source), tableFlattenerOptions_(options) {}
bool SerializeXml(const xml::XmlResource* xml, const std::string& path, bool utf16,
- IArchiveWriter* writer) override {
+ IArchiveWriter* writer, uint32_t compression_flags) override {
BigBuffer buffer(4096);
XmlFlattenerOptions options = {};
options.use_utf16 = utf16;
@@ -144,8 +147,7 @@ class BinaryApkSerializer : public IApkSerializer {
}
io::BigBufferInputStream input_stream(&buffer);
- return io::CopyInputStreamToArchive(context_, &input_stream, path, ArchiveEntry::kCompress,
- writer);
+ return io::CopyInputStreamToArchive(context_, &input_stream, path, compression_flags, writer);
}
bool SerializeTable(ResourceTable* table, IArchiveWriter* writer) override {
@@ -186,7 +188,8 @@ class BinaryApkSerializer : public IApkSerializer {
return false;
}
- if (!SerializeXml(xml.get(), *file->path, false /*utf16*/, writer)) {
+ if (!SerializeXml(xml.get(), *file->path, false /*utf16*/, writer,
+ file->file->WasCompressed() ? ArchiveEntry::kCompress : 0u)) {
context_->GetDiagnostics()->Error(DiagMessage(source_)
<< "failed to serialize to binary XML: " << *file->path);
return false;
@@ -216,10 +219,10 @@ class ProtoApkSerializer : public IApkSerializer {
: IApkSerializer(context, source) {}
bool SerializeXml(const xml::XmlResource* xml, const std::string& path, bool utf16,
- IArchiveWriter* writer) override {
+ IArchiveWriter* writer, uint32_t compression_flags) override {
pb::XmlNode pb_node;
SerializeXmlResourceToPb(*xml, &pb_node);
- return io::CopyProtoToArchive(context_, &pb_node, path, ArchiveEntry::kCompress, writer);
+ return io::CopyProtoToArchive(context_, &pb_node, path, compression_flags, writer);
}
bool SerializeTable(ResourceTable* table, IArchiveWriter* writer) override {
@@ -246,7 +249,8 @@ class ProtoApkSerializer : public IApkSerializer {
return false;
}
- if (!SerializeXml(xml.get(), *file->path, false /*utf16*/, writer)) {
+ if (!SerializeXml(xml.get(), *file->path, false /*utf16*/, writer,
+ file->file->WasCompressed() ? ArchiveEntry::kCompress : 0u)) {
context_->GetDiagnostics()->Error(DiagMessage(source_)
<< "failed to serialize to proto XML: " << *file->path);
return false;
diff --git a/tools/stats_log_api_gen/Collation.cpp b/tools/stats_log_api_gen/Collation.cpp
index 4245700ed90d..d1f42f8b398e 100644
--- a/tools/stats_log_api_gen/Collation.cpp
+++ b/tools/stats_log_api_gen/Collation.cpp
@@ -251,7 +251,7 @@ int collate_atom(const Descriptor *atom, AtomDecl *atomDecl,
}
atomDecl->fields.push_back(atField);
- if (field->options().GetExtension(os::statsd::stateFieldOption).option() ==
+ if (field->options().GetExtension(os::statsd::state_field_option).option() ==
os::statsd::StateField::PRIMARY) {
if (javaType == JAVA_TYPE_UNKNOWN ||
javaType == JAVA_TYPE_ATTRIBUTION_CHAIN ||
@@ -261,7 +261,7 @@ int collate_atom(const Descriptor *atom, AtomDecl *atomDecl,
atomDecl->primaryFields.push_back(it->first);
}
- if (field->options().GetExtension(os::statsd::stateFieldOption).option() ==
+ if (field->options().GetExtension(os::statsd::state_field_option).option() ==
os::statsd::StateField::EXCLUSIVE) {
if (javaType == JAVA_TYPE_UNKNOWN ||
javaType == JAVA_TYPE_ATTRIBUTION_CHAIN ||
diff --git a/tools/stats_log_api_gen/test.proto b/tools/stats_log_api_gen/test.proto
index 264a865e3b39..f6359748a27e 100644
--- a/tools/stats_log_api_gen/test.proto
+++ b/tools/stats_log_api_gen/test.proto
@@ -127,33 +127,33 @@ message GoodStateAtoms {
// The atom has only primary field but no exclusive state field.
message BadStateAtom1 {
optional int32 uid = 1
- [(android.os.statsd.stateFieldOption).option = PRIMARY];
+ [(android.os.statsd.state_field_option).option = PRIMARY];
}
// Only primative types can be annotated.
message BadStateAtom2 {
repeated android.os.statsd.AttributionNode attribution = 1
- [(android.os.statsd.stateFieldOption).option = PRIMARY];
+ [(android.os.statsd.state_field_option).option = PRIMARY];
optional int32 state = 2
- [(android.os.statsd.stateFieldOption).option = EXCLUSIVE];
+ [(android.os.statsd.state_field_option).option = EXCLUSIVE];
}
// Having 2 exclusive state field in the atom means the atom is badly designed.
// E.g., putting bluetooth state and wifi state in the same atom.
message BadStateAtom3 {
optional int32 uid = 1
- [(android.os.statsd.stateFieldOption).option = PRIMARY];
+ [(android.os.statsd.state_field_option).option = PRIMARY];
optional int32 state = 2
- [(android.os.statsd.stateFieldOption).option = EXCLUSIVE];
+ [(android.os.statsd.state_field_option).option = EXCLUSIVE];
optional int32 state2 = 3
- [(android.os.statsd.stateFieldOption).option = EXCLUSIVE];
+ [(android.os.statsd.state_field_option).option = EXCLUSIVE];
}
message GoodStateAtom1 {
optional int32 uid = 1
- [(android.os.statsd.stateFieldOption).option = PRIMARY];
+ [(android.os.statsd.state_field_option).option = PRIMARY];
optional int32 state = 2
- [(android.os.statsd.stateFieldOption).option = EXCLUSIVE];
+ [(android.os.statsd.state_field_option).option = EXCLUSIVE];
}
// Atoms can have exclusive state field, but no primary field. That means
@@ -161,16 +161,16 @@ message GoodStateAtom1 {
message GoodStateAtom2 {
optional int32 uid = 1;
optional int32 state = 2
- [(android.os.statsd.stateFieldOption).option = EXCLUSIVE];
+ [(android.os.statsd.state_field_option).option = EXCLUSIVE];
}
// We can have more than one primary fields. That means their combination is a
// primary key.
message GoodStateAtom3 {
optional int32 uid = 1
- [(android.os.statsd.stateFieldOption).option = PRIMARY];
+ [(android.os.statsd.state_field_option).option = PRIMARY];
optional int32 tid = 2
- [(android.os.statsd.stateFieldOption).option = PRIMARY];
+ [(android.os.statsd.state_field_option).option = PRIMARY];
optional int32 state = 3
- [(android.os.statsd.stateFieldOption).option = EXCLUSIVE];
+ [(android.os.statsd.state_field_option).option = EXCLUSIVE];
} \ No newline at end of file
diff --git a/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java b/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java
index b4dfac6c01c7..6076175ce9d1 100644
--- a/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java
+++ b/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java
@@ -102,6 +102,12 @@ public abstract class ProvisioningCallback {
public static final int OSU_FAILURE_NO_OSU_ACTIVITY_FOUND = 14;
/**
+ * The reason code for provisioning failure when the status of a SOAP message is not the
+ * expected message status.
+ */
+ public static final int OSU_FAILURE_UNEXPECTED_SOAP_MESSAGE_STATUS = 15;
+
+ /**
* The status code for provisioning flow to indicate connecting to OSU AP
*/
public static final int OSU_STATUS_AP_CONNECTING = 1;
@@ -147,6 +153,11 @@ public abstract class ProvisioningCallback {
public static final int OSU_STATUS_SECOND_SOAP_EXCHANGE = 9;
/**
+ * The status code for provisioning flow to indicate starting the third SOAP exchange.
+ */
+ public static final int OSU_STATUS_THIRD_SOAP_EXCHANGE = 10;
+
+ /**
* Provisioning status for OSU failure
*
* @param status indicates error condition
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/pps/HomeSpTest.java b/wifi/tests/src/android/net/wifi/hotspot2/pps/HomeSpTest.java
index 5c9df6a0186c..c7993e308d17 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/pps/HomeSpTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/pps/HomeSpTest.java
@@ -189,8 +189,7 @@ public class HomeSpTest {
Map<String, Long> homeNetworkIds = new HashMap<>();
byte[] rawSsidBytes = new byte[33];
Arrays.fill(rawSsidBytes, (byte) 'a');
- homeNetworkIds.put(
- StringFactory.newStringFromBytes(rawSsidBytes, StandardCharsets.UTF_8), 0x1234L);
+ homeNetworkIds.put(new String(rawSsidBytes, StandardCharsets.UTF_8), 0x1234L);
homeSp.setHomeNetworkIds(homeNetworkIds);
assertFalse(homeSp.validate());
}