diff options
436 files changed, 7320 insertions, 4842 deletions
diff --git a/Android.bp b/Android.bp index 9e838b3efcc1..121decbbec50 100644 --- a/Android.bp +++ b/Android.bp @@ -162,49 +162,54 @@ filegroup { path: "wifi/java", } -framework_srcs = [ - // Java/AIDL sources under frameworks/base - ":framework-core-sources", - ":framework-drm-sources", - ":framework-graphics-sources", - ":framework-keystore-sources", - ":framework-location-sources", - ":framework-lowpan-sources", - ":framework-media-sources", - ":framework-mca-effect-sources", - ":framework-mca-filterfw-sources", - ":framework-mca-filterpacks-sources", - ":framework-opengl-sources", - ":framework-rs-sources", - ":framework-sax-sources", - ":framework-telecomm-sources", - ":framework-telephony-sources", - ":framework-wifi-sources", - ":PacProcessor-aidl-sources", - ":ProxyHandler-aidl-sources", - - // AIDL sources from external directories - ":dumpstate_aidl", - ":framework_native_aidl", - ":gatekeeper_aidl", - ":gsiservice_aidl", - ":incidentcompanion_aidl", - ":installd_aidl", - ":keystore_aidl", - ":libaudioclient_aidl", - ":libbinder_aidl", - ":libbluetooth-binder-aidl", - ":libcamera_client_aidl", - ":libcamera_client_framework_aidl", - ":libupdate_engine_aidl", - ":storaged_aidl", - ":vold_aidl", - - // etc. - "core/java/**/*.logtags", - ":framework-javastream-protos", - ":framework-statslog-gen", -] +filegroup { + name: "framework-srcs", + srcs: [ + // Java/AIDL sources under frameworks/base + ":framework-core-sources", + ":framework-drm-sources", + ":framework-graphics-sources", + ":framework-keystore-sources", + ":framework-location-sources", + ":framework-lowpan-sources", + ":framework-media-sources", + ":framework-mca-effect-sources", + ":framework-mca-filterfw-sources", + ":framework-mca-filterpacks-sources", + ":framework-opengl-sources", + ":framework-rs-sources", + ":framework-sax-sources", + ":framework-telecomm-sources", + ":framework-telephony-sources", + ":framework-wifi-sources", + ":PacProcessor-aidl-sources", + ":ProxyHandler-aidl-sources", + + // AIDL sources from external directories + ":dumpstate_aidl", + ":framework_native_aidl", + ":gatekeeper_aidl", + ":gsiservice_aidl", + ":incidentcompanion_aidl", + ":installd_aidl", + ":keystore_aidl", + ":libaudioclient_aidl", + ":libbinder_aidl", + ":libbluetooth-binder-aidl", + ":libcamera_client_aidl", + ":libcamera_client_framework_aidl", + ":libupdate_engine_aidl", + ":storaged_aidl", + ":vold_aidl", + + // For the generated R.java and Manifest.java + ":framework-res{.aapt.srcjar}", + + // etc. + ":framework-javastream-protos", + ":framework-statslog-gen", + ], +} java_defaults { name: "framework-aidl-export-defaults", @@ -231,32 +236,11 @@ java_defaults { }, } -java_defaults { - name: "framework-defaults", - defaults: ["framework-aidl-export-defaults"], - installable: true, - - srcs: framework_srcs, - - aidl: { - generate_get_transaction_name: true, - }, - - exclude_srcs: [ - // See comment on framework-atb-backward-compatibility module below - "core/java/android/content/pm/AndroidTestBaseUpdater.java", - ], - - sdk_version: "core_platform", - libs: [ - "ext", - "updatable_media_stubs", - ], - - jarjar_rules: ":framework-jarjar-rules", - +// Collection of classes that are generated from non-Java files that are not listed in +// framework_srcs. These have no or very limited dependency to the framework. +java_library { + name: "framework-internal-utils", static_libs: [ - "mimemap", "apex_aidl_interface-java", "suspend_control_aidl_interface-java", "framework-protos", @@ -290,6 +274,38 @@ java_defaults { "com.android.sysprop.apex", "PlatformProperties", ], + sdk_version: "core_platform", + installable: false, +} + +java_defaults { + name: "framework-defaults", + defaults: ["framework-aidl-export-defaults"], + installable: true, + + srcs: [ + ":framework-srcs", + "core/java/**/*.logtags", + ], + + aidl: { + generate_get_transaction_name: true, + }, + + exclude_srcs: [ + // See comment on framework-atb-backward-compatibility module below + "core/java/android/content/pm/AndroidTestBaseUpdater.java", + ], + + sdk_version: "core_platform", + libs: [ + "ext", + "updatable_media_stubs", + ], + + jarjar_rules: ":framework-jarjar-rules", + + static_libs: ["framework-internal-utils"], required: [ // TODO: remove gps_debug when the build system propagates "required" properly. @@ -374,7 +390,6 @@ java_library { platform_compat_config { name: "framework-platform-compat-config", - prefix: "framework", src: ":framework-annotation-proc", } @@ -760,7 +775,7 @@ python_binary_host { ], } -// TODO: Don't rely on this list once droiddoc can take a list of packages to document +// TODO: Don't rely on this list by switching package.html into package-info.java frameworks_base_subdirs = [ "core/java", "graphics/java", @@ -780,13 +795,6 @@ frameworks_base_subdirs = [ "rs/java", ] -packages_to_document = [ - "android", - "javax/microedition/khronos", - "org/apache/http/conn", - "org/apache/http/params", -] - // Make the api/current.txt file available for use by modules in other // directories. filegroup { @@ -879,17 +887,17 @@ metalava_framework_docs_args += " --replace-documentation " + stubs_defaults { name: "framework-doc-stubs-default", srcs: [ + ":framework-srcs", + "core/java/**/*.logtags", "test-base/src/**/*.java", ":opt-telephony-srcs", ":opt-net-voip-srcs", ":core_public_api_files", - ":updatable-media-srcs-without-aidls", + ":updatable-media-srcs", "test-mock/src/**/*.java", "test-runner/src/**/*.java", ":jobscheduler-framework-source", ], - srcs_lib: "framework-minus-apex", - srcs_lib_whitelist_pkgs: packages_to_document, libs: framework_docs_only_libs, local_sourcepaths: frameworks_base_subdirs, create_doc_stubs: true, @@ -936,17 +944,23 @@ doc_defaults { create_stubs: false, } +doc_defaults { + name: "framework-dokka-docs-default", + create_stubs: false, +} + stubs_defaults { name: "metalava-api-stubs-default", srcs: [ + ":framework-srcs", + "core/java/**/*.logtags", ":opt-telephony-srcs", ":opt-net-voip-srcs", ":core_public_api_files", - ":updatable-media-srcs-without-aidls", + ":updatable-media-srcs", ":jobscheduler-framework-source", ], - srcs_lib: "framework-minus-apex", - srcs_lib_whitelist_pkgs: packages_to_document, + libs: ["framework-internal-utils"], local_sourcepaths: frameworks_base_subdirs, installable: false, annotations_enabled: true, @@ -960,6 +974,7 @@ stubs_defaults { "sdk-dir", "api-versions-jars-dir", ], + sdk_version: "core_platform", } droidstubs { @@ -1109,7 +1124,7 @@ droiddoc { } droiddoc { - name: "ds-docs", + name: "ds-docs-java", defaults: ["framework-docs-default"], srcs: [ ":framework-doc-stubs", @@ -1138,6 +1153,58 @@ droiddoc { } droiddoc { + name: "ds-docs-kt", + defaults: ["framework-dokka-docs-default"], + srcs: [ + ":framework-doc-stubs", + ], + args: "-noJdkLink -links https://kotlinlang.org/api/latest/jvm/stdlib/^external/dokka/package-list " + + "-noStdlibLink", + proofread_file: "ds-dokka-proofread.txt", + dokka_enabled: true, +} + +java_genrule { + name: "ds-docs", + tools: [ + "zip2zip", + "merge_zips", + ], + srcs: [ + ":ds-docs-java{.docs.zip}", + ":ds-docs-kt{.docs.zip}", + ], + out: ["ds-docs.zip"], + dist: { + targets: ["docs"], + }, + cmd: "$(location zip2zip) -i $(location :ds-docs-kt{.docs.zip}) -o $(genDir)/ds-docs-kt-moved.zip **/*:en/reference/kotlin && " + + "$(location merge_zips) $(out) $(location :ds-docs-java{.docs.zip}) $(genDir)/ds-docs-kt-moved.zip", +} + +java_genrule { + name: "ds-docs-switched", + tools: [ + "switcher4", + "soong_zip", + ], + srcs: [ + ":ds-docs-java{.docs.zip}", + ":ds-docs-kt{.docs.zip}", + ], + out: ["ds-docs-switched.zip"], + dist: { + targets: ["docs"], + }, + cmd: "unzip $(location :ds-docs-java{.docs.zip}) -d $(genDir) && " + + "unzip $(location :ds-docs-kt{.docs.zip}) -d $(genDir)/en/reference/kotlin && " + + "SWITCHER=$$(cd $$(dirname $(location switcher4)) && pwd)/$$(basename $(location switcher4)) && " + + "(cd $(genDir)/en/reference && $$SWITCHER --work platform) && " + + "$(location soong_zip) -o $(out) -C $(genDir) -D $(genDir)", +} + + +droiddoc { name: "ds-static-docs", defaults: ["framework-docs-default"], srcs: [ @@ -1271,6 +1338,7 @@ droidstubs { ":openjdk_java_files", ":opt-telephony-common-srcs", ], + arg_files: [ "core/res/AndroidManifest.xml", ], @@ -1405,7 +1473,7 @@ filegroup { // annotations to private apis aidl_mapping { name: "framework-aidl-mappings", - srcs: framework_srcs, + srcs: [":framework-srcs"], output: "framework-aidl-mappings.txt", } diff --git a/apex/jobscheduler/framework/java/android/os/IDeviceIdleController.aidl b/apex/jobscheduler/framework/java/android/os/IDeviceIdleController.aidl index aa255bf660d5..9d5becbf77cd 100644 --- a/apex/jobscheduler/framework/java/android/os/IDeviceIdleController.aidl +++ b/apex/jobscheduler/framework/java/android/os/IDeviceIdleController.aidl @@ -16,7 +16,6 @@ package android.os; -import android.os.IMaintenanceActivityListener; import android.os.UserHandle; /** @hide */ @@ -44,8 +43,6 @@ interface IDeviceIdleController { long addPowerSaveTempWhitelistAppForMms(String name, int userId, String reason); long addPowerSaveTempWhitelistAppForSms(String name, int userId, String reason); void exitIdle(String reason); - boolean registerMaintenanceActivityListener(IMaintenanceActivityListener listener); - void unregisterMaintenanceActivityListener(IMaintenanceActivityListener listener); int setPreIdleTimeoutMode(int Mode); void resetPreIdleTimeoutMode(); } diff --git a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java index 62930b0ff134..d0e38b4a4e36 100644 --- a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java +++ b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java @@ -51,14 +51,12 @@ import android.os.Environment; import android.os.FileUtils; import android.os.Handler; import android.os.IDeviceIdleController; -import android.os.IMaintenanceActivityListener; import android.os.Looper; import android.os.Message; import android.os.PowerManager; import android.os.PowerManager.ServiceType; import android.os.PowerManagerInternal; import android.os.Process; -import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.ResultReceiver; import android.os.ServiceManager; @@ -448,7 +446,6 @@ public class DeviceIdleController extends SystemService // down. private boolean mJobsActive; private boolean mAlarmsActive; - private boolean mReportedMaintenanceActivity; /* Factor to apply to INACTIVE_TIMEOUT and IDLE_AFTER_INACTIVE_TIMEOUT in order to enter * STATE_IDLE faster or slower. Don't apply this to SENSING_TIMEOUT or LOCATING_TIMEOUT because: @@ -463,9 +460,6 @@ public class DeviceIdleController extends SystemService public final AtomicFile mConfigFile; - private final RemoteCallbackList<IMaintenanceActivityListener> mMaintenanceActivityListeners = - new RemoteCallbackList<IMaintenanceActivityListener>(); - /** * Package names the system has white-listed to opt out of power save restrictions, * except for device idle mode. @@ -1309,7 +1303,6 @@ public class DeviceIdleController extends SystemService private static final int MSG_REPORT_IDLE_OFF = 4; private static final int MSG_REPORT_ACTIVE = 5; private static final int MSG_TEMP_APP_WHITELIST_TIMEOUT = 6; - private static final int MSG_REPORT_MAINTENANCE_ACTIVITY = 7; private static final int MSG_FINISH_IDLE_OP = 8; private static final int MSG_REPORT_TEMP_APP_WHITELIST_CHANGED = 9; private static final int MSG_SEND_CONSTRAINT_MONITORING = 10; @@ -1410,22 +1403,6 @@ public class DeviceIdleController extends SystemService int appId = msg.arg1; checkTempAppWhitelistTimeout(appId); } break; - case MSG_REPORT_MAINTENANCE_ACTIVITY: { - // TODO: What is keeping the device awake at this point? Does it need to be? - boolean active = (msg.arg1 == 1); - final int size = mMaintenanceActivityListeners.beginBroadcast(); - try { - for (int i = 0; i < size; i++) { - try { - mMaintenanceActivityListeners.getBroadcastItem(i) - .onMaintenanceActivityChanged(active); - } catch (RemoteException ignored) { - } - } - } finally { - mMaintenanceActivityListeners.finishBroadcast(); - } - } break; case MSG_FINISH_IDLE_OP: { // mActiveIdleWakeLock is held at this point decActiveIdleOps(); @@ -1594,16 +1571,6 @@ public class DeviceIdleController extends SystemService } } - @Override public boolean registerMaintenanceActivityListener( - IMaintenanceActivityListener listener) { - return DeviceIdleController.this.registerMaintenanceActivityListener(listener); - } - - @Override public void unregisterMaintenanceActivityListener( - IMaintenanceActivityListener listener) { - DeviceIdleController.this.unregisterMaintenanceActivityListener(listener); - } - @Override public int setPreIdleTimeoutMode(int mode) { getContext().enforceCallingOrSelfPermission(Manifest.permission.DEVICE_POWER, null); @@ -3131,7 +3098,6 @@ public class DeviceIdleController extends SystemService void setJobsActive(boolean active) { synchronized (this) { mJobsActive = active; - reportMaintenanceActivityIfNeededLocked(); if (!active) { exitMaintenanceEarlyIfNeededLocked(); } @@ -3147,19 +3113,6 @@ public class DeviceIdleController extends SystemService } } - boolean registerMaintenanceActivityListener(IMaintenanceActivityListener listener) { - synchronized (this) { - mMaintenanceActivityListeners.register(listener); - return mReportedMaintenanceActivity; - } - } - - void unregisterMaintenanceActivityListener(IMaintenanceActivityListener listener) { - synchronized (this) { - mMaintenanceActivityListeners.unregister(listener); - } - } - @VisibleForTesting int setPreIdleTimeoutMode(int mode) { return setPreIdleTimeoutFactor(getPreIdleTimeoutByMode(mode)); @@ -3281,17 +3234,6 @@ public class DeviceIdleController extends SystemService } } - void reportMaintenanceActivityIfNeededLocked() { - boolean active = mJobsActive; - if (active == mReportedMaintenanceActivity) { - return; - } - mReportedMaintenanceActivity = active; - Message msg = mHandler.obtainMessage(MSG_REPORT_MAINTENANCE_ACTIVITY, - mReportedMaintenanceActivity ? 1 : 0, 0); - mHandler.sendMessage(msg); - } - @VisibleForTesting long getNextAlarmTime() { return mNextAlarmTime; diff --git a/apex/statsd/Android.bp b/apex/statsd/Android.bp new file mode 100644 index 000000000000..d76a40e9e26d --- /dev/null +++ b/apex/statsd/Android.bp @@ -0,0 +1,46 @@ +// Copyright (C) 2019 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. + +apex { + name: "com.android.os.statsd", + + manifest: "apex_manifest.json", + + // optional. if unspecified, a default one is auto-generated + //androidManifest: "AndroidManifest.xml", + + // libc.so and libcutils.so are included in the apex + // native_shared_libs: ["libc", "libcutils"], + // binaries: ["vold"], + // java_libs: ["core-all"], + // prebuilts: ["my_prebuilt"], + + compile_multilib: "both", + + key: "com.android.os.statsd.key", + certificate: ":com.android.os.statsd.certificate", +} + +apex_key { + name: "com.android.os.statsd.key", + public_key: "com.android.os.statsd.avbpubkey", + private_key: "com.android.os.statsd.pem", +} + +android_app_certificate { + name: "com.android.os.statsd.certificate", + // This will use com.android.os.statsd.x509.pem (the cert) and + // com.android.os.statsd.pk8 (the private key) + certificate: "com.android.os.statsd", +} diff --git a/apex/statsd/apex_manifest.json b/apex/statsd/apex_manifest.json new file mode 100644 index 000000000000..0c0ad860f3d1 --- /dev/null +++ b/apex/statsd/apex_manifest.json @@ -0,0 +1,5 @@ +{ + "name": "com.android.os.statsd", + "version": 1 +} + diff --git a/apex/statsd/com.android.os.statsd.avbpubkey b/apex/statsd/com.android.os.statsd.avbpubkey Binary files differnew file mode 100644 index 000000000000..d78af8b8bef2 --- /dev/null +++ b/apex/statsd/com.android.os.statsd.avbpubkey diff --git a/apex/statsd/com.android.os.statsd.pem b/apex/statsd/com.android.os.statsd.pem new file mode 100644 index 000000000000..558e17fd6864 --- /dev/null +++ b/apex/statsd/com.android.os.statsd.pem @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIJKgIBAAKCAgEA893bbpkivKEiNgfknYBSlzC0csaKU/ddBm5Pb4ZFuab+LQSR +9DDc5JrsmxyrsrvuwL/zAtMbkyYWzEiUxJtx/w0bw8rC90GoPRSCmxyI0ZK8FuPy +IAQ7UeNfTWZ485mAUaTSasGIfQ3DY4F0P+aUSijeG3NUY02nALHDMqJX7lXR+mL1 +DUYDg05KB0jxQwlYqBeujTPPiAzEqm3PlBoHuan8/qgK2wdQMTVg/fieUD3lupmV +Wj2dRZgqfBPA16ZbV4Uo0j0bZSf+fQLiXlU2VJGb5i/FQfjLqMKGABDI0MgK7Sc2 +m4ySpV4g4XKDv/vw6Dw4kwWC7mATEVAkH+q6V7uiZeN6a7w30UMtPI8fPaUvAP3L +VBjCBIv/3m+CKkWcNxOZ3sQBQl5bS05dxcfiVsBvBLYbvQgC+Wy0Sc3b+1pXFT/E +uAsbZ4CyVsi1+PAdx3h5e2QAyNCXgZDOcvTUyxY6JLTE0LOVHmI4fJEujBex//Oz +PCRHvC8K+KiljyQWf/NYrLSD3QGYAjVMtQh7yu2yhzWzgBUxyhuv3rY4ATXsN3bJ +wW4w7/L/RSLSW5+lp/NoJOD9utbsKTyGMHOY6K8JLOmhv3ORoAEmLYlFTI+FqBi9 +AH1HQEKCyh8Z/bYHLUzGWl6FqAMtcnuintv40BbKyt0/D1ItdbSNKmOZ5rkCAwEA +AQKCAgAY7ll8mRNADYkd1Pi+UVwgMM6B3WJO6z8LZUOhtyxxqmzZ1VnGiShMBrqh +sPCsuSHTeswxQbvT81TpVZI/91RUKtbn0VbVSFUWyX4AtY4XPtUT0gHy2/vkh0Y6 +93ruDIdd0Wfhmh+GCV4sUhO8ZKpMWpk6XTQHYuzr2UCHcKlkqElrO6qpzLqXNe3D +iOWBYPc7WBB0RxO0aPnCIq/SCEc55/MBZdSWR80e+sILtNsagPl3djQaoanub3wI +a0yPv2YfMHHX7H9cfBY8WYsi8bs4MhqqEcAs2m6XtitU3mJpVcooLJYcmOZ1GYZr +BfYKLouWcnGmNi4IiLHqVzMaQDkEhAZsRaAXCkoVVrFBedLlmLPpiUIQlINF4vxe +3IcekTKWyMzkU6h+K8T15MU5mLSqeL2Gji1JIwKJno51FZ9uc++pUJVtfYQmNny8 +8RKvQ1hv/S5yLQKgN+VkNbaWlUoMP73dtUe3m/At71/2Dj7xB0KtcgT1lEMrM1GR +oynJAJLz/d0n5RUUREwkZZMcA4fQVC7Db6vpK69jPiQMShpZ3JKCEjfYLUuN0slt +FPhjiR175E0vTRuLoIj4kXNwLLswH0c9zqrKM2S92SCxAV3E4JJGKhUZalvT9s1g +LrPhMCl6CsOES98T87d3RyAIK0iVRCnRUG3bc+8rzyRd4fzkAQKCAQEA/UjmCSm3 +H46t/1w7YBZPew7SFQOAJe81iDzbonc3fNPD2R8lxtD3MwdvrQ5f9fhT4+uveWNr +dyBX7ppnissyM3LZRN+7BdeIVVeIPVen6Ou9W2i7q18ZoQx9IpRcZEw5tGJFZaGx +EmyPN4i1K0ccUkGbBvbXXQ/tcG3wElRpBAc5/TQ8vrpUgHll2/MbYhowx6P9uHv5 +thoyG98X+7Fbg8ikzw5GtyuedXfyX1CpJ7yUQVS2PEaOMXOkZdx2bbWRAYYCpsqB +dMmjs2PsFhZHu6CpLhlocHbfUiRztCUCaMZJPQXFSVmy8QDMvZEdVLvad9Poi8ny +lmHVRgxaNbAtIQKCAQEA9nscqRaaO7hIX9bOUxcDbI0486Ws4H0hAFApIN+6/LP4 +hkxey3xWArTYWrvSG1d5GkJAdn99ayWzo2PevmJlrhIJiO1QqYBAk+87cnhwSCmB +kb0sGkNWcc/xNRy7eqdhyCmVhaUnIbORee+cD6qiu/l2BAclTf2ZARFOGXjhQkvt +cDbc/9ZR467ceXbiTIU34Be4xnNAY1mo59jvwl9eqxgpefYTqPhcZ7OmlDli77Hd +XuRfuxLZCscv7A9M5Enc2zwOEP5VwRNwYzYtMm2Yh9CQZxNWC7JVh1Gw5MPFzsGl +sgEdb4WGneN6PPLQHK7NF0f7wYSNnF0i3XSME9MumQKCAQEA0qMbWydr+TyJC0LC +xigHtUkgAQXGPsXuePxTk4sdhBwAVcKHgg4qZi+a+gpoV4BLE9LfPU4nAwzM08to +rI5Lk2nBsnt1Z2hVItQGoy0QoK3b7fbti5ktETf3oRhMtcSGgLLxD5ImVjId8Isq +T3F15hpVOLdzZxtl1Qg4jKXSJ91yplYY5mzC9Yz/3qkQbsdlJcIFsLS5eG3UmkUw +Bsr6VmA4X1F6Eb6eqwYzdHz6D+fOS36NhxcODaYkY+myO46xptixv8/NVTiTgQ5q +OfwRb8Iur/3FUzIoioFyD7Bvjn7ITY1NArEsFS0bF9Nk1yDakKiUThyGN/Xojbac +FuYKwQKCAQEAxOWJ+qU8phJLdowBHC0ZJiEWasRhep9auoZOpJ01IWOfV6EwZLs5 +dkYDQ1Agwoi5DDn6hu7HQM3IV/CS4mF2OnzcMw7ozc7PR53nTkVZ5LuLbuHAlmZO +avKjDDucpJmLqjtV34IT5X8t6kt3zqgQAbuBBCy1Jz07ebfaPMzsnWpMDcU1/AW4 +OvrX0wweMOSGwzQP/i/ZMsRQAo2w0gQfeuv9Thk+kU99ebXwjx3co//hCEnFE4s1 +6L8/0AJU+VTr4hJyZi7WUDt4HzkLF+qm22/Hux+eMA/Q9R1UAxtFLCpTdAQiAJGY +/Q3X+1I434DgAwYU3f1Gpq9cB65vq/KamQKCAQEAjIub5wde/ttHlLALvnOXrbqe +nUIfWHExMzhul/rkr8fFEJwij2nZUuN2EWUGzBWQQoNXw5QKHLZyPsyFUOa/P2BS +osnffAa+sumL4k36E71xFdTVV5ExyTXZVB49sPmUpivP9gEucFFqDHKjGsF45dBF ++DZdykLUIv+/jQUzXGkZ5Wv/r52YUNho4EZdwnlJ2so7cxnsYnjW+c1nlp17tkq5 +DfwktkeD9iFzlaZ66vLoO44luaBm+lC3xM2sHinOTwbk0gvhJAIoLfkOYhpmGc8A +4W/E1OHfVz6xqVDsMBFhRbQpHNkf8XZNqkIoqHVMTaMOJJlM+lb0+A9B8Bm/XA== +-----END RSA PRIVATE KEY----- diff --git a/apex/statsd/com.android.os.statsd.pk8 b/apex/statsd/com.android.os.statsd.pk8 Binary files differnew file mode 100644 index 000000000000..49910f80a05c --- /dev/null +++ b/apex/statsd/com.android.os.statsd.pk8 diff --git a/apex/statsd/com.android.os.statsd.x509.pem b/apex/statsd/com.android.os.statsd.x509.pem new file mode 100644 index 000000000000..e7b16b2048cb --- /dev/null +++ b/apex/statsd/com.android.os.statsd.x509.pem @@ -0,0 +1,30 @@ +-----BEGIN CERTIFICATE----- +MIIFDTCCAvWgAwIBAgIUCnta1LAl5fMMLLQx//4zWz9A2A8wDQYJKoZIhvcNAQEL +BQAwFTETMBEGA1UECgwKR29vZ2xlIExMQzAgFw0xOTA4MTIyMjM5MzBaGA80NzU3 +MDcwODIyMzkzMFowFTETMBEGA1UECgwKR29vZ2xlIExMQzCCAiIwDQYJKoZIhvcN +AQEBBQADggIPADCCAgoCggIBAOranWZ19jkXCF9WIlXv01tUUvLKMHWKV7X9Earw +cL7/aax0pFbNJutgyBUiOszbR+0T7quZxz6jACu+6y7iaMJnvMluZsfTi+p2UvQt +y6Ql7ZUOQ7bVluCFIW5hZ+8d9RrLmZdvX1r4YfF6HufDBkAbj+os+y6407OezJAV +8EATpemc9gsCC4RJZpwzTs1RUXMD4UoNrLZAE8+7iaJZeBxmz0MAPj92pYc9M7/d +xInzYvOR08/uEpHt8jlMdVgSQS/FaRlIOIqcGBk3cjkjDlpVATQ4Hyjy+IPQPjTD +bJUmDJiYeBCyY/pYZQvTQjl8s+fvykTsF9Lfb+E+PhZ0+N8pRi7sUSpisZHSiqaN +W3oxYWc0YQSuzygHHog8HH/azHX5L805g/+Rwfb/cUF9eJgjq0vrkFnsz4UKgKNV +hHL90mfqpbc2UvJ8VY8BvIjbsHQ77LrBKlqI9VMPorttpTOuwHHJPKsyN972F0Ul +lRB6CwFE8csVGWXoNaDZWBv7xTDdbdirmlKDNueg9pw6ksYV2Is9Dv8PxmsZvb+4 +oftC/hb4X1Pudn01PPs9Tx44CwHuVLENUwlDEVzG5zNetsv9kAuCYt3VRVF+NYqj +NAfLbxCKLe25wGzJrZUEJ1YrYIjpUbfwnttEad/9Pu13DAS7HZwn5vwqEKB/1LlT +NSUXAgMBAAGjUzBRMB0GA1UdDgQWBBSKElkhJSbzgh8+iysye8SrkmJ62DAfBgNV +HSMEGDAWgBSKElkhJSbzgh8+iysye8SrkmJ62DAPBgNVHRMBAf8EBTADAQH/MA0G +CSqGSIb3DQEBCwUAA4ICAQANFGnc2wJBrFbh2nzhl06g4TjPKGRCw365vZ1A3T9O +jXP0lToHDxB33TpKk6d7zszR1uPphQQxgzhSVZB/jx8q4kWSSoKoF9Dlx7h8rAt+ +2TM5DaBvxrwu5mqOALwQuF81wap1Pl2L2fFHvygCm8b+Ci4iS5vcr0axNnp1rK1b +vUtRWY4mfxTjJYcgeCVUGskqTb+cCxQZ6Icno6VTKajT1FybRmD3KZJaUuLbNEN+ +IE4nGTMG2WZ5Hl2vR8JJp1sYYn8T3ElMAb0MSNFkqsfI+tToEwGsuJDgYEdtEnzf +lTycQvn5NhrIZRRN3pqSyWpAU7p9mmyTK0PHMz2D/Rtfb7lE692vXzxCmZND51mc +YXCCoanV6eZZ7Sbqzh60+5QV38hgFBst5l8CcFaWWSFK9nBWdzS5lhs9lmQ4aiYd +IE0qsNZgMob+TTP1VW39hu4EDjNmOrKfimM9J2tcPZ5QP01DgETPvAsB7vn2Xz9J +HGt5ntiSV4W2izDP8viQ1M5NvfdBaUhcnNsE6/sxfU0USRs2hrEp1oiqrv4p6V0P +qOt7C2/YtJzkrxfsHZAxBUSRHa7LwtzgeiJDUivHn94VnAzSAH8MLx6CzDPQ8HWN +NiZFxTKfMVyjEmbQ2PalHWB8pWtpdEh7X4rzaqhnLBTis3pGssASgo3ArLIYleAU ++g== +-----END CERTIFICATE----- diff --git a/api/current.txt b/api/current.txt index 81ecceb03fc1..99ae1c86d208 100644 --- a/api/current.txt +++ b/api/current.txt @@ -2816,7 +2816,7 @@ package android.accessibilityservice { method public int describeContents(); method public int getDisplayId(); method public int getGestureId(); - method public void writeToParcel(android.os.Parcel, int); + method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.accessibilityservice.AccessibilityGestureInfo> CREATOR; } @@ -10875,9 +10875,7 @@ package android.content { method @Nullable public String getString(String, @Nullable String); method @Nullable public java.util.Set<java.lang.String> getStringSet(String, @Nullable java.util.Set<java.lang.String>); method public void registerOnSharedPreferenceChangeListener(android.content.SharedPreferences.OnSharedPreferenceChangeListener); - method public default void registerOnSharedPreferencesClearListener(@NonNull android.content.SharedPreferences.OnSharedPreferencesClearListener); method public void unregisterOnSharedPreferenceChangeListener(android.content.SharedPreferences.OnSharedPreferenceChangeListener); - method public default void unregisterOnSharedPreferencesClearListener(@NonNull android.content.SharedPreferences.OnSharedPreferencesClearListener); } public static interface SharedPreferences.Editor { @@ -10897,10 +10895,6 @@ package android.content { method public void onSharedPreferenceChanged(android.content.SharedPreferences, String); } - public static interface SharedPreferences.OnSharedPreferencesClearListener { - method public void onSharedPreferencesClear(@NonNull android.content.SharedPreferences, @NonNull java.util.Set<java.lang.String>); - } - public class SyncAdapterType implements android.os.Parcelable { ctor public SyncAdapterType(String, String, boolean, boolean); ctor public SyncAdapterType(android.os.Parcel); @@ -28204,7 +28198,7 @@ package android.media.tv { method public android.media.tv.TvTrackInfo.Builder setAudioChannelCount(int); method public android.media.tv.TvTrackInfo.Builder setAudioSampleRate(int); method public android.media.tv.TvTrackInfo.Builder setDescription(CharSequence); - method public android.media.tv.TvTrackInfo.Builder setEncrypted(boolean); + method @NonNull public android.media.tv.TvTrackInfo.Builder setEncrypted(boolean); method public android.media.tv.TvTrackInfo.Builder setExtra(android.os.Bundle); method public android.media.tv.TvTrackInfo.Builder setLanguage(String); method public android.media.tv.TvTrackInfo.Builder setVideoActiveFormatDescription(byte); @@ -44082,7 +44076,7 @@ package android.telephony { public class CarrierConfigManager { method @Nullable public android.os.PersistableBundle getConfig(); - method @Nullable public android.os.PersistableBundle getConfigByComponentForSubId(String, int); + method @Nullable public android.os.PersistableBundle getConfigByComponentForSubId(@NonNull String, int); method @Nullable public android.os.PersistableBundle getConfigForSubId(int); method public static boolean isConfigForIdentifiedCarrier(android.os.PersistableBundle); method public void notifyConfigChangedForSubId(int); @@ -53727,6 +53721,7 @@ package android.view.textclassifier { public final class TextClassificationSessionId implements android.os.Parcelable { method public int describeContents(); + method @NonNull public String flattenToString(); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.view.textclassifier.TextClassificationSessionId> CREATOR; } @@ -53814,6 +53809,7 @@ package android.view.textclassifier { field public static final int TYPE_AUTO_SELECTION = 5; // 0x5 field public static final int TYPE_COPY_ACTION = 9; // 0x9 field public static final int TYPE_CUT_ACTION = 11; // 0xb + field public static final int TYPE_LINKS_GENERATED = 21; // 0x15 field public static final int TYPE_LINK_CLICKED = 7; // 0x7 field public static final int TYPE_MANUAL_REPLY = 19; // 0x13 field public static final int TYPE_OTHER_ACTION = 16; // 0x10 diff --git a/api/removed.txt b/api/removed.txt index db784a8d792c..74a934672adb 100644 --- a/api/removed.txt +++ b/api/removed.txt @@ -5,10 +5,6 @@ package android.app { method @Deprecated public static int getMaxNumPictureInPictureActions(); } - public class KeyguardManager { - method @Deprecated public void dismissKeyguard(@NonNull android.app.Activity, @Nullable android.app.KeyguardManager.KeyguardDismissCallback, @Nullable android.os.Handler); - } - public class Notification implements android.os.Parcelable { method @Deprecated public String getChannel(); method public static Class<? extends android.app.Notification.Style> getNotificationStyleClass(String); diff --git a/api/system-current.txt b/api/system-current.txt index 61ca84ac971d..e87007fe345b 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -1150,7 +1150,8 @@ package android.app.role { method @Nullable public final android.os.IBinder onBind(@Nullable android.content.Intent); method @WorkerThread public abstract boolean onClearRoleHolders(@NonNull String, int); method @WorkerThread public abstract boolean onGrantDefaultRoles(); - method public abstract boolean onIsApplicationQualifiedForRole(@NonNull String, @NonNull String); + method @Deprecated public abstract boolean onIsApplicationQualifiedForRole(@NonNull String, @NonNull String); + method public boolean onIsApplicationVisibleForRole(@NonNull String, @NonNull String); method public abstract boolean onIsRoleVisible(@NonNull String); method @WorkerThread public abstract boolean onRemoveRoleHolder(@NonNull String, @NonNull String, int); field public static final String SERVICE_INTERFACE = "android.app.role.RoleControllerService"; @@ -1206,7 +1207,7 @@ package android.app.usage { public static final class UsageEvents.Event { method public int getInstanceId(); - method public String getNotificationChannelId(); + method @Nullable public String getNotificationChannelId(); method @Nullable public String getTaskRootClassName(); method @Nullable public String getTaskRootPackageName(); method public boolean isInstantApp(); diff --git a/api/test-current.txt b/api/test-current.txt index 7e1c67de2c16..b2ed91b20dfe 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -82,6 +82,7 @@ package android.app { } public class ActivityOptions { + method public static void setExitTransitionTimeout(long); method public void setLaunchActivityType(int); method public void setLaunchTaskId(int); method public void setLaunchWindowingMode(int); diff --git a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java index 76b905d8985f..ed717c491467 100644 --- a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java +++ b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java @@ -125,6 +125,11 @@ public class Bmgr { return; } + if ("autorestore".equals(op)) { + doAutoRestore(userId); + return; + } + if ("enabled".equals(op)) { doEnabled(userId); return; @@ -213,6 +218,26 @@ public class Bmgr { return true; } + private void doAutoRestore(int userId) { + String arg = nextArg(); + if (arg == null) { + showUsage(); + return; + } + + try { + boolean enable = Boolean.parseBoolean(arg); + mBmgr.setAutoRestore(enable); + System.out.println( + "Auto restore is now " + + (enable ? "enabled" : "disabled") + + " for user " + + userId); + } catch (RemoteException e) { + handleRemoteException(e); + } + } + private String activatedToString(boolean activated) { return activated ? "activated" : "deactivated"; } @@ -918,6 +943,7 @@ public class Bmgr { System.err.println(" bmgr init TRANSPORT..."); System.err.println(" bmgr activate BOOL"); System.err.println(" bmgr activated"); + System.err.println(" bmgr autorestore BOOL"); System.err.println(""); System.err.println("The '--user' option specifies the user on which the operation is run."); System.err.println("It must be the first argument before the operation."); @@ -992,6 +1018,9 @@ public class Bmgr { System.err.println(""); System.err.println("The 'activated' command reports the current activated/deactivated"); System.err.println("state of the backup mechanism."); + System.err.println(""); + System.err.println("The 'autorestore' command enables or disables automatic restore when"); + System.err.println("a new package is installed."); } private static class BackupMonitor extends IBackupManagerMonitor.Stub { diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto index b01b0a8e083c..273277953569 100644 --- a/cmds/statsd/src/atoms.proto +++ b/cmds/statsd/src/atoms.proto @@ -337,7 +337,7 @@ message Atom { } // Pulled events will start at field 10000. - // Next: 10062 + // Next: 10064 oneof pulled { WifiBytesTransfer wifi_bytes_transfer = 10000; WifiBytesTransferByFgBg wifi_bytes_transfer_by_fg_bg = 10001; @@ -401,6 +401,8 @@ message Atom { CoolingDevice cooling_device = 10059; AppOps app_ops = 10060; ProcessSystemIonHeapSize process_system_ion_heap_size = 10061; + SurfaceflingerStatsGlobalInfo surfaceflinger_stats_global_info = 10062; + SurfaceflingerStatsLayerInfo surfaceflinger_stats_layer_info = 10063; } // DO NOT USE field numbers above 100,000 in AOSP. @@ -7087,3 +7089,77 @@ message UpdateEngineSuccessfulUpdateReported { // The number of reboot of the device during a successful update. optional int32 reboot_count = 7; } + +/** + * Global display pipeline metrics reported by SurfaceFlinger. + * Pulled from: + * frameworks/native/services/surfaceflinger/TimeStats/TimeStats.cpp + */ +message SurfaceflingerStatsGlobalInfo { + // Total number of frames presented during the tracing period + optional int64 total_frames = 1; + // Total number of frames missed + optional int64 missed_frames = 2; + // Total number of frames that fell back to client composition + optional int64 client_composition_frames = 3; + // Total time the display was turned on + optional int64 display_on_millis = 4; + // Total time that was spent performing animations. + // This is derived from the present-to-present layer histogram + optional int64 animation_millis = 5; +} + +/** + * Per-layer display pipeline metrics reported by SurfaceFlinger. + * The number of layers uploaded will be restricted due to size limitations. + * Pulled from: + * frameworks/native/services/surfaceflinger/TimeStats/TimeStats.cpp + */ +message SurfaceflingerStatsLayerInfo { + // The layer for this set of metrics + // For now we can infer that the package name is included in the layer + // name. + optional string layer_name = 1; + // Total number of frames presented + optional int64 total_frames = 2; + // Total number of dropped frames while latching a buffer for this layer. + optional int64 dropped_frames = 3; + // Set of timings measured between successive presentation timestamps. + optional FrameTimingHistogram present_to_present = 4 + [(android.os.statsd.log_mode) = MODE_BYTES]; + // Set of timings measured from when an app queued a buffer for + // presentation, until the buffer was actually presented to the + // display. + optional FrameTimingHistogram post_to_present = 5 + [(android.os.statsd.log_mode) = MODE_BYTES]; + // Set of timings measured from when a buffer is ready to be presented, + // until the buffer was actually presented to the display. + optional FrameTimingHistogram acquire_to_present = 6 + [(android.os.statsd.log_mode) = MODE_BYTES]; + // Set of timings measured from when a buffer was latched by + // SurfaceFlinger, until the buffer was presented to the display + optional FrameTimingHistogram latch_to_present = 7 + [(android.os.statsd.log_mode) = MODE_BYTES]; + // Set of timings measured from the desired presentation to the actual + // presentation time + optional FrameTimingHistogram desired_to_present = 8 + [(android.os.statsd.log_mode) = MODE_BYTES]; + // Set of timings measured from when an app queued a buffer for + // presentation, until the buffer was ready to be presented. + optional FrameTimingHistogram post_to_acquire = 9 + [(android.os.statsd.log_mode) = MODE_BYTES]; +} + +/** + * Histogram of frame counts bucketed by time in milliseconds. + * Because of size limitations, we hard-cap the number of buckets, with + * buckets for corresponding to larger milliseconds being less precise. + */ +message FrameTimingHistogram { + // Timings in milliseconds that describes a set of histogram buckets + repeated int32 time_millis_buckets = 1; + // Number of frames that match to each time_millis, i.e. the bucket + // contents + // It's required that len(time_millis) == len(frame_count) + repeated int64 frame_counts = 2; +} diff --git a/cmds/statsd/src/main.cpp b/cmds/statsd/src/main.cpp index 68082c2dc4d2..42132ee0daae 100644 --- a/cmds/statsd/src/main.cpp +++ b/cmds/statsd/src/main.cpp @@ -78,7 +78,7 @@ int main(int /*argc*/, char** /*argv*/) { ps->giveThreadPoolName(); IPCThreadState::self()->disableBackgroundScheduling(true); - ::android::hardware::configureRpcThreadpool(1 /*threads*/, false /*willJoin*/); + ::android::hardware::configureRpcThreadpool(4 /*threads*/, false /*willJoin*/); std::shared_ptr<LogEventQueue> eventQueue = std::make_shared<LogEventQueue>(2000 /*buffer limit. Buffer is NOT pre-allocated*/); diff --git a/config/hiddenapi-greylist-max-o.txt b/config/hiddenapi-greylist-max-o.txt index d9c1cd0313fc..15026b0d1fd7 100644 --- a/config/hiddenapi-greylist-max-o.txt +++ b/config/hiddenapi-greylist-max-o.txt @@ -3040,7 +3040,6 @@ Landroid/app/admin/IDevicePolicyManager$Stub$Proxy;->retrievePreRebootSecurityLo Landroid/app/admin/IDevicePolicyManager$Stub$Proxy;->retrieveSecurityLogs(Landroid/content/ComponentName;)Landroid/content/pm/ParceledListSlice; Landroid/app/admin/IDevicePolicyManager$Stub$Proxy;->setAccountManagementDisabled(Landroid/content/ComponentName;Ljava/lang/String;Z)V Landroid/app/admin/IDevicePolicyManager$Stub$Proxy;->setActiveAdmin(Landroid/content/ComponentName;ZI)V -Landroid/app/admin/IDevicePolicyManager$Stub$Proxy;->setActivePasswordState(Landroid/app/admin/PasswordMetrics;I)V Landroid/app/admin/IDevicePolicyManager$Stub$Proxy;->setAffiliationIds(Landroid/content/ComponentName;Ljava/util/List;)V Landroid/app/admin/IDevicePolicyManager$Stub$Proxy;->setAlwaysOnVpnPackage(Landroid/content/ComponentName;Ljava/lang/String;Z)Z Landroid/app/admin/IDevicePolicyManager$Stub$Proxy;->setApplicationHidden(Landroid/content/ComponentName;Ljava/lang/String;Ljava/lang/String;Z)Z @@ -3305,7 +3304,6 @@ Landroid/app/admin/IDevicePolicyManager$Stub;->TRANSACTION_retrievePreRebootSecu Landroid/app/admin/IDevicePolicyManager$Stub;->TRANSACTION_retrieveSecurityLogs:I Landroid/app/admin/IDevicePolicyManager$Stub;->TRANSACTION_setAccountManagementDisabled:I Landroid/app/admin/IDevicePolicyManager$Stub;->TRANSACTION_setActiveAdmin:I -Landroid/app/admin/IDevicePolicyManager$Stub;->TRANSACTION_setActivePasswordState:I Landroid/app/admin/IDevicePolicyManager$Stub;->TRANSACTION_setAffiliationIds:I Landroid/app/admin/IDevicePolicyManager$Stub;->TRANSACTION_setAlwaysOnVpnPackage:I Landroid/app/admin/IDevicePolicyManager$Stub;->TRANSACTION_setApplicationHidden:I @@ -3569,7 +3567,6 @@ Landroid/app/admin/IDevicePolicyManager;->retrievePreRebootSecurityLogs(Landroid Landroid/app/admin/IDevicePolicyManager;->retrieveSecurityLogs(Landroid/content/ComponentName;)Landroid/content/pm/ParceledListSlice; Landroid/app/admin/IDevicePolicyManager;->setAccountManagementDisabled(Landroid/content/ComponentName;Ljava/lang/String;Z)V Landroid/app/admin/IDevicePolicyManager;->setActiveAdmin(Landroid/content/ComponentName;ZI)V -Landroid/app/admin/IDevicePolicyManager;->setActivePasswordState(Landroid/app/admin/PasswordMetrics;I)V Landroid/app/admin/IDevicePolicyManager;->setAffiliationIds(Landroid/content/ComponentName;Ljava/util/List;)V Landroid/app/admin/IDevicePolicyManager;->setAlwaysOnVpnPackage(Landroid/content/ComponentName;Ljava/lang/String;Z)Z Landroid/app/admin/IDevicePolicyManager;->setApplicationHidden(Landroid/content/ComponentName;Ljava/lang/String;Ljava/lang/String;Z)Z diff --git a/core/java/android/accessibilityservice/AccessibilityGestureInfo.java b/core/java/android/accessibilityservice/AccessibilityGestureInfo.java index dc50a4c6c633..28c1dea1dbe7 100644 --- a/core/java/android/accessibilityservice/AccessibilityGestureInfo.java +++ b/core/java/android/accessibilityservice/AccessibilityGestureInfo.java @@ -114,6 +114,7 @@ public final class AccessibilityGestureInfo implements Parcelable { return mGestureId; } + @NonNull @Override public String toString() { StringBuilder stringBuilder = new StringBuilder("AccessibilityGestureInfo["); @@ -133,7 +134,7 @@ public final class AccessibilityGestureInfo implements Parcelable { } @Override - public void writeToParcel(Parcel parcel, int flags) { + public void writeToParcel(@NonNull Parcel parcel, int flags) { parcel.writeInt(mGestureId); parcel.writeInt(mDisplayId); } diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java index 4730bd0880a3..a8daf91eadc0 100644 --- a/core/java/android/accessibilityservice/AccessibilityService.java +++ b/core/java/android/accessibilityservice/AccessibilityService.java @@ -635,7 +635,7 @@ public abstract class AccessibilityService extends Service { * Gets the root node in the currently active window if this service * can retrieve window content. The active window is the one that the user * is currently touching or the window with input focus, if the user is not - * touching any window. + * touching any window. It could be from any logical display. * <p> * The currently active window is defined as the window that most recently fired one * of the following events: diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java index b8d9575f4b0f..67728840ada8 100644 --- a/core/java/android/app/ActivityOptions.java +++ b/core/java/android/app/ActivityOptions.java @@ -829,6 +829,17 @@ public class ActivityOptions { return exit; } + /** + * Needed for virtual devices because they can be slow enough that the 1 second timeout + * triggers when it doesn't on normal devices. + * + * @hide + */ + @TestApi + public static void setExitTransitionTimeout(long timeoutMillis) { + ExitTransitionCoordinator.sMaxWaitMillis = timeoutMillis; + } + /** @hide */ static ActivityOptions makeSceneTransitionAnimation(Activity activity, ExitTransitionCoordinator exitCoordinator, ArrayList<String> sharedElementNames, diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index 34045c995aed..9353e0b5db27 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -30,7 +30,6 @@ import android.annotation.UnsupportedAppUsage; import android.app.usage.UsageStatsManager; import android.content.Context; import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ParceledListSlice; import android.media.AudioAttributes.AttributeUsage; import android.os.Binder; @@ -3220,7 +3219,7 @@ public class AppOpsManager { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (this == obj) { return true; } @@ -3251,6 +3250,7 @@ public class AppOpsManager { return result; } + @NonNull @Override public String toString() { return getClass().getSimpleName() + "[from:" @@ -3486,7 +3486,7 @@ public class AppOpsManager { }; @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (this == obj) { return true; } @@ -3718,7 +3718,7 @@ public class AppOpsManager { }; @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (this == obj) { return true; } @@ -4072,7 +4072,7 @@ public class AppOpsManager { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (this == obj) { return true; } diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index 0478ac89fbbb..d74399c54bda 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -127,6 +127,7 @@ public class ApplicationPackageManager extends PackageManager { * @hide */ public static final boolean DEBUG_TRACE_GRANTS = false; + public static final boolean DEBUG_TRACE_PERMISSION_UPDATES = false; private static final int DEFAULT_EPHEMERAL_COOKIE_MAX_SIZE_BYTES = 16384; // 16KB @@ -690,7 +691,7 @@ public class ApplicationPackageManager extends PackageManager { UserHandle user) { if (DEBUG_TRACE_GRANTS && shouldTraceGrant(packageName, permissionName, user.getIdentifier())) { - Log.i(TAG, "App " + mContext.getPackageName() + " is granting " + Log.i(TAG, "App " + mContext.getPackageName() + " is granting " + packageName + " " + permissionName + " for user " + user.getIdentifier(), new RuntimeException()); } try { @@ -708,9 +709,9 @@ public class ApplicationPackageManager extends PackageManager { @Override public void revokeRuntimePermission(String packageName, String permName, UserHandle user) { - if (DEBUG_TRACE_GRANTS + if (DEBUG_TRACE_PERMISSION_UPDATES && shouldTraceGrant(packageName, permName, user.getIdentifier())) { - Log.i(TAG, "App " + mContext.getPackageName() + " is revoking " + Log.i(TAG, "App " + mContext.getPackageName() + " is revoking " + packageName + " " + permName + " for user " + user.getIdentifier(), new RuntimeException()); } try { @@ -734,9 +735,10 @@ public class ApplicationPackageManager extends PackageManager { @Override public void updatePermissionFlags(String permName, String packageName, int flagMask, int flagValues, UserHandle user) { - if (DEBUG_TRACE_GRANTS + if (DEBUG_TRACE_PERMISSION_UPDATES && shouldTraceGrant(packageName, permName, user.getIdentifier())) { Log.i(TAG, "App " + mContext.getPackageName() + " is updating flags for " + + packageName + " " + permName + " for user " + user.getIdentifier() + ": " + DebugUtils.flagsToString(PackageManager.class, "FLAG_PERMISSION_", flagMask) + " := " + DebugUtils.flagsToString( diff --git a/core/java/android/app/ExitTransitionCoordinator.java b/core/java/android/app/ExitTransitionCoordinator.java index 48a711e79c39..68824cd26eaa 100644 --- a/core/java/android/app/ExitTransitionCoordinator.java +++ b/core/java/android/app/ExitTransitionCoordinator.java @@ -48,7 +48,7 @@ import java.util.ArrayList; */ class ExitTransitionCoordinator extends ActivityTransitionCoordinator { private static final String TAG = "ExitTransitionCoordinator"; - private static final long MAX_WAIT_MS = 1000; + static long sMaxWaitMillis = 1000; private Bundle mSharedElementBundle; private boolean mExitNotified; @@ -120,7 +120,7 @@ class ExitTransitionCoordinator extends ActivityTransitionCoordinator { private void delayCancel() { if (mHandler != null) { - mHandler.sendEmptyMessageDelayed(MSG_CANCEL, MAX_WAIT_MS); + mHandler.sendEmptyMessageDelayed(MSG_CANCEL, sMaxWaitMillis); } } diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java index 667758755c99..9b667a118ebc 100644 --- a/core/java/android/app/KeyguardManager.java +++ b/core/java/android/app/KeyguardManager.java @@ -32,7 +32,6 @@ import android.content.pm.ResolveInfo; import android.hardware.biometrics.BiometricPrompt; import android.os.Binder; import android.os.Build; -import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; @@ -508,13 +507,6 @@ public class KeyguardManager { } } - /** @removed */ - @Deprecated - public void dismissKeyguard(@NonNull Activity activity, - @Nullable KeyguardDismissCallback callback, @Nullable Handler handler) { - requestDismissKeyguard(activity, callback); - } - /** * If the device is currently locked (see {@link #isKeyguardLocked()}, requests the Keyguard to * be dismissed. diff --git a/core/java/android/app/SharedPreferencesImpl.java b/core/java/android/app/SharedPreferencesImpl.java index 9162626e1b37..9f865b41afc6 100644 --- a/core/java/android/app/SharedPreferencesImpl.java +++ b/core/java/android/app/SharedPreferencesImpl.java @@ -16,17 +16,19 @@ package android.app; -import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UnsupportedAppUsage; +import android.compat.Compatibility; +import android.compat.annotation.ChangeId; +import android.compat.annotation.EnabledAfter; import android.content.SharedPreferences; +import android.os.Build; import android.os.FileUtils; import android.os.Looper; import android.system.ErrnoException; import android.system.Os; import android.system.StructStat; import android.system.StructTimespec; -import android.util.ArraySet; import android.util.Log; import com.android.internal.annotations.GuardedBy; @@ -62,6 +64,15 @@ final class SharedPreferencesImpl implements SharedPreferences { /** If a fsync takes more than {@value #MAX_FSYNC_DURATION_MILLIS} ms, warn */ private static final long MAX_FSYNC_DURATION_MILLIS = 256; + /** + * There will now be a callback to {@link + * OnSharedPreferenceChangeListener#onSharedPreferenceChanged(SharedPreferences, String)} with + * a {@code null} key on {@link Editor#clear()}. + */ + @ChangeId + @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.Q) + private static final long CALLBACK_ON_CLEAR_CHANGE = 119147584L; + // Lock ordering rules: // - acquire SharedPreferencesImpl.mLock before EditorImpl.mLock // - acquire mWritingToDiskLock before EditorImpl.mLock @@ -94,10 +105,6 @@ final class SharedPreferencesImpl implements SharedPreferences { private final WeakHashMap<OnSharedPreferenceChangeListener, Object> mListeners = new WeakHashMap<OnSharedPreferenceChangeListener, Object>(); - @GuardedBy("mLock") - private final WeakHashMap<OnSharedPreferencesClearListener, Object> mClearListeners = - new WeakHashMap<>(); - /** Current memory state (always increasing) */ @GuardedBy("this") private long mCurrentMemoryStateGeneration; @@ -258,28 +265,6 @@ final class SharedPreferencesImpl implements SharedPreferences { } } - @Override - public void registerOnSharedPreferencesClearListener( - @NonNull OnSharedPreferencesClearListener listener) { - if (listener == null) { - throw new IllegalArgumentException("listener cannot be null."); - } - synchronized (mLock) { - mClearListeners.put(listener, CONTENT); - } - } - - @Override - public void unregisterOnSharedPreferencesClearListener( - @NonNull OnSharedPreferencesClearListener listener) { - if (listener == null) { - throw new IllegalArgumentException("listener cannot be null."); - } - synchronized (mLock) { - mClearListeners.remove(listener); - } - } - @GuardedBy("mLock") private void awaitLoadedLocked() { if (!mLoaded) { @@ -388,10 +373,9 @@ final class SharedPreferencesImpl implements SharedPreferences { // Return value from EditorImpl#commitToMemory() private static class MemoryCommitResult { final long memoryStateGeneration; + final boolean keysCleared; @Nullable final List<String> keysModified; - @Nullable final Set<String> keysCleared; @Nullable final Set<OnSharedPreferenceChangeListener> listeners; - @Nullable final Set<OnSharedPreferencesClearListener> clearListeners; final Map<String, Object> mapToWriteToDisk; final CountDownLatch writtenToDiskLatch = new CountDownLatch(1); @@ -399,16 +383,14 @@ final class SharedPreferencesImpl implements SharedPreferences { volatile boolean writeToDiskResult = false; boolean wasWritten = false; - private MemoryCommitResult(long memoryStateGeneration, @Nullable List<String> keysModified, + private MemoryCommitResult(long memoryStateGeneration, boolean keysCleared, + @Nullable List<String> keysModified, @Nullable Set<OnSharedPreferenceChangeListener> listeners, - @Nullable Set<String> keysCleared, - @Nullable Set<OnSharedPreferencesClearListener> clearListeners, Map<String, Object> mapToWriteToDisk) { this.memoryStateGeneration = memoryStateGeneration; + this.keysCleared = keysCleared; this.keysModified = keysModified; this.listeners = listeners; - this.keysCleared = keysCleared; - this.clearListeners = clearListeners; this.mapToWriteToDisk = mapToWriteToDisk; } @@ -526,16 +508,14 @@ final class SharedPreferencesImpl implements SharedPreferences { // SharedPreferences instance back, which has the // changes reflected in memory. notifyListeners(mcr); - notifyClearListeners(mcr); } // Returns true if any changes were made private MemoryCommitResult commitToMemory() { long memoryStateGeneration; + boolean keysCleared = false; List<String> keysModified = null; - Set<String> keysCleared = null; Set<OnSharedPreferenceChangeListener> listeners = null; - Set<OnSharedPreferencesClearListener> clearListeners = null; Map<String, Object> mapToWriteToDisk; synchronized (SharedPreferencesImpl.this.mLock) { @@ -557,23 +537,16 @@ final class SharedPreferencesImpl implements SharedPreferences { keysModified = new ArrayList<String>(); listeners = new HashSet<OnSharedPreferenceChangeListener>(mListeners.keySet()); } - boolean hasClearListeners = !mClearListeners.isEmpty(); - if (hasClearListeners) { - keysCleared = new ArraySet<>(); - clearListeners = new HashSet<>(mClearListeners.keySet()); - } synchronized (mEditorLock) { boolean changesMade = false; if (mClear) { if (!mapToWriteToDisk.isEmpty()) { - if (hasClearListeners) { - keysCleared.addAll(mapToWriteToDisk.keySet()); - } changesMade = true; mapToWriteToDisk.clear(); } + keysCleared = true; mClear = false; } @@ -613,8 +586,8 @@ final class SharedPreferencesImpl implements SharedPreferences { memoryStateGeneration = mCurrentMemoryStateGeneration; } } - return new MemoryCommitResult(memoryStateGeneration, keysModified, listeners, - keysCleared, clearListeners, mapToWriteToDisk); + return new MemoryCommitResult(memoryStateGeneration, keysCleared, keysModified, + listeners, mapToWriteToDisk); } @Override @@ -641,16 +614,21 @@ final class SharedPreferencesImpl implements SharedPreferences { } } notifyListeners(mcr); - notifyClearListeners(mcr); return mcr.writeToDiskResult; } private void notifyListeners(final MemoryCommitResult mcr) { - if (mcr.listeners == null || mcr.keysModified == null || - mcr.keysModified.size() == 0) { + if (mcr.listeners == null || (mcr.keysModified == null && !mcr.keysCleared)) { return; } if (Looper.myLooper() == Looper.getMainLooper()) { + if (mcr.keysCleared && Compatibility.isChangeEnabled(CALLBACK_ON_CLEAR_CHANGE)) { + for (OnSharedPreferenceChangeListener listener : mcr.listeners) { + if (listener != null) { + listener.onSharedPreferenceChanged(SharedPreferencesImpl.this, null); + } + } + } for (int i = mcr.keysModified.size() - 1; i >= 0; i--) { final String key = mcr.keysModified.get(i); for (OnSharedPreferenceChangeListener listener : mcr.listeners) { @@ -664,24 +642,6 @@ final class SharedPreferencesImpl implements SharedPreferences { ActivityThread.sMainThreadHandler.post(() -> notifyListeners(mcr)); } } - - private void notifyClearListeners(final MemoryCommitResult mcr) { - if (mcr.clearListeners == null || mcr.keysCleared == null - || mcr.keysCleared.isEmpty()) { - return; - } - if (Looper.myLooper() == Looper.getMainLooper()) { - for (OnSharedPreferencesClearListener listener : mcr.clearListeners) { - if (listener != null) { - listener.onSharedPreferencesClear(SharedPreferencesImpl.this, - mcr.keysCleared); - } - } - } else { - // Run this function on the main thread. - ActivityThread.sMainThreadHandler.post(() -> notifyClearListeners(mcr)); - } - } } /** diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java index 205e7a13092b..28413be29a1d 100644 --- a/core/java/android/app/StatusBarManager.java +++ b/core/java/android/app/StatusBarManager.java @@ -620,6 +620,7 @@ public class StatusBarManager { mNotificationIcons = true; } + @NonNull @Override public String toString() { StringBuilder sb = new StringBuilder(); diff --git a/core/java/android/app/Vr2dDisplayProperties.java b/core/java/android/app/Vr2dDisplayProperties.java index fc200bf05253..d2a49fb82e70 100644 --- a/core/java/android/app/Vr2dDisplayProperties.java +++ b/core/java/android/app/Vr2dDisplayProperties.java @@ -18,6 +18,7 @@ package android.app; import android.annotation.IntDef; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; @@ -74,6 +75,7 @@ public final class Vr2dDisplayProperties implements Parcelable { return result; } + @NonNull @Override public String toString() { return "Vr2dDisplayProperties{" @@ -86,7 +88,7 @@ public final class Vr2dDisplayProperties implements Parcelable { } @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index ff5a043b9336..a136bbda2a3e 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -5764,21 +5764,6 @@ public class DevicePolicyManager { /** * @hide */ - @UnsupportedAppUsage - @RequiresFeature(PackageManager.FEATURE_SECURE_LOCK_SCREEN) - public void setActivePasswordState(PasswordMetrics metrics, int userHandle) { - if (mService != null) { - try { - mService.setActivePasswordState(metrics, userHandle); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - } - - /** - * @hide - */ @RequiresFeature(PackageManager.FEATURE_SECURE_LOCK_SCREEN) public void reportPasswordChanged(@UserIdInt int userId) { if (mService != null) { diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index 5cdef6d39dc6..0da5b7a1cf62 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -131,7 +131,6 @@ interface IDevicePolicyManager { void forceRemoveActiveAdmin(in ComponentName policyReceiver, int userHandle); boolean hasGrantedPolicy(in ComponentName policyReceiver, int usesPolicy, int userHandle); - void setActivePasswordState(in PasswordMetrics metrics, int userHandle); void reportPasswordChanged(int userId); void reportFailedPasswordAttempt(int userHandle); void reportSuccessfulPasswordAttempt(int userHandle); diff --git a/core/java/android/app/backup/RestoreDescription.java b/core/java/android/app/backup/RestoreDescription.java index 7854394bb02e..498b68642d9d 100644 --- a/core/java/android/app/backup/RestoreDescription.java +++ b/core/java/android/app/backup/RestoreDescription.java @@ -16,6 +16,7 @@ package android.app.backup; +import android.annotation.NonNull; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; @@ -52,6 +53,7 @@ public class RestoreDescription implements Parcelable { /** This package's restore data is a tarball-type full data stream */ public static final int TYPE_FULL_STREAM = 2; + @NonNull @Override public String toString() { return "RestoreDescription{" + mPackageName + " : " diff --git a/core/java/android/app/prediction/AppPredictionContext.java b/core/java/android/app/prediction/AppPredictionContext.java index 298b0031d726..d14238bb2672 100644 --- a/core/java/android/app/prediction/AppPredictionContext.java +++ b/core/java/android/app/prediction/AppPredictionContext.java @@ -90,7 +90,7 @@ public final class AppPredictionContext implements Parcelable { } @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (o == this) return true; if (!getClass().equals(o != null ? o.getClass() : null)) return false; diff --git a/core/java/android/app/prediction/AppPredictionSessionId.java b/core/java/android/app/prediction/AppPredictionSessionId.java index 281a16f7715a..e5e06f859ac6 100644 --- a/core/java/android/app/prediction/AppPredictionSessionId.java +++ b/core/java/android/app/prediction/AppPredictionSessionId.java @@ -16,6 +16,7 @@ package android.app.prediction; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.TestApi; import android.os.Parcel; @@ -46,7 +47,7 @@ public final class AppPredictionSessionId implements Parcelable { } @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (!getClass().equals(o != null ? o.getClass() : null)) return false; AppPredictionSessionId other = (AppPredictionSessionId) o; diff --git a/core/java/android/app/prediction/AppTarget.java b/core/java/android/app/prediction/AppTarget.java index 147c5000e333..6f2149007b8d 100644 --- a/core/java/android/app/prediction/AppTarget.java +++ b/core/java/android/app/prediction/AppTarget.java @@ -151,7 +151,7 @@ public final class AppTarget implements Parcelable { } @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (!getClass().equals(o != null ? o.getClass() : null)) return false; AppTarget other = (AppTarget) o; diff --git a/core/java/android/app/prediction/AppTargetEvent.java b/core/java/android/app/prediction/AppTargetEvent.java index 54b95639f68f..26ff0c17da2e 100644 --- a/core/java/android/app/prediction/AppTargetEvent.java +++ b/core/java/android/app/prediction/AppTargetEvent.java @@ -98,7 +98,7 @@ public final class AppTargetEvent implements Parcelable { } @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (!getClass().equals(o != null ? o.getClass() : null)) return false; AppTargetEvent other = (AppTargetEvent) o; diff --git a/core/java/android/app/prediction/AppTargetId.java b/core/java/android/app/prediction/AppTargetId.java index 3603f5f3ab10..052fdc11ef21 100644 --- a/core/java/android/app/prediction/AppTargetId.java +++ b/core/java/android/app/prediction/AppTargetId.java @@ -16,6 +16,7 @@ package android.app.prediction; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.TestApi; import android.os.Parcel; @@ -59,7 +60,7 @@ public final class AppTargetId implements Parcelable { } @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (!getClass().equals(o != null ? o.getClass() : null)) return false; AppTargetId other = (AppTargetId) o; diff --git a/core/java/android/app/role/IRoleController.aidl b/core/java/android/app/role/IRoleController.aidl index 19762e0841b1..8a43d7fa9036 100644 --- a/core/java/android/app/role/IRoleController.aidl +++ b/core/java/android/app/role/IRoleController.aidl @@ -36,5 +36,8 @@ oneway interface IRoleController { void isApplicationQualifiedForRole(in String roleName, in String packageName, in RemoteCallback callback); + void isApplicationVisibleForRole(in String roleName, in String packageName, + in RemoteCallback callback); + void isRoleVisible(in String roleName, in RemoteCallback callback); } diff --git a/core/java/android/app/role/RoleControllerManager.java b/core/java/android/app/role/RoleControllerManager.java index 98b11a7b1a9b..16ddbc147d82 100644 --- a/core/java/android/app/role/RoleControllerManager.java +++ b/core/java/android/app/role/RoleControllerManager.java @@ -183,6 +183,9 @@ public class RoleControllerManager { /** * @see RoleControllerService#onIsApplicationQualifiedForRole(String, String) + * + * @deprecated Use {@link #isApplicationVisibleForRole(String, String, Executor, Consumer)} + * instead. */ @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS) public void isApplicationQualifiedForRole(@NonNull String roleName, @NonNull String packageName, @@ -197,6 +200,21 @@ public class RoleControllerManager { } /** + * @see RoleControllerService#onIsApplicationVisibleForRole(String, String) + */ + @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS) + public void isApplicationVisibleForRole(@NonNull String roleName, @NonNull String packageName, + @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) { + AndroidFuture<Bundle> operation = mRemoteService.postAsync(service -> { + AndroidFuture<Bundle> future = new AndroidFuture<>(); + service.isApplicationVisibleForRole(roleName, packageName, + new RemoteCallback(future::complete)); + return future; + }); + propagateCallback(operation, "isApplicationVisibleForRole", executor, callback); + } + + /** * @see RoleControllerService#onIsRoleVisible(String) */ @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS) diff --git a/core/java/android/app/role/RoleControllerService.java b/core/java/android/app/role/RoleControllerService.java index 2bc94560edd7..85db6a45a1bd 100644 --- a/core/java/android/app/role/RoleControllerService.java +++ b/core/java/android/app/role/RoleControllerService.java @@ -153,6 +153,20 @@ public abstract class RoleControllerService extends Service { } @Override + public void isApplicationVisibleForRole(String roleName, String packageName, + RemoteCallback callback) { + enforceCallingPermission(Manifest.permission.MANAGE_ROLE_HOLDERS, null); + + Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); + Preconditions.checkStringNotEmpty(packageName, + "packageName cannot be null or empty"); + Preconditions.checkNotNull(callback, "callback cannot be null"); + + boolean visible = onIsApplicationVisibleForRole(roleName, packageName); + callback.sendResult(visible ? Bundle.EMPTY : null); + } + + @Override public void isRoleVisible(String roleName, RemoteCallback callback) { enforceCallingPermission(Manifest.permission.MANAGE_ROLE_HOLDERS, null); @@ -256,11 +270,26 @@ public abstract class RoleControllerService extends Service { * @param packageName package name of the application to check for * * @return whether the application is qualified for the role + * + * @deprecated Implement {@link #onIsApplicationVisibleForRole(String, String)} instead. */ public abstract boolean onIsApplicationQualifiedForRole(@NonNull String roleName, @NonNull String packageName); /** + * Check whether an application is visible for a role. + * + * @param roleName name of the role to check for + * @param packageName package name of the application to check for + * + * @return whether the application is visible for the role + */ + public boolean onIsApplicationVisibleForRole(@NonNull String roleName, + @NonNull String packageName) { + return onIsApplicationQualifiedForRole(roleName, packageName); + } + + /** * Check whether a role should be visible to user. * * @param roleName name of the role to check for diff --git a/core/java/android/app/usage/CacheQuotaHint.java b/core/java/android/app/usage/CacheQuotaHint.java index b92d538ce281..b5aed49f211e 100644 --- a/core/java/android/app/usage/CacheQuotaHint.java +++ b/core/java/android/app/usage/CacheQuotaHint.java @@ -81,7 +81,7 @@ public final class CacheQuotaHint implements Parcelable { } @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (o instanceof CacheQuotaHint) { final CacheQuotaHint other = (CacheQuotaHint) o; return Objects.equals(mUuid, other.mUuid) diff --git a/core/java/android/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java index b564c3121d2e..84c68552c40a 100644 --- a/core/java/android/app/usage/UsageEvents.java +++ b/core/java/android/app/usage/UsageEvents.java @@ -554,6 +554,7 @@ public final class UsageEvents implements Parcelable { * event is of type {@link #NOTIFICATION_INTERRUPTION}, otherwise it returns null; * @hide */ + @Nullable @SystemApi public String getNotificationChannelId() { return mNotificationChannelId; diff --git a/core/java/android/bluetooth/BluetoothPan.java b/core/java/android/bluetooth/BluetoothPan.java index fb78789ba8ad..cfb363a0834c 100644 --- a/core/java/android/bluetooth/BluetoothPan.java +++ b/core/java/android/bluetooth/BluetoothPan.java @@ -118,6 +118,8 @@ public final class BluetoothPan implements BluetoothProfile { */ public static final int PAN_OPERATION_SUCCESS = 1004; + private final Context mContext; + private BluetoothAdapter mAdapter; private final BluetoothProfileConnector<IBluetoothPan> mProfileConnector = new BluetoothProfileConnector(this, BluetoothProfile.PAN, @@ -136,6 +138,7 @@ public final class BluetoothPan implements BluetoothProfile { @UnsupportedAppUsage /*package*/ BluetoothPan(Context context, ServiceListener listener) { mAdapter = BluetoothAdapter.getDefaultAdapter(); + mContext = context; mProfileConnector.connect(context, listener); } @@ -287,11 +290,12 @@ public final class BluetoothPan implements BluetoothProfile { @UnsupportedAppUsage public void setBluetoothTethering(boolean value) { - if (DBG) log("setBluetoothTethering(" + value + ")"); + String pkgName = mContext.getOpPackageName(); + if (DBG) log("setBluetoothTethering(" + value + "), calling package:" + pkgName); final IBluetoothPan service = getService(); if (service != null && isEnabled()) { try { - service.setBluetoothTethering(value); + service.setBluetoothTethering(value, pkgName); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); } diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java index f297c0631a30..9dbfbc7795a3 100644 --- a/core/java/android/content/ContentProvider.java +++ b/core/java/android/content/ContentProvider.java @@ -1033,12 +1033,13 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall /** @hide */ public final void setTransportLoggingEnabled(boolean enabled) { - if (mTransport != null) { - if (enabled) { - mTransport.mInterface = new LoggingContentInterface(getClass().getSimpleName(), this); - } else { - mTransport.mInterface = this; - } + if (mTransport == null) { + return; + } + if (enabled) { + mTransport.mInterface = new LoggingContentInterface(getClass().getSimpleName(), this); + } else { + mTransport.mInterface = this; } } diff --git a/core/java/android/content/ContentProviderOperation.java b/core/java/android/content/ContentProviderOperation.java index 621f331b52b2..5c2de57d77a5 100644 --- a/core/java/android/content/ContentProviderOperation.java +++ b/core/java/android/content/ContentProviderOperation.java @@ -684,10 +684,26 @@ public class ContentProviderOperation implements Parcelable { return new ContentProviderOperation(this); } - private void setValue(@NonNull String key, @NonNull Object value) { + private void ensureValues() { if (mValues == null) { mValues = new ArrayMap<>(); } + } + + private void ensureExtras() { + if (mExtras == null) { + mExtras = new ArrayMap<>(); + } + } + + private void ensureSelectionArgs() { + if (mSelectionArgs == null) { + mSelectionArgs = new SparseArray<>(); + } + } + + private void setValue(@NonNull String key, @NonNull Object value) { + ensureValues(); final boolean oldReference = mValues.get(key) instanceof BackReference; final boolean newReference = value instanceof BackReference; if (!oldReference || newReference) { @@ -696,9 +712,7 @@ public class ContentProviderOperation implements Parcelable { } private void setExtra(@NonNull String key, @NonNull Object value) { - if (mExtras == null) { - mExtras = new ArrayMap<>(); - } + ensureExtras(); final boolean oldReference = mExtras.get(key) instanceof BackReference; final boolean newReference = value instanceof BackReference; if (!oldReference || newReference) { @@ -707,9 +721,7 @@ public class ContentProviderOperation implements Parcelable { } private void setSelectionArg(int index, @NonNull Object value) { - if (mSelectionArgs == null) { - mSelectionArgs = new SparseArray<>(); - } + ensureSelectionArgs(); final boolean oldReference = mSelectionArgs.get(index) instanceof BackReference; final boolean newReference = value instanceof BackReference; if (!oldReference || newReference) { @@ -728,6 +740,7 @@ public class ContentProviderOperation implements Parcelable { */ public @NonNull Builder withValues(@NonNull ContentValues values) { assertValuesAllowed(); + ensureValues(); final ArrayMap<String, Object> rawValues = values.getValues(); for (int i = 0; i < rawValues.size(); i++) { setValue(rawValues.keyAt(i), rawValues.valueAt(i)); @@ -815,6 +828,7 @@ public class ContentProviderOperation implements Parcelable { */ public @NonNull Builder withExtras(@NonNull Bundle extras) { assertExtrasAllowed(); + ensureExtras(); for (String key : extras.keySet()) { setExtra(key, extras.get(key)); } @@ -885,6 +899,7 @@ public class ContentProviderOperation implements Parcelable { assertSelectionAllowed(); mSelection = selection; if (selectionArgs != null) { + ensureSelectionArgs(); for (int i = 0; i < selectionArgs.length; i++) { setSelectionArg(i, selectionArgs[i]); } diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 5dcc291cbbb4..b612f1c4672a 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -854,11 +854,16 @@ public abstract class Context { * to any callers for the same name, meaning they will see each other's * edits as soon as they are made. * - * This method is thead-safe. + * <p>This method is thread-safe. * - * @param name Desired preferences file. If a preferences file by this name - * does not exist, it will be created when you retrieve an - * editor (SharedPreferences.edit()) and then commit changes (Editor.commit()). + * <p>If the preferences directory does not already exist, it will be created when this method + * is called. + * + * <p>If a preferences file by this name does not exist, it will be created when you retrieve an + * editor ({@link SharedPreferences#edit()}) and then commit changes ({@link + * SharedPreferences.Editor#commit()} or {@link SharedPreferences.Editor#apply()}). + * + * @param name Desired preferences file. * @param mode Operating mode. * * @return The single {@link SharedPreferences} instance that can be used diff --git a/core/java/android/content/SharedPreferences.java b/core/java/android/content/SharedPreferences.java index 9d87e2550c95..c193868fc3fd 100644 --- a/core/java/android/content/SharedPreferences.java +++ b/core/java/android/content/SharedPreferences.java @@ -16,7 +16,6 @@ package android.content; -import android.annotation.NonNull; import android.annotation.Nullable; import java.util.Map; @@ -58,33 +57,18 @@ public interface SharedPreferences { * * <p>This callback will be run on your main thread. * - * <p><em>Note: This callback will not be triggered when preferences are cleared via - * {@link Editor#clear()}. However, from {@link android.os.Build.VERSION_CODES#R Android R} - * onwards, you can use {@link OnSharedPreferencesClearListener} to register for - * {@link Editor#clear()} callbacks.</em> - * - * @param sharedPreferences The {@link SharedPreferences} that received - * the change. - * @param key The key of the preference that was changed, added, or - * removed. - */ - void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key); - } - - /** - * Interface definition for a callback to be invoked when shared preferences are cleared. - */ - public interface OnSharedPreferencesClearListener { - /** - * Called when shared preferences are cleared via {@link Editor#clear()}. - * - * <p>This callback will be run on your main thread. + * <p><em>Note: This callback will not be triggered when preferences are cleared + * via {@link Editor#clear()}, unless targeting {@link android.os.Build.VERSION_CODES#R} + * on devices running OS versions {@link android.os.Build.VERSION_CODES#R Android R} + * or later.</em> * * @param sharedPreferences The {@link SharedPreferences} that received the change. - * @param keys The set of keys that were cleared. + * @param key The key of the preference that was changed, added, or removed. Apps targeting + * {@link android.os.Build.VERSION_CODES#R} on devices running OS versions + * {@link android.os.Build.VERSION_CODES#R Android R} or later, will receive + * a {@code null} value when preferences are cleared. */ - void onSharedPreferencesClear(@NonNull SharedPreferences sharedPreferences, - @NonNull Set<String> keys); + void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key); } /** @@ -405,35 +389,4 @@ public interface SharedPreferences { * @see #registerOnSharedPreferenceChangeListener */ void unregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener); - - /** - * Registers a callback to be invoked when preferences are cleared via {@link Editor#clear()}. - * - * <p class="caution"><strong>Caution:</strong> The preference manager does - * not currently store a strong reference to the listener. You must store a - * strong reference to the listener, or it will be susceptible to garbage - * collection. We recommend you keep a reference to the listener in the - * instance data of an object that will exist as long as you need the - * listener.</p> - * - * @param listener The callback that will run. - * @see #unregisterOnSharedPreferencesClearListener - */ - default void registerOnSharedPreferencesClearListener( - @NonNull OnSharedPreferencesClearListener listener) { - throw new UnsupportedOperationException( - "registerOnSharedPreferencesClearListener not implemented"); - } - - /** - * Unregisters a previous callback for {@link Editor#clear()}. - * - * @param listener The callback that should be unregistered. - * @see #registerOnSharedPreferencesClearListener - */ - default void unregisterOnSharedPreferencesClearListener( - @NonNull OnSharedPreferencesClearListener listener) { - throw new UnsupportedOperationException( - "unregisterOnSharedPreferencesClearListener not implemented"); - } } diff --git a/core/java/android/content/om/OverlayInfo.java b/core/java/android/content/om/OverlayInfo.java index f39fc6674a11..1a78f793c008 100644 --- a/core/java/android/content/om/OverlayInfo.java +++ b/core/java/android/content/om/OverlayInfo.java @@ -413,7 +413,7 @@ public final class OverlayInfo implements Parcelable { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (this == obj) { return true; } @@ -448,6 +448,7 @@ public final class OverlayInfo implements Parcelable { return true; } + @NonNull @Override public String toString() { return "OverlayInfo { overlay=" + packageName + ", targetPackage=" + targetPackageName diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java index 037a149bfe37..c74daa8eadfc 100644 --- a/core/java/android/content/pm/LauncherApps.java +++ b/core/java/android/content/pm/LauncherApps.java @@ -503,9 +503,38 @@ public class LauncherApps { } /** - * Retrieves a list of launchable activities that match {@link Intent#ACTION_MAIN} and - * {@link Intent#CATEGORY_LAUNCHER}, for a specified user. Result may include - * synthesized activities like app details Activity injected by system. + * Retrieves a list of activities that specify {@link Intent#ACTION_MAIN} and + * {@link Intent#CATEGORY_LAUNCHER}, across all apps, for a specified user. If an app doesn't + * have any activities that specify <code>ACTION_MAIN</code> or <code>CATEGORY_LAUNCHER</code>, + * the system adds a synthesized activity to the list. This synthesized activity represents the + * app's details page within system settings. + * + * <p class="note"><b>Note: </b>It's possible for system apps, such as app stores, to prevent + * the system from adding synthesized activities to the returned list.</p> + * + * <p>As of <a href="/reference/android/os/Build.VERSION_CODES.html#Q">Android Q</a>, at least + * one of the app's activities or synthesized activities appears in the returned list unless the + * app satisfies at least one of the following conditions:</p> + * <ul> + * <li>The app is a system app.</li> + * <li>The app doesn't request any <a href="/guide/topics/permissions/overview">permissions</a>. + * </li> + * <li>The <code><application></code> tag in the app's manifest doesn't contain any child + * elements that represent + * <a href="/guide/components/fundamentals#DeclaringComponents">app components</a>.</li> + * </ul> + * + * <p>Additionally, the system hides synthesized activities for some or all apps in the + * following enterprise-related cases:</p> + * <ul> + * <li>If the device is a + * <a href="https://developers.google.com/android/work/overview#company-owned-devices-for-knowledge-workers">fully + * managed device</a>, no synthesized activities for any app appear in the returned list.</li> + * <li>If the current user has a + * <a href="https://developers.google.com/android/work/overview#employee-owned-devices-byod">work + * profile</a>, no synthesized activities for the user's work apps appear in the returned + * list.</li> + * </ul> * * @param packageName The specific package to query. If null, it checks all installed packages * in the profile. diff --git a/core/java/android/content/pm/SuspendDialogInfo.java b/core/java/android/content/pm/SuspendDialogInfo.java index db8f8c2387d6..73b75df80e5b 100644 --- a/core/java/android/content/pm/SuspendDialogInfo.java +++ b/core/java/android/content/pm/SuspendDialogInfo.java @@ -185,7 +185,7 @@ public final class SuspendDialogInfo implements Parcelable { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (this == obj) { return true; } @@ -200,6 +200,7 @@ public final class SuspendDialogInfo implements Parcelable { && Objects.equals(mDialogMessage, otherDialogInfo.mDialogMessage); } + @NonNull @Override public String toString() { final StringBuilder builder = new StringBuilder("SuspendDialogInfo: {"); diff --git a/core/java/android/content/rollback/RollbackManager.java b/core/java/android/content/rollback/RollbackManager.java index 1609f53d3d3b..73b8a48d9153 100644 --- a/core/java/android/content/rollback/RollbackManager.java +++ b/core/java/android/content/rollback/RollbackManager.java @@ -74,10 +74,7 @@ public final class RollbackManager { } /** - * Returns a list of all currently available rollbacks. This includes ones for very recently - * installed packages (even if onFinished has not yet been called). As a result, packages that - * very recently failed to install may also be included, but those rollbacks will fail with - * 'rollback not available'. + * Returns a list of all currently available rollbacks. * * @throws SecurityException if the caller does not have appropriate permissions. */ diff --git a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java index 3e130c530cad..c28cf8f30bf7 100644 --- a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java +++ b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java @@ -129,7 +129,7 @@ public class CameraDeviceUserShim implements ICameraDeviceUser { public CameraLooper(int cameraId) { mCameraId = cameraId; - mThread = new Thread(this); + mThread = new Thread(this, "LegacyCameraLooper"); mThread.start(); } diff --git a/core/java/android/hardware/display/AmbientBrightnessDayStats.java b/core/java/android/hardware/display/AmbientBrightnessDayStats.java index b25ef8d6a88f..350bc30d8d24 100644 --- a/core/java/android/hardware/display/AmbientBrightnessDayStats.java +++ b/core/java/android/hardware/display/AmbientBrightnessDayStats.java @@ -17,6 +17,7 @@ package android.hardware.display; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.TestApi; import android.os.Parcel; @@ -136,7 +137,7 @@ public final class AmbientBrightnessDayStats implements Parcelable { }; @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (this == obj) { return true; } @@ -161,6 +162,7 @@ public final class AmbientBrightnessDayStats implements Parcelable { return result; } + @NonNull @Override public String toString() { StringBuilder bucketBoundariesString = new StringBuilder(); diff --git a/core/java/android/hardware/display/BrightnessConfiguration.java b/core/java/android/hardware/display/BrightnessConfiguration.java index 5b63dcfa7ad6..4c2e297d2133 100644 --- a/core/java/android/hardware/display/BrightnessConfiguration.java +++ b/core/java/android/hardware/display/BrightnessConfiguration.java @@ -145,6 +145,7 @@ public final class BrightnessConfiguration implements Parcelable { return 0; } + @NonNull @Override public String toString() { StringBuilder sb = new StringBuilder("BrightnessConfiguration{["); @@ -184,7 +185,7 @@ public final class BrightnessConfiguration implements Parcelable { } @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (o == this) { return true; } diff --git a/core/java/android/hardware/display/BrightnessCorrection.java b/core/java/android/hardware/display/BrightnessCorrection.java index b029accab576..22df778a1368 100644 --- a/core/java/android/hardware/display/BrightnessCorrection.java +++ b/core/java/android/hardware/display/BrightnessCorrection.java @@ -18,6 +18,7 @@ package android.hardware.display; import android.annotation.FloatRange; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.TestApi; import android.os.Parcel; @@ -98,13 +99,13 @@ public final class BrightnessCorrection implements Parcelable { * * @return A string representation. */ + @NonNull public String toString() { return mImplementation.toString(); } - @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (o == this) { return true; } diff --git a/core/java/android/hardware/hdmi/HdmiDeviceInfo.java b/core/java/android/hardware/hdmi/HdmiDeviceInfo.java index 136211679c6b..55b07268d201 100644 --- a/core/java/android/hardware/hdmi/HdmiDeviceInfo.java +++ b/core/java/android/hardware/hdmi/HdmiDeviceInfo.java @@ -16,6 +16,8 @@ package android.hardware.hdmi; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; @@ -458,6 +460,7 @@ public class HdmiDeviceInfo implements Parcelable { } } + @NonNull @Override public String toString() { StringBuffer s = new StringBuffer(); @@ -493,7 +496,7 @@ public class HdmiDeviceInfo implements Parcelable { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (!(obj instanceof HdmiDeviceInfo)) { return false; } diff --git a/core/java/android/hardware/hdmi/HdmiPortInfo.java b/core/java/android/hardware/hdmi/HdmiPortInfo.java index f53f45891f1a..2623458aff5b 100644 --- a/core/java/android/hardware/hdmi/HdmiPortInfo.java +++ b/core/java/android/hardware/hdmi/HdmiPortInfo.java @@ -15,6 +15,8 @@ */ package android.hardware.hdmi; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; @@ -162,6 +164,7 @@ public final class HdmiPortInfo implements Parcelable { dest.writeInt(mMhlSupported ? 1 : 0); } + @NonNull @Override public String toString() { StringBuffer s = new StringBuffer(); @@ -175,7 +178,7 @@ public final class HdmiPortInfo implements Parcelable { } @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (!(o instanceof HdmiPortInfo)) { return false; } diff --git a/core/java/android/hardware/location/ContextHubInfo.java b/core/java/android/hardware/location/ContextHubInfo.java index b5da381a4f99..a11f2e9e8373 100644 --- a/core/java/android/hardware/location/ContextHubInfo.java +++ b/core/java/android/hardware/location/ContextHubInfo.java @@ -15,6 +15,7 @@ */ package android.hardware.location; +import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.hardware.contexthub.V1_0.ContextHub; @@ -248,6 +249,7 @@ public class ContextHubInfo implements Parcelable { return mChrePatchVersion; } + @NonNull @Override public String toString() { String retVal = ""; diff --git a/core/java/android/hardware/location/ContextHubIntentEvent.java b/core/java/android/hardware/location/ContextHubIntentEvent.java index d1190ab28ed5..754327a17dc7 100644 --- a/core/java/android/hardware/location/ContextHubIntentEvent.java +++ b/core/java/android/hardware/location/ContextHubIntentEvent.java @@ -192,6 +192,7 @@ public class ContextHubIntentEvent { return mNanoAppMessage; } + @NonNull @Override public String toString() { String out = "ContextHubIntentEvent[eventType = " + mEventType diff --git a/core/java/android/hardware/location/ContextHubMessage.java b/core/java/android/hardware/location/ContextHubMessage.java index 1c98427b9c23..6777c53940a6 100644 --- a/core/java/android/hardware/location/ContextHubMessage.java +++ b/core/java/android/hardware/location/ContextHubMessage.java @@ -16,6 +16,7 @@ package android.hardware.location; +import android.annotation.NonNull; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; @@ -127,7 +128,7 @@ public class ContextHubMessage implements Parcelable { out.writeByteArray(mData); } - public static final @android.annotation.NonNull Parcelable.Creator<ContextHubMessage> CREATOR + public static final @NonNull Parcelable.Creator<ContextHubMessage> CREATOR = new Parcelable.Creator<ContextHubMessage>() { public ContextHubMessage createFromParcel(Parcel in) { return new ContextHubMessage(in); @@ -138,6 +139,7 @@ public class ContextHubMessage implements Parcelable { } }; + @NonNull @Override public String toString() { int length = mData.length; diff --git a/core/java/android/hardware/location/GeofenceHardwareMonitorEvent.java b/core/java/android/hardware/location/GeofenceHardwareMonitorEvent.java index fbbf6870bd5a..78cca9601a2d 100644 --- a/core/java/android/hardware/location/GeofenceHardwareMonitorEvent.java +++ b/core/java/android/hardware/location/GeofenceHardwareMonitorEvent.java @@ -16,6 +16,7 @@ package android.hardware.location; +import android.annotation.NonNull; import android.annotation.SystemApi; import android.location.Location; import android.os.Parcel; @@ -72,7 +73,7 @@ public class GeofenceHardwareMonitorEvent implements Parcelable { return mLocation; } - public static final @android.annotation.NonNull Creator<GeofenceHardwareMonitorEvent> CREATOR = + public static final @NonNull Creator<GeofenceHardwareMonitorEvent> CREATOR = new Creator<GeofenceHardwareMonitorEvent>() { @Override public GeofenceHardwareMonitorEvent createFromParcel(Parcel source) { @@ -108,6 +109,7 @@ public class GeofenceHardwareMonitorEvent implements Parcelable { parcel.writeParcelable(mLocation, flags); } + @NonNull @Override public String toString() { return String.format( diff --git a/core/java/android/hardware/location/MemoryRegion.java b/core/java/android/hardware/location/MemoryRegion.java index ecd369a42841..c033228441b1 100644 --- a/core/java/android/hardware/location/MemoryRegion.java +++ b/core/java/android/hardware/location/MemoryRegion.java @@ -16,6 +16,7 @@ package android.hardware.location; +import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.os.Parcel; @@ -79,6 +80,7 @@ public class MemoryRegion implements Parcelable{ return mIsExecutable; } + @NonNull @Override public String toString() { String mask = ""; diff --git a/core/java/android/hardware/location/NanoApp.java b/core/java/android/hardware/location/NanoApp.java index 3fbb0690698c..6a734f369730 100644 --- a/core/java/android/hardware/location/NanoApp.java +++ b/core/java/android/hardware/location/NanoApp.java @@ -15,6 +15,7 @@ */ package android.hardware.location; +import android.annotation.NonNull; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; @@ -370,6 +371,7 @@ public class NanoApp implements Parcelable { } }; + @NonNull @Override public String toString() { String retVal = "Id : " + mAppId; diff --git a/core/java/android/hardware/location/NanoAppFilter.java b/core/java/android/hardware/location/NanoAppFilter.java index 0700dd1be423..1d8b69d0ede9 100644 --- a/core/java/android/hardware/location/NanoAppFilter.java +++ b/core/java/android/hardware/location/NanoAppFilter.java @@ -16,6 +16,7 @@ package android.hardware.location; +import android.annotation.NonNull; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; @@ -131,6 +132,7 @@ public class NanoAppFilter implements Parcelable { (versionsMatch(mVersionRestrictionMask, mAppVersion, info.getAppVersion())); } + @NonNull @Override public String toString() { return "nanoAppId: 0x" + Long.toHexString(mAppId) diff --git a/core/java/android/hardware/location/NanoAppInstanceInfo.java b/core/java/android/hardware/location/NanoAppInstanceInfo.java index a6c754d971e3..ea1175639e23 100644 --- a/core/java/android/hardware/location/NanoAppInstanceInfo.java +++ b/core/java/android/hardware/location/NanoAppInstanceInfo.java @@ -219,6 +219,7 @@ public class NanoAppInstanceInfo implements Parcelable { } }; + @NonNull @Override public String toString() { String retVal = "handle : " + mHandle; diff --git a/core/java/android/hardware/location/NanoAppMessage.java b/core/java/android/hardware/location/NanoAppMessage.java index 078532a0e644..bb3e81ad0ec1 100644 --- a/core/java/android/hardware/location/NanoAppMessage.java +++ b/core/java/android/hardware/location/NanoAppMessage.java @@ -15,6 +15,7 @@ */ package android.hardware.location; +import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.os.Parcel; @@ -136,7 +137,7 @@ public final class NanoAppMessage implements Parcelable { out.writeByteArray(mMessageBody); } - public static final @android.annotation.NonNull Creator<NanoAppMessage> CREATOR = + public static final @NonNull Creator<NanoAppMessage> CREATOR = new Creator<NanoAppMessage>() { @Override public NanoAppMessage createFromParcel(Parcel in) { @@ -149,6 +150,7 @@ public final class NanoAppMessage implements Parcelable { } }; + @NonNull @Override public String toString() { int length = mMessageBody.length; diff --git a/core/java/android/hardware/radio/ProgramList.java b/core/java/android/hardware/radio/ProgramList.java index f4fd1b6fb75f..ec318b749a5d 100644 --- a/core/java/android/hardware/radio/ProgramList.java +++ b/core/java/android/hardware/radio/ProgramList.java @@ -377,7 +377,7 @@ public final class ProgramList implements AutoCloseable { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (this == obj) return true; if (!(obj instanceof Filter)) return false; Filter other = (Filter) obj; @@ -389,6 +389,7 @@ public final class ProgramList implements AutoCloseable { return true; } + @NonNull @Override public String toString() { return "Filter [mIdentifierTypes=" + mIdentifierTypes diff --git a/core/java/android/hardware/radio/ProgramSelector.java b/core/java/android/hardware/radio/ProgramSelector.java index b32185533524..d525753a1874 100644 --- a/core/java/android/hardware/radio/ProgramSelector.java +++ b/core/java/android/hardware/radio/ProgramSelector.java @@ -485,6 +485,7 @@ public final class ProgramSelector implements Parcelable { return new ProgramSelector(programType, primary, secondary, null); } + @NonNull @Override public String toString() { StringBuilder sb = new StringBuilder("ProgramSelector(type=").append(mProgramType) @@ -502,7 +503,7 @@ public final class ProgramSelector implements Parcelable { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (this == obj) return true; if (!(obj instanceof ProgramSelector)) return false; ProgramSelector other = (ProgramSelector) obj; @@ -611,6 +612,7 @@ public final class ProgramSelector implements Parcelable { return mValue; } + @NonNull @Override public String toString() { return "Identifier(" + mType + ", " + mValue + ")"; @@ -622,7 +624,7 @@ public final class ProgramSelector implements Parcelable { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (this == obj) return true; if (!(obj instanceof Identifier)) return false; Identifier other = (Identifier) obj; diff --git a/core/java/android/hardware/radio/RadioManager.java b/core/java/android/hardware/radio/RadioManager.java index a7ff64412fc3..6ea2ac414704 100644 --- a/core/java/android/hardware/radio/RadioManager.java +++ b/core/java/android/hardware/radio/RadioManager.java @@ -485,6 +485,7 @@ public class RadioManager { return 0; } + @NonNull @Override public String toString() { return "ModuleProperties [mId=" + mId @@ -507,7 +508,7 @@ public class RadioManager { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (this == obj) return true; if (!(obj instanceof ModuleProperties)) return false; ModuleProperties other = (ModuleProperties) obj; @@ -660,6 +661,7 @@ public class RadioManager { return 0; } + @NonNull @Override public String toString() { return "BandDescriptor [mRegion=" + mRegion + ", mType=" + mType + ", mLowerLimit=" @@ -679,7 +681,7 @@ public class RadioManager { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (this == obj) return true; if (!(obj instanceof BandDescriptor)) @@ -788,6 +790,7 @@ public class RadioManager { return 0; } + @NonNull @Override public String toString() { return "FmBandDescriptor [ "+ super.toString() + " mStereo=" + mStereo @@ -808,7 +811,7 @@ public class RadioManager { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (this == obj) return true; if (!super.equals(obj)) @@ -877,6 +880,7 @@ public class RadioManager { return 0; } + @NonNull @Override public String toString() { return "AmBandDescriptor [ "+ super.toString() + " mStereo=" + mStereo + "]"; @@ -891,7 +895,7 @@ public class RadioManager { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (this == obj) return true; if (!super.equals(obj)) @@ -997,6 +1001,7 @@ public class RadioManager { return 0; } + @NonNull @Override public String toString() { return "BandConfig [ " + mDescriptor.toString() + "]"; @@ -1011,7 +1016,7 @@ public class RadioManager { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (this == obj) return true; if (!(obj instanceof BandConfig)) @@ -1125,6 +1130,7 @@ public class RadioManager { return 0; } + @NonNull @Override public String toString() { return "FmBandConfig [" + super.toString() @@ -1145,7 +1151,7 @@ public class RadioManager { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (this == obj) return true; if (!super.equals(obj)) @@ -1317,6 +1323,7 @@ public class RadioManager { return 0; } + @NonNull @Override public String toString() { return "AmBandConfig [" + super.toString() @@ -1332,7 +1339,7 @@ public class RadioManager { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (this == obj) return true; if (!super.equals(obj)) @@ -1656,6 +1663,7 @@ public class RadioManager { return 0; } + @NonNull @Override public String toString() { return "ProgramInfo" @@ -1676,7 +1684,7 @@ public class RadioManager { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (this == obj) return true; if (!(obj instanceof ProgramInfo)) return false; ProgramInfo other = (ProgramInfo) obj; diff --git a/core/java/android/hardware/radio/RadioMetadata.java b/core/java/android/hardware/radio/RadioMetadata.java index 76304bda05a1..a882c2fe877c 100644 --- a/core/java/android/hardware/radio/RadioMetadata.java +++ b/core/java/android/hardware/radio/RadioMetadata.java @@ -16,6 +16,7 @@ package android.hardware.radio; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.graphics.Bitmap; import android.graphics.BitmapFactory; @@ -279,7 +280,7 @@ public final class RadioMetadata implements Parcelable { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (this == obj) return true; if (!(obj instanceof RadioMetadata)) return false; Bundle otherBundle = ((RadioMetadata) obj).mBundle; @@ -308,6 +309,7 @@ public final class RadioMetadata implements Parcelable { mBundle = in.readBundle(); } + @NonNull @Override public String toString() { StringBuilder sb = new StringBuilder("RadioMetadata["); diff --git a/core/java/android/hardware/soundtrigger/SoundTrigger.java b/core/java/android/hardware/soundtrigger/SoundTrigger.java index 5b5bd7661bc5..f96f47dfaffc 100644 --- a/core/java/android/hardware/soundtrigger/SoundTrigger.java +++ b/core/java/android/hardware/soundtrigger/SoundTrigger.java @@ -22,6 +22,7 @@ import static android.system.OsConstants.ENOSYS; import static android.system.OsConstants.EPERM; import static android.system.OsConstants.EPIPE; +import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.UnsupportedAppUsage; @@ -829,7 +830,7 @@ public class SoundTrigger { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (this == obj) return true; if (obj == null) @@ -869,6 +870,7 @@ public class SoundTrigger { return true; } + @NonNull @Override public String toString() { return "RecognitionEvent [status=" + status + ", soundModelHandle=" + soundModelHandle diff --git a/core/java/android/hardware/usb/UsbPort.java b/core/java/android/hardware/usb/UsbPort.java index c674480c2a75..506230ecec86 100644 --- a/core/java/android/hardware/usb/UsbPort.java +++ b/core/java/android/hardware/usb/UsbPort.java @@ -327,7 +327,7 @@ public final class UsbPort { return false; } - + @NonNull @Override public String toString() { return "UsbPort{id=" + mId + ", supportedModes=" + modeToString(mSupportedModes) diff --git a/core/java/android/hardware/usb/UsbPortStatus.java b/core/java/android/hardware/usb/UsbPortStatus.java index 5e9a410a6b84..43c418e2cb26 100644 --- a/core/java/android/hardware/usb/UsbPortStatus.java +++ b/core/java/android/hardware/usb/UsbPortStatus.java @@ -17,6 +17,7 @@ package android.hardware.usb; import android.annotation.IntDef; +import android.annotation.NonNull; import android.annotation.SystemApi; import android.hardware.usb.V1_0.Constants; import android.os.Parcel; @@ -322,6 +323,7 @@ public final class UsbPortStatus implements Parcelable { return mContaminantProtectionStatus; } + @NonNull @Override public String toString() { return "UsbPortStatus{connected=" + isConnected() @@ -352,7 +354,7 @@ public final class UsbPortStatus implements Parcelable { dest.writeInt(mContaminantDetectionStatus); } - public static final @android.annotation.NonNull Parcelable.Creator<UsbPortStatus> CREATOR = + public static final @NonNull Parcelable.Creator<UsbPortStatus> CREATOR = new Parcelable.Creator<UsbPortStatus>() { @Override public UsbPortStatus createFromParcel(Parcel in) { diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index 82d4d1d10d7e..83391f368ac1 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -19,6 +19,7 @@ package android.inputmethodservice; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; +import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE; import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; import static java.lang.annotation.RetentionPolicy.SOURCE; @@ -62,6 +63,7 @@ import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; +import android.view.ViewRootImpl; import android.view.ViewTreeObserver; import android.view.Window; import android.view.WindowManager; @@ -595,12 +597,12 @@ public class InputMethodService extends AbstractInputMethodService { if (DEBUG) Log.v(TAG, "hideSoftInput()"); final boolean wasVisible = mIsPreRendered ? mDecorViewVisible && mWindowVisible : isInputViewShown(); + applyVisibilityInInsetsConsumerIfNecessary(false /* setVisible */); if (mIsPreRendered) { if (DEBUG) { Log.v(TAG, "Making IME window invisible"); } setImeWindowStatus(IME_ACTIVE | IME_INVISIBLE, mBackDisposition); - applyVisibilityInInsetsConsumer(false /* setVisible */); onPreRenderedWindowVisibilityChanged(false /* setVisible */); } else { mShowInputFlags = 0; @@ -632,11 +634,11 @@ public class InputMethodService extends AbstractInputMethodService { if (DEBUG) { Log.v(TAG, "Making IME window visible"); } - applyVisibilityInInsetsConsumer(true /* setVisible */); onPreRenderedWindowVisibilityChanged(true /* setVisible */); } else { showWindow(true); } + applyVisibilityInInsetsConsumerIfNecessary(true /* setVisible */); } // If user uses hard keyboard, IME button should always be shown. setImeWindowStatus(mapToImeWindowStatus(), mBackDisposition); @@ -1974,16 +1976,20 @@ public class InputMethodService extends AbstractInputMethodService { /** * Apply the IME visibility in {@link android.view.ImeInsetsSourceConsumer} when - * pre-rendering is enabled. + * {@link ViewRootImpl.sNewInsetsMode} is enabled. * @param setVisible {@code true} to make it visible, false to hide it. */ - private void applyVisibilityInInsetsConsumer(boolean setVisible) { - if (!mIsPreRendered) { + private void applyVisibilityInInsetsConsumerIfNecessary(boolean setVisible) { + if (!isVisibilityAppliedUsingInsetsConsumer()) { return; } mPrivOps.applyImeVisibility(setVisible); } + private boolean isVisibilityAppliedUsingInsetsConsumer() { + return ViewRootImpl.sNewInsetsMode > NEW_INSETS_MODE_NONE; + } + private void finishViews(boolean finishingInput) { if (mInputViewStarted) { if (DEBUG) Log.v(TAG, "CALL: onFinishInputView"); @@ -2007,7 +2013,11 @@ public class InputMethodService extends AbstractInputMethodService { mWindowVisible = false; finishViews(false /* finishingInput */); if (mDecorViewVisible) { - mWindow.hide(); + // When insets API is enabled, it is responsible for client and server side + // visibility of IME window. + if (!isVisibilityAppliedUsingInsetsConsumer()) { + mWindow.hide(); + } mDecorViewVisible = false; onWindowHidden(); mDecorViewWasVisible = false; diff --git a/core/java/android/net/INetworkPolicyListener.aidl b/core/java/android/net/INetworkPolicyListener.aidl index 10667aecd128..106b7be5c8d3 100644 --- a/core/java/android/net/INetworkPolicyListener.aidl +++ b/core/java/android/net/INetworkPolicyListener.aidl @@ -22,5 +22,5 @@ oneway interface INetworkPolicyListener { void onMeteredIfacesChanged(in String[] meteredIfaces); void onRestrictBackgroundChanged(boolean restrictBackground); void onUidPoliciesChanged(int uid, int uidPolicies); - void onSubscriptionOverride(int subId, int overrideMask, int overrideValue); + void onSubscriptionOverride(int subId, int overrideMask, int overrideValue, long networkTypeMask); } diff --git a/core/java/android/net/INetworkPolicyManager.aidl b/core/java/android/net/INetworkPolicyManager.aidl index 385cb1d68b57..90327663e34b 100644 --- a/core/java/android/net/INetworkPolicyManager.aidl +++ b/core/java/android/net/INetworkPolicyManager.aidl @@ -76,7 +76,7 @@ interface INetworkPolicyManager { SubscriptionPlan[] getSubscriptionPlans(int subId, String callingPackage); void setSubscriptionPlans(int subId, in SubscriptionPlan[] plans, String callingPackage); String getSubscriptionPlansOwner(int subId); - void setSubscriptionOverride(int subId, int overrideMask, int overrideValue, long timeoutMillis, String callingPackage); + void setSubscriptionOverride(int subId, int overrideMask, int overrideValue, long networkTypeMask, long timeoutMillis, String callingPackage); void factoryReset(String subscriber); diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index 83813da80c44..45d0c7313fca 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -861,6 +861,7 @@ public final class IpSecManager { return mResourceId; } + @NonNull @Override public String toString() { return new StringBuilder() diff --git a/core/java/android/net/NetworkKey.java b/core/java/android/net/NetworkKey.java index 0a9a3c8f5084..a101da7b4b9c 100644 --- a/core/java/android/net/NetworkKey.java +++ b/core/java/android/net/NetworkKey.java @@ -16,6 +16,7 @@ package android.net; +import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.net.wifi.ScanResult; @@ -152,7 +153,7 @@ public class NetworkKey implements Parcelable { } @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; @@ -166,6 +167,7 @@ public class NetworkKey implements Parcelable { return Objects.hash(type, wifiKey); } + @NonNull @Override public String toString() { switch (type) { diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java index bf272625e713..628dcd2691cf 100644 --- a/core/java/android/net/NetworkPolicyManager.java +++ b/core/java/android/net/NetworkPolicyManager.java @@ -380,6 +380,7 @@ public class NetworkPolicyManager { @Override public void onMeteredIfacesChanged(String[] meteredIfaces) { } @Override public void onRestrictBackgroundChanged(boolean restrictBackground) { } @Override public void onUidPoliciesChanged(int uid, int uidPolicies) { } - @Override public void onSubscriptionOverride(int subId, int overrideMask, int overrideValue) { } + @Override public void onSubscriptionOverride(int subId, int overrideMask, int overrideValue, + long networkTypeMask) { } } } diff --git a/core/java/android/net/RssiCurve.java b/core/java/android/net/RssiCurve.java index a173b0c2b97b..668e96618f34 100644 --- a/core/java/android/net/RssiCurve.java +++ b/core/java/android/net/RssiCurve.java @@ -16,6 +16,8 @@ package android.net; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; @@ -170,7 +172,7 @@ public class RssiCurve implements Parcelable { * not considered equal to each other. */ @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; @@ -187,6 +189,7 @@ public class RssiCurve implements Parcelable { return Objects.hash(start, bucketWidth, activeNetworkRssiBoost) ^ Arrays.hashCode(rssiBuckets); } + @NonNull @Override public String toString() { StringBuilder sb = new StringBuilder(); diff --git a/core/java/android/net/ScoredNetwork.java b/core/java/android/net/ScoredNetwork.java index effc1aa54735..64b3bf1e0aa0 100644 --- a/core/java/android/net/ScoredNetwork.java +++ b/core/java/android/net/ScoredNetwork.java @@ -16,6 +16,7 @@ package android.net; +import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.os.Bundle; @@ -182,7 +183,7 @@ public class ScoredNetwork implements Parcelable { } @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; @@ -220,6 +221,7 @@ public class ScoredNetwork implements Parcelable { return Objects.hash(networkKey, rssiCurve, meteredHint, attributes); } + @NonNull @Override public String toString() { StringBuilder out = new StringBuilder( diff --git a/core/java/android/net/StaticIpConfiguration.java b/core/java/android/net/StaticIpConfiguration.java index d6deba5d41cc..5bc9953e0d05 100644 --- a/core/java/android/net/StaticIpConfiguration.java +++ b/core/java/android/net/StaticIpConfiguration.java @@ -236,6 +236,7 @@ public final class StaticIpConfiguration implements Parcelable { return lp; } + @NonNull @Override public String toString() { StringBuffer str = new StringBuffer(); @@ -267,7 +268,7 @@ public final class StaticIpConfiguration implements Parcelable { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (this == obj) return true; if (!(obj instanceof StaticIpConfiguration)) return false; diff --git a/core/java/android/net/WebAddress.java b/core/java/android/net/WebAddress.java index fbc281f26ce8..994c794e6997 100644 --- a/core/java/android/net/WebAddress.java +++ b/core/java/android/net/WebAddress.java @@ -18,6 +18,7 @@ package android.net; import static android.util.Patterns.GOOD_IRI_CHAR; +import android.annotation.NonNull; import android.annotation.SystemApi; import android.annotation.UnsupportedAppUsage; import android.os.Build; @@ -132,6 +133,7 @@ public class WebAddress { if (mScheme.equals("")) mScheme = "http"; } + @NonNull @Override public String toString() { String port = ""; diff --git a/core/java/android/net/WifiKey.java b/core/java/android/net/WifiKey.java index e3a93a8d0b8f..bc9d8c54090a 100644 --- a/core/java/android/net/WifiKey.java +++ b/core/java/android/net/WifiKey.java @@ -16,6 +16,8 @@ package android.net; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; @@ -91,7 +93,7 @@ public class WifiKey implements Parcelable { } @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; @@ -105,6 +107,7 @@ public class WifiKey implements Parcelable { return Objects.hash(ssid, bssid); } + @NonNull @Override public String toString() { return "WifiKey[SSID=" + ssid + ",BSSID=" + bssid + "]"; diff --git a/core/java/android/net/apf/ApfCapabilities.java b/core/java/android/net/apf/ApfCapabilities.java index 4dd2ace59c62..b1de74e817bc 100644 --- a/core/java/android/net/apf/ApfCapabilities.java +++ b/core/java/android/net/apf/ApfCapabilities.java @@ -17,6 +17,7 @@ package android.net.apf; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.TestApi; import android.content.res.Resources; @@ -91,6 +92,7 @@ public final class ApfCapabilities implements Parcelable { } }; + @NonNull @Override public String toString() { return String.format("%s{version: %d, maxSize: %d, format: %d}", getClass().getSimpleName(), @@ -98,7 +100,7 @@ public final class ApfCapabilities implements Parcelable { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (!(obj instanceof ApfCapabilities)) return false; final ApfCapabilities other = (ApfCapabilities) obj; return apfVersionSupported == other.apfVersionSupported diff --git a/core/java/android/net/metrics/ApfProgramEvent.java b/core/java/android/net/metrics/ApfProgramEvent.java index e9c209c9cb3b..8243be9c1355 100644 --- a/core/java/android/net/metrics/ApfProgramEvent.java +++ b/core/java/android/net/metrics/ApfProgramEvent.java @@ -18,6 +18,7 @@ package android.net.metrics; import android.annotation.IntDef; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.TestApi; import android.annotation.UnsupportedAppUsage; @@ -185,6 +186,7 @@ public final class ApfProgramEvent implements IpConnectivityLog.Event { return 0; } + @NonNull @Override public String toString() { String lifetimeString = (lifetime < Long.MAX_VALUE) ? lifetime + "s" : "forever"; @@ -193,7 +195,7 @@ public final class ApfProgramEvent implements IpConnectivityLog.Event { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (obj == null || !(obj.getClass().equals(ApfProgramEvent.class))) return false; final ApfProgramEvent other = (ApfProgramEvent) obj; return lifetime == other.lifetime diff --git a/core/java/android/net/metrics/ApfStats.java b/core/java/android/net/metrics/ApfStats.java index b9637774e926..eac5579f9eaa 100644 --- a/core/java/android/net/metrics/ApfStats.java +++ b/core/java/android/net/metrics/ApfStats.java @@ -17,6 +17,7 @@ package android.net.metrics; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.TestApi; import android.annotation.UnsupportedAppUsage; @@ -260,6 +261,7 @@ public final class ApfStats implements IpConnectivityLog.Event { return 0; } + @NonNull @Override public String toString() { return new StringBuilder("ApfStats(") @@ -276,7 +278,7 @@ public final class ApfStats implements IpConnectivityLog.Event { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (obj == null || !(obj.getClass().equals(ApfStats.class))) return false; final ApfStats other = (ApfStats) obj; return durationMs == other.durationMs diff --git a/core/java/android/net/metrics/DhcpClientEvent.java b/core/java/android/net/metrics/DhcpClientEvent.java index 2fed7363b713..5f9f50708a49 100644 --- a/core/java/android/net/metrics/DhcpClientEvent.java +++ b/core/java/android/net/metrics/DhcpClientEvent.java @@ -17,6 +17,7 @@ package android.net.metrics; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.TestApi; import android.annotation.UnsupportedAppUsage; @@ -97,13 +98,14 @@ public final class DhcpClientEvent implements IpConnectivityLog.Event { return 0; } + @NonNull @Override public String toString() { return String.format("DhcpClientEvent(%s, %dms)", msg, durationMs); } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (obj == null || !(obj.getClass().equals(DhcpClientEvent.class))) return false; final DhcpClientEvent other = (DhcpClientEvent) obj; return TextUtils.equals(msg, other.msg) diff --git a/core/java/android/net/metrics/DhcpErrorEvent.java b/core/java/android/net/metrics/DhcpErrorEvent.java index 876000463cb1..32efb5adafcd 100644 --- a/core/java/android/net/metrics/DhcpErrorEvent.java +++ b/core/java/android/net/metrics/DhcpErrorEvent.java @@ -16,6 +16,7 @@ package android.net.metrics; +import android.annotation.NonNull; import android.annotation.SystemApi; import android.annotation.TestApi; import android.os.Parcel; @@ -108,6 +109,7 @@ public final class DhcpErrorEvent implements IpConnectivityLog.Event { return (0xFFFF0000 & errorCode) | (0xFF & option); } + @NonNull @Override public String toString() { return String.format("DhcpErrorEvent(%s)", Decoder.constants.get(errorCode)); diff --git a/core/java/android/net/metrics/IpManagerEvent.java b/core/java/android/net/metrics/IpManagerEvent.java index ba05c5900acf..f14abb895cb4 100644 --- a/core/java/android/net/metrics/IpManagerEvent.java +++ b/core/java/android/net/metrics/IpManagerEvent.java @@ -17,6 +17,8 @@ package android.net.metrics; import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.TestApi; import android.os.Parcel; @@ -95,6 +97,7 @@ public final class IpManagerEvent implements IpConnectivityLog.Event { } }; + @NonNull @Override public String toString() { return String.format("IpManagerEvent(%s, %dms)", @@ -102,7 +105,7 @@ public final class IpManagerEvent implements IpConnectivityLog.Event { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (obj == null || !(obj.getClass().equals(IpManagerEvent.class))) return false; final IpManagerEvent other = (IpManagerEvent) obj; return eventType == other.eventType diff --git a/core/java/android/net/metrics/IpReachabilityEvent.java b/core/java/android/net/metrics/IpReachabilityEvent.java index d4ba2943d72b..79e01d7116b6 100644 --- a/core/java/android/net/metrics/IpReachabilityEvent.java +++ b/core/java/android/net/metrics/IpReachabilityEvent.java @@ -16,6 +16,8 @@ package android.net.metrics; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.TestApi; import android.os.Parcel; @@ -85,6 +87,7 @@ public final class IpReachabilityEvent implements IpConnectivityLog.Event { } }; + @NonNull @Override public String toString() { int hi = eventType & 0xff00; @@ -94,7 +97,7 @@ public final class IpReachabilityEvent implements IpConnectivityLog.Event { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (obj == null || !(obj.getClass().equals(IpReachabilityEvent.class))) return false; final IpReachabilityEvent other = (IpReachabilityEvent) obj; return eventType == other.eventType; diff --git a/core/java/android/net/metrics/NetworkEvent.java b/core/java/android/net/metrics/NetworkEvent.java index 0c57ec644226..fe603cf9305c 100644 --- a/core/java/android/net/metrics/NetworkEvent.java +++ b/core/java/android/net/metrics/NetworkEvent.java @@ -17,6 +17,8 @@ package android.net.metrics; import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.TestApi; import android.os.Parcel; @@ -115,6 +117,7 @@ public final class NetworkEvent implements IpConnectivityLog.Event { } }; + @NonNull @Override public String toString() { return String.format("NetworkEvent(%s, %dms)", @@ -122,7 +125,7 @@ public final class NetworkEvent implements IpConnectivityLog.Event { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (obj == null || !(obj.getClass().equals(NetworkEvent.class))) return false; final NetworkEvent other = (NetworkEvent) obj; return eventType == other.eventType diff --git a/core/java/android/net/metrics/RaEvent.java b/core/java/android/net/metrics/RaEvent.java index 3fd87c23b87d..661f648fc74e 100644 --- a/core/java/android/net/metrics/RaEvent.java +++ b/core/java/android/net/metrics/RaEvent.java @@ -17,6 +17,7 @@ package android.net.metrics; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.TestApi; import android.os.Parcel; @@ -85,6 +86,7 @@ public final class RaEvent implements IpConnectivityLog.Event { return 0; } + @NonNull @Override public String toString() { return new StringBuilder("RaEvent(lifetimes: ") @@ -98,7 +100,7 @@ public final class RaEvent implements IpConnectivityLog.Event { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (obj == null || !(obj.getClass().equals(RaEvent.class))) return false; final RaEvent other = (RaEvent) obj; return routerLifetime == other.routerLifetime diff --git a/core/java/android/net/metrics/ValidationProbeEvent.java b/core/java/android/net/metrics/ValidationProbeEvent.java index 1aaa50d139e0..8fab64ae6c4e 100644 --- a/core/java/android/net/metrics/ValidationProbeEvent.java +++ b/core/java/android/net/metrics/ValidationProbeEvent.java @@ -18,6 +18,7 @@ package android.net.metrics; import android.annotation.IntDef; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.TestApi; import android.os.Parcel; @@ -164,6 +165,7 @@ public final class ValidationProbeEvent implements IpConnectivityLog.Event { return Decoder.constants.get(probeType & 0xff00, "UNKNOWN"); } + @NonNull @Override public String toString() { return String.format("ValidationProbeEvent(%s:%d %s, %dms)", @@ -171,7 +173,7 @@ public final class ValidationProbeEvent implements IpConnectivityLog.Event { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (obj == null || !(obj.getClass().equals(ValidationProbeEvent.class))) return false; final ValidationProbeEvent other = (ValidationProbeEvent) obj; return durationMs == other.durationMs diff --git a/core/java/android/net/util/MultinetworkPolicyTracker.java b/core/java/android/net/util/MultinetworkPolicyTracker.java index f7e494d830ac..4e88149b8095 100644 --- a/core/java/android/net/util/MultinetworkPolicyTracker.java +++ b/core/java/android/net/util/MultinetworkPolicyTracker.java @@ -64,7 +64,7 @@ public class MultinetworkPolicyTracker { private final Context mContext; private final Handler mHandler; - private final Runnable mReevaluateRunnable; + private final Runnable mAvoidBadWifiCallback; private final List<Uri> mSettingsUris; private final ContentResolver mResolver; private final SettingObserver mSettingObserver; @@ -81,12 +81,7 @@ public class MultinetworkPolicyTracker { public MultinetworkPolicyTracker(Context ctx, Handler handler, Runnable avoidBadWifiCallback) { mContext = ctx; mHandler = handler; - mReevaluateRunnable = () -> { - if (updateAvoidBadWifi() && avoidBadWifiCallback != null) { - avoidBadWifiCallback.run(); - } - updateMeteredMultipathPreference(); - }; + mAvoidBadWifiCallback = avoidBadWifiCallback; mSettingsUris = Arrays.asList( Settings.Global.getUriFor(NETWORK_AVOID_BAD_WIFI), Settings.Global.getUriFor(NETWORK_METERED_MULTIPATH_PREFERENCE)); @@ -95,15 +90,15 @@ public class MultinetworkPolicyTracker { mBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - reevaluate(); + reevaluateInternal(); } }; - TelephonyManager.from(ctx).listen(new PhoneStateListener() { + TelephonyManager.from(ctx).listen(new PhoneStateListener(handler.getLooper()) { @Override public void onActiveDataSubscriptionIdChanged(int subId) { mActiveSubId = subId; - reevaluate(); + reevaluateInternal(); } }, PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE); @@ -119,7 +114,7 @@ public class MultinetworkPolicyTracker { final IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); mContext.registerReceiverAsUser( - mBroadcastReceiver, UserHandle.ALL, intentFilter, null, null); + mBroadcastReceiver, UserHandle.ALL, intentFilter, null, mHandler); reevaluate(); } @@ -164,7 +159,17 @@ public class MultinetworkPolicyTracker { @VisibleForTesting public void reevaluate() { - mHandler.post(mReevaluateRunnable); + mHandler.post(this::reevaluateInternal); + } + + /** + * Reevaluate the settings. Must be called on the handler thread. + */ + private void reevaluateInternal() { + if (updateAvoidBadWifi() && mAvoidBadWifiCallback != null) { + mAvoidBadWifiCallback.run(); + } + updateMeteredMultipathPreference(); } public boolean updateAvoidBadWifi() { diff --git a/core/java/android/nfc/cardemulation/ApduServiceInfo.java b/core/java/android/nfc/cardemulation/ApduServiceInfo.java index 4675600fe1d6..d9000e43be0b 100644 --- a/core/java/android/nfc/cardemulation/ApduServiceInfo.java +++ b/core/java/android/nfc/cardemulation/ApduServiceInfo.java @@ -114,7 +114,7 @@ public final class ApduServiceInfo implements Parcelable { * @hide */ @UnsupportedAppUsage - public ApduServiceInfo(ResolveInfo info, String description, + public ApduServiceInfo(ResolveInfo info, boolean onHost, String description, ArrayList<AidGroup> staticAidGroups, ArrayList<AidGroup> dynamicAidGroups, boolean requiresUnlock, int bannerResource, int uid, String settingsActivityName, String offHost, String staticOffHost) { @@ -124,7 +124,7 @@ public final class ApduServiceInfo implements Parcelable { this.mDynamicAidGroups = new HashMap<String, AidGroup>(); this.mOffHostName = offHost; this.mStaticOffHostName = staticOffHost; - this.mOnHost = (offHost == null); + this.mOnHost = onHost; this.mRequiresDeviceUnlock = requiresUnlock; for (AidGroup aidGroup : staticAidGroups) { this.mStaticAidGroups.put(aidGroup.category, aidGroup); @@ -570,7 +570,7 @@ public final class ApduServiceInfo implements Parcelable { int bannerResource = source.readInt(); int uid = source.readInt(); String settingsActivityName = source.readString(); - return new ApduServiceInfo(info, description, staticAidGroups, + return new ApduServiceInfo(info, onHost, description, staticAidGroups, dynamicAidGroups, requiresUnlock, bannerResource, uid, settingsActivityName, offHostName, staticOffHostName); } diff --git a/core/java/android/os/BatterySaverPolicyConfig.java b/core/java/android/os/BatterySaverPolicyConfig.java index 3801cbd48cdd..3f6ce4fa807c 100644 --- a/core/java/android/os/BatterySaverPolicyConfig.java +++ b/core/java/android/os/BatterySaverPolicyConfig.java @@ -161,6 +161,7 @@ public final class BatterySaverPolicyConfig implements Parcelable { dest.writeInt(mLocationMode); } + @NonNull @Override public String toString() { StringBuilder sb = new StringBuilder(); diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java index 6178b2bf5817..553372174a4d 100644 --- a/core/java/android/os/Binder.java +++ b/core/java/android/os/Binder.java @@ -645,6 +645,17 @@ public class Binder implements IBinder { * Called before onTransact. * * @return an object that will be passed back to #onTransactEnded (or null). + * @hide + */ + @Nullable + default Object onTransactStarted(@NonNull IBinder binder, int transactionCode, int flags) { + return onTransactStarted(binder, transactionCode); + } + + /** + * Called before onTransact. + * + * @return an object that will be passed back to #onTransactEnded (or null). */ @Nullable Object onTransactStarted(@NonNull IBinder binder, int transactionCode); diff --git a/core/java/android/os/BinderProxy.java b/core/java/android/os/BinderProxy.java index 97c0a13e7a2b..c74cef85f3ea 100644 --- a/core/java/android/os/BinderProxy.java +++ b/core/java/android/os/BinderProxy.java @@ -496,7 +496,7 @@ public final class BinderProxy implements IBinder { if (transactListener != null) { final int origWorkSourceUid = Binder.getCallingWorkSourceUid(); - session = transactListener.onTransactStarted(this, code); + session = transactListener.onTransactStarted(this, code, flags); // Allow the listener to update the work source uid. We need to update the request // header if the uid is updated. diff --git a/core/java/android/os/IMaintenanceActivityListener.aidl b/core/java/android/os/IMaintenanceActivityListener.aidl deleted file mode 100644 index 6a2581faaa58..000000000000 --- a/core/java/android/os/IMaintenanceActivityListener.aidl +++ /dev/null @@ -1,22 +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. - */ - -package android.os; - -/** @hide */ -oneway interface IMaintenanceActivityListener { - void onMaintenanceActivityChanged(boolean active); -} diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl index 135138030e43..9b8a40a6cab0 100644 --- a/core/java/android/os/INetworkManagementService.aidl +++ b/core/java/android/os/INetworkManagementService.aidl @@ -150,6 +150,14 @@ interface INetworkManagementService void startTethering(in String[] dhcpRanges); /** + * Start tethering services with the specified dhcp server range and + * DNS proxy config. + * {@code boolean} is used to control legacy DNS proxy server. + * {@code String[]} is a set of start end pairs defining the ranges. + */ + void startTetheringWithConfiguration(boolean usingLegacyDnsProxy, in String[] dhcpRanges); + + /** * Stop currently running tethering services */ @UnsupportedAppUsage diff --git a/core/java/android/os/IncidentManager.java b/core/java/android/os/IncidentManager.java index a94fd65943a9..09e1c0f6ab1f 100644 --- a/core/java/android/os/IncidentManager.java +++ b/core/java/android/os/IncidentManager.java @@ -255,7 +255,7 @@ public class IncidentManager { * @inheritDoc */ @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (this == obj) { return true; } diff --git a/core/java/android/os/IncidentReportArgs.java b/core/java/android/os/IncidentReportArgs.java index a1f2430f4ee3..7e858e1dc390 100644 --- a/core/java/android/os/IncidentReportArgs.java +++ b/core/java/android/os/IncidentReportArgs.java @@ -16,6 +16,7 @@ package android.os; +import android.annotation.NonNull; import android.annotation.SystemApi; import android.annotation.TestApi; import android.os.Parcel; @@ -117,6 +118,7 @@ public final class IncidentReportArgs implements Parcelable { /** * Print this report as a string. */ + @NonNull @Override public String toString() { final StringBuilder sb = new StringBuilder("Incident("); diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java index 2a4576adf192..271020db0ccd 100644 --- a/core/java/android/os/ParcelFileDescriptor.java +++ b/core/java/android/os/ParcelFileDescriptor.java @@ -616,10 +616,11 @@ public class ParcelFileDescriptor implements Parcelable, Closeable { public static File getFile(FileDescriptor fd) throws IOException { try { final String path = Os.readlink("/proc/self/fd/" + fd.getInt$()); - if (OsConstants.S_ISREG(Os.stat(path).st_mode)) { + if (OsConstants.S_ISREG(Os.stat(path).st_mode) + || OsConstants.S_ISCHR(Os.stat(path).st_mode)) { return new File(path); } else { - throw new IOException("Not a regular file: " + path); + throw new IOException("Not a regular file or character device: " + path); } } catch (ErrnoException e) { throw e.rethrowAsIOException(); diff --git a/core/java/android/os/ServiceSpecificException.java b/core/java/android/os/ServiceSpecificException.java index 03d5d3e195e0..49ce40bb6ee9 100644 --- a/core/java/android/os/ServiceSpecificException.java +++ b/core/java/android/os/ServiceSpecificException.java @@ -15,6 +15,7 @@ */ package android.os; +import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; @@ -44,6 +45,7 @@ public class ServiceSpecificException extends RuntimeException { this.errorCode = errorCode; } + @NonNull @Override public String toString() { return super.toString() + " (code " + errorCode + ")"; diff --git a/core/java/android/os/UserManagerInternal.java b/core/java/android/os/UserManagerInternal.java index f302263f23ce..ddd949d64a1f 100644 --- a/core/java/android/os/UserManagerInternal.java +++ b/core/java/android/os/UserManagerInternal.java @@ -15,6 +15,7 @@ */ package android.os; +import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; import android.content.Context; @@ -231,4 +232,9 @@ public abstract class UserManagerInternal { * found. */ public abstract @Nullable UserInfo getUserInfo(@UserIdInt int userId); + + /** + * Gets all {@link UserInfo UserInfos}. + */ + public abstract @NonNull UserInfo[] getUserInfos(); } diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java index 702b41beb071..26da0a0aee07 100644 --- a/core/java/android/os/VibrationEffect.java +++ b/core/java/android/os/VibrationEffect.java @@ -53,7 +53,7 @@ public abstract class VibrationEffect implements Parcelable { public static final int MAX_AMPLITUDE = 255; /** - * A click effect. + * A click effect. Use this effect as a baseline, as it's the most common type of click effect. * * @see #get(int) */ @@ -67,7 +67,7 @@ public abstract class VibrationEffect implements Parcelable { public static final int EFFECT_DOUBLE_CLICK = Effect.DOUBLE_CLICK; /** - * A tick effect. + * A tick effect. This effect is less strong compared to {@link #EFFECT_CLICK}. * @see #get(int) */ public static final int EFFECT_TICK = Effect.TICK; @@ -89,7 +89,7 @@ public abstract class VibrationEffect implements Parcelable { public static final int EFFECT_POP = Effect.POP; /** - * A heavy click effect. + * A heavy click effect. This effect is stronger than {@link #EFFECT_CLICK}. * @see #get(int) */ public static final int EFFECT_HEAVY_CLICK = Effect.HEAVY_CLICK; diff --git a/core/java/android/os/WorkSource.java b/core/java/android/os/WorkSource.java index 114de2378a1f..9cc9aac490c7 100644 --- a/core/java/android/os/WorkSource.java +++ b/core/java/android/os/WorkSource.java @@ -1,5 +1,6 @@ package android.os; +import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.TestApi; @@ -205,7 +206,7 @@ public class WorkSource implements Parcelable { } @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (o instanceof WorkSource) { WorkSource other = (WorkSource) o; @@ -989,6 +990,7 @@ public class WorkSource implements Parcelable { mTags = tags; } + @NonNull @Override public String toString() { StringBuilder result = new StringBuilder("WorkChain{"); @@ -1015,7 +1017,7 @@ public class WorkSource implements Parcelable { } @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (o instanceof WorkChain) { WorkChain other = (WorkChain) o; diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java index 42816c064ab0..5e359589dfc2 100644 --- a/core/java/android/permission/PermissionManager.java +++ b/core/java/android/permission/PermissionManager.java @@ -19,6 +19,7 @@ package android.permission; import android.Manifest; import android.annotation.IntRange; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.SystemService; @@ -144,7 +145,7 @@ public final class PermissionManager { private final int mTargetSdk; @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; SplitPermissionInfo that = (SplitPermissionInfo) o; diff --git a/core/java/android/printservice/PrintServiceInfo.java b/core/java/android/printservice/PrintServiceInfo.java index 565843e9bba5..0c1b61d583b3 100644 --- a/core/java/android/printservice/PrintServiceInfo.java +++ b/core/java/android/printservice/PrintServiceInfo.java @@ -17,6 +17,7 @@ package android.printservice; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.content.ComponentName; import android.content.Context; @@ -292,7 +293,7 @@ public final class PrintServiceInfo implements Parcelable { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (this == obj) { return true; } @@ -313,6 +314,7 @@ public final class PrintServiceInfo implements Parcelable { return true; } + @NonNull @Override public String toString() { StringBuilder builder = new StringBuilder(); diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java index b7676b611fe3..4b9daf1c9486 100644 --- a/core/java/android/provider/DeviceConfig.java +++ b/core/java/android/provider/DeviceConfig.java @@ -775,8 +775,9 @@ public final class DeviceConfig { * * @param namespace The namespace these properties belong to. * @param keyValueMap A map between property names and property values. + * @hide */ - Properties(@NonNull String namespace, @Nullable Map<String, String> keyValueMap) { + public Properties(@NonNull String namespace, @Nullable Map<String, String> keyValueMap) { Preconditions.checkNotNull(namespace); mNamespace = namespace; mMap = new HashMap(); diff --git a/core/java/android/provider/SearchIndexableData.java b/core/java/android/provider/SearchIndexableData.java index a60be5363d62..87f9af39f5ba 100644 --- a/core/java/android/provider/SearchIndexableData.java +++ b/core/java/android/provider/SearchIndexableData.java @@ -16,6 +16,7 @@ package android.provider; +import android.annotation.NonNull; import android.annotation.SystemApi; import android.content.Context; @@ -139,6 +140,7 @@ public abstract class SearchIndexableData { context = ctx; } + @NonNull @Override public String toString() { final StringBuilder sb = new StringBuilder(); diff --git a/core/java/android/provider/SearchIndexableResource.java b/core/java/android/provider/SearchIndexableResource.java index 1eb17345f09d..0765b6be0032 100644 --- a/core/java/android/provider/SearchIndexableResource.java +++ b/core/java/android/provider/SearchIndexableResource.java @@ -16,6 +16,7 @@ package android.provider; +import android.annotation.NonNull; import android.annotation.SystemApi; import android.content.Context; @@ -66,6 +67,7 @@ public class SearchIndexableResource extends SearchIndexableData { super(context); } + @NonNull @Override public String toString() { final StringBuilder sb = new StringBuilder(); diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index f573d8771178..dd3942e084cd 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -16,20 +16,6 @@ package android.provider; -import static android.provider.settings.validators.SettingsValidators.ANY_INTEGER_VALIDATOR; -import static android.provider.settings.validators.SettingsValidators.ANY_STRING_VALIDATOR; -import static android.provider.settings.validators.SettingsValidators.BOOLEAN_VALIDATOR; -import static android.provider.settings.validators.SettingsValidators.COMPONENT_NAME_VALIDATOR; -import static android.provider.settings.validators.SettingsValidators.JSON_OBJECT_VALIDATOR; -import static android.provider.settings.validators.SettingsValidators.LENIENT_IP_ADDRESS_VALIDATOR; -import static android.provider.settings.validators.SettingsValidators.LOCALE_VALIDATOR; -import static android.provider.settings.validators.SettingsValidators.NON_NEGATIVE_INTEGER_VALIDATOR; -import static android.provider.settings.validators.SettingsValidators.NULLABLE_COMPONENT_NAME_VALIDATOR; -import static android.provider.settings.validators.SettingsValidators.PACKAGE_NAME_VALIDATOR; -import static android.provider.settings.validators.SettingsValidators.TILE_LIST_VALIDATOR; -import static android.provider.settings.validators.SettingsValidators.TTS_LIST_VALIDATOR; -import static android.provider.settings.validators.SettingsValidators.URI_VALIDATOR; - import android.Manifest; import android.annotation.IntDef; import android.annotation.IntRange; @@ -63,9 +49,7 @@ import android.content.res.Configuration; import android.content.res.Resources; import android.database.Cursor; import android.database.SQLException; -import android.hardware.display.ColorDisplayManager; import android.location.LocationManager; -import android.media.AudioFormat; import android.net.ConnectivityManager; import android.net.NetworkScoreManager; import android.net.Uri; @@ -83,12 +67,6 @@ import android.os.RemoteException; import android.os.ResultReceiver; import android.os.ServiceManager; import android.os.UserHandle; -import android.provider.settings.validators.ComponentNameListValidator; -import android.provider.settings.validators.DiscreteValueValidator; -import android.provider.settings.validators.InclusiveFloatRangeValidator; -import android.provider.settings.validators.InclusiveIntegerRangeValidator; -import android.provider.settings.validators.PackageNameListValidator; -import android.provider.settings.validators.Validator; import android.speech.tts.TextToSpeech; import android.telephony.SubscriptionManager; import android.text.TextUtils; @@ -106,7 +84,6 @@ import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.net.URISyntaxException; -import java.text.SimpleDateFormat; import java.util.HashMap; import java.util.HashSet; import java.util.Locale; @@ -3120,30 +3097,6 @@ public final class Settings { @Deprecated public static final String STAY_ON_WHILE_PLUGGED_IN = Global.STAY_ON_WHILE_PLUGGED_IN; - private static final Validator STAY_ON_WHILE_PLUGGED_IN_VALIDATOR = new Validator() { - @Override - public boolean validate(String value) { - try { - int val = Integer.parseInt(value); - return (val == 0) - || (val == BatteryManager.BATTERY_PLUGGED_AC) - || (val == BatteryManager.BATTERY_PLUGGED_USB) - || (val == BatteryManager.BATTERY_PLUGGED_WIRELESS) - || (val == (BatteryManager.BATTERY_PLUGGED_AC - | BatteryManager.BATTERY_PLUGGED_USB)) - || (val == (BatteryManager.BATTERY_PLUGGED_AC - | BatteryManager.BATTERY_PLUGGED_WIRELESS)) - || (val == (BatteryManager.BATTERY_PLUGGED_USB - | BatteryManager.BATTERY_PLUGGED_WIRELESS)) - || (val == (BatteryManager.BATTERY_PLUGGED_AC - | BatteryManager.BATTERY_PLUGGED_USB - | BatteryManager.BATTERY_PLUGGED_WIRELESS)); - } catch (NumberFormatException e) { - return false; - } - } - }; - /** * What happens when the user presses the end call button if they're not * on a call.<br/> @@ -3156,9 +3109,6 @@ public final class Settings { */ public static final String END_BUTTON_BEHAVIOR = "end_button_behavior"; - private static final Validator END_BUTTON_BEHAVIOR_VALIDATOR = - new InclusiveIntegerRangeValidator(0, 3); - /** * END_BUTTON_BEHAVIOR value for "go home". * @hide @@ -3183,8 +3133,6 @@ public final class Settings { */ public static final String ADVANCED_SETTINGS = "advanced_settings"; - private static final Validator ADVANCED_SETTINGS_VALIDATOR = BOOLEAN_VALIDATOR; - /** * ADVANCED_SETTINGS default value. * @hide @@ -3285,8 +3233,6 @@ public final class Settings { @Deprecated public static final String WIFI_USE_STATIC_IP = "wifi_use_static_ip"; - private static final Validator WIFI_USE_STATIC_IP_VALIDATOR = BOOLEAN_VALIDATOR; - /** * The static IP address. * <p> @@ -3297,8 +3243,6 @@ public final class Settings { @Deprecated public static final String WIFI_STATIC_IP = "wifi_static_ip"; - private static final Validator WIFI_STATIC_IP_VALIDATOR = LENIENT_IP_ADDRESS_VALIDATOR; - /** * If using static IP, the gateway's IP address. * <p> @@ -3309,8 +3253,6 @@ public final class Settings { @Deprecated public static final String WIFI_STATIC_GATEWAY = "wifi_static_gateway"; - private static final Validator WIFI_STATIC_GATEWAY_VALIDATOR = LENIENT_IP_ADDRESS_VALIDATOR; - /** * If using static IP, the net mask. * <p> @@ -3321,8 +3263,6 @@ public final class Settings { @Deprecated public static final String WIFI_STATIC_NETMASK = "wifi_static_netmask"; - private static final Validator WIFI_STATIC_NETMASK_VALIDATOR = LENIENT_IP_ADDRESS_VALIDATOR; - /** * If using static IP, the primary DNS's IP address. * <p> @@ -3333,8 +3273,6 @@ public final class Settings { @Deprecated public static final String WIFI_STATIC_DNS1 = "wifi_static_dns1"; - private static final Validator WIFI_STATIC_DNS1_VALIDATOR = LENIENT_IP_ADDRESS_VALIDATOR; - /** * If using static IP, the secondary DNS's IP address. * <p> @@ -3345,8 +3283,6 @@ public final class Settings { @Deprecated public static final String WIFI_STATIC_DNS2 = "wifi_static_dns2"; - private static final Validator WIFI_STATIC_DNS2_VALIDATOR = LENIENT_IP_ADDRESS_VALIDATOR; - /** * Determines whether remote devices may discover and/or connect to * this device. @@ -3358,9 +3294,6 @@ public final class Settings { public static final String BLUETOOTH_DISCOVERABILITY = "bluetooth_discoverability"; - private static final Validator BLUETOOTH_DISCOVERABILITY_VALIDATOR = - new InclusiveIntegerRangeValidator(0, 2); - /** * Bluetooth discoverability timeout. If this value is nonzero, then * Bluetooth becomes discoverable for a certain number of seconds, @@ -3369,9 +3302,6 @@ public final class Settings { public static final String BLUETOOTH_DISCOVERABILITY_TIMEOUT = "bluetooth_discoverability_timeout"; - private static final Validator BLUETOOTH_DISCOVERABILITY_TIMEOUT_VALIDATOR = - NON_NEGATIVE_INTEGER_VALIDATOR; - /** * @deprecated Use {@link android.provider.Settings.Secure#LOCK_PATTERN_ENABLED} * instead @@ -3404,32 +3334,11 @@ public final class Settings { @Deprecated public static final String NEXT_ALARM_FORMATTED = "next_alarm_formatted"; - private static final Validator NEXT_ALARM_FORMATTED_VALIDATOR = new Validator() { - private static final int MAX_LENGTH = 1000; - - @Override - public boolean validate(String value) { - // TODO: No idea what the correct format is. - return value == null || value.length() < MAX_LENGTH; - } - }; - /** * Scaling factor for fonts, float. */ public static final String FONT_SCALE = "font_scale"; - private static final Validator FONT_SCALE_VALIDATOR = new Validator() { - @Override - public boolean validate(@Nullable String value) { - try { - return Float.parseFloat(value) >= 0; - } catch (NumberFormatException | NullPointerException e) { - return false; - } - } - }; - /** * The serialized system locale value. * @@ -3466,34 +3375,12 @@ public final class Settings { @Deprecated public static final String DIM_SCREEN = "dim_screen"; - private static final Validator DIM_SCREEN_VALIDATOR = BOOLEAN_VALIDATOR; - /** * The display color mode. * @hide */ public static final String DISPLAY_COLOR_MODE = "display_color_mode"; - private static final Validator DISPLAY_COLOR_MODE_VALIDATOR = new Validator() { - @Override - public boolean validate(@Nullable String value) { - // Assume the actual validation that this device can properly handle this kind of - // color mode further down in ColorDisplayManager / ColorDisplayService. - try { - final int setting = Integer.parseInt(value); - final boolean isInFrameworkRange = - setting >= ColorDisplayManager.COLOR_MODE_NATURAL - && setting <= ColorDisplayManager.COLOR_MODE_AUTOMATIC; - final boolean isInVendorRange = - setting >= ColorDisplayManager.VENDOR_COLOR_MODE_RANGE_MIN - && setting <= ColorDisplayManager.VENDOR_COLOR_MODE_RANGE_MAX; - return isInFrameworkRange || isInVendorRange; - } catch (NumberFormatException | NullPointerException e) { - return false; - } - } - }; - /** * The user selected min refresh rate in frames per second. * @@ -3510,9 +3397,6 @@ public final class Settings { */ public static final String PEAK_REFRESH_RATE = "peak_refresh_rate"; - private static final Validator PEAK_REFRESH_RATE_VALIDATOR = - new InclusiveFloatRangeValidator(24f, Float.MAX_VALUE); - /** * The amount of time in milliseconds before the device goes to sleep or begins * to dream after a period of inactivity. This value is also known as the @@ -3525,9 +3409,6 @@ public final class Settings { */ public static final String SCREEN_OFF_TIMEOUT = "screen_off_timeout"; - private static final Validator SCREEN_OFF_TIMEOUT_VALIDATOR = - NON_NEGATIVE_INTEGER_VALIDATOR; - /** * The screen backlight brightness between 0 and 255. */ @@ -3539,16 +3420,11 @@ public final class Settings { */ public static final String SCREEN_BRIGHTNESS_FOR_VR = "screen_brightness_for_vr"; - private static final Validator SCREEN_BRIGHTNESS_FOR_VR_VALIDATOR = - new InclusiveIntegerRangeValidator(0, 255); - /** * Control whether to enable automatic brightness mode. */ public static final String SCREEN_BRIGHTNESS_MODE = "screen_brightness_mode"; - private static final Validator SCREEN_BRIGHTNESS_MODE_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Adjustment to auto-brightness to make it generally more (>0.0 <1.0) * or less (<0.0 >-1.0) bright. @@ -3557,9 +3433,6 @@ public final class Settings { @UnsupportedAppUsage public static final String SCREEN_AUTO_BRIGHTNESS_ADJ = "screen_auto_brightness_adj"; - private static final Validator SCREEN_AUTO_BRIGHTNESS_ADJ_VALIDATOR = - new InclusiveFloatRangeValidator(-1, 1); - /** * SCREEN_BRIGHTNESS_MODE value for manual mode. */ @@ -3576,8 +3449,6 @@ public final class Settings { */ public static final String ADAPTIVE_SLEEP = "adaptive_sleep"; - private static final Validator ADAPTIVE_SLEEP_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Control whether the process CPU usage meter should be shown. * @@ -3604,9 +3475,6 @@ public final class Settings { */ public static final String MODE_RINGER_STREAMS_AFFECTED = "mode_ringer_streams_affected"; - private static final Validator MODE_RINGER_STREAMS_AFFECTED_VALIDATOR = - NON_NEGATIVE_INTEGER_VALIDATOR; - /** * Determines which streams are affected by mute. The * stream type's bit should be set to 1 if it should be muted when a mute request @@ -3614,17 +3482,12 @@ public final class Settings { */ public static final String MUTE_STREAMS_AFFECTED = "mute_streams_affected"; - private static final Validator MUTE_STREAMS_AFFECTED_VALIDATOR = - NON_NEGATIVE_INTEGER_VALIDATOR; - /** * Whether vibrate is on for different events. This is used internally, * changing this value will not change the vibrate. See AudioManager. */ public static final String VIBRATE_ON = "vibrate_on"; - private static final Validator VIBRATE_ON_VALIDATOR = BOOLEAN_VALIDATOR; - /** * If 1, redirects the system vibrator to all currently attached input devices * that support vibration. If there are no such input devices, then the system @@ -3639,8 +3502,6 @@ public final class Settings { */ public static final String VIBRATE_INPUT_DEVICES = "vibrate_input_devices"; - private static final Validator VIBRATE_INPUT_DEVICES_VALIDATOR = BOOLEAN_VALIDATOR; - /** * The intensity of notification vibrations, if configurable. * @@ -3691,9 +3552,6 @@ public final class Settings { public static final String HAPTIC_FEEDBACK_INTENSITY = "haptic_feedback_intensity"; - private static final Validator VIBRATION_INTENSITY_VALIDATOR = - new InclusiveIntegerRangeValidator(0, 3); - /** * Ringer volume. This is used internally, changing this value will not * change the volume. See AudioManager. @@ -3772,8 +3630,6 @@ public final class Settings { @UnsupportedAppUsage public static final String MASTER_MONO = "master_mono"; - private static final Validator MASTER_MONO_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Master balance (float -1.f = 100% left, 0.f = dead center, 1.f = 100% right). * @@ -3781,9 +3637,6 @@ public final class Settings { */ public static final String MASTER_BALANCE = "master_balance"; - private static final Validator MASTER_BALANCE_VALIDATOR = - new InclusiveFloatRangeValidator(-1.f, 1.f); - /** * Whether the notifications should use the ring volume (value of 1) or * a separate notification volume (value of 0). In most cases, users @@ -3802,8 +3655,6 @@ public final class Settings { public static final String NOTIFICATIONS_USE_RING_VOLUME = "notifications_use_ring_volume"; - private static final Validator NOTIFICATIONS_USE_RING_VOLUME_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Whether silent mode should allow vibration feedback. This is used * internally in AudioService and the Sound settings activity to @@ -3819,8 +3670,6 @@ public final class Settings { @UnsupportedAppUsage public static final String VIBRATE_IN_SILENT = "vibrate_in_silent"; - private static final Validator VIBRATE_IN_SILENT_VALIDATOR = BOOLEAN_VALIDATOR; - /** * The mapping of stream type (integer) to its setting. * @@ -3867,8 +3716,6 @@ public final class Settings { */ public static final String RINGTONE = "ringtone"; - private static final Validator RINGTONE_VALIDATOR = URI_VALIDATOR; - /** * A {@link Uri} that will point to the current default ringtone at any * given time. @@ -3892,8 +3739,6 @@ public final class Settings { */ public static final String NOTIFICATION_SOUND = "notification_sound"; - private static final Validator NOTIFICATION_SOUND_VALIDATOR = URI_VALIDATOR; - /** * A {@link Uri} that will point to the current default notification * sound at any given time. @@ -3915,8 +3760,6 @@ public final class Settings { */ public static final String ALARM_ALERT = "alarm_alert"; - private static final Validator ALARM_ALERT_VALIDATOR = URI_VALIDATOR; - /** * A {@link Uri} that will point to the current default alarm alert at * any given time. @@ -3937,42 +3780,30 @@ public final class Settings { */ public static final String MEDIA_BUTTON_RECEIVER = "media_button_receiver"; - private static final Validator MEDIA_BUTTON_RECEIVER_VALIDATOR = COMPONENT_NAME_VALIDATOR; - /** * Setting to enable Auto Replace (AutoText) in text editors. 1 = On, 0 = Off */ public static final String TEXT_AUTO_REPLACE = "auto_replace"; - private static final Validator TEXT_AUTO_REPLACE_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Setting to enable Auto Caps in text editors. 1 = On, 0 = Off */ public static final String TEXT_AUTO_CAPS = "auto_caps"; - private static final Validator TEXT_AUTO_CAPS_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Setting to enable Auto Punctuate in text editors. 1 = On, 0 = Off. This * feature converts two spaces to a "." and space. */ public static final String TEXT_AUTO_PUNCTUATE = "auto_punctuate"; - private static final Validator TEXT_AUTO_PUNCTUATE_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Setting to showing password characters in text editors. 1 = On, 0 = Off */ public static final String TEXT_SHOW_PASSWORD = "show_password"; - private static final Validator TEXT_SHOW_PASSWORD_VALIDATOR = BOOLEAN_VALIDATOR; - public static final String SHOW_GTALK_SERVICE_STATUS = "SHOW_GTALK_SERVICE_STATUS"; - private static final Validator SHOW_GTALK_SERVICE_STATUS_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Name of activity to use for wallpaper on the home screen. * @@ -3981,18 +3812,6 @@ public final class Settings { @Deprecated public static final String WALLPAPER_ACTIVITY = "wallpaper_activity"; - private static final Validator WALLPAPER_ACTIVITY_VALIDATOR = new Validator() { - private static final int MAX_LENGTH = 1000; - - @Override - public boolean validate(String value) { - if (value != null && value.length() > MAX_LENGTH) { - return false; - } - return ComponentName.unflattenFromString(value) != null; - } - }; - /** * @deprecated Use {@link android.provider.Settings.Global#AUTO_TIME} * instead @@ -4000,8 +3819,6 @@ public final class Settings { @Deprecated public static final String AUTO_TIME = Global.AUTO_TIME; - private static final Validator AUTO_TIME_VALIDATOR = BOOLEAN_VALIDATOR; - /** * @deprecated Use {@link android.provider.Settings.Global#AUTO_TIME_ZONE} * instead @@ -4009,8 +3826,6 @@ public final class Settings { @Deprecated public static final String AUTO_TIME_ZONE = Global.AUTO_TIME_ZONE; - private static final Validator AUTO_TIME_ZONE_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Display times as 12 or 24 hours * 12 @@ -4018,10 +3833,6 @@ public final class Settings { */ public static final String TIME_12_24 = "time_12_24"; - /** @hide */ - public static final Validator TIME_12_24_VALIDATOR = - new DiscreteValueValidator(new String[] {"12", "24", null}); - /** * Date format string * mm/dd/yyyy @@ -4030,19 +3841,6 @@ public final class Settings { */ public static final String DATE_FORMAT = "date_format"; - /** @hide */ - public static final Validator DATE_FORMAT_VALIDATOR = new Validator() { - @Override - public boolean validate(@Nullable String value) { - try { - new SimpleDateFormat(value); - return true; - } catch (IllegalArgumentException | NullPointerException e) { - return false; - } - } - }; - /** * Whether the setup wizard has been run before (on first boot), or if * it still needs to be run. @@ -4052,9 +3850,6 @@ public final class Settings { */ public static final String SETUP_WIZARD_HAS_RUN = "setup_wizard_has_run"; - /** @hide */ - public static final Validator SETUP_WIZARD_HAS_RUN_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Scaling factor for normal window animations. Setting to 0 will disable window * animations. @@ -4091,9 +3886,6 @@ public final class Settings { */ public static final String ACCELEROMETER_ROTATION = "accelerometer_rotation"; - /** @hide */ - public static final Validator ACCELEROMETER_ROTATION_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Default screen rotation when no other policy applies. * When {@link #ACCELEROMETER_ROTATION} is zero and no on-screen Activity expresses a @@ -4104,10 +3896,6 @@ public final class Settings { */ public static final String USER_ROTATION = "user_rotation"; - /** @hide */ - public static final Validator USER_ROTATION_VALIDATOR = - new InclusiveIntegerRangeValidator(0, 3); - /** * Control whether the rotation lock toggle in the System UI should be hidden. * Typically this is done for accessibility purposes to make it harder for @@ -4123,10 +3911,6 @@ public final class Settings { public static final String HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY = "hide_rotation_lock_toggle_for_accessibility"; - /** @hide */ - public static final Validator HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY_VALIDATOR = - BOOLEAN_VALIDATOR; - /** * Whether the phone vibrates when it is ringing due to an incoming call. This will * be used by Phone and Setting apps; it shouldn't affect other apps. @@ -4139,9 +3923,6 @@ public final class Settings { */ public static final String VIBRATE_WHEN_RINGING = "vibrate_when_ringing"; - /** @hide */ - public static final Validator VIBRATE_WHEN_RINGING_VALIDATOR = BOOLEAN_VALIDATOR; - /** * When {@code 1}, Telecom enhanced call blocking functionality is enabled. When * {@code 0}, enhanced call blocking functionality is disabled. @@ -4156,9 +3937,6 @@ public final class Settings { */ public static final String DTMF_TONE_WHEN_DIALING = "dtmf_tone"; - /** @hide */ - public static final Validator DTMF_TONE_WHEN_DIALING_VALIDATOR = BOOLEAN_VALIDATOR; - /** * CDMA only settings * DTMF tone type played by the dialer when dialing. @@ -4167,9 +3945,6 @@ public final class Settings { */ public static final String DTMF_TONE_TYPE_WHEN_DIALING = "dtmf_tone_type"; - /** @hide */ - public static final Validator DTMF_TONE_TYPE_WHEN_DIALING_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Whether the hearing aid is enabled. The value is * boolean (1 or 0). @@ -4178,9 +3953,6 @@ public final class Settings { @UnsupportedAppUsage public static final String HEARING_AID = "hearing_aid"; - /** @hide */ - public static final Validator HEARING_AID_VALIDATOR = BOOLEAN_VALIDATOR; - /** * CDMA only settings * TTY Mode @@ -4193,28 +3965,18 @@ public final class Settings { @UnsupportedAppUsage public static final String TTY_MODE = "tty_mode"; - /** @hide */ - public static final Validator TTY_MODE_VALIDATOR = - new InclusiveIntegerRangeValidator(0, 3); - /** * Whether the sounds effects (key clicks, lid open ...) are enabled. The value is * boolean (1 or 0). */ public static final String SOUND_EFFECTS_ENABLED = "sound_effects_enabled"; - /** @hide */ - public static final Validator SOUND_EFFECTS_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Whether haptic feedback (Vibrate on tap) is enabled. The value is * boolean (1 or 0). */ public static final String HAPTIC_FEEDBACK_ENABLED = "haptic_feedback_enabled"; - /** @hide */ - public static final Validator HAPTIC_FEEDBACK_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR; - /** * @deprecated Each application that shows web suggestions should have its own * setting for this. @@ -4222,9 +3984,6 @@ public final class Settings { @Deprecated public static final String SHOW_WEB_SUGGESTIONS = "show_web_suggestions"; - /** @hide */ - public static final Validator SHOW_WEB_SUGGESTIONS_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Whether the notification LED should repeatedly flash when a notification is * pending. The value is boolean (1 or 0). @@ -4233,9 +3992,6 @@ public final class Settings { @UnsupportedAppUsage public static final String NOTIFICATION_LIGHT_PULSE = "notification_light_pulse"; - /** @hide */ - public static final Validator NOTIFICATION_LIGHT_PULSE_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Show pointer location on screen? * 0 = no @@ -4245,9 +4001,6 @@ public final class Settings { @UnsupportedAppUsage public static final String POINTER_LOCATION = "pointer_location"; - /** @hide */ - public static final Validator POINTER_LOCATION_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Show touch positions on screen? * 0 = no @@ -4257,9 +4010,6 @@ public final class Settings { @UnsupportedAppUsage public static final String SHOW_TOUCHES = "show_touches"; - /** @hide */ - public static final Validator SHOW_TOUCHES_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Log raw orientation data from * {@link com.android.server.policy.WindowOrientationListener} for use with the @@ -4271,9 +4021,6 @@ public final class Settings { public static final String WINDOW_ORIENTATION_LISTENER_LOG = "window_orientation_listener_log"; - /** @hide */ - public static final Validator WINDOW_ORIENTATION_LISTENER_LOG_VALIDATOR = BOOLEAN_VALIDATOR; - /** * @deprecated Use {@link android.provider.Settings.Global#POWER_SOUNDS_ENABLED} * instead @@ -4282,8 +4029,6 @@ public final class Settings { @Deprecated public static final String POWER_SOUNDS_ENABLED = Global.POWER_SOUNDS_ENABLED; - private static final Validator POWER_SOUNDS_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR; - /** * @deprecated Use {@link android.provider.Settings.Global#DOCK_SOUNDS_ENABLED} * instead @@ -4293,8 +4038,6 @@ public final class Settings { @UnsupportedAppUsage public static final String DOCK_SOUNDS_ENABLED = Global.DOCK_SOUNDS_ENABLED; - private static final Validator DOCK_SOUNDS_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Whether to play sounds when the keyguard is shown and dismissed. * @hide @@ -4302,18 +4045,12 @@ public final class Settings { @UnsupportedAppUsage public static final String LOCKSCREEN_SOUNDS_ENABLED = "lockscreen_sounds_enabled"; - /** @hide */ - public static final Validator LOCKSCREEN_SOUNDS_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Whether the lockscreen should be completely disabled. * @hide */ public static final String LOCKSCREEN_DISABLED = "lockscreen.disabled"; - /** @hide */ - public static final Validator LOCKSCREEN_DISABLED_VALIDATOR = BOOLEAN_VALIDATOR; - /** * @deprecated Use {@link android.provider.Settings.Global#LOW_BATTERY_SOUND} * instead @@ -4384,9 +4121,6 @@ public final class Settings { */ public static final String SIP_RECEIVE_CALLS = "sip_receive_calls"; - /** @hide */ - public static final Validator SIP_RECEIVE_CALLS_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Call Preference String. * "SIP_ALWAYS" : Always use SIP with network access @@ -4395,29 +4129,18 @@ public final class Settings { */ public static final String SIP_CALL_OPTIONS = "sip_call_options"; - /** @hide */ - public static final Validator SIP_CALL_OPTIONS_VALIDATOR = - new DiscreteValueValidator( - new String[] {"SIP_ALWAYS", "SIP_ADDRESS_ONLY"}); - /** * One of the sip call options: Always use SIP with network access. * @hide */ public static final String SIP_ALWAYS = "SIP_ALWAYS"; - /** @hide */ - public static final Validator SIP_ALWAYS_VALIDATOR = BOOLEAN_VALIDATOR; - /** * One of the sip call options: Only if destination is a SIP address. * @hide */ public static final String SIP_ADDRESS_ONLY = "SIP_ADDRESS_ONLY"; - /** @hide */ - public static final Validator SIP_ADDRESS_ONLY_VALIDATOR = BOOLEAN_VALIDATOR; - /** * @deprecated Use SIP_ALWAYS or SIP_ADDRESS_ONLY instead. Formerly used to indicate that * the user should be prompted each time a call is made whether it should be placed using @@ -4428,9 +4151,6 @@ public final class Settings { @Deprecated public static final String SIP_ASK_ME_EACH_TIME = "SIP_ASK_ME_EACH_TIME"; - /** @hide */ - public static final Validator SIP_ASK_ME_EACH_TIME_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Pointer speed setting. * This is an integer value in a range between -7 and +7, so there are 15 possible values. @@ -4442,19 +4162,12 @@ public final class Settings { @UnsupportedAppUsage public static final String POINTER_SPEED = "pointer_speed"; - /** @hide */ - public static final Validator POINTER_SPEED_VALIDATOR = - new InclusiveFloatRangeValidator(-7, 7); - /** * Whether lock-to-app will be triggered by long-press on recents. * @hide */ public static final String LOCK_TO_APP_ENABLED = "lock_to_app_enabled"; - /** @hide */ - public static final Validator LOCK_TO_APP_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR; - /** * I am the lolrus. * <p> @@ -4464,18 +4177,6 @@ public final class Settings { */ public static final String EGG_MODE = "egg_mode"; - /** @hide */ - public static final Validator EGG_MODE_VALIDATOR = new Validator() { - @Override - public boolean validate(@Nullable String value) { - try { - return Long.parseLong(value) >= 0; - } catch (NumberFormatException e) { - return false; - } - } - }; - /** * Setting to determine whether or not to show the battery percentage in the status bar. * 0 - Don't show percentage @@ -4484,9 +4185,6 @@ public final class Settings { */ public static final String SHOW_BATTERY_PERCENT = "status_bar_show_battery_percent"; - /** @hide */ - private static final Validator SHOW_BATTERY_PERCENT_VALIDATOR = BOOLEAN_VALIDATOR; - /** * IMPORTANT: If you add a new public settings you also have to add it to * PUBLIC_SETTINGS below. If the new setting is hidden you have to add @@ -4495,73 +4193,6 @@ public final class Settings { */ /** - * Settings to backup. This is here so that it's in the same place as the settings - * keys and easy to update. - * - * NOTE: Settings are backed up and restored in the order they appear - * in this array. If you have one setting depending on another, - * make sure that they are ordered appropriately. - * - * @hide - */ - @UnsupportedAppUsage - public static final String[] SETTINGS_TO_BACKUP = { - STAY_ON_WHILE_PLUGGED_IN, // moved to global - WIFI_USE_STATIC_IP, - WIFI_STATIC_IP, - WIFI_STATIC_GATEWAY, - WIFI_STATIC_NETMASK, - WIFI_STATIC_DNS1, - WIFI_STATIC_DNS2, - BLUETOOTH_DISCOVERABILITY, - BLUETOOTH_DISCOVERABILITY_TIMEOUT, - FONT_SCALE, - DIM_SCREEN, - SCREEN_OFF_TIMEOUT, - SCREEN_BRIGHTNESS_MODE, - SCREEN_AUTO_BRIGHTNESS_ADJ, - SCREEN_BRIGHTNESS_FOR_VR, - ADAPTIVE_SLEEP, - VIBRATE_INPUT_DEVICES, - MODE_RINGER_STREAMS_AFFECTED, - TEXT_AUTO_REPLACE, - TEXT_AUTO_CAPS, - TEXT_AUTO_PUNCTUATE, - TEXT_SHOW_PASSWORD, - AUTO_TIME, // moved to global - AUTO_TIME_ZONE, // moved to global - TIME_12_24, - DATE_FORMAT, - DTMF_TONE_WHEN_DIALING, - DTMF_TONE_TYPE_WHEN_DIALING, - HEARING_AID, - TTY_MODE, - MASTER_MONO, - MASTER_BALANCE, - SOUND_EFFECTS_ENABLED, - HAPTIC_FEEDBACK_ENABLED, - POWER_SOUNDS_ENABLED, // moved to global - DOCK_SOUNDS_ENABLED, // moved to global - LOCKSCREEN_SOUNDS_ENABLED, - SHOW_WEB_SUGGESTIONS, - SIP_CALL_OPTIONS, - SIP_RECEIVE_CALLS, - POINTER_SPEED, - VIBRATE_WHEN_RINGING, - RINGTONE, - LOCK_TO_APP_ENABLED, - NOTIFICATION_SOUND, - ACCELEROMETER_ROTATION, - SHOW_BATTERY_PERCENT, - NOTIFICATION_VIBRATION_INTENSITY, - RING_VIBRATION_INTENSITY, - HAPTIC_FEEDBACK_INTENSITY, - DISPLAY_COLOR_MODE, - ALARM_ALERT, - NOTIFICATION_LIGHT_PULSE, - }; - - /** * Keys we no longer back up under the current schema, but want to continue to * process when restoring historical backup datasets. * @@ -4681,99 +4312,6 @@ public final class Settings { } /** - * These are all public system settings - * - * All settings in {@link SETTINGS_TO_BACKUP} array *must* have a non-null validator, - * otherwise they won't be restored. - * - * @hide - */ - @UnsupportedAppUsage - public static final Map<String, Validator> VALIDATORS = new ArrayMap<>(); - static { - VALIDATORS.put(STAY_ON_WHILE_PLUGGED_IN, STAY_ON_WHILE_PLUGGED_IN_VALIDATOR); - VALIDATORS.put(END_BUTTON_BEHAVIOR, END_BUTTON_BEHAVIOR_VALIDATOR); - VALIDATORS.put(WIFI_USE_STATIC_IP, WIFI_USE_STATIC_IP_VALIDATOR); - VALIDATORS.put(BLUETOOTH_DISCOVERABILITY, BLUETOOTH_DISCOVERABILITY_VALIDATOR); - VALIDATORS.put(BLUETOOTH_DISCOVERABILITY_TIMEOUT, - BLUETOOTH_DISCOVERABILITY_TIMEOUT_VALIDATOR); - VALIDATORS.put(NEXT_ALARM_FORMATTED, NEXT_ALARM_FORMATTED_VALIDATOR); - VALIDATORS.put(FONT_SCALE, FONT_SCALE_VALIDATOR); - VALIDATORS.put(DIM_SCREEN, DIM_SCREEN_VALIDATOR); - VALIDATORS.put(DISPLAY_COLOR_MODE, DISPLAY_COLOR_MODE_VALIDATOR); - VALIDATORS.put(SCREEN_OFF_TIMEOUT, SCREEN_OFF_TIMEOUT_VALIDATOR); - VALIDATORS.put(SCREEN_BRIGHTNESS_FOR_VR, SCREEN_BRIGHTNESS_FOR_VR_VALIDATOR); - VALIDATORS.put(SCREEN_BRIGHTNESS_MODE, SCREEN_BRIGHTNESS_MODE_VALIDATOR); - VALIDATORS.put(ADAPTIVE_SLEEP, ADAPTIVE_SLEEP_VALIDATOR); - VALIDATORS.put(MODE_RINGER_STREAMS_AFFECTED, MODE_RINGER_STREAMS_AFFECTED_VALIDATOR); - VALIDATORS.put(MUTE_STREAMS_AFFECTED, MUTE_STREAMS_AFFECTED_VALIDATOR); - VALIDATORS.put(VIBRATE_ON, VIBRATE_ON_VALIDATOR); - VALIDATORS.put(NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_VALIDATOR); - VALIDATORS.put(RING_VIBRATION_INTENSITY, VIBRATION_INTENSITY_VALIDATOR); - VALIDATORS.put(HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_VALIDATOR); - VALIDATORS.put(RINGTONE, RINGTONE_VALIDATOR); - VALIDATORS.put(NOTIFICATION_SOUND, NOTIFICATION_SOUND_VALIDATOR); - VALIDATORS.put(ALARM_ALERT, ALARM_ALERT_VALIDATOR); - VALIDATORS.put(TEXT_AUTO_REPLACE, TEXT_AUTO_REPLACE_VALIDATOR); - VALIDATORS.put(TEXT_AUTO_CAPS, TEXT_AUTO_CAPS_VALIDATOR); - VALIDATORS.put(TEXT_AUTO_PUNCTUATE, TEXT_AUTO_PUNCTUATE_VALIDATOR); - VALIDATORS.put(TEXT_SHOW_PASSWORD, TEXT_SHOW_PASSWORD_VALIDATOR); - VALIDATORS.put(AUTO_TIME, AUTO_TIME_VALIDATOR); - VALIDATORS.put(AUTO_TIME_ZONE, AUTO_TIME_ZONE_VALIDATOR); - VALIDATORS.put(SHOW_GTALK_SERVICE_STATUS, SHOW_GTALK_SERVICE_STATUS_VALIDATOR); - VALIDATORS.put(WALLPAPER_ACTIVITY, WALLPAPER_ACTIVITY_VALIDATOR); - VALIDATORS.put(TIME_12_24, TIME_12_24_VALIDATOR); - VALIDATORS.put(DATE_FORMAT, DATE_FORMAT_VALIDATOR); - VALIDATORS.put(SETUP_WIZARD_HAS_RUN, SETUP_WIZARD_HAS_RUN_VALIDATOR); - VALIDATORS.put(ACCELEROMETER_ROTATION, ACCELEROMETER_ROTATION_VALIDATOR); - VALIDATORS.put(USER_ROTATION, USER_ROTATION_VALIDATOR); - VALIDATORS.put(DTMF_TONE_WHEN_DIALING, DTMF_TONE_WHEN_DIALING_VALIDATOR); - VALIDATORS.put(SOUND_EFFECTS_ENABLED, SOUND_EFFECTS_ENABLED_VALIDATOR); - VALIDATORS.put(HAPTIC_FEEDBACK_ENABLED, HAPTIC_FEEDBACK_ENABLED_VALIDATOR); - VALIDATORS.put(POWER_SOUNDS_ENABLED, POWER_SOUNDS_ENABLED_VALIDATOR); - VALIDATORS.put(DOCK_SOUNDS_ENABLED, DOCK_SOUNDS_ENABLED_VALIDATOR); - VALIDATORS.put(SHOW_WEB_SUGGESTIONS, SHOW_WEB_SUGGESTIONS_VALIDATOR); - VALIDATORS.put(WIFI_USE_STATIC_IP, WIFI_USE_STATIC_IP_VALIDATOR); - VALIDATORS.put(END_BUTTON_BEHAVIOR, END_BUTTON_BEHAVIOR_VALIDATOR); - VALIDATORS.put(ADVANCED_SETTINGS, ADVANCED_SETTINGS_VALIDATOR); - VALIDATORS.put(SCREEN_AUTO_BRIGHTNESS_ADJ, SCREEN_AUTO_BRIGHTNESS_ADJ_VALIDATOR); - VALIDATORS.put(VIBRATE_INPUT_DEVICES, VIBRATE_INPUT_DEVICES_VALIDATOR); - VALIDATORS.put(MASTER_MONO, MASTER_MONO_VALIDATOR); - VALIDATORS.put(MASTER_BALANCE, MASTER_BALANCE_VALIDATOR); - VALIDATORS.put(NOTIFICATIONS_USE_RING_VOLUME, NOTIFICATIONS_USE_RING_VOLUME_VALIDATOR); - VALIDATORS.put(VIBRATE_IN_SILENT, VIBRATE_IN_SILENT_VALIDATOR); - VALIDATORS.put(MEDIA_BUTTON_RECEIVER, MEDIA_BUTTON_RECEIVER_VALIDATOR); - VALIDATORS.put(HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY, - HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY_VALIDATOR); - VALIDATORS.put(VIBRATE_WHEN_RINGING, VIBRATE_WHEN_RINGING_VALIDATOR); - VALIDATORS.put(DTMF_TONE_TYPE_WHEN_DIALING, DTMF_TONE_TYPE_WHEN_DIALING_VALIDATOR); - VALIDATORS.put(HEARING_AID, HEARING_AID_VALIDATOR); - VALIDATORS.put(TTY_MODE, TTY_MODE_VALIDATOR); - VALIDATORS.put(NOTIFICATION_LIGHT_PULSE, NOTIFICATION_LIGHT_PULSE_VALIDATOR); - VALIDATORS.put(POINTER_LOCATION, POINTER_LOCATION_VALIDATOR); - VALIDATORS.put(SHOW_TOUCHES, SHOW_TOUCHES_VALIDATOR); - VALIDATORS.put(WINDOW_ORIENTATION_LISTENER_LOG, - WINDOW_ORIENTATION_LISTENER_LOG_VALIDATOR); - VALIDATORS.put(LOCKSCREEN_SOUNDS_ENABLED, LOCKSCREEN_SOUNDS_ENABLED_VALIDATOR); - VALIDATORS.put(LOCKSCREEN_DISABLED, LOCKSCREEN_DISABLED_VALIDATOR); - VALIDATORS.put(SIP_RECEIVE_CALLS, SIP_RECEIVE_CALLS_VALIDATOR); - VALIDATORS.put(SIP_CALL_OPTIONS, SIP_CALL_OPTIONS_VALIDATOR); - VALIDATORS.put(SIP_ALWAYS, SIP_ALWAYS_VALIDATOR); - VALIDATORS.put(SIP_ADDRESS_ONLY, SIP_ADDRESS_ONLY_VALIDATOR); - VALIDATORS.put(SIP_ASK_ME_EACH_TIME, SIP_ASK_ME_EACH_TIME_VALIDATOR); - VALIDATORS.put(POINTER_SPEED, POINTER_SPEED_VALIDATOR); - VALIDATORS.put(LOCK_TO_APP_ENABLED, LOCK_TO_APP_ENABLED_VALIDATOR); - VALIDATORS.put(EGG_MODE, EGG_MODE_VALIDATOR); - VALIDATORS.put(WIFI_STATIC_IP, WIFI_STATIC_IP_VALIDATOR); - VALIDATORS.put(WIFI_STATIC_GATEWAY, WIFI_STATIC_GATEWAY_VALIDATOR); - VALIDATORS.put(WIFI_STATIC_NETMASK, WIFI_STATIC_NETMASK_VALIDATOR); - VALIDATORS.put(WIFI_STATIC_DNS1, WIFI_STATIC_DNS1_VALIDATOR); - VALIDATORS.put(WIFI_STATIC_DNS2, WIFI_STATIC_DNS2_VALIDATOR); - VALIDATORS.put(SHOW_BATTERY_PERCENT, SHOW_BATTERY_PERCENT_VALIDATOR); - VALIDATORS.put(NOTIFICATION_LIGHT_PULSE, BOOLEAN_VALIDATOR); - } - - /** * These entries are considered common between the personal and the managed profile, * since the managed profile doesn't get to change them. */ @@ -4859,8 +4397,6 @@ public final class Settings { @Deprecated public static final String BLUETOOTH_ON = Global.BLUETOOTH_ON; - private static final Validator BLUETOOTH_ON_VALIDATOR = BOOLEAN_VALIDATOR; - /** * @deprecated Use {@link android.provider.Settings.Global#DATA_ROAMING} instead */ @@ -4938,8 +4474,6 @@ public final class Settings { @Deprecated public static final String USB_MASS_STORAGE_ENABLED = Global.USB_MASS_STORAGE_ENABLED; - private static final Validator USB_MASS_STORAGE_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR; - /** * @deprecated Use {@link android.provider.Settings.Global#USE_GOOGLE_MAIL} instead */ @@ -4969,9 +4503,6 @@ public final class Settings { public static final String WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON = Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON; - private static final Validator WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON_VALIDATOR = - BOOLEAN_VALIDATOR; - /** * @deprecated Use * {@link android.provider.Settings.Global#WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY} instead @@ -4980,9 +4511,6 @@ public final class Settings { public static final String WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY = Global.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY; - private static final Validator WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY_VALIDATOR = - NON_NEGATIVE_INTEGER_VALIDATOR; - /** * @deprecated Use {@link android.provider.Settings.Global#WIFI_NUM_OPEN_NETWORKS_KEPT} * instead @@ -4990,9 +4518,6 @@ public final class Settings { @Deprecated public static final String WIFI_NUM_OPEN_NETWORKS_KEPT = Global.WIFI_NUM_OPEN_NETWORKS_KEPT; - private static final Validator WIFI_NUM_OPEN_NETWORKS_KEPT_VALIDATOR = - NON_NEGATIVE_INTEGER_VALIDATOR; - /** * @deprecated Use {@link android.provider.Settings.Global#WIFI_ON} instead */ @@ -5757,8 +5282,6 @@ public final class Settings { @Deprecated public static final String BUGREPORT_IN_POWER_MENU = "bugreport_in_power_menu"; - private static final Validator BUGREPORT_IN_POWER_MENU_VALIDATOR = BOOLEAN_VALIDATOR; - /** * @deprecated Use {@link android.provider.Settings.Global#ADB_ENABLED} instead */ @@ -5776,8 +5299,6 @@ public final class Settings { @Deprecated public static final String ALLOW_MOCK_LOCATION = "mock_location"; - private static final Validator ALLOW_MOCK_LOCATION_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Setting to indicate that on device captions are enabled. * @@ -5786,8 +5307,6 @@ public final class Settings { @SystemApi public static final String ODI_CAPTIONS_ENABLED = "odi_captions_enabled"; - private static final Validator ODI_CAPTIONS_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR; - /** * On Android 8.0 (API level 26) and higher versions of the platform, * a 64-bit number (expressed as a hexadecimal string), unique to @@ -5833,8 +5352,6 @@ public final class Settings { @Deprecated public static final String BLUETOOTH_ON = Global.BLUETOOTH_ON; - private static final Validator BLUETOOTH_ON_VALIDATOR = BOOLEAN_VALIDATOR; - /** * @deprecated Use {@link android.provider.Settings.Global#DATA_ROAMING} instead */ @@ -5882,9 +5399,6 @@ public final class Settings { @TestApi public static final String AUTOFILL_SERVICE = "autofill_service"; - private static final Validator AUTOFILL_SERVICE_VALIDATOR = - NULLABLE_COMPONENT_NAME_VALIDATOR; - /** * Boolean indicating if Autofill supports field classification. * @@ -6098,8 +5612,6 @@ public final class Settings { */ public static final String SHOW_IME_WITH_HARD_KEYBOARD = "show_ime_with_hard_keyboard"; - private static final Validator SHOW_IME_WITH_HARD_KEYBOARD_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Host name and port for global http proxy. Uses ':' seperator for * between host and port. @@ -6367,9 +5879,6 @@ public final class Settings { */ public static final String LOCK_SCREEN_CUSTOM_CLOCK_FACE = "lock_screen_custom_clock_face"; - private static final Validator LOCK_SCREEN_CUSTOM_CLOCK_FACE_VALIDATOR = - JSON_OBJECT_VALIDATOR; - /** * Indicates which clock face to show on lock screen and AOD while docked. * @hide @@ -6435,8 +5944,6 @@ public final class Settings { @Deprecated public static final String USB_MASS_STORAGE_ENABLED = Global.USB_MASS_STORAGE_ENABLED; - private static final Validator USB_MASS_STORAGE_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR; - /** * @deprecated Use {@link android.provider.Settings.Global#USE_GOOGLE_MAIL} instead */ @@ -6448,8 +5955,6 @@ public final class Settings { */ public static final String ACCESSIBILITY_ENABLED = "accessibility_enabled"; - private static final Validator ACCESSIBILITY_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Setting specifying if the accessibility shortcut is enabled. * @hide @@ -6457,8 +5962,6 @@ public final class Settings { public static final String ACCESSIBILITY_SHORTCUT_ENABLED = "accessibility_shortcut_enabled"; - private static final Validator ACCESSIBILITY_SHORTCUT_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Setting specifying if the accessibility shortcut is enabled. * @hide @@ -6466,9 +5969,6 @@ public final class Settings { public static final String ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN = "accessibility_shortcut_on_lock_screen"; - private static final Validator ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN_VALIDATOR = - BOOLEAN_VALIDATOR; - /** * Setting specifying if the accessibility shortcut dialog has been shown to this user. * @hide @@ -6476,9 +5976,6 @@ public final class Settings { public static final String ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN = "accessibility_shortcut_dialog_shown"; - private static final Validator ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN_VALIDATOR = - BOOLEAN_VALIDATOR; - /** * Setting specifying the accessibility service to be toggled via the accessibility * shortcut. Must be its flattened {@link ComponentName}. @@ -6488,9 +5985,6 @@ public final class Settings { public static final String ACCESSIBILITY_SHORTCUT_TARGET_SERVICE = "accessibility_shortcut_target_service"; - private static final Validator ACCESSIBILITY_SHORTCUT_TARGET_SERVICE_VALIDATOR = - NULLABLE_COMPONENT_NAME_VALIDATOR; - /** * Setting specifying the accessibility service or feature to be toggled via the * accessibility button in the navigation bar. This is either a flattened @@ -6501,32 +5995,17 @@ public final class Settings { public static final String ACCESSIBILITY_BUTTON_TARGET_COMPONENT = "accessibility_button_target_component"; - private static final Validator ACCESSIBILITY_BUTTON_TARGET_COMPONENT_VALIDATOR = - new Validator() { - @Override - public boolean validate(@Nullable String value) { - // technically either ComponentName or class name, but there's proper value - // validation at callsites, so allow any non-null string - return value != null; - } - }; - /** * If touch exploration is enabled. */ public static final String TOUCH_EXPLORATION_ENABLED = "touch_exploration_enabled"; - private static final Validator TOUCH_EXPLORATION_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR; - /** * List of the enabled accessibility providers. */ public static final String ENABLED_ACCESSIBILITY_SERVICES = "enabled_accessibility_services"; - private static final Validator ENABLED_ACCESSIBILITY_SERVICES_VALIDATOR = - new ComponentNameListValidator(":"); - /** * List of the accessibility services to which the user has granted * permission to put the device into touch exploration mode. @@ -6536,17 +6015,12 @@ public final class Settings { public static final String TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES = "touch_exploration_granted_accessibility_services"; - private static final Validator TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES_VALIDATOR = - new ComponentNameListValidator(":"); - /** * Whether the Global Actions Panel is enabled. * @hide */ public static final String GLOBAL_ACTIONS_PANEL_ENABLED = "global_actions_panel_enabled"; - private static final Validator GLOBAL_ACTIONS_PANEL_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Whether the Global Actions Panel can be toggled on or off in Settings. * @hide @@ -6568,17 +6042,12 @@ public final class Settings { @SystemApi public static final String HUSH_GESTURE_USED = "hush_gesture_used"; - private static final Validator HUSH_GESTURE_USED_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Number of times the user has manually clicked the ringer toggle * @hide */ public static final String MANUAL_RINGER_TOGGLE_COUNT = "manual_ringer_toggle_count"; - private static final Validator MANUAL_RINGER_TOGGLE_COUNT_VALIDATOR = - NON_NEGATIVE_INTEGER_VALIDATOR; - /** * Whether to play a sound for charging events. * @hide @@ -6600,8 +6069,6 @@ public final class Settings { */ public static final String ZEN_DURATION = "zen_duration"; - private static final Validator ZEN_DURATION_VALIDATOR = ANY_INTEGER_VALIDATOR; - /** @hide */ public static final int ZEN_DURATION_PROMPT = -1; /** @hide */ public static final int ZEN_DURATION_FOREVER = 0; @@ -6637,8 +6104,6 @@ public final class Settings { */ public static final String IN_CALL_NOTIFICATION_ENABLED = "in_call_notification_enabled"; - private static final Validator IN_CALL_NOTIFICATION_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Uri of the slice that's presented on the keyguard. * Defaults to a slice with the date and next alarm. @@ -6665,9 +6130,6 @@ public final class Settings { public static final String ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED = "high_text_contrast_enabled"; - private static final Validator ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED_VALIDATOR = - BOOLEAN_VALIDATOR; - /** * Setting that specifies whether the display magnification is enabled via a system-wide * triple tap gesture. Display magnifications allows the user to zoom in the display content @@ -6680,9 +6142,6 @@ public final class Settings { public static final String ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED = "accessibility_display_magnification_enabled"; - private static final Validator ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED_VALIDATOR = - BOOLEAN_VALIDATOR; - /** * Setting that specifies whether the display magnification is enabled via a shortcut * affordance within the system's navigation area. Display magnifications allows the user to @@ -6695,9 +6154,6 @@ public final class Settings { public static final String ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED = "accessibility_display_magnification_navbar_enabled"; - private static final Validator ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED_VALIDATOR - = BOOLEAN_VALIDATOR; - /** * Setting that specifies what the display magnification scale is. * Display magnifications allows the user to zoom in the display @@ -6711,9 +6167,6 @@ public final class Settings { public static final String ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE = "accessibility_display_magnification_scale"; - private static final Validator ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE_VALIDATOR = - new InclusiveFloatRangeValidator(1.0f, Float.MAX_VALUE); - /** * Unused mangnification setting * @@ -6766,9 +6219,6 @@ public final class Settings { public static final String ACCESSIBILITY_CAPTIONING_ENABLED = "accessibility_captioning_enabled"; - private static final Validator ACCESSIBILITY_CAPTIONING_ENABLED_VALIDATOR = - BOOLEAN_VALIDATOR; - /** * Setting that specifies the language for captions as a locale string, * e.g. en_US. @@ -6779,8 +6229,6 @@ public final class Settings { public static final String ACCESSIBILITY_CAPTIONING_LOCALE = "accessibility_captioning_locale"; - private static final Validator ACCESSIBILITY_CAPTIONING_LOCALE_VALIDATOR = LOCALE_VALIDATOR; - /** * Integer property that specifies the preset style for captions, one * of: @@ -6795,10 +6243,6 @@ public final class Settings { public static final String ACCESSIBILITY_CAPTIONING_PRESET = "accessibility_captioning_preset"; - private static final Validator ACCESSIBILITY_CAPTIONING_PRESET_VALIDATOR = - new DiscreteValueValidator(new String[]{"-1", "0", "1", "2", - "3", "4"}); - /** * Integer property that specifes the background color for captions as a * packed 32-bit color. @@ -6809,9 +6253,6 @@ public final class Settings { public static final String ACCESSIBILITY_CAPTIONING_BACKGROUND_COLOR = "accessibility_captioning_background_color"; - private static final Validator ACCESSIBILITY_CAPTIONING_BACKGROUND_COLOR_VALIDATOR = - ANY_INTEGER_VALIDATOR; - /** * Integer property that specifes the foreground color for captions as a * packed 32-bit color. @@ -6822,9 +6263,6 @@ public final class Settings { public static final String ACCESSIBILITY_CAPTIONING_FOREGROUND_COLOR = "accessibility_captioning_foreground_color"; - private static final Validator ACCESSIBILITY_CAPTIONING_FOREGROUND_COLOR_VALIDATOR = - ANY_INTEGER_VALIDATOR; - /** * Integer property that specifes the edge type for captions, one of: * <ul> @@ -6839,9 +6277,6 @@ public final class Settings { public static final String ACCESSIBILITY_CAPTIONING_EDGE_TYPE = "accessibility_captioning_edge_type"; - private static final Validator ACCESSIBILITY_CAPTIONING_EDGE_TYPE_VALIDATOR = - new DiscreteValueValidator(new String[]{"0", "1", "2"}); - /** * Integer property that specifes the edge color for captions as a * packed 32-bit color. @@ -6853,9 +6288,6 @@ public final class Settings { public static final String ACCESSIBILITY_CAPTIONING_EDGE_COLOR = "accessibility_captioning_edge_color"; - private static final Validator ACCESSIBILITY_CAPTIONING_EDGE_COLOR_VALIDATOR = - ANY_INTEGER_VALIDATOR; - /** * Integer property that specifes the window color for captions as a * packed 32-bit color. @@ -6866,9 +6298,6 @@ public final class Settings { public static final String ACCESSIBILITY_CAPTIONING_WINDOW_COLOR = "accessibility_captioning_window_color"; - private static final Validator ACCESSIBILITY_CAPTIONING_WINDOW_COLOR_VALIDATOR = - ANY_INTEGER_VALIDATOR; - /** * String property that specifies the typeface for captions, one of: * <ul> @@ -6885,10 +6314,6 @@ public final class Settings { public static final String ACCESSIBILITY_CAPTIONING_TYPEFACE = "accessibility_captioning_typeface"; - private static final Validator ACCESSIBILITY_CAPTIONING_TYPEFACE_VALIDATOR = - new DiscreteValueValidator(new String[]{"DEFAULT", - "MONOSPACE", "SANS_SERIF", "SERIF"}); - /** * Floating point property that specifies font scaling for captions. * @@ -6897,18 +6322,12 @@ public final class Settings { public static final String ACCESSIBILITY_CAPTIONING_FONT_SCALE = "accessibility_captioning_font_scale"; - private static final Validator ACCESSIBILITY_CAPTIONING_FONT_SCALE_VALIDATOR = - new InclusiveFloatRangeValidator(0.5f, 2.0f); - /** * Setting that specifies whether display color inversion is enabled. */ public static final String ACCESSIBILITY_DISPLAY_INVERSION_ENABLED = "accessibility_display_inversion_enabled"; - private static final Validator ACCESSIBILITY_DISPLAY_INVERSION_ENABLED_VALIDATOR = - BOOLEAN_VALIDATOR; - /** * Setting that specifies whether display color space adjustment is * enabled. @@ -6919,9 +6338,6 @@ public final class Settings { public static final String ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED = "accessibility_display_daltonizer_enabled"; - private static final Validator ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED_VALIDATOR = - BOOLEAN_VALIDATOR; - /** * Integer property that specifies the type of color space adjustment to * perform. Valid values are defined in AccessibilityManager and Settings arrays.xml: @@ -6938,10 +6354,6 @@ public final class Settings { public static final String ACCESSIBILITY_DISPLAY_DALTONIZER = "accessibility_display_daltonizer"; - private static final Validator ACCESSIBILITY_DISPLAY_DALTONIZER_VALIDATOR = - new DiscreteValueValidator( - new String[] {"-1", "0", "11", "12", "13"}); - /** * Setting that specifies whether automatic click when the mouse pointer stops moving is * enabled. @@ -6952,9 +6364,6 @@ public final class Settings { public static final String ACCESSIBILITY_AUTOCLICK_ENABLED = "accessibility_autoclick_enabled"; - private static final Validator ACCESSIBILITY_AUTOCLICK_ENABLED_VALIDATOR = - BOOLEAN_VALIDATOR; - /** * Integer setting specifying amount of time in ms the mouse pointer has to stay still * before performing click when {@link #ACCESSIBILITY_AUTOCLICK_ENABLED} is set. @@ -6965,9 +6374,6 @@ public final class Settings { public static final String ACCESSIBILITY_AUTOCLICK_DELAY = "accessibility_autoclick_delay"; - private static final Validator ACCESSIBILITY_AUTOCLICK_DELAY_VALIDATOR = - NON_NEGATIVE_INTEGER_VALIDATOR; - /** * Whether or not larger size icons are used for the pointer of mouse/trackpad for * accessibility. @@ -6978,9 +6384,6 @@ public final class Settings { public static final String ACCESSIBILITY_LARGE_POINTER_ICON = "accessibility_large_pointer_icon"; - private static final Validator ACCESSIBILITY_LARGE_POINTER_ICON_VALIDATOR = - BOOLEAN_VALIDATOR; - /** * The timeout for considering a press to be a long press in milliseconds. * @hide @@ -6988,9 +6391,6 @@ public final class Settings { @UnsupportedAppUsage public static final String LONG_PRESS_TIMEOUT = "long_press_timeout"; - private static final Validator LONG_PRESS_TIMEOUT_VALIDATOR = - NON_NEGATIVE_INTEGER_VALIDATOR; - /** * The duration in milliseconds between the first tap's up event and the second tap's * down event for an interaction to be considered part of the same multi-press. @@ -7046,8 +6446,6 @@ public final class Settings { */ public static final String DISPLAY_DENSITY_FORCED = "display_density_forced"; - static final Validator DISPLAY_DENSITY_FORCED_VALIDATOR = NON_NEGATIVE_INTEGER_VALIDATOR; - /** * Setting to always use the default text-to-speech settings regardless * of the application settings. @@ -7065,22 +6463,16 @@ public final class Settings { */ public static final String TTS_DEFAULT_RATE = "tts_default_rate"; - private static final Validator TTS_DEFAULT_RATE_VALIDATOR = NON_NEGATIVE_INTEGER_VALIDATOR; - /** * Default text-to-speech engine pitch. 100 = 1x */ public static final String TTS_DEFAULT_PITCH = "tts_default_pitch"; - private static final Validator TTS_DEFAULT_PITCH_VALIDATOR = NON_NEGATIVE_INTEGER_VALIDATOR; - /** * Default text-to-speech engine. */ public static final String TTS_DEFAULT_SYNTH = "tts_default_synth"; - private static final Validator TTS_DEFAULT_SYNTH_VALIDATOR = PACKAGE_NAME_VALIDATOR; - /** * Default text-to-speech language. * @@ -7128,16 +6520,11 @@ public final class Settings { */ public static final String TTS_DEFAULT_LOCALE = "tts_default_locale"; - private static final Validator TTS_DEFAULT_LOCALE_VALIDATOR = TTS_LIST_VALIDATOR; - /** * Space delimited list of plugin packages that are enabled. */ public static final String TTS_ENABLED_PLUGINS = "tts_enabled_plugins"; - private static final Validator TTS_ENABLED_PLUGINS_VALIDATOR = - new PackageNameListValidator(" "); - /** * @deprecated Use {@link android.provider.Settings.Global#WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON} * instead. @@ -7146,9 +6533,6 @@ public final class Settings { public static final String WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON = Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON; - private static final Validator WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON_VALIDATOR = - BOOLEAN_VALIDATOR; - /** * @deprecated Use {@link android.provider.Settings.Global#WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY} * instead. @@ -7157,9 +6541,6 @@ public final class Settings { public static final String WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY = Global.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY; - private static final Validator WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY_VALIDATOR = - NON_NEGATIVE_INTEGER_VALIDATOR; - /** * @deprecated Use {@link android.provider.Settings.Global#WIFI_NUM_OPEN_NETWORKS_KEPT} * instead. @@ -7168,9 +6549,6 @@ public final class Settings { public static final String WIFI_NUM_OPEN_NETWORKS_KEPT = Global.WIFI_NUM_OPEN_NETWORKS_KEPT; - private static final Validator WIFI_NUM_OPEN_NETWORKS_KEPT_VALIDATOR = - NON_NEGATIVE_INTEGER_VALIDATOR; - /** * @deprecated Use {@link android.provider.Settings.Global#WIFI_ON} * instead. @@ -7329,9 +6707,6 @@ public final class Settings { public static final String PREFERRED_TTY_MODE = "preferred_tty_mode"; - private static final Validator PREFERRED_TTY_MODE_VALIDATOR = - new DiscreteValueValidator(new String[]{"0", "1", "2", "3"}); - /** * Whether the enhanced voice privacy mode is enabled. * 0 = normal voice privacy @@ -7340,8 +6715,6 @@ public final class Settings { */ public static final String ENHANCED_VOICE_PRIVACY_ENABLED = "enhanced_voice_privacy_enabled"; - private static final Validator ENHANCED_VOICE_PRIVACY_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Whether the TTY mode mode is enabled. * 0 = disabled @@ -7350,8 +6723,6 @@ public final class Settings { */ public static final String TTY_MODE_ENABLED = "tty_mode_enabled"; - private static final Validator TTY_MODE_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR; - /** * User-selected RTT mode. When on, outgoing and incoming calls will be answered as RTT * calls when supported by the device and carrier. Boolean value. @@ -7360,8 +6731,6 @@ public final class Settings { */ public static final String RTT_CALLING_MODE = "rtt_calling_mode"; - private static final Validator RTT_CALLING_MODE_VALIDATOR = BOOLEAN_VALIDATOR; - /** /** * Controls whether settings backup is enabled. @@ -7539,32 +6908,24 @@ public final class Settings { */ public static final String MOUNT_PLAY_NOTIFICATION_SND = "mount_play_not_snd"; - private static final Validator MOUNT_PLAY_NOTIFICATION_SND_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Whether or not UMS auto-starts on UMS host detection. (0 = false, 1 = true) * @hide */ public static final String MOUNT_UMS_AUTOSTART = "mount_ums_autostart"; - private static final Validator MOUNT_UMS_AUTOSTART_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Whether or not a notification is displayed on UMS host detection. (0 = false, 1 = true) * @hide */ public static final String MOUNT_UMS_PROMPT = "mount_ums_prompt"; - private static final Validator MOUNT_UMS_PROMPT_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Whether or not a notification is displayed while UMS is enabled. (0 = false, 1 = true) * @hide */ public static final String MOUNT_UMS_NOTIFY_ENABLED = "mount_ums_notify_enabled"; - private static final Validator MOUNT_UMS_NOTIFY_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR; - /** * If nonzero, ANRs in invisible background processes bring up a dialog. * Otherwise, the process will be silently killed. @@ -7583,9 +6944,6 @@ public final class Settings { public static final String SHOW_FIRST_CRASH_DIALOG_DEV_OPTION = "show_first_crash_dialog_dev_option"; - private static final Validator SHOW_FIRST_CRASH_DIALOG_DEV_OPTION_VALIDATOR = - BOOLEAN_VALIDATOR; - /** * The {@link ComponentName} string of the service to be used as the voice recognition * service. @@ -7644,9 +7002,6 @@ public final class Settings { @UnsupportedAppUsage public static final String INCALL_POWER_BUTTON_BEHAVIOR = "incall_power_button_behavior"; - private static final Validator INCALL_POWER_BUTTON_BEHAVIOR_VALIDATOR = - new DiscreteValueValidator(new String[]{"1", "2"}); - /** * INCALL_POWER_BUTTON_BEHAVIOR value for "turn off screen". * @hide @@ -7702,8 +7057,6 @@ public final class Settings { */ public static final String WAKE_GESTURE_ENABLED = "wake_gesture_enabled"; - private static final Validator WAKE_GESTURE_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Whether the device should doze if configured. * @hide @@ -7711,8 +7064,6 @@ public final class Settings { @UnsupportedAppUsage public static final String DOZE_ENABLED = "doze_enabled"; - private static final Validator DOZE_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Indicates whether doze should be always on. * <p> @@ -7724,16 +7075,12 @@ public final class Settings { @TestApi public static final String DOZE_ALWAYS_ON = "doze_always_on"; - private static final Validator DOZE_ALWAYS_ON_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Whether the device should pulse on pick up gesture. * @hide */ public static final String DOZE_PICK_UP_GESTURE = "doze_pulse_on_pick_up"; - private static final Validator DOZE_PICK_UP_GESTURE_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Whether the device should pulse on long press gesture. * @hide @@ -7746,24 +7093,18 @@ public final class Settings { */ public static final String DOZE_DOUBLE_TAP_GESTURE = "doze_pulse_on_double_tap"; - private static final Validator DOZE_DOUBLE_TAP_GESTURE_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Whether the device should respond to the SLPI tap gesture. * @hide */ public static final String DOZE_TAP_SCREEN_GESTURE = "doze_tap_gesture"; - private static final Validator DOZE_TAP_SCREEN_GESTURE_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Gesture that wakes up the display, showing some version of the lock screen. * @hide */ public static final String DOZE_WAKE_LOCK_SCREEN_GESTURE = "doze_wake_screen_gesture"; - private static final Validator DOZE_WAKE_LOCK_SCREEN_GESTURE_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Gesture that wakes up the display, toggling between {@link Display.STATE_OFF} and * {@link Display.STATE_DOZE}. @@ -7771,16 +7112,12 @@ public final class Settings { */ public static final String DOZE_WAKE_DISPLAY_GESTURE = "doze_wake_display_gesture"; - private static final Validator DOZE_WAKE_DISPLAY_GESTURE_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Gesture that skips media. * @hide */ public static final String SKIP_GESTURE = "skip_gesture"; - private static final Validator SKIP_GESTURE_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Count of successful gestures. * @hide @@ -7793,9 +7130,6 @@ public final class Settings { */ public static final String SKIP_TOUCH_COUNT = "skip_touch_count"; - private static final Validator SKIP_GESTURE_COUNT_VALIDATOR = - NON_NEGATIVE_INTEGER_VALIDATOR; - /** * Direction to advance media for skip gesture * @hide @@ -7803,21 +7137,11 @@ public final class Settings { public static final String SKIP_DIRECTION = "skip_gesture_direction"; /** - * Only used if FeatureFlag "settings_skip_direction_mutable" is enabled. - * If feature flag is disabled, should assume SKIP_DIRECTION = 0. - * 0 / false = right to left to advance to next - * 1 / true = left to right to advance to next - */ - private static final Validator SKIP_DIRECTION_VALIDATOR = BOOLEAN_VALIDATOR; - - /** * Gesture that silences sound (alarms, notification, calls). * @hide */ public static final String SILENCE_GESTURE = "silence_gesture"; - private static final Validator SILENCE_GESTURE_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Count of successful silence alarms gestures. * @hide @@ -7854,9 +7178,6 @@ public final class Settings { */ public static final String SILENCE_CALL_TOUCH_COUNT = "silence_call_touch_count"; - private static final Validator SILENCE_GESTURE_COUNT_VALIDATOR = - NON_NEGATIVE_INTEGER_VALIDATOR; - /** * The current night mode that has been selected by the user. Owned * and controlled by UiModeManagerService. Constants are as per @@ -7865,17 +7186,12 @@ public final class Settings { */ public static final String UI_NIGHT_MODE = "ui_night_mode"; - private static final Validator UI_NIGHT_MODE_VALIDATOR = - new InclusiveIntegerRangeValidator(0, 2); - /** * Whether screensavers are enabled. * @hide */ public static final String SCREENSAVER_ENABLED = "screensaver_enabled"; - private static final Validator SCREENSAVER_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR; - /** * The user's chosen screensaver components. * @@ -7885,9 +7201,6 @@ public final class Settings { */ public static final String SCREENSAVER_COMPONENTS = "screensaver_components"; - private static final Validator SCREENSAVER_COMPONENTS_VALIDATOR = - new ComponentNameListValidator(","); - /** * If screensavers are enabled, whether the screensaver should be automatically launched * when the device is inserted into a (desk) dock. @@ -7895,8 +7208,6 @@ public final class Settings { */ public static final String SCREENSAVER_ACTIVATE_ON_DOCK = "screensaver_activate_on_dock"; - private static final Validator SCREENSAVER_ACTIVATE_ON_DOCK_VALIDATOR = BOOLEAN_VALIDATOR; - /** * If screensavers are enabled, whether the screensaver should be automatically launched * when the screen times out when not on battery. @@ -7904,8 +7215,6 @@ public final class Settings { */ public static final String SCREENSAVER_ACTIVATE_ON_SLEEP = "screensaver_activate_on_sleep"; - private static final Validator SCREENSAVER_ACTIVATE_ON_SLEEP_VALIDATOR = BOOLEAN_VALIDATOR; - /** * If screensavers are enabled, the default screensaver component. * @hide @@ -7919,9 +7228,6 @@ public final class Settings { @UnsupportedAppUsage public static final String NFC_PAYMENT_DEFAULT_COMPONENT = "nfc_payment_default_component"; - private static final Validator NFC_PAYMENT_DEFAULT_COMPONENT_VALIDATOR = - COMPONENT_NAME_VALIDATOR; - /** * Whether NFC payment is handled by the foreground application or a default. * @hide @@ -8037,9 +7343,6 @@ public final class Settings { public static final String ENABLED_NOTIFICATION_ASSISTANT = "enabled_notification_assistant"; - private static final Validator ENABLED_NOTIFICATION_ASSISTANT_VALIDATOR = - new ComponentNameListValidator(":"); - /** * Read only list of the service components that the current user has explicitly allowed to * see all of the user's notifications, separated by ':'. @@ -8052,9 +7355,6 @@ public final class Settings { @UnsupportedAppUsage public static final String ENABLED_NOTIFICATION_LISTENERS = "enabled_notification_listeners"; - private static final Validator ENABLED_NOTIFICATION_LISTENERS_VALIDATOR = - new ComponentNameListValidator(":"); - /** * Read only list of the packages that the current user has explicitly allowed to * manage do not disturb, separated by ':'. @@ -8067,9 +7367,6 @@ public final class Settings { public static final String ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES = "enabled_notification_policy_access_packages"; - private static final Validator ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES_VALIDATOR = - new PackageNameListValidator(":"); - /** * Defines whether managed profile ringtones should be synced from it's parent profile * <p> @@ -8083,8 +7380,6 @@ public final class Settings { @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS) public static final String SYNC_PARENT_SOUNDS = "sync_parent_sounds"; - private static final Validator SYNC_PARENT_SOUNDS_VALIDATOR = BOOLEAN_VALIDATOR; - /** @hide */ @UnsupportedAppUsage public static final String IMMERSIVE_MODE_CONFIRMATIONS = "immersive_mode_confirmations"; @@ -8218,8 +7513,6 @@ public final class Settings { */ public static final String DOUBLE_TAP_TO_WAKE = "double_tap_to_wake"; - private static final Validator DOUBLE_TAP_TO_WAKE_VALIDATOR = BOOLEAN_VALIDATOR; - /** * The current assistant component. It could be a voice interaction service, * or an activity that handles ACTION_ASSIST, or empty which means using the default @@ -8240,8 +7533,6 @@ public final class Settings { */ public static final String CAMERA_GESTURE_DISABLED = "camera_gesture_disabled"; - private static final Validator CAMERA_GESTURE_DISABLED_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Whether the camera launch gesture to double tap the power button when the screen is off * should be disabled. @@ -8251,9 +7542,6 @@ public final class Settings { public static final String CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED = "camera_double_tap_power_gesture_disabled"; - private static final Validator CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED_VALIDATOR = - BOOLEAN_VALIDATOR; - /** * Whether the camera double twist gesture to flip between front and back mode should be * enabled. @@ -8263,9 +7551,6 @@ public final class Settings { public static final String CAMERA_DOUBLE_TWIST_TO_FLIP_ENABLED = "camera_double_twist_to_flip_enabled"; - private static final Validator CAMERA_DOUBLE_TWIST_TO_FLIP_ENABLED_VALIDATOR = - BOOLEAN_VALIDATOR; - /** * Whether or not the smart camera lift trigger that launches the camera when the user moves * the phone into a position for taking photos should be enabled. @@ -8302,9 +7587,6 @@ public final class Settings { */ public static final String FACE_UNLOCK_KEYGUARD_ENABLED = "face_unlock_keyguard_enabled"; - private static final Validator FACE_UNLOCK_KEYGUARD_ENABLED_VALIDATOR = - BOOLEAN_VALIDATOR; - /** * Whether or not face unlock dismisses the keyguard. * @hide @@ -8312,9 +7594,6 @@ public final class Settings { public static final String FACE_UNLOCK_DISMISSES_KEYGUARD = "face_unlock_dismisses_keyguard"; - private static final Validator FACE_UNLOCK_DISMISSES_KEYGUARD_VALIDATOR = - BOOLEAN_VALIDATOR; - /** * Whether or not media is shown automatically when bypassing as a heads up. * @hide @@ -8322,9 +7601,6 @@ public final class Settings { public static final String SHOW_MEDIA_WHEN_BYPASSING = "show_media_when_bypassing"; - private static final Validator SHOW_MEDIA_WHEN_BYPASSING_VALIDATOR = - BOOLEAN_VALIDATOR; - /** * Whether or not face unlock requires attention. This is a cached value, the source of * truth is obtained through the HAL. @@ -8348,9 +7624,6 @@ public final class Settings { */ public static final String FACE_UNLOCK_APP_ENABLED = "face_unlock_app_enabled"; - private static final Validator FACE_UNLOCK_APP_ENABLED_VALIDATOR = - BOOLEAN_VALIDATOR; - /** * Whether or not face unlock always requires user confirmation, meaning {@link * android.hardware.biometrics.BiometricPrompt.Builder#setConfirmationRequired(boolean)} @@ -8361,9 +7634,6 @@ public final class Settings { public static final String FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION = "face_unlock_always_require_confirmation"; - private static final Validator FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION_VALIDATOR = - BOOLEAN_VALIDATOR; - /** * Whether or not debugging is enabled. * @hide @@ -8378,9 +7648,6 @@ public final class Settings { */ public static final String ASSIST_GESTURE_ENABLED = "assist_gesture_enabled"; - private static final Validator ASSIST_GESTURE_ENABLED_VALIDATOR = - BOOLEAN_VALIDATOR; - /** * Sensitivity control for the assist gesture. * @@ -8396,9 +7663,6 @@ public final class Settings { public static final String ASSIST_GESTURE_SILENCE_ALERTS_ENABLED = "assist_gesture_silence_alerts_enabled"; - private static final Validator ASSIST_GESTURE_SILENCE_ALERTS_ENABLED_VALIDATOR = - BOOLEAN_VALIDATOR; - /** * Whether the assist gesture should wake the phone. * @@ -8407,9 +7671,6 @@ public final class Settings { public static final String ASSIST_GESTURE_WAKE_ENABLED = "assist_gesture_wake_enabled"; - private static final Validator ASSIST_GESTURE_WAKE_ENABLED_VALIDATOR = - BOOLEAN_VALIDATOR; - /** * Indicates whether the Assist Gesture Deferred Setup has been completed. * <p> @@ -8426,18 +7687,12 @@ public final class Settings { */ public static final String TRUST_AGENTS_EXTEND_UNLOCK = "trust_agents_extend_unlock"; - private static final Validator TRUST_AGENTS_EXTEND_UNLOCK_VALIDATOR = - BOOLEAN_VALIDATOR; - /** * Control whether the screen locks when trust is lost. * @hide */ public static final String LOCK_SCREEN_WHEN_TRUST_LOST = "lock_screen_when_trust_lost"; - private static final Validator LOCK_SCREEN_WHEN_TRUST_LOST_VALIDATOR = - BOOLEAN_VALIDATOR; - /** * Control whether Night display is currently activated. * @hide @@ -8450,9 +7705,6 @@ public final class Settings { */ public static final String NIGHT_DISPLAY_AUTO_MODE = "night_display_auto_mode"; - private static final Validator NIGHT_DISPLAY_AUTO_MODE_VALIDATOR = - new InclusiveIntegerRangeValidator(0, 2); - /** * Control the color temperature of Night Display, represented in Kelvin. * @hide @@ -8460,9 +7712,6 @@ public final class Settings { public static final String NIGHT_DISPLAY_COLOR_TEMPERATURE = "night_display_color_temperature"; - private static final Validator NIGHT_DISPLAY_COLOR_TEMPERATURE_VALIDATOR = - NON_NEGATIVE_INTEGER_VALIDATOR; - /** * Custom time when Night display is scheduled to activate. * Represented as milliseconds from midnight (e.g. 79200000 == 10pm). @@ -8471,9 +7720,6 @@ public final class Settings { public static final String NIGHT_DISPLAY_CUSTOM_START_TIME = "night_display_custom_start_time"; - private static final Validator NIGHT_DISPLAY_CUSTOM_START_TIME_VALIDATOR = - NON_NEGATIVE_INTEGER_VALIDATOR; - /** * Custom time when Night display is scheduled to deactivate. * Represented as milliseconds from midnight (e.g. 21600000 == 6am). @@ -8481,9 +7727,6 @@ public final class Settings { */ public static final String NIGHT_DISPLAY_CUSTOM_END_TIME = "night_display_custom_end_time"; - private static final Validator NIGHT_DISPLAY_CUSTOM_END_TIME_VALIDATOR = - NON_NEGATIVE_INTEGER_VALIDATOR; - /** * A String representing the LocalDateTime when Night display was last activated. Use to * decide whether to apply the current activated state after a reboot or user change. In @@ -8499,9 +7742,6 @@ public final class Settings { */ public static final String DISPLAY_WHITE_BALANCE_ENABLED = "display_white_balance_enabled"; - private static final Validator DISPLAY_WHITE_BALANCE_ENABLED_VALIDATOR = - BOOLEAN_VALIDATOR; - /** * Names of the service components that the current user has explicitly allowed to * be a VR mode listener, separated by ':'. @@ -8511,9 +7751,6 @@ public final class Settings { @TestApi public static final String ENABLED_VR_LISTENERS = "enabled_vr_listeners"; - private static final Validator ENABLED_VR_LISTENERS_VALIDATOR = - new ComponentNameListValidator(":"); - /** * Behavior of the display while in VR mode. * @@ -8523,9 +7760,6 @@ public final class Settings { */ public static final String VR_DISPLAY_MODE = "vr_display_mode"; - private static final Validator VR_DISPLAY_MODE_VALIDATOR = - new DiscreteValueValidator(new String[]{"0", "1"}); - /** * Lower the display persistence while the system is in VR mode. * @@ -8590,9 +7824,6 @@ public final class Settings { public static final String AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN = "automatic_storage_manager_days_to_retain"; - private static final Validator AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN_VALIDATOR = - NON_NEGATIVE_INTEGER_VALIDATOR; - /** * Default number of days of information for the automatic storage manager to retain. * @@ -8608,7 +7839,6 @@ public final class Settings { public static final String AUTOMATIC_STORAGE_MANAGER_BYTES_CLEARED = "automatic_storage_manager_bytes_cleared"; - /** * Last run time for the automatic storage manager. * @@ -8616,7 +7846,6 @@ public final class Settings { */ public static final String AUTOMATIC_STORAGE_MANAGER_LAST_RUN = "automatic_storage_manager_last_run"; - /** * If the automatic storage manager has been disabled by policy. Note that this doesn't * mean that the automatic storage manager is prevented from being re-enabled -- this only @@ -8634,8 +7863,6 @@ public final class Settings { public static final String SYSTEM_NAVIGATION_KEYS_ENABLED = "system_navigation_keys_enabled"; - private static final Validator SYSTEM_NAVIGATION_KEYS_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Holds comma separated list of ordering of QS tiles. * @@ -8643,8 +7870,6 @@ public final class Settings { */ public static final String QS_TILES = "sysui_qs_tiles"; - private static final Validator QS_TILES_VALIDATOR = TILE_LIST_VALIDATOR; - /** * Specifies whether the web action API is enabled. * @@ -8681,8 +7906,6 @@ public final class Settings { @TestApi public static final String NOTIFICATION_BADGING = "notification_badging"; - private static final Validator NOTIFICATION_BADGING_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Whether the notification bubbles are globally enabled * The value is boolean (1 or 0). @@ -8691,8 +7914,6 @@ public final class Settings { @TestApi public static final String NOTIFICATION_BUBBLES = "notification_bubbles"; - private static final Validator NOTIFICATION_BUBBLES_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Whether notifications are dismissed by a right-to-left swipe (instead of a left-to-right * swipe). @@ -8701,24 +7922,18 @@ public final class Settings { */ public static final String NOTIFICATION_DISMISS_RTL = "notification_dismiss_rtl"; - private static final Validator NOTIFICATION_DISMISS_RTL_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Comma separated list of QS tiles that have been auto-added already. * @hide */ public static final String QS_AUTO_ADDED_TILES = "qs_auto_tiles"; - private static final Validator QS_AUTO_ADDED_TILES_VALIDATOR = TILE_LIST_VALIDATOR; - /** * Whether the Lockdown button should be shown in the power menu. * @hide */ public static final String LOCKDOWN_IN_POWER_MENU = "lockdown_in_power_menu"; - private static final Validator LOCKDOWN_IN_POWER_MENU_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Backup manager behavioral parameters. * This is encoded as a key=value list, separated by commas. Ex: @@ -8790,9 +8005,6 @@ public final class Settings { @SystemApi public static final int VOLUME_HUSH_MUTE = 2; - private static final Validator VOLUME_HUSH_GESTURE_VALIDATOR = - NON_NEGATIVE_INTEGER_VALIDATOR; - /** * The number of times (integer) the user has manually enabled battery saver. * @hide @@ -8869,9 +8081,6 @@ public final class Settings { public static final String THEME_CUSTOMIZATION_OVERLAY_PACKAGES = "theme_customization_overlay_packages"; - private static final Validator THEME_CUSTOMIZATION_OVERLAY_PACKAGES_VALIDATOR = - JSON_OBJECT_VALIDATOR; - /** * Navigation bar mode. * 0 = 3 button @@ -8881,8 +8090,6 @@ public final class Settings { */ public static final String NAVIGATION_MODE = "navigation_mode"; - private static final Validator NAVIGATION_MODE_VALIDATOR = - new DiscreteValueValidator(new String[] {"0", "1", "2"}); /** * Controls whether aware is enabled. @@ -8890,162 +8097,12 @@ public final class Settings { */ public static final String AWARE_ENABLED = "aware_enabled"; - private static final Validator AWARE_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Controls whether aware_lock is enabled. * @hide */ public static final String AWARE_LOCK_ENABLED = "aware_lock_enabled"; - private static final Validator AWARE_LOCK_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR; - - /** - * This are the settings to be backed up. - * - * NOTE: Settings are backed up and restored in the order they appear - * in this array. If you have one setting depending on another, - * make sure that they are ordered appropriately. - * - * @hide - */ - @UnsupportedAppUsage - public static final String[] SETTINGS_TO_BACKUP = { - BUGREPORT_IN_POWER_MENU, // moved to global - ALLOW_MOCK_LOCATION, - USB_MASS_STORAGE_ENABLED, // moved to global - ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, - ACCESSIBILITY_DISPLAY_DALTONIZER, - ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, - ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, - ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED, - AUTOFILL_SERVICE, - ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, - ENABLED_ACCESSIBILITY_SERVICES, - ENABLED_VR_LISTENERS, - TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES, - TOUCH_EXPLORATION_ENABLED, - ACCESSIBILITY_ENABLED, - ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, - ACCESSIBILITY_BUTTON_TARGET_COMPONENT, - ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, - ACCESSIBILITY_SHORTCUT_ENABLED, - ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN, - ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED, - ACCESSIBILITY_CAPTIONING_PRESET, - ACCESSIBILITY_CAPTIONING_ENABLED, - ACCESSIBILITY_CAPTIONING_LOCALE, - ACCESSIBILITY_CAPTIONING_BACKGROUND_COLOR, - ACCESSIBILITY_CAPTIONING_FOREGROUND_COLOR, - ACCESSIBILITY_CAPTIONING_EDGE_TYPE, - ACCESSIBILITY_CAPTIONING_EDGE_COLOR, - ACCESSIBILITY_CAPTIONING_TYPEFACE, - ACCESSIBILITY_CAPTIONING_FONT_SCALE, - ACCESSIBILITY_CAPTIONING_WINDOW_COLOR, - TTS_DEFAULT_RATE, - TTS_DEFAULT_PITCH, - TTS_DEFAULT_SYNTH, - TTS_ENABLED_PLUGINS, - TTS_DEFAULT_LOCALE, - SHOW_IME_WITH_HARD_KEYBOARD, - WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, // moved to global - WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY, // moved to global - WIFI_NUM_OPEN_NETWORKS_KEPT, // moved to global - MOUNT_PLAY_NOTIFICATION_SND, - MOUNT_UMS_AUTOSTART, - MOUNT_UMS_PROMPT, - MOUNT_UMS_NOTIFY_ENABLED, - DOUBLE_TAP_TO_WAKE, - WAKE_GESTURE_ENABLED, - LONG_PRESS_TIMEOUT, - CAMERA_GESTURE_DISABLED, - ACCESSIBILITY_AUTOCLICK_ENABLED, - ACCESSIBILITY_AUTOCLICK_DELAY, - ACCESSIBILITY_LARGE_POINTER_ICON, - PREFERRED_TTY_MODE, - ENHANCED_VOICE_PRIVACY_ENABLED, - TTY_MODE_ENABLED, - RTT_CALLING_MODE, - INCALL_POWER_BUTTON_BEHAVIOR, - NIGHT_DISPLAY_CUSTOM_START_TIME, - NIGHT_DISPLAY_CUSTOM_END_TIME, - NIGHT_DISPLAY_COLOR_TEMPERATURE, - NIGHT_DISPLAY_AUTO_MODE, - DISPLAY_WHITE_BALANCE_ENABLED, - SYNC_PARENT_SOUNDS, - CAMERA_DOUBLE_TWIST_TO_FLIP_ENABLED, - CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, - SYSTEM_NAVIGATION_KEYS_ENABLED, - QS_TILES, - DOZE_ENABLED, - DOZE_ALWAYS_ON, - DOZE_PICK_UP_GESTURE, - DOZE_DOUBLE_TAP_GESTURE, - DOZE_TAP_SCREEN_GESTURE, - DOZE_WAKE_LOCK_SCREEN_GESTURE, - DOZE_WAKE_DISPLAY_GESTURE, - NFC_PAYMENT_DEFAULT_COMPONENT, - AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN, - FACE_UNLOCK_KEYGUARD_ENABLED, - SHOW_MEDIA_WHEN_BYPASSING, - FACE_UNLOCK_DISMISSES_KEYGUARD, - FACE_UNLOCK_APP_ENABLED, - FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION, - ASSIST_GESTURE_ENABLED, - ASSIST_GESTURE_SILENCE_ALERTS_ENABLED, - ASSIST_GESTURE_WAKE_ENABLED, - VR_DISPLAY_MODE, - NOTIFICATION_BADGING, - NOTIFICATION_BUBBLES, - NOTIFICATION_DISMISS_RTL, - QS_AUTO_ADDED_TILES, - SCREENSAVER_ENABLED, - SCREENSAVER_COMPONENTS, - SCREENSAVER_ACTIVATE_ON_DOCK, - SCREENSAVER_ACTIVATE_ON_SLEEP, - LOCKDOWN_IN_POWER_MENU, - SHOW_FIRST_CRASH_DIALOG_DEV_OPTION, - VOLUME_HUSH_GESTURE, - MANUAL_RINGER_TOGGLE_COUNT, - HUSH_GESTURE_USED, - IN_CALL_NOTIFICATION_ENABLED, - LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, - LOCK_SCREEN_CUSTOM_CLOCK_FACE, - LOCK_SCREEN_SHOW_NOTIFICATIONS, - LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, - SHOW_NOTIFICATION_SNOOZE, - ZEN_DURATION, - SHOW_ZEN_UPGRADE_NOTIFICATION, - SHOW_ZEN_SETTINGS_SUGGESTION, - ZEN_SETTINGS_UPDATED, - ZEN_SETTINGS_SUGGESTION_VIEWED, - CHARGING_SOUNDS_ENABLED, - CHARGING_VIBRATION_ENABLED, - ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS, - ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS, - NOTIFICATION_NEW_INTERRUPTION_MODEL, - TRUST_AGENTS_EXTEND_UNLOCK, - UI_NIGHT_MODE, - LOCK_SCREEN_WHEN_TRUST_LOST, - SKIP_GESTURE, - SKIP_DIRECTION, - SILENCE_GESTURE, - THEME_CUSTOMIZATION_OVERLAY_PACKAGES, - NAVIGATION_MODE, - AWARE_ENABLED, - SKIP_GESTURE_COUNT, - SKIP_TOUCH_COUNT, - SILENCE_ALARMS_GESTURE_COUNT, - SILENCE_CALL_GESTURE_COUNT, - SILENCE_TIMER_GESTURE_COUNT, - SILENCE_ALARMS_TOUCH_COUNT, - SILENCE_CALL_TOUCH_COUNT, - SILENCE_TIMER_TOUCH_COUNT, - DARK_MODE_DIALOG_SEEN, - GLOBAL_ACTIONS_PANEL_ENABLED, - AWARE_LOCK_ENABLED - }; - /** * The settings values which should only be restored if the target device is the * same as the source device @@ -9061,201 +8118,6 @@ public final class Settings { }; /** - * All settings in {@link SETTINGS_TO_BACKUP} and {@link DEVICE_SPECIFIC_SETTINGS_TO_BACKUP} - * array *must* have a non-null validator, otherwise they won't be restored. - * - * @hide - */ - public static final Map<String, Validator> VALIDATORS = new ArrayMap<>(); - static { - VALIDATORS.put(BUGREPORT_IN_POWER_MENU, BUGREPORT_IN_POWER_MENU_VALIDATOR); - VALIDATORS.put(ALLOW_MOCK_LOCATION, ALLOW_MOCK_LOCATION_VALIDATOR); - VALIDATORS.put(USB_MASS_STORAGE_ENABLED, USB_MASS_STORAGE_ENABLED_VALIDATOR); - VALIDATORS.put(ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, - ACCESSIBILITY_DISPLAY_INVERSION_ENABLED_VALIDATOR); - VALIDATORS.put(ACCESSIBILITY_DISPLAY_DALTONIZER, - ACCESSIBILITY_DISPLAY_DALTONIZER_VALIDATOR); - VALIDATORS.put(ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, - ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED_VALIDATOR); - VALIDATORS.put(ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, - ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED_VALIDATOR); - VALIDATORS.put(ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED, - ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED_VALIDATOR); - VALIDATORS.put(AUTOFILL_SERVICE, AUTOFILL_SERVICE_VALIDATOR); - VALIDATORS.put(ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, - ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE_VALIDATOR); - VALIDATORS.put(ENABLED_ACCESSIBILITY_SERVICES, - ENABLED_ACCESSIBILITY_SERVICES_VALIDATOR); - VALIDATORS.put(ENABLED_VR_LISTENERS, ENABLED_VR_LISTENERS_VALIDATOR); - VALIDATORS.put(TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES, - TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES_VALIDATOR); - VALIDATORS.put(TOUCH_EXPLORATION_ENABLED, TOUCH_EXPLORATION_ENABLED_VALIDATOR); - VALIDATORS.put(ACCESSIBILITY_ENABLED, ACCESSIBILITY_ENABLED_VALIDATOR); - VALIDATORS.put(ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, - ACCESSIBILITY_SHORTCUT_TARGET_SERVICE_VALIDATOR); - VALIDATORS.put(ACCESSIBILITY_BUTTON_TARGET_COMPONENT, - ACCESSIBILITY_BUTTON_TARGET_COMPONENT_VALIDATOR); - VALIDATORS.put(ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, - ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN_VALIDATOR); - VALIDATORS.put(ACCESSIBILITY_SHORTCUT_ENABLED, - ACCESSIBILITY_SHORTCUT_ENABLED_VALIDATOR); - VALIDATORS.put(ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN, - ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN_VALIDATOR); - VALIDATORS.put(ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED, - ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED_VALIDATOR); - VALIDATORS.put(ACCESSIBILITY_CAPTIONING_PRESET, - ACCESSIBILITY_CAPTIONING_PRESET_VALIDATOR); - VALIDATORS.put(ACCESSIBILITY_CAPTIONING_ENABLED, - ACCESSIBILITY_CAPTIONING_ENABLED_VALIDATOR); - VALIDATORS.put(ACCESSIBILITY_CAPTIONING_LOCALE, - ACCESSIBILITY_CAPTIONING_LOCALE_VALIDATOR); - VALIDATORS.put(ACCESSIBILITY_CAPTIONING_BACKGROUND_COLOR, - ACCESSIBILITY_CAPTIONING_BACKGROUND_COLOR_VALIDATOR); - VALIDATORS.put(ACCESSIBILITY_CAPTIONING_FOREGROUND_COLOR, - ACCESSIBILITY_CAPTIONING_FOREGROUND_COLOR_VALIDATOR); - VALIDATORS.put(ACCESSIBILITY_CAPTIONING_EDGE_TYPE, - ACCESSIBILITY_CAPTIONING_EDGE_TYPE_VALIDATOR); - VALIDATORS.put(ACCESSIBILITY_CAPTIONING_EDGE_COLOR, - ACCESSIBILITY_CAPTIONING_EDGE_COLOR_VALIDATOR); - VALIDATORS.put(ACCESSIBILITY_CAPTIONING_TYPEFACE, - ACCESSIBILITY_CAPTIONING_TYPEFACE_VALIDATOR); - VALIDATORS.put(ACCESSIBILITY_CAPTIONING_FONT_SCALE, - ACCESSIBILITY_CAPTIONING_FONT_SCALE_VALIDATOR); - VALIDATORS.put(ACCESSIBILITY_CAPTIONING_WINDOW_COLOR, - ACCESSIBILITY_CAPTIONING_WINDOW_COLOR_VALIDATOR); - VALIDATORS.put(TTS_DEFAULT_RATE, TTS_DEFAULT_RATE_VALIDATOR); - VALIDATORS.put(TTS_DEFAULT_PITCH, TTS_DEFAULT_PITCH_VALIDATOR); - VALIDATORS.put(TTS_DEFAULT_SYNTH, TTS_DEFAULT_SYNTH_VALIDATOR); - VALIDATORS.put(TTS_ENABLED_PLUGINS, TTS_ENABLED_PLUGINS_VALIDATOR); - VALIDATORS.put(TTS_DEFAULT_LOCALE, TTS_DEFAULT_LOCALE_VALIDATOR); - VALIDATORS.put(SHOW_IME_WITH_HARD_KEYBOARD, SHOW_IME_WITH_HARD_KEYBOARD_VALIDATOR); - VALIDATORS.put(WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, - WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON_VALIDATOR); - VALIDATORS.put(WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY, - WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY_VALIDATOR); - VALIDATORS.put(WIFI_NUM_OPEN_NETWORKS_KEPT, WIFI_NUM_OPEN_NETWORKS_KEPT_VALIDATOR); - VALIDATORS.put(MOUNT_PLAY_NOTIFICATION_SND, MOUNT_PLAY_NOTIFICATION_SND_VALIDATOR); - VALIDATORS.put(MOUNT_UMS_AUTOSTART, MOUNT_UMS_AUTOSTART_VALIDATOR); - VALIDATORS.put(MOUNT_UMS_PROMPT, MOUNT_UMS_PROMPT_VALIDATOR); - VALIDATORS.put(MOUNT_UMS_NOTIFY_ENABLED, MOUNT_UMS_NOTIFY_ENABLED_VALIDATOR); - VALIDATORS.put(DOUBLE_TAP_TO_WAKE, DOUBLE_TAP_TO_WAKE_VALIDATOR); - VALIDATORS.put(WAKE_GESTURE_ENABLED, WAKE_GESTURE_ENABLED_VALIDATOR); - VALIDATORS.put(LONG_PRESS_TIMEOUT, LONG_PRESS_TIMEOUT_VALIDATOR); - VALIDATORS.put(CAMERA_GESTURE_DISABLED, CAMERA_GESTURE_DISABLED_VALIDATOR); - VALIDATORS.put(ACCESSIBILITY_AUTOCLICK_ENABLED, - ACCESSIBILITY_AUTOCLICK_ENABLED_VALIDATOR); - VALIDATORS.put(ACCESSIBILITY_AUTOCLICK_DELAY, ACCESSIBILITY_AUTOCLICK_DELAY_VALIDATOR); - VALIDATORS.put(ACCESSIBILITY_LARGE_POINTER_ICON, - ACCESSIBILITY_LARGE_POINTER_ICON_VALIDATOR); - VALIDATORS.put(PREFERRED_TTY_MODE, PREFERRED_TTY_MODE_VALIDATOR); - VALIDATORS.put(ENHANCED_VOICE_PRIVACY_ENABLED, - ENHANCED_VOICE_PRIVACY_ENABLED_VALIDATOR); - VALIDATORS.put(TTY_MODE_ENABLED, TTY_MODE_ENABLED_VALIDATOR); - VALIDATORS.put(RTT_CALLING_MODE, RTT_CALLING_MODE_VALIDATOR); - VALIDATORS.put(INCALL_POWER_BUTTON_BEHAVIOR, INCALL_POWER_BUTTON_BEHAVIOR_VALIDATOR); - VALIDATORS.put(NIGHT_DISPLAY_CUSTOM_START_TIME, - NIGHT_DISPLAY_CUSTOM_START_TIME_VALIDATOR); - VALIDATORS.put(NIGHT_DISPLAY_CUSTOM_END_TIME, NIGHT_DISPLAY_CUSTOM_END_TIME_VALIDATOR); - VALIDATORS.put(NIGHT_DISPLAY_COLOR_TEMPERATURE, - NIGHT_DISPLAY_COLOR_TEMPERATURE_VALIDATOR); - VALIDATORS.put(NIGHT_DISPLAY_AUTO_MODE, NIGHT_DISPLAY_AUTO_MODE_VALIDATOR); - VALIDATORS.put(DISPLAY_WHITE_BALANCE_ENABLED, DISPLAY_WHITE_BALANCE_ENABLED_VALIDATOR); - VALIDATORS.put(SYNC_PARENT_SOUNDS, SYNC_PARENT_SOUNDS_VALIDATOR); - VALIDATORS.put(CAMERA_DOUBLE_TWIST_TO_FLIP_ENABLED, - CAMERA_DOUBLE_TWIST_TO_FLIP_ENABLED_VALIDATOR); - VALIDATORS.put(CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, - CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED_VALIDATOR); - VALIDATORS.put(SYSTEM_NAVIGATION_KEYS_ENABLED, - SYSTEM_NAVIGATION_KEYS_ENABLED_VALIDATOR); - VALIDATORS.put(QS_TILES, QS_TILES_VALIDATOR); - VALIDATORS.put(DOZE_ENABLED, DOZE_ENABLED_VALIDATOR); - VALIDATORS.put(DOZE_ALWAYS_ON, DOZE_ALWAYS_ON_VALIDATOR); - VALIDATORS.put(DOZE_PICK_UP_GESTURE, DOZE_PICK_UP_GESTURE_VALIDATOR); - VALIDATORS.put(DOZE_DOUBLE_TAP_GESTURE, DOZE_DOUBLE_TAP_GESTURE_VALIDATOR); - VALIDATORS.put(DOZE_TAP_SCREEN_GESTURE, DOZE_TAP_SCREEN_GESTURE_VALIDATOR); - VALIDATORS.put(DOZE_WAKE_LOCK_SCREEN_GESTURE, DOZE_WAKE_LOCK_SCREEN_GESTURE_VALIDATOR); - VALIDATORS.put(DOZE_WAKE_DISPLAY_GESTURE, DOZE_WAKE_DISPLAY_GESTURE_VALIDATOR); - VALIDATORS.put(NFC_PAYMENT_DEFAULT_COMPONENT, NFC_PAYMENT_DEFAULT_COMPONENT_VALIDATOR); - VALIDATORS.put(AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN, - AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN_VALIDATOR); - VALIDATORS.put(FACE_UNLOCK_KEYGUARD_ENABLED, FACE_UNLOCK_KEYGUARD_ENABLED_VALIDATOR); - VALIDATORS.put(FACE_UNLOCK_DISMISSES_KEYGUARD, - FACE_UNLOCK_DISMISSES_KEYGUARD_VALIDATOR); - VALIDATORS.put(SHOW_MEDIA_WHEN_BYPASSING, SHOW_MEDIA_WHEN_BYPASSING_VALIDATOR); - VALIDATORS.put(FACE_UNLOCK_APP_ENABLED, FACE_UNLOCK_APP_ENABLED_VALIDATOR); - VALIDATORS.put(FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION, - FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION_VALIDATOR); - VALIDATORS.put(ASSIST_GESTURE_ENABLED, ASSIST_GESTURE_ENABLED_VALIDATOR); - VALIDATORS.put(ASSIST_GESTURE_SILENCE_ALERTS_ENABLED, - ASSIST_GESTURE_SILENCE_ALERTS_ENABLED_VALIDATOR); - VALIDATORS.put(ASSIST_GESTURE_WAKE_ENABLED, ASSIST_GESTURE_WAKE_ENABLED_VALIDATOR); - VALIDATORS.put(VR_DISPLAY_MODE, VR_DISPLAY_MODE_VALIDATOR); - VALIDATORS.put(NOTIFICATION_BADGING, NOTIFICATION_BADGING_VALIDATOR); - VALIDATORS.put(NOTIFICATION_BUBBLES, NOTIFICATION_BUBBLES_VALIDATOR); - VALIDATORS.put(NOTIFICATION_DISMISS_RTL, NOTIFICATION_DISMISS_RTL_VALIDATOR); - VALIDATORS.put(QS_AUTO_ADDED_TILES, QS_AUTO_ADDED_TILES_VALIDATOR); - VALIDATORS.put(SCREENSAVER_ENABLED, SCREENSAVER_ENABLED_VALIDATOR); - VALIDATORS.put(SCREENSAVER_COMPONENTS, SCREENSAVER_COMPONENTS_VALIDATOR); - VALIDATORS.put(SCREENSAVER_ACTIVATE_ON_DOCK, SCREENSAVER_ACTIVATE_ON_DOCK_VALIDATOR); - VALIDATORS.put(SCREENSAVER_ACTIVATE_ON_SLEEP, SCREENSAVER_ACTIVATE_ON_SLEEP_VALIDATOR); - VALIDATORS.put(LOCKDOWN_IN_POWER_MENU, LOCKDOWN_IN_POWER_MENU_VALIDATOR); - VALIDATORS.put(SHOW_FIRST_CRASH_DIALOG_DEV_OPTION, - SHOW_FIRST_CRASH_DIALOG_DEV_OPTION_VALIDATOR); - VALIDATORS.put(VOLUME_HUSH_GESTURE, VOLUME_HUSH_GESTURE_VALIDATOR); - VALIDATORS.put(ENABLED_NOTIFICATION_LISTENERS, - ENABLED_NOTIFICATION_LISTENERS_VALIDATOR); //legacy restore setting - VALIDATORS.put(ENABLED_NOTIFICATION_ASSISTANT, - ENABLED_NOTIFICATION_ASSISTANT_VALIDATOR); //legacy restore setting - VALIDATORS.put(ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES, - ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES_VALIDATOR); //legacy restore setting - VALIDATORS.put(HUSH_GESTURE_USED, HUSH_GESTURE_USED_VALIDATOR); - VALIDATORS.put(MANUAL_RINGER_TOGGLE_COUNT, MANUAL_RINGER_TOGGLE_COUNT_VALIDATOR); - VALIDATORS.put(IN_CALL_NOTIFICATION_ENABLED, IN_CALL_NOTIFICATION_ENABLED_VALIDATOR); - VALIDATORS.put(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, BOOLEAN_VALIDATOR); - VALIDATORS.put(LOCK_SCREEN_SHOW_NOTIFICATIONS, BOOLEAN_VALIDATOR); - VALIDATORS.put(LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, BOOLEAN_VALIDATOR); - VALIDATORS.put(SHOW_NOTIFICATION_SNOOZE, BOOLEAN_VALIDATOR); - VALIDATORS.put(ZEN_DURATION, ZEN_DURATION_VALIDATOR); - VALIDATORS.put(SHOW_ZEN_UPGRADE_NOTIFICATION, BOOLEAN_VALIDATOR); - VALIDATORS.put(SHOW_ZEN_SETTINGS_SUGGESTION, BOOLEAN_VALIDATOR); - VALIDATORS.put(ZEN_SETTINGS_UPDATED, BOOLEAN_VALIDATOR); - VALIDATORS.put(ZEN_SETTINGS_SUGGESTION_VIEWED, BOOLEAN_VALIDATOR); - VALIDATORS.put(CHARGING_SOUNDS_ENABLED, BOOLEAN_VALIDATOR); - VALIDATORS.put(CHARGING_VIBRATION_ENABLED, BOOLEAN_VALIDATOR); - VALIDATORS.put(ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS, - NON_NEGATIVE_INTEGER_VALIDATOR); - VALIDATORS.put(ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS, NON_NEGATIVE_INTEGER_VALIDATOR); - VALIDATORS.put(USER_SETUP_COMPLETE, BOOLEAN_VALIDATOR); - VALIDATORS.put(ASSIST_GESTURE_SETUP_COMPLETE, BOOLEAN_VALIDATOR); - VALIDATORS.put(NOTIFICATION_NEW_INTERRUPTION_MODEL, BOOLEAN_VALIDATOR); - VALIDATORS.put(TRUST_AGENTS_EXTEND_UNLOCK, TRUST_AGENTS_EXTEND_UNLOCK_VALIDATOR); - VALIDATORS.put(LOCK_SCREEN_CUSTOM_CLOCK_FACE, LOCK_SCREEN_CUSTOM_CLOCK_FACE_VALIDATOR); - VALIDATORS.put(LOCK_SCREEN_WHEN_TRUST_LOST, LOCK_SCREEN_WHEN_TRUST_LOST_VALIDATOR); - VALIDATORS.put(SKIP_GESTURE, SKIP_GESTURE_VALIDATOR); - VALIDATORS.put(SKIP_DIRECTION, SKIP_DIRECTION_VALIDATOR); - VALIDATORS.put(SKIP_DIRECTION, SKIP_DIRECTION_VALIDATOR); - VALIDATORS.put(SILENCE_GESTURE, SILENCE_GESTURE_VALIDATOR); - VALIDATORS.put(THEME_CUSTOMIZATION_OVERLAY_PACKAGES, - THEME_CUSTOMIZATION_OVERLAY_PACKAGES_VALIDATOR); - VALIDATORS.put(NAVIGATION_MODE, NAVIGATION_MODE_VALIDATOR); - VALIDATORS.put(AWARE_ENABLED, AWARE_ENABLED_VALIDATOR); - VALIDATORS.put(SKIP_GESTURE_COUNT, SKIP_GESTURE_COUNT_VALIDATOR); - VALIDATORS.put(SKIP_TOUCH_COUNT, SKIP_GESTURE_COUNT_VALIDATOR); - VALIDATORS.put(SILENCE_ALARMS_GESTURE_COUNT, SILENCE_GESTURE_COUNT_VALIDATOR); - VALIDATORS.put(SILENCE_TIMER_GESTURE_COUNT, SILENCE_GESTURE_COUNT_VALIDATOR); - VALIDATORS.put(SILENCE_CALL_GESTURE_COUNT, SILENCE_GESTURE_COUNT_VALIDATOR); - VALIDATORS.put(SILENCE_ALARMS_TOUCH_COUNT, SILENCE_GESTURE_COUNT_VALIDATOR); - VALIDATORS.put(SILENCE_TIMER_TOUCH_COUNT, SILENCE_GESTURE_COUNT_VALIDATOR); - VALIDATORS.put(SILENCE_CALL_TOUCH_COUNT, SILENCE_GESTURE_COUNT_VALIDATOR); - VALIDATORS.put(ODI_CAPTIONS_ENABLED, ODI_CAPTIONS_ENABLED_VALIDATOR); - VALIDATORS.put(DARK_MODE_DIALOG_SEEN, BOOLEAN_VALIDATOR); - VALIDATORS.put(UI_NIGHT_MODE, UI_NIGHT_MODE_VALIDATOR); - VALIDATORS.put(GLOBAL_ACTIONS_PANEL_ENABLED, GLOBAL_ACTIONS_PANEL_ENABLED_VALIDATOR); - VALIDATORS.put(AWARE_LOCK_ENABLED, AWARE_LOCK_ENABLED_VALIDATOR); - VALIDATORS.put(DISPLAY_DENSITY_FORCED, DISPLAY_DENSITY_FORCED_VALIDATOR); - } - - /** * Keys we no longer back up under the current schema, but want to continue to * process when restoring historical backup datasets. * @@ -9387,8 +8249,6 @@ public final class Settings { */ public static final String APPLY_RAMPING_RINGER = "apply_ramping_ringer"; - private static final Validator APPLY_RAMPING_RINGER_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Setting whether the global gesture for enabling accessibility is enabled. * If this gesture is enabled the user will be able to perfrom it to enable @@ -9516,16 +8376,12 @@ public final class Settings { */ public static final String AUTO_TIME = "auto_time"; - private static final Validator AUTO_TIME_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Value to specify if the user prefers the time zone * to be automatically fetched from the network (NITZ). 1=yes, 0=no */ public static final String AUTO_TIME_ZONE = "auto_time_zone"; - private static final Validator AUTO_TIME_ZONE_VALIDATOR = BOOLEAN_VALIDATOR; - /** * URI for the car dock "in" event sound. * @hide @@ -9556,8 +8412,6 @@ public final class Settings { */ public static final String DOCK_SOUNDS_ENABLED = "dock_sounds_enabled"; - private static final Validator DOCK_SOUNDS_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Whether to play a sound for dock events, only when an accessibility service is on. * @hide @@ -9595,8 +8449,6 @@ public final class Settings { */ public static final String POWER_SOUNDS_ENABLED = "power_sounds_enabled"; - private static final Validator POWER_SOUNDS_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR; - /** * URI for the "wireless charging started" and "wired charging started" sound. * @hide @@ -9612,8 +8464,6 @@ public final class Settings { @Deprecated public static final String CHARGING_SOUNDS_ENABLED = "charging_sounds_enabled"; - private static final Validator CHARGING_SOUNDS_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Whether to vibrate for wireless charging events. * @deprecated Use {@link android.provider.Settings.Secure#CHARGING_VIBRATION_ENABLED} @@ -9622,8 +8472,6 @@ public final class Settings { @Deprecated public static final String CHARGING_VIBRATION_ENABLED = "charging_vibration_enabled"; - private static final Validator CHARGING_VIBRATION_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Whether we keep the device on while the device is plugged in. * Supported values are: @@ -9637,30 +8485,6 @@ public final class Settings { */ public static final String STAY_ON_WHILE_PLUGGED_IN = "stay_on_while_plugged_in"; - private static final Validator STAY_ON_WHILE_PLUGGED_IN_VALIDATOR = new Validator() { - @Override - public boolean validate(@Nullable String value) { - try { - int val = Integer.parseInt(value); - return (val == 0) - || (val == BatteryManager.BATTERY_PLUGGED_AC) - || (val == BatteryManager.BATTERY_PLUGGED_USB) - || (val == BatteryManager.BATTERY_PLUGGED_WIRELESS) - || (val == (BatteryManager.BATTERY_PLUGGED_AC - | BatteryManager.BATTERY_PLUGGED_USB)) - || (val == (BatteryManager.BATTERY_PLUGGED_AC - | BatteryManager.BATTERY_PLUGGED_WIRELESS)) - || (val == (BatteryManager.BATTERY_PLUGGED_USB - | BatteryManager.BATTERY_PLUGGED_WIRELESS)) - || (val == (BatteryManager.BATTERY_PLUGGED_AC - | BatteryManager.BATTERY_PLUGGED_USB - | BatteryManager.BATTERY_PLUGGED_WIRELESS)); - } catch (NumberFormatException e) { - return false; - } - } - }; - /** * When the user has enable the option to have a "bug report" command * in the power menu. @@ -9668,8 +8492,6 @@ public final class Settings { */ public static final String BUGREPORT_IN_POWER_MENU = "bugreport_in_power_menu"; - private static final Validator BUGREPORT_IN_POWER_MENU_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Whether ADB is enabled. */ @@ -9700,8 +8522,6 @@ public final class Settings { */ public static final String BLUETOOTH_ON = "bluetooth_on"; - private static final Validator BLUETOOTH_ON_VALIDATOR = BOOLEAN_VALIDATOR; - /** * CDMA Cell Broadcast SMS * 0 = CDMA Cell Broadcast SMS disabled @@ -10426,8 +9246,6 @@ public final class Settings { */ public static final String USB_MASS_STORAGE_ENABLED = "usb_mass_storage_enabled"; - private static final Validator USB_MASS_STORAGE_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR; - /** * If this setting is set (to anything), then all references * to Gmail on the device must change to Google Mail. @@ -10580,9 +9398,6 @@ public final class Settings { public static final String WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON = "wifi_networks_available_notification_on"; - private static final Validator WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON_VALIDATOR = - BOOLEAN_VALIDATOR; - /** * {@hide} */ @@ -10596,9 +9411,6 @@ public final class Settings { public static final String WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY = "wifi_networks_available_repeat_delay"; - private static final Validator WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY_VALIDATOR = - NON_NEGATIVE_INTEGER_VALIDATOR; - /** * 802.11 country code in ISO 3166 format * @hide @@ -10628,9 +9440,6 @@ public final class Settings { */ public static final String WIFI_NUM_OPEN_NETWORKS_KEPT = "wifi_num_open_networks_kept"; - private static final Validator WIFI_NUM_OPEN_NETWORKS_KEPT_VALIDATOR = - NON_NEGATIVE_INTEGER_VALIDATOR; - /** * Whether the Wi-Fi should be on. Only the Wi-Fi service should touch this. */ @@ -10669,8 +9478,6 @@ public final class Settings { */ public static final String SOFT_AP_TIMEOUT_ENABLED = "soft_ap_timeout_enabled"; - private static final Validator SOFT_AP_TIMEOUT_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Value to specify if Wi-Fi Wakeup feature is enabled. * @@ -10680,8 +9487,6 @@ public final class Settings { @SystemApi public static final String WIFI_WAKEUP_ENABLED = "wifi_wakeup_enabled"; - private static final Validator WIFI_WAKEUP_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Value to specify whether network quality scores and badging should be shown in the UI. * @@ -10717,8 +9522,6 @@ public final class Settings { public static final String NETWORK_RECOMMENDATIONS_ENABLED = "network_recommendations_enabled"; - private static final Validator NETWORK_RECOMMENDATIONS_ENABLED_VALIDATOR = - new DiscreteValueValidator(new String[] {"-1", "0", "1"}); /** * Which package name to use for network recommendations. If null, network recommendations @@ -10743,13 +9546,6 @@ public final class Settings { @TestApi public static final String USE_OPEN_WIFI_PACKAGE = "use_open_wifi_package"; - private static final Validator USE_OPEN_WIFI_PACKAGE_VALIDATOR = new Validator() { - @Override - public boolean validate(@Nullable String value) { - return (value == null) || PACKAGE_NAME_VALIDATOR.validate(value); - } - }; - /** * The number of milliseconds the {@link com.android.server.NetworkScoreService} * will give a recommendation request to complete before returning a default response. @@ -10781,8 +9577,6 @@ public final class Settings { */ public static final String WIFI_SCAN_THROTTLE_ENABLED = "wifi_scan_throttle_enabled"; - private static final Validator WIFI_SCAN_THROTTLE_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Settings to allow BLE scans to be enabled even when Bluetooth is turned off for * connectivity. @@ -10888,9 +9682,6 @@ public final class Settings { public static final String WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED = "wifi_watchdog_poor_network_test_enabled"; - private static final Validator WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED_VALIDATOR = - ANY_STRING_VALIDATOR; - /** * Setting to turn on suspend optimizations at screen off on Wi-Fi. Enabled by default and * needs to be set to 0 to disable it. @@ -10974,9 +9765,6 @@ public final class Settings { public static final String WIFI_PNO_FREQUENCY_CULLING_ENABLED = "wifi_pno_frequency_culling_enabled"; - private static final Validator WIFI_PNO_FREQUENCY_CULLING_ENABLED_VALIDATOR = - BOOLEAN_VALIDATOR; - /** * Setting to enable including recency information when determining pno network priorities. * Disabled by default, and setting it to 1 will enable it. @@ -10986,9 +9774,6 @@ public final class Settings { public static final String WIFI_PNO_RECENCY_SORTING_ENABLED = "wifi_pno_recency_sorting_enabled"; - private static final Validator WIFI_PNO_RECENCY_SORTING_ENABLED_VALIDATOR = - BOOLEAN_VALIDATOR; - /** * Setting to enable the Wi-Fi link probing. * Enabled by default, and setting it to 0 will disable it. @@ -10998,9 +9783,6 @@ public final class Settings { public static final String WIFI_LINK_PROBING_ENABLED = "wifi_link_probing_enabled"; - private static final Validator WIFI_LINK_PROBING_ENABLED_VALIDATOR = - BOOLEAN_VALIDATOR; - /** * The maximum number of times we will retry a connection to an access * point for which we have failed in acquiring an IP address from DHCP. @@ -11540,15 +10322,11 @@ public final class Settings { */ public static final String PRIVATE_DNS_MODE = "private_dns_mode"; - private static final Validator PRIVATE_DNS_MODE_VALIDATOR = ANY_STRING_VALIDATOR; - /** * @hide */ public static final String PRIVATE_DNS_SPECIFIER = "private_dns_specifier"; - private static final Validator PRIVATE_DNS_SPECIFIER_VALIDATOR = ANY_STRING_VALIDATOR; - /** * Forced override of the default mode (hardcoded as "automatic", nee "opportunistic"). * This allows changing the default mode without effectively disabling other modes, @@ -12291,9 +11069,6 @@ public final class Settings { public static final String APP_AUTO_RESTRICTION_ENABLED = "app_auto_restriction_enabled"; - private static final Validator APP_AUTO_RESTRICTION_ENABLED_VALIDATOR = - BOOLEAN_VALIDATOR; - /** * Feature flag to enable or disable the Forced App Standby feature. * Type: int (0 for false, 1 for true) @@ -12568,9 +11343,6 @@ public final class Settings { */ public static final String EMERGENCY_TONE = "emergency_tone"; - private static final Validator EMERGENCY_TONE_VALIDATOR = - new DiscreteValueValidator(new String[] {"0", "1", "2"}); - /** * CDMA only settings * Whether the auto retry is enabled. The value is @@ -12579,8 +11351,6 @@ public final class Settings { */ public static final String CALL_AUTO_RETRY = "call_auto_retry"; - private static final Validator CALL_AUTO_RETRY_VALIDATOR = BOOLEAN_VALIDATOR; - /** * A setting that can be read whether the emergency affordance is currently needed. * The value is a boolean (1 or 0). @@ -12598,9 +11368,6 @@ public final class Settings { public static final String ENABLE_AUTOMATIC_SYSTEM_SERVER_HEAP_DUMPS = "enable_automatic_system_server_heap_dumps"; - private static final Validator ENABLE_AUTOMATIC_SYSTEM_SERVER_HEAP_DUMPS_VALIDATOR = - new DiscreteValueValidator(new String[] {"0", "1"}); - /** * See RIL_PreferredNetworkType in ril.h * @hide @@ -12792,9 +11559,6 @@ public final class Settings { public static final String LOW_POWER_MODE_STICKY_AUTO_DISABLE_LEVEL = "low_power_sticky_auto_disable_level"; - private static final Validator LOW_POWER_MODE_STICKY_AUTO_DISABLE_LEVEL_VALIDATOR = - new InclusiveIntegerRangeValidator(0, 100); - /** * Whether sticky battery saver should be deactivated once the battery level has reached the * threshold specified by {@link #LOW_POWER_MODE_STICKY_AUTO_DISABLE_LEVEL}. @@ -12804,9 +11568,6 @@ public final class Settings { public static final String LOW_POWER_MODE_STICKY_AUTO_DISABLE_ENABLED = "low_power_sticky_auto_disable_enabled"; - private static final Validator LOW_POWER_MODE_STICKY_AUTO_DISABLE_ENABLED_VALIDATOR = - new DiscreteValueValidator(new String[] {"0", "1"}); - /** * Battery level [1-100] at which low power mode automatically turns on. * If 0, it will not automatically turn on. For Q and newer, it will only automatically @@ -12819,9 +11580,6 @@ public final class Settings { */ public static final String LOW_POWER_MODE_TRIGGER_LEVEL = "low_power_trigger_level"; - private static final Validator LOW_POWER_MODE_TRIGGER_LEVEL_VALIDATOR = - new InclusiveIntegerRangeValidator(0, 100); - /** * Whether battery saver is currently set to trigger based on percentage, dynamic power * savings trigger, or none. See {@link AutoPowerSaveModeTriggers} for @@ -12832,9 +11590,6 @@ public final class Settings { @TestApi public static final String AUTOMATIC_POWER_SAVE_MODE = "automatic_power_save_mode"; - private static final Validator AUTOMATIC_POWER_SAVE_MODE_VALIDATOR = - new DiscreteValueValidator(new String[] {"0", "1"}); - /** * The setting that backs the disable threshold for the setPowerSavingsWarning api in * PowerManager @@ -12845,8 +11600,6 @@ public final class Settings { @TestApi public static final String DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD = "dynamic_power_savings_disable_threshold"; - private static final Validator DYNAMIC_POWER_SAVINGS_VALIDATOR = - new InclusiveIntegerRangeValidator(0, 100); /** * The setting which backs the setDynamicPowerSaveHint api in PowerManager. @@ -12934,8 +11687,6 @@ public final class Settings { */ public static final String DOCK_AUDIO_MEDIA_ENABLED = "dock_audio_media_enabled"; - private static final Validator DOCK_AUDIO_MEDIA_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR; - /** * The surround sound formats AC3, DTS or IEC61937 are * available for use if they are detected. @@ -12995,9 +11746,6 @@ public final class Settings { */ public static final String ENCODED_SURROUND_OUTPUT = "encoded_surround_output"; - private static final Validator ENCODED_SURROUND_OUTPUT_VALIDATOR = - new DiscreteValueValidator(new String[] {"0", "1", "2", "3"}); - /** * Surround sounds formats that are enabled when ENCODED_SURROUND_OUTPUT is set to * ENCODED_SURROUND_OUTPUT_MANUAL. Encoded as comma separated list. Allowed values @@ -13010,32 +11758,6 @@ public final class Settings { public static final String ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS = "encoded_surround_output_enabled_formats"; - private static final Validator ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS_VALIDATOR = - new Validator() { - @Override - public boolean validate(@Nullable String value) { - try { - String[] surroundFormats = TextUtils.split(value, ","); - for (String format : surroundFormats) { - int audioFormat = Integer.valueOf(format); - boolean isSurroundFormat = false; - for (int sf : AudioFormat.SURROUND_SOUND_ENCODING) { - if (sf == audioFormat) { - isSurroundFormat = true; - break; - } - } - if (!isSurroundFormat) { - return false; - } - } - return true; - } catch (NumberFormatException e) { - return false; - } - } - }; - /** * Persisted safe headphone volume management state by AudioService * @hide @@ -13278,8 +12000,6 @@ public final class Settings { @Deprecated public static final String ZEN_DURATION = "zen_duration"; - private static final Validator ZEN_DURATION_VALIDATOR = ANY_INTEGER_VALIDATOR; - /** * @deprecated Use {@link android.provider.Settings.Secure#ZEN_DURATION_PROMPT} instead * @hide @@ -13736,8 +12456,6 @@ public final class Settings { */ public static final String AWARE_ALLOWED = "aware_allowed"; - private static final Validator AWARE_ALLOWED_VALIDATOR = BOOLEAN_VALIDATOR; - /** * Overrides internal R.integer.config_longPressOnPowerBehavior. * Allowable values detailed in frameworks/base/core/res/res/values/config.xml. @@ -13746,8 +12464,6 @@ public final class Settings { */ public static final String POWER_BUTTON_LONG_PRESS = "power_button_long_press"; - private static final Validator POWER_BUTTON_LONG_PRESS_VALIDATOR = - new InclusiveIntegerRangeValidator(0, 5); /** * Overrides internal R.integer.config_veryLongPressOnPowerBehavior. @@ -13757,126 +12473,6 @@ public final class Settings { */ public static final String POWER_BUTTON_VERY_LONG_PRESS = "power_button_very_long_press"; - private static final Validator POWER_BUTTON_VERY_LONG_PRESS_VALIDATOR = - new InclusiveIntegerRangeValidator(0, 1); - - /** - * Settings to backup. This is here so that it's in the same place as the settings - * keys and easy to update. - * - * These keys may be mentioned in the SETTINGS_TO_BACKUP arrays in System - * and Secure as well. This is because those tables drive both backup and - * restore, and restore needs to properly whitelist keys that used to live - * in those namespaces. The keys will only actually be backed up / restored - * if they are also mentioned in this table (Global.SETTINGS_TO_BACKUP). - * - * NOTE: Settings are backed up and restored in the order they appear - * in this array. If you have one setting depending on another, - * make sure that they are ordered appropriately. - * - * NOTE: This table should only be used for settings which should be restored - * between different types of devices {@see #DEVICE_SPECIFIC_SETTINGS_TO_BACKUP} - * - * @hide - */ - public static final String[] SETTINGS_TO_BACKUP = { - APPLY_RAMPING_RINGER, - BUGREPORT_IN_POWER_MENU, - STAY_ON_WHILE_PLUGGED_IN, - APP_AUTO_RESTRICTION_ENABLED, - AUTO_TIME, - AUTO_TIME_ZONE, - POWER_SOUNDS_ENABLED, - DOCK_SOUNDS_ENABLED, - CHARGING_SOUNDS_ENABLED, - USB_MASS_STORAGE_ENABLED, - NETWORK_RECOMMENDATIONS_ENABLED, - WIFI_WAKEUP_ENABLED, - WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, - USE_OPEN_WIFI_PACKAGE, - WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED, - EMERGENCY_TONE, - CALL_AUTO_RETRY, - DOCK_AUDIO_MEDIA_ENABLED, - ENABLE_AUTOMATIC_SYSTEM_SERVER_HEAP_DUMPS, - ENCODED_SURROUND_OUTPUT, - ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS, - LOW_POWER_MODE_TRIGGER_LEVEL, - LOW_POWER_MODE_STICKY_AUTO_DISABLE_ENABLED, - LOW_POWER_MODE_STICKY_AUTO_DISABLE_LEVEL, - BLUETOOTH_ON, - PRIVATE_DNS_MODE, - PRIVATE_DNS_SPECIFIER, - SOFT_AP_TIMEOUT_ENABLED, - ZEN_DURATION, - CHARGING_VIBRATION_ENABLED, - AWARE_ALLOWED, - }; - - /** - * All settings in {@link SETTINGS_TO_BACKUP} array *must* have a non-null validator, - * otherwise they won't be restored. - * - * @hide - */ - public static final Map<String, Validator> VALIDATORS = new ArrayMap<>(); - - static { - VALIDATORS.put(APPLY_RAMPING_RINGER, APPLY_RAMPING_RINGER_VALIDATOR); - VALIDATORS.put(BUGREPORT_IN_POWER_MENU, BUGREPORT_IN_POWER_MENU_VALIDATOR); - VALIDATORS.put(STAY_ON_WHILE_PLUGGED_IN, STAY_ON_WHILE_PLUGGED_IN_VALIDATOR); - VALIDATORS.put(AUTO_TIME, AUTO_TIME_VALIDATOR); - VALIDATORS.put(AUTO_TIME_ZONE, AUTO_TIME_ZONE_VALIDATOR); - VALIDATORS.put(POWER_SOUNDS_ENABLED, POWER_SOUNDS_ENABLED_VALIDATOR); - VALIDATORS.put(DOCK_SOUNDS_ENABLED, DOCK_SOUNDS_ENABLED_VALIDATOR); - VALIDATORS.put(CHARGING_SOUNDS_ENABLED, CHARGING_SOUNDS_ENABLED_VALIDATOR); - VALIDATORS.put(USB_MASS_STORAGE_ENABLED, USB_MASS_STORAGE_ENABLED_VALIDATOR); - VALIDATORS.put(NETWORK_RECOMMENDATIONS_ENABLED, - NETWORK_RECOMMENDATIONS_ENABLED_VALIDATOR); - VALIDATORS.put(WIFI_WAKEUP_ENABLED, WIFI_WAKEUP_ENABLED_VALIDATOR); - VALIDATORS.put(WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, - WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON_VALIDATOR); - VALIDATORS.put(USE_OPEN_WIFI_PACKAGE, USE_OPEN_WIFI_PACKAGE_VALIDATOR); - VALIDATORS.put(WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED, - WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED_VALIDATOR); - VALIDATORS.put(EMERGENCY_TONE, EMERGENCY_TONE_VALIDATOR); - VALIDATORS.put(CALL_AUTO_RETRY, CALL_AUTO_RETRY_VALIDATOR); - VALIDATORS.put(DOCK_AUDIO_MEDIA_ENABLED, DOCK_AUDIO_MEDIA_ENABLED_VALIDATOR); - VALIDATORS.put(ENABLE_AUTOMATIC_SYSTEM_SERVER_HEAP_DUMPS, - ENABLE_AUTOMATIC_SYSTEM_SERVER_HEAP_DUMPS_VALIDATOR); - VALIDATORS.put(ENCODED_SURROUND_OUTPUT, ENCODED_SURROUND_OUTPUT_VALIDATOR); - VALIDATORS.put(ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS, - ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS_VALIDATOR); - VALIDATORS.put(LOW_POWER_MODE_STICKY_AUTO_DISABLE_LEVEL, - LOW_POWER_MODE_STICKY_AUTO_DISABLE_LEVEL_VALIDATOR); - VALIDATORS.put(LOW_POWER_MODE_STICKY_AUTO_DISABLE_ENABLED, - LOW_POWER_MODE_STICKY_AUTO_DISABLE_ENABLED_VALIDATOR); - VALIDATORS.put(LOW_POWER_MODE_TRIGGER_LEVEL, LOW_POWER_MODE_TRIGGER_LEVEL_VALIDATOR); - VALIDATORS.put(LOW_POWER_MODE_TRIGGER_LEVEL_MAX, - LOW_POWER_MODE_TRIGGER_LEVEL_VALIDATOR); - VALIDATORS.put(AUTOMATIC_POWER_SAVE_MODE, AUTOMATIC_POWER_SAVE_MODE_VALIDATOR); - VALIDATORS.put(DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD, - DYNAMIC_POWER_SAVINGS_VALIDATOR); - VALIDATORS.put(BLUETOOTH_ON, BLUETOOTH_ON_VALIDATOR); - VALIDATORS.put(PRIVATE_DNS_MODE, PRIVATE_DNS_MODE_VALIDATOR); - VALIDATORS.put(PRIVATE_DNS_SPECIFIER, PRIVATE_DNS_SPECIFIER_VALIDATOR); - VALIDATORS.put(SOFT_AP_TIMEOUT_ENABLED, SOFT_AP_TIMEOUT_ENABLED_VALIDATOR); - VALIDATORS.put(WIFI_SCAN_THROTTLE_ENABLED, WIFI_SCAN_THROTTLE_ENABLED_VALIDATOR); - VALIDATORS.put(APP_AUTO_RESTRICTION_ENABLED, APP_AUTO_RESTRICTION_ENABLED_VALIDATOR); - VALIDATORS.put(ZEN_DURATION, ZEN_DURATION_VALIDATOR); - VALIDATORS.put(CHARGING_VIBRATION_ENABLED, CHARGING_VIBRATION_ENABLED_VALIDATOR); - VALIDATORS.put(DEVICE_PROVISIONING_MOBILE_DATA_ENABLED, BOOLEAN_VALIDATOR); - VALIDATORS.put(REQUIRE_PASSWORD_TO_DECRYPT, BOOLEAN_VALIDATOR); - VALIDATORS.put(DEVICE_DEMO_MODE, BOOLEAN_VALIDATOR); - VALIDATORS.put(WIFI_PNO_FREQUENCY_CULLING_ENABLED, - WIFI_PNO_FREQUENCY_CULLING_ENABLED_VALIDATOR); - VALIDATORS.put(WIFI_PNO_RECENCY_SORTING_ENABLED, - WIFI_PNO_RECENCY_SORTING_ENABLED_VALIDATOR); - VALIDATORS.put(WIFI_LINK_PROBING_ENABLED, WIFI_LINK_PROBING_ENABLED_VALIDATOR); - VALIDATORS.put(AWARE_ALLOWED, AWARE_ALLOWED_VALIDATOR); - VALIDATORS.put(POWER_BUTTON_LONG_PRESS, POWER_BUTTON_LONG_PRESS_VALIDATOR); - VALIDATORS.put(POWER_BUTTON_VERY_LONG_PRESS, POWER_BUTTON_VERY_LONG_PRESS_VALIDATOR); - } /** * Global settings that shouldn't be persisted. diff --git a/core/java/android/provider/TEST_MAPPING b/core/java/android/provider/TEST_MAPPING index 52a6a4585581..773be80be270 100644 --- a/core/java/android/provider/TEST_MAPPING +++ b/core/java/android/provider/TEST_MAPPING @@ -7,6 +7,14 @@ "include-annotation": "android.platform.test.annotations.Presubmit" } ] + }, + { + "name": "SettingsProviderTest", + "options": [ + { + "include-annotation": "android.platform.test.annotations.Presubmit" + } + ] } ] } diff --git a/core/java/android/service/autofill/augmented/FillRequest.java b/core/java/android/service/autofill/augmented/FillRequest.java index 9a97bb203f5a..0b44470670de 100644 --- a/core/java/android/service/autofill/augmented/FillRequest.java +++ b/core/java/android/service/autofill/augmented/FillRequest.java @@ -81,6 +81,7 @@ public final class FillRequest { return mProxy.getSmartSuggestionParams(); } + @NonNull @Override public String toString() { return "FillRequest[act=" + getActivityComponent().flattenToShortString() diff --git a/core/java/android/service/autofill/augmented/PresentationParams.java b/core/java/android/service/autofill/augmented/PresentationParams.java index 334487dd6ab4..8b3a001f58e6 100644 --- a/core/java/android/service/autofill/augmented/PresentationParams.java +++ b/core/java/android/service/autofill/augmented/PresentationParams.java @@ -82,6 +82,7 @@ public abstract class PresentationParams { return mBounds; } + @NonNull @Override public String toString() { return mBounds.toString(); diff --git a/core/java/android/service/contentcapture/ActivityEvent.java b/core/java/android/service/contentcapture/ActivityEvent.java index fc781c2035f6..b741cff9328e 100644 --- a/core/java/android/service/contentcapture/ActivityEvent.java +++ b/core/java/android/service/contentcapture/ActivityEvent.java @@ -111,6 +111,7 @@ public final class ActivityEvent implements Parcelable { } } + @NonNull @Override public String toString() { return new StringBuilder("ActivityEvent[").append(mComponentName.toShortString()) diff --git a/core/java/android/service/euicc/EuiccProfileInfo.java b/core/java/android/service/euicc/EuiccProfileInfo.java index 702837b3083c..6c357ccdd03d 100644 --- a/core/java/android/service/euicc/EuiccProfileInfo.java +++ b/core/java/android/service/euicc/EuiccProfileInfo.java @@ -16,6 +16,7 @@ package android.service.euicc; import android.annotation.IntDef; +import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.UnsupportedAppUsage; @@ -395,7 +396,7 @@ public final class EuiccProfileInfo implements Parcelable { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (this == obj) { return true; } @@ -430,6 +431,7 @@ public final class EuiccProfileInfo implements Parcelable { return result; } + @NonNull @Override public String toString() { return "EuiccProfileInfo (nickname=" diff --git a/core/java/android/service/notification/Adjustment.java b/core/java/android/service/notification/Adjustment.java index aa11445079cd..8ab687f0d001 100644 --- a/core/java/android/service/notification/Adjustment.java +++ b/core/java/android/service/notification/Adjustment.java @@ -257,6 +257,7 @@ public final class Adjustment implements Parcelable { dest.writeString(mIssuer); } + @NonNull @Override public String toString() { return "Adjustment{" diff --git a/core/java/android/service/notification/NotificationStats.java b/core/java/android/service/notification/NotificationStats.java index 2b4c24cbb069..8be114ca321e 100644 --- a/core/java/android/service/notification/NotificationStats.java +++ b/core/java/android/service/notification/NotificationStats.java @@ -16,6 +16,8 @@ package android.service.notification; import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.TestApi; import android.app.RemoteInput; @@ -266,7 +268,7 @@ public final class NotificationStats implements Parcelable { } @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; @@ -293,6 +295,7 @@ public final class NotificationStats implements Parcelable { return result; } + @NonNull @Override public String toString() { final StringBuilder sb = new StringBuilder("NotificationStats{"); diff --git a/core/java/android/service/notification/SnoozeCriterion.java b/core/java/android/service/notification/SnoozeCriterion.java index 938cc10fec2a..eb624c9d85f4 100644 --- a/core/java/android/service/notification/SnoozeCriterion.java +++ b/core/java/android/service/notification/SnoozeCriterion.java @@ -15,6 +15,7 @@ */ package android.service.notification; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.TestApi; import android.os.Parcel; @@ -118,7 +119,7 @@ public final class SnoozeCriterion implements Parcelable { } @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; diff --git a/core/java/android/service/resolver/ResolverTarget.java b/core/java/android/service/resolver/ResolverTarget.java index 33b328393028..b3657c458ba7 100644 --- a/core/java/android/service/resolver/ResolverTarget.java +++ b/core/java/android/service/resolver/ResolverTarget.java @@ -16,13 +16,10 @@ package android.service.resolver; +import android.annotation.NonNull; import android.annotation.SystemApi; -import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; -import android.util.ArrayMap; - -import java.util.Map; /** * A ResolverTarget contains features by which an app or option will be ranked, in @@ -173,6 +170,7 @@ public final class ResolverTarget implements Parcelable { } // serialize the class to a string. + @NonNull @Override public String toString() { return "ResolverTarget{" diff --git a/core/java/android/service/watchdog/ExplicitHealthCheckService.java b/core/java/android/service/watchdog/ExplicitHealthCheckService.java index dc9c85808240..619c507c2bd3 100644 --- a/core/java/android/service/watchdog/ExplicitHealthCheckService.java +++ b/core/java/android/service/watchdog/ExplicitHealthCheckService.java @@ -229,13 +229,14 @@ public abstract class ExplicitHealthCheckService extends Service { return mHealthCheckTimeoutMillis; } + @NonNull @Override public String toString() { return "PackageConfig{" + mPackageName + ", " + mHealthCheckTimeoutMillis + "}"; } @Override - public boolean equals(Object other) { + public boolean equals(@Nullable Object other) { if (other == this) { return true; } diff --git a/core/java/android/text/format/Time.java b/core/java/android/text/format/Time.java index bab4bc362c0d..3b6ec0b95802 100644 --- a/core/java/android/text/format/Time.java +++ b/core/java/android/text/format/Time.java @@ -937,9 +937,12 @@ public class Time { } /** - * Returns true if the day of the given time is the epoch on the Julian Calendar - * (January 1, 1970 on the Gregorian calendar). - * + * Returns true if the instant of the supplied time would be for the + * Gregorian calendar date January 1, 1970 <em>for a user observing UTC + * </em>, i.e. the timezone of the time object is ignored. + * <p> + * See {@link #getJulianDay(long, long)} for how to determine the Julian day + * for the timezone of the time object. * <p> * This method can return an incorrect answer when the date / time fields have * been set to a local time that contradicts the available timezone information. @@ -949,31 +952,39 @@ public class Time { */ public static boolean isEpoch(Time time) { long millis = time.toMillis(true); - return getJulianDay(millis, 0) == EPOCH_JULIAN_DAY; + return getJulianDay(millis, 0 /* UTC offset */) == EPOCH_JULIAN_DAY; } /** * Computes the Julian day number for a point in time in a particular - * timezone. The Julian day for a given date is the same for every - * timezone. For example, the Julian day for July 1, 2008 is 2454649. + * timezone. The Julian day for a given calendar date is the same for + * every timezone. For example, the Julian day for July 1, 2008 is + * 2454649. * * <p>Callers must pass the time in UTC millisecond (as can be returned * by {@link #toMillis(boolean)} or {@link #normalize(boolean)}) - * and the offset from UTC of the timezone in seconds (as might be in - * {@link #gmtoff}). + * and the offset from UTC of the timezone in seconds at that time (as + * might be in {@link #gmtoff}). * * <p>The Julian day is useful for testing if two events occur on the * same calendar date and for determining the relative time of an event * from the present ("yesterday", "3 days ago", etc.). * * @param millis the time in UTC milliseconds - * @param gmtoff the offset from UTC in seconds + * @param gmtoffSeconds the offset from UTC in seconds * @return the Julian day + * @deprecated Use {@link java.time.temporal.JulianFields#JULIAN_DAY} instead. */ - public static int getJulianDay(long millis, long gmtoff) { - long offsetMillis = gmtoff * 1000; - long julianDay = (millis + offsetMillis) / DateUtils.DAY_IN_MILLIS; - return (int) julianDay + EPOCH_JULIAN_DAY; + @Deprecated + public static int getJulianDay(long millis, long gmtoffSeconds) { + long offsetMillis = gmtoffSeconds * 1000; + long adjustedMillis = millis + offsetMillis; + long julianDay = adjustedMillis / DateUtils.DAY_IN_MILLIS; + // Negative adjustedMillis values must round towards Integer.MIN_VALUE. + if (adjustedMillis < 0 && adjustedMillis % DateUtils.DAY_IN_MILLIS != 0) { + julianDay--; + } + return (int) (julianDay + EPOCH_JULIAN_DAY); } /** diff --git a/core/java/android/view/GestureExclusionTracker.java b/core/java/android/view/GestureExclusionTracker.java index 6fcdd714f827..fcc14c196730 100644 --- a/core/java/android/view/GestureExclusionTracker.java +++ b/core/java/android/view/GestureExclusionTracker.java @@ -44,7 +44,7 @@ class GestureExclusionTracker { while (i.hasNext()) { final GestureExclusionViewInfo info = i.next(); final View v = info.getView(); - if (v == null || !v.isAttachedToWindow()) { + if (v == null || !v.isAttachedToWindow() || !v.isShown()) { mGestureExclusionViewsChanged = true; i.remove(); continue; @@ -122,7 +122,8 @@ class GestureExclusionTracker { public int update() { final View excludedView = getView(); - if (excludedView == null || !excludedView.isAttachedToWindow()) return GONE; + if (excludedView == null || !excludedView.isAttachedToWindow() + || !excludedView.isShown()) return GONE; final List<Rect> localRects = excludedView.getSystemGestureExclusionRects(); final List<Rect> newRects = new ArrayList<>(localRects.size()); for (Rect src : localRects) { diff --git a/core/java/android/view/ImeInsetsSourceConsumer.java b/core/java/android/view/ImeInsetsSourceConsumer.java index 83abf1a33b2d..3bf44ac92a58 100644 --- a/core/java/android/view/ImeInsetsSourceConsumer.java +++ b/core/java/android/view/ImeInsetsSourceConsumer.java @@ -42,7 +42,6 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer { * editor {@link #mFocusedEditor} if {@link #isServedEditorRendered} is {@code true}. */ private boolean mShowOnNextImeRender; - private boolean mHasWindowFocus; public ImeInsetsSourceConsumer( InsetsState state, Supplier<Transaction> transactionSupplier, @@ -68,23 +67,18 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer { } public void applyImeVisibility(boolean setVisible) { - if (!mHasWindowFocus) { - // App window doesn't have focus, any visibility changes would be no-op. - return; - } - mController.applyImeVisibility(setVisible); } @Override public void onWindowFocusGained() { - mHasWindowFocus = true; + super.onWindowFocusGained(); getImm().registerImeConsumer(this); } @Override public void onWindowFocusLost() { - mHasWindowFocus = false; + super.onWindowFocusLost(); getImm().unregisterImeConsumer(this); } diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java index bf16e3dedd49..d0ecae9e34e4 100644 --- a/core/java/android/view/InsetsController.java +++ b/core/java/android/view/InsetsController.java @@ -296,7 +296,8 @@ public class InsetsController implements WindowInsetsController { final ArraySet<Integer> internalTypes = mState.toInternalType(types); final SparseArray<InsetsSourceConsumer> consumers = new SparseArray<>(); - Pair<Integer, Boolean> typesReadyPair = collectConsumers(fromIme, internalTypes, consumers); + Pair<Integer, Boolean> typesReadyPair = collectConsumers( + fromIme, internalTypes, consumers, listener); int typesReady = typesReadyPair.first; boolean isReady = typesReadyPair.second; if (!isReady) { @@ -324,13 +325,16 @@ public class InsetsController implements WindowInsetsController { * @return Pair of (types ready to animate, is ready to animate). */ private Pair<Integer, Boolean> collectConsumers(boolean fromIme, - ArraySet<Integer> internalTypes, SparseArray<InsetsSourceConsumer> consumers) { + ArraySet<Integer> internalTypes, SparseArray<InsetsSourceConsumer> consumers, + WindowInsetsAnimationControlListener listener) { int typesReady = 0; boolean isReady = true; for (int i = internalTypes.size() - 1; i >= 0; i--) { InsetsSourceConsumer consumer = getSourceConsumer(internalTypes.valueAt(i)); - if (consumer.getControl() != null) { - if (!consumer.isVisible()) { + // Double check for IME that IME target window has focus. + if (consumer.getType() != TYPE_IME || consumer.hasWindowFocus()) { + boolean setVisible = !consumer.isVisible(); + if (setVisible) { // Show request switch(consumer.requestShow(fromIme)) { case ShowResult.SHOW_IMMEDIATELY: @@ -357,8 +361,11 @@ public class InsetsController implements WindowInsetsController { } consumers.put(consumer.getType(), consumer); } else { - // TODO: Let calling app know it's not possible, or wait - // TODO: Remove it from types + // window doesnt have focus, no-op. + isReady = false; + // TODO: Let the calling app know that window has lost focus and + // show()/hide()/controlWindowInsetsAnimation requests will be ignored. + typesReady &= ~InsetsState.toPublicType(consumer.getType()); } } return new Pair<>(typesReady, isReady); @@ -533,7 +540,10 @@ public class InsetsController implements WindowInsetsController { @Override public void onCancelled() { - mAnimator.cancel(); + // Animator can be null when it is cancelled before onReady() completes. + if (mAnimator != null) { + mAnimator.cancel(); + } } private void onAnimationFinish() { diff --git a/core/java/android/view/InsetsSourceConsumer.java b/core/java/android/view/InsetsSourceConsumer.java index a7801583f643..9edccb3fb221 100644 --- a/core/java/android/view/InsetsSourceConsumer.java +++ b/core/java/android/view/InsetsSourceConsumer.java @@ -58,6 +58,7 @@ public class InsetsSourceConsumer { private final @InternalInsetType int mType; private final InsetsState mState; private @Nullable InsetsSourceControl mSourceControl; + private boolean mHasWindowFocus; public InsetsSourceConsumer(@InternalInsetType int type, InsetsState state, Supplier<Transaction> transactionSupplier, InsetsController controller) { @@ -104,12 +105,20 @@ public class InsetsSourceConsumer { /** * Called when current window gains focus */ - public void onWindowFocusGained() {} + public void onWindowFocusGained() { + mHasWindowFocus = true; + } /** * Called when current window loses focus. */ - public void onWindowFocusLost() {} + public void onWindowFocusLost() { + mHasWindowFocus = false; + } + + boolean hasWindowFocus() { + return mHasWindowFocus; + } boolean applyLocalVisibilityOverride() { @@ -153,7 +162,6 @@ public class InsetsSourceConsumer { return; } mVisible = visible; - applyHiddenToControl(); applyLocalVisibilityOverride(); mController.notifyVisibilityChanged(); } diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java index b76f2a175346..a04c39b63c85 100644 --- a/core/java/android/view/InsetsState.java +++ b/core/java/android/view/InsetsState.java @@ -17,6 +17,7 @@ package android.view; import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL; +import static android.view.ViewRootImpl.NEW_INSETS_MODE_IME; import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE; import static android.view.WindowInsets.Type.MANDATORY_SYSTEM_GESTURES; import static android.view.WindowInsets.Type.SIZE; @@ -161,13 +162,15 @@ public class InsetsState implements Parcelable { continue; } + boolean skipNonImeInImeMode = ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_IME + && source.getType() != TYPE_IME; boolean skipSystemBars = ViewRootImpl.sNewInsetsMode != NEW_INSETS_MODE_FULL && (type == TYPE_TOP_BAR || type == TYPE_NAVIGATION_BAR); boolean skipIme = source.getType() == TYPE_IME && (legacySoftInputMode & LayoutParams.SOFT_INPUT_ADJUST_RESIZE) == 0; boolean skipLegacyTypes = ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_NONE && (toPublicType(type) & Type.compatSystemInsets()) != 0; - if (skipSystemBars || skipIme || skipLegacyTypes) { + if (skipSystemBars || skipIme || skipLegacyTypes || skipNonImeInImeMode) { typeVisibilityMap[indexOf(toPublicType(type))] = source.isVisible(); continue; } diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 1779a80b5d09..6ce712061db0 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -14403,6 +14403,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } notifyAppearedOrDisappearedForContentCaptureIfNeeded(isVisible); + updateSystemGestureExclusionRects(); } /** diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java index d474b4d79e9e..61debc8d8468 100644 --- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java +++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java @@ -4745,8 +4745,8 @@ public class AccessibilityNodeInfo implements Parcelable { /** * Obtains a pooled instance. * - * @param rowCount The number of rows. - * @param columnCount The number of columns. + * @param rowCount The number of rows, or -1 if count is unknown. + * @param columnCount The number of columns, or -1 if count is unknown. * @param hierarchical Whether the collection is hierarchical. */ public static CollectionInfo obtain(int rowCount, int columnCount, @@ -4800,7 +4800,7 @@ public class AccessibilityNodeInfo implements Parcelable { /** * Gets the number of rows. * - * @return The row count. + * @return The row count, or -1 if count is unknown. */ public int getRowCount() { return mRowCount; @@ -4809,7 +4809,7 @@ public class AccessibilityNodeInfo implements Parcelable { /** * Gets the number of columns. * - * @return The column count. + * @return The column count, or -1 if count is unknown. */ public int getColumnCount() { return mColumnCount; diff --git a/core/java/android/view/contentcapture/ContentCaptureEvent.java b/core/java/android/view/contentcapture/ContentCaptureEvent.java index bd386292f95d..c29d251e6535 100644 --- a/core/java/android/view/contentcapture/ContentCaptureEvent.java +++ b/core/java/android/view/contentcapture/ContentCaptureEvent.java @@ -373,6 +373,7 @@ public final class ContentCaptureEvent implements Parcelable { } } + @NonNull @Override public String toString() { final StringBuilder string = new StringBuilder("ContentCaptureEvent[type=") diff --git a/core/java/android/view/textclassifier/OWNERS b/core/java/android/view/textclassifier/OWNERS new file mode 100644 index 000000000000..893a083398fa --- /dev/null +++ b/core/java/android/view/textclassifier/OWNERS @@ -0,0 +1,10 @@ +# Bug component: 709498 + +toki@google.com +tonymak@google.com +zilka@google.com +jalt@google.com +joannechung@google.com +svetoslavganov@google.com +eugeniom@google.com +samsellem@google.com
\ No newline at end of file diff --git a/core/java/android/view/textclassifier/TextClassificationSessionId.java b/core/java/android/view/textclassifier/TextClassificationSessionId.java index 5e62a116947d..8b68e17aa681 100644 --- a/core/java/android/view/textclassifier/TextClassificationSessionId.java +++ b/core/java/android/view/textclassifier/TextClassificationSessionId.java @@ -96,8 +96,6 @@ public final class TextClassificationSessionId implements Parcelable { * Flattens this id to a string. * * @return The flattened id. - * - * @hide */ public @NonNull String flattenToString() { return mValue; diff --git a/core/java/android/view/textclassifier/TextClassifierEvent.java b/core/java/android/view/textclassifier/TextClassifierEvent.java index a041296f97db..eb6aec07aad9 100644 --- a/core/java/android/view/textclassifier/TextClassifierEvent.java +++ b/core/java/android/view/textclassifier/TextClassifierEvent.java @@ -86,11 +86,13 @@ public abstract class TextClassifierEvent implements Parcelable { TYPE_ACTIONS_SHOWN, TYPE_LINK_CLICKED, TYPE_OVERTYPE, TYPE_COPY_ACTION, TYPE_PASTE_ACTION, TYPE_CUT_ACTION, TYPE_SHARE_ACTION, TYPE_SMART_ACTION, TYPE_SELECTION_DRAG, TYPE_SELECTION_DESTROYED, TYPE_OTHER_ACTION, TYPE_SELECT_ALL, - TYPE_SELECTION_RESET, TYPE_MANUAL_REPLY, TYPE_ACTIONS_GENERATED}) + TYPE_SELECTION_RESET, TYPE_MANUAL_REPLY, TYPE_ACTIONS_GENERATED, TYPE_LINKS_GENERATED}) public @interface Type { // For custom event types, use range 1,000,000+. } + // All these event type constants are required to match with those defined in + // textclassifier_enums.proto. /** User started a new selection. */ public static final int TYPE_SELECTION_STARTED = 1; /** User modified an existing selection. */ @@ -131,6 +133,8 @@ public abstract class TextClassifierEvent implements Parcelable { public static final int TYPE_MANUAL_REPLY = 19; /** TextClassifier generated some actions */ public static final int TYPE_ACTIONS_GENERATED = 20; + /** Some text links were generated.*/ + public static final int TYPE_LINKS_GENERATED = 21; @Category private final int mEventCategory; @@ -365,7 +369,8 @@ public abstract class TextClassifierEvent implements Parcelable { out.append(this.getClass().getSimpleName()); out.append("{"); out.append("mEventCategory=").append(mEventCategory); - out.append(", mEventTypes=").append(Arrays.toString(mEntityTypes)); + out.append(", mEventType=").append(mEventType); + out.append(", mEntityTypes=").append(Arrays.toString(mEntityTypes)); out.append(", mEventContext=").append(mEventContext); out.append(", mResultId=").append(mResultId); out.append(", mEventIndex=").append(mEventIndex); @@ -373,11 +378,19 @@ public abstract class TextClassifierEvent implements Parcelable { out.append(", mScores=").append(Arrays.toString(mScores)); out.append(", mModelName=").append(mModelName); out.append(", mActionIndices=").append(Arrays.toString(mActionIndices)); + toString(out); out.append("}"); return out.toString(); } /** + * Overrides this to append extra fields to the output of {@link #toString()}. + * <p> + * Extra fields should be formatted like this: ", {field_name}={field_value}". + */ + void toString(StringBuilder out) {} + + /** * Returns a {@link SelectionEvent} equivalent of this event; or {@code null} if it can not be * converted to a {@link SelectionEvent}. * @hide @@ -811,6 +824,16 @@ public abstract class TextClassifierEvent implements Parcelable { return mRelativeSuggestedWordEndIndex; } + @Override + void toString(StringBuilder out) { + out.append(", getRelativeWordStartIndex=").append(mRelativeWordStartIndex); + out.append(", getRelativeWordEndIndex=").append(mRelativeWordEndIndex); + out.append(", getRelativeSuggestedWordStartIndex=") + .append(mRelativeSuggestedWordStartIndex); + out.append(", getRelativeSuggestedWordEndIndex=") + .append(mRelativeSuggestedWordEndIndex); + } + /** * Builder class for {@link TextSelectionEvent}. */ diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index e4b5eaa56aa6..2af7ac729174 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -1843,8 +1843,8 @@ public class WebView extends AbsoluteLayout /** * Injects the supplied Java object into this WebView. The object is - * injected into the JavaScript context of the main frame, using the - * supplied name. This allows the Java object's methods to be + * injected into all frames of the web page, including all the iframes, + * using the supplied name. This allows the Java object's methods to be * accessed from JavaScript. For applications targeted to API * level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1} * and above, only public methods that are annotated with @@ -1883,6 +1883,11 @@ public class WebView extends AbsoluteLayout * thread of this WebView. Care is therefore required to maintain thread * safety. * </li> + * <li> Because the object is exposed to all the frames, any frame could + * obtain the object name and call methods on it. There is no way to tell the + * calling frame's origin from the app side, so the app must not assume that + * the caller is trustworthy unless the app can guarantee that no third party + * content is ever loaded into the WebView even inside an iframe.</li> * <li> The Java object's fields are not accessible.</li> * <li> For applications targeted to API level {@link android.os.Build.VERSION_CODES#LOLLIPOP} * and above, methods of injected Java objects are enumerable from @@ -2807,7 +2812,7 @@ public class WebView extends AbsoluteLayout } @Override - public void onProvideContentCaptureStructure(ViewStructure structure, int flags) { + public void onProvideContentCaptureStructure(@NonNull ViewStructure structure, int flags) { mProvider.getViewDelegate().onProvideContentCaptureStructure(structure, flags); } diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java index 5b129f4c6e52..1de2e7272f4d 100644 --- a/core/java/com/android/internal/os/RuntimeInit.java +++ b/core/java/com/android/internal/os/RuntimeInit.java @@ -20,7 +20,6 @@ import android.annotation.UnsupportedAppUsage; import android.app.ActivityManager; import android.app.ActivityThread; import android.app.ApplicationErrorReport; -import android.content.type.MimeMapImpl; import android.os.Build; import android.os.DeadObjectException; import android.os.Debug; @@ -34,9 +33,6 @@ import com.android.internal.logging.AndroidConfig; import com.android.server.NetworkManagementSocketTagger; import dalvik.system.RuntimeHooks; import dalvik.system.VMRuntime; - -import libcore.net.MimeMap; - import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; @@ -214,14 +210,6 @@ public class RuntimeInit { RuntimeHooks.setTimeZoneIdSupplier(() -> SystemProperties.get("persist.sys.timezone")); /* - * Replace libcore's minimal default mapping between MIME types and file - * extensions with a mapping that's suitable for Android. Android's mapping - * contains many more entries that are derived from IANA registrations but - * with several customizations (extensions, overrides). - */ - MimeMap.setDefault(MimeMapImpl.createDefaultInstance()); - - /* * Sets handler for java.util.logging to use Android log facilities. * The odd "new instance-and-then-throw-away" is a mirror of how * the "java.util.logging.config.class" system property works. We diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java index 9ea9b06ea050..b5d494540f8a 100644 --- a/core/java/com/android/internal/os/ZygoteInit.java +++ b/core/java/com/android/internal/os/ZygoteInit.java @@ -92,11 +92,6 @@ public class ZygoteInit { private static final int LOG_BOOT_PROGRESS_PRELOAD_START = 3020; private static final int LOG_BOOT_PROGRESS_PRELOAD_END = 3030; - /** - * when preloading, GC after allocating this many bytes - */ - private static final int PRELOAD_GC_THRESHOLD = 50000; - private static final String ABI_LIST_ARG = "--abi-list="; // TODO (chriswailes): Re-name this --zygote-socket-name= and then add a @@ -281,11 +276,6 @@ public class ZygoteInit { droppedPriviliges = true; } - // Alter the target heap utilization. With explicit GCs this - // is not likely to have any effect. - float defaultUtilization = runtime.getTargetHeapUtilization(); - runtime.setTargetHeapUtilization(0.8f); - try { BufferedReader br = new BufferedReader(new InputStreamReader(is), Zygote.SOCKET_BUFFER_SIZE); @@ -301,9 +291,6 @@ public class ZygoteInit { Trace.traceBegin(Trace.TRACE_TAG_DALVIK, line); try { - if (false) { - Log.v(TAG, "Preloading " + line + "..."); - } // Load and explicitly initialize the given class. Use // Class.forName(String, boolean, ClassLoader) to avoid repeated stack lookups // (to derive the caller's class-loader). Use true to force initialization, and @@ -334,8 +321,6 @@ public class ZygoteInit { Log.e(TAG, "Error reading " + PRELOADED_CLASSES + ".", e); } finally { IoUtils.closeQuietly(is); - // Restore default. - runtime.setTargetHeapUtilization(defaultUtilization); // Fill in dex caches with classes, fields, and methods brought in by preloading. Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadDexCaches"); diff --git a/core/java/com/android/internal/widget/LockSettingsInternal.java b/core/java/com/android/internal/widget/LockSettingsInternal.java index d459bfbbcdc4..aab2f4b288b2 100644 --- a/core/java/com/android/internal/widget/LockSettingsInternal.java +++ b/core/java/com/android/internal/widget/LockSettingsInternal.java @@ -16,6 +16,8 @@ package com.android.internal.widget; +import android.annotation.Nullable; +import android.app.admin.PasswordMetrics; /** * LockSettingsService local system service interface. @@ -61,4 +63,18 @@ public abstract class LockSettingsInternal { long tokenHandle, byte[] token, int requestedQuality, int userId); public abstract boolean unlockUserWithToken(long tokenHandle, byte[] token, int userId); + + /** + * Returns PasswordMetrics object corresponding to the given user's lockscreen password. + * If the user has a password but its metrics isn't known yet (for example if the device + * has not been unlocked since boot), this method will return {@code null}. + * If the user has no password, a default PasswordMetrics (PASSWORD_QUALITY_UNSPECIFIED) + * will be returned. + * + * Calling this method on a managed profile user with unified challenge is undefined. + * + * @param userHandle the user for whom to provide metrics. + * @return the user password metrics. + */ + public abstract @Nullable PasswordMetrics getUserPasswordMetrics(int userHandle); } diff --git a/core/java/com/package.html b/core/java/com/package.html new file mode 100644 index 000000000000..8f35da9a8158 --- /dev/null +++ b/core/java/com/package.html @@ -0,0 +1,8 @@ +<!-- + This file is to hide classes in com.* packages from SDK +--> +<html> +<body> + {@hide} +</body> +</html> diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp index 2987c5ed56b5..11d321f0b038 100644 --- a/core/jni/android/graphics/Graphics.cpp +++ b/core/jni/android/graphics/Graphics.cpp @@ -220,10 +220,10 @@ SkIRect* GraphicsJNI::jrect_to_irect(JNIEnv* env, jobject obj, SkIRect* ir) { ALOG_ASSERT(env->IsInstanceOf(obj, gRect_class)); - ir->set(env->GetIntField(obj, gRect_leftFieldID), - env->GetIntField(obj, gRect_topFieldID), - env->GetIntField(obj, gRect_rightFieldID), - env->GetIntField(obj, gRect_bottomFieldID)); + ir->setLTRB(env->GetIntField(obj, gRect_leftFieldID), + env->GetIntField(obj, gRect_topFieldID), + env->GetIntField(obj, gRect_rightFieldID), + env->GetIntField(obj, gRect_bottomFieldID)); return ir; } @@ -241,10 +241,10 @@ SkRect* GraphicsJNI::jrectf_to_rect(JNIEnv* env, jobject obj, SkRect* r) { ALOG_ASSERT(env->IsInstanceOf(obj, gRectF_class)); - r->set(env->GetFloatField(obj, gRectF_leftFieldID), - env->GetFloatField(obj, gRectF_topFieldID), - env->GetFloatField(obj, gRectF_rightFieldID), - env->GetFloatField(obj, gRectF_bottomFieldID)); + r->setLTRB(env->GetFloatField(obj, gRectF_leftFieldID), + env->GetFloatField(obj, gRectF_topFieldID), + env->GetFloatField(obj, gRectF_rightFieldID), + env->GetFloatField(obj, gRectF_bottomFieldID)); return r; } @@ -252,10 +252,10 @@ SkRect* GraphicsJNI::jrect_to_rect(JNIEnv* env, jobject obj, SkRect* r) { ALOG_ASSERT(env->IsInstanceOf(obj, gRect_class)); - r->set(SkIntToScalar(env->GetIntField(obj, gRect_leftFieldID)), - SkIntToScalar(env->GetIntField(obj, gRect_topFieldID)), - SkIntToScalar(env->GetIntField(obj, gRect_rightFieldID)), - SkIntToScalar(env->GetIntField(obj, gRect_bottomFieldID))); + r->setLTRB(SkIntToScalar(env->GetIntField(obj, gRect_leftFieldID)), + SkIntToScalar(env->GetIntField(obj, gRect_topFieldID)), + SkIntToScalar(env->GetIntField(obj, gRect_rightFieldID)), + SkIntToScalar(env->GetIntField(obj, gRect_bottomFieldID))); return r; } diff --git a/core/jni/android/graphics/Region.cpp b/core/jni/android/graphics/Region.cpp index 1fb5fe3b99f1..87662f713449 100644 --- a/core/jni/android/graphics/Region.cpp +++ b/core/jni/android/graphics/Region.cpp @@ -61,7 +61,7 @@ static void Region_setRegion(JNIEnv* env, jobject, jlong dstHandle, jlong srcHan static jboolean Region_setRect(JNIEnv* env, jobject, jlong dstHandle, jint left, jint top, jint right, jint bottom) { SkRegion* dst = reinterpret_cast<SkRegion*>(dstHandle); - bool result = dst->setRect(left, top, right, bottom); + bool result = dst->setRect({left, top, right, bottom}); return boolTojboolean(result); } @@ -92,10 +92,7 @@ static jboolean Region_getBoundaryPath(JNIEnv* env, jobject, jlong regionHandle, static jboolean Region_op0(JNIEnv* env, jobject, jlong dstHandle, jint left, jint top, jint right, jint bottom, jint op) { SkRegion* dst = reinterpret_cast<SkRegion*>(dstHandle); - SkIRect ir; - - ir.set(left, top, right, bottom); - bool result = dst->op(ir, (SkRegion::Op)op); + bool result = dst->op({left, top, right, bottom}, (SkRegion::Op)op); return boolTojboolean(result); } @@ -139,13 +136,13 @@ static jboolean Region_contains(JNIEnv* env, jobject region, jint x, jint y) { } static jboolean Region_quickContains(JNIEnv* env, jobject region, jint left, jint top, jint right, jint bottom) { - bool result = GetSkRegion(env, region)->quickContains(left, top, right, bottom); + bool result = GetSkRegion(env, region)->quickContains({left, top, right, bottom}); return boolTojboolean(result); } static jboolean Region_quickRejectIIII(JNIEnv* env, jobject region, jint left, jint top, jint right, jint bottom) { SkIRect ir; - ir.set(left, top, right, bottom); + ir.setLTRB(left, top, right, bottom); bool result = GetSkRegion(env, region)->quickReject(ir); return boolTojboolean(result); } @@ -224,7 +221,7 @@ static jlong Region_createFromParcel(JNIEnv* env, jobject clazz, jobject parcel) SkRegion* region = new SkRegion; for (size_t x = 0; x + 4 <= rects.size(); x += 4) { - region->op(rects[x], rects[x+1], rects[x+2], rects[x+3], SkRegion::kUnion_Op); + region->op({rects[x], rects[x+1], rects[x+2], rects[x+3]}, SkRegion::kUnion_Op); } return reinterpret_cast<jlong>(region); diff --git a/core/jni/android_hardware_input_InputWindowHandle.cpp b/core/jni/android_hardware_input_InputWindowHandle.cpp index 64caf33c346a..2265268f4d20 100644 --- a/core/jni/android_hardware_input_InputWindowHandle.cpp +++ b/core/jni/android_hardware_input_InputWindowHandle.cpp @@ -29,6 +29,7 @@ #include "android_hardware_input_InputWindowHandle.h" #include "android_hardware_input_InputApplicationHandle.h" #include "android_util_Binder.h" +#include <binder/IPCThreadState.h> namespace android { @@ -80,6 +81,12 @@ NativeInputWindowHandle::NativeInputWindowHandle(jweak objWeak) : NativeInputWindowHandle::~NativeInputWindowHandle() { JNIEnv* env = AndroidRuntime::getJNIEnv(); env->DeleteWeakGlobalRef(mObjWeak); + + // Clear the weak reference to the layer handle and flush any binder ref count operations so we + // do not hold on to any binder references. + // TODO(b/139697085) remove this after it can be flushed automatically + mInfo.touchableRegionCropHandle.clear(); + IPCThreadState::self()->flushCommands(); } jobject NativeInputWindowHandle::getInputWindowHandleObjLocalRef(JNIEnv* env) { diff --git a/core/proto/android/stats/textclassifier/textclassifier_enums.proto b/core/proto/android/stats/textclassifier/textclassifier_enums.proto index 1885f19c6377..4be7b7c2df7c 100644 --- a/core/proto/android/stats/textclassifier/textclassifier_enums.proto +++ b/core/proto/android/stats/textclassifier/textclassifier_enums.proto @@ -60,6 +60,8 @@ enum EventType { MANUAL_REPLY = 19; // TextClassifier generated some actions ACTIONS_GENERATED = 20; + // Some text links were generated + LINKS_GENERATED = 21; } enum WidgetType { diff --git a/core/res/TEST_MAPPING b/core/res/TEST_MAPPING index 1d22d7823dd5..ccd91a41ab68 100644 --- a/core/res/TEST_MAPPING +++ b/core/res/TEST_MAPPING @@ -4,7 +4,7 @@ "name": "CtsPermission2TestCases", "options": [ { - "include-filter": "android.permission2.cts.PermissionPolicyTest#testPlatformPermissionPolicyUnaltered" + "include-filter": "android.permission2.cts.PermissionPolicyTest#platformPermissionPolicyIsUnaltered" } ] } diff --git a/core/res/res/values-mcc450-mnc08/config.xml b/core/res/res/values-mcc450-mnc08/config.xml index ca26ec1e810a..5edbaed11152 100644 --- a/core/res/res/values-mcc450-mnc08/config.xml +++ b/core/res/res/values-mcc450-mnc08/config.xml @@ -28,4 +28,14 @@ <!-- Do not set the system language as value of EF LI/EF PL --> <bool name="config_use_sim_language_file">false</bool> + <!-- Configures encoding type to parse the User Data of an SMS for reserved TP-DCS value. + Refer to SmsConstants.java + ENCODING_UNKNOWN = 0; + ENCODING_7BIT = 1; + ENCODING_8BIT = 2; + ENCODING_16BIT = 3; + ENCODING_KSC5601 = 4; + --> + <integer name="default_reserved_data_coding_scheme">4</integer> + </resources> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 0a60d71809fd..2cd39cb96c9b 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -3038,6 +3038,16 @@ string that's stored in 8-bit unpacked format) characters.--> <bool translatable="false" name="config_sms_decode_gsm_8bit_data">false</bool> + <!-- Configures encoding type to parse the User Data of an SMS for reserved TP-DCS value. + Refer to SmsConstants.java + ENCODING_UNKNOWN = 0; + ENCODING_7BIT = 1; + ENCODING_8BIT = 2; + ENCODING_16BIT = 3; + ENCODING_KSC5601 = 4; + --> + <integer name="default_reserved_data_coding_scheme">2</integer> + <!-- If EMS is not supported, framework breaks down EMS into single segment SMS and adds page info " x/y". This config is used to set which carrier doesn't support EMS and whether page info should be added at the beginning or the end. diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 58fc585b26b2..eaebd91cd92b 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -2657,6 +2657,7 @@ <java-symbol type="attr" name="ambientShadowAlpha" /> <java-symbol type="attr" name="spotShadowAlpha" /> <java-symbol type="bool" name="config_sms_decode_gsm_8bit_data" /> + <java-symbol type="integer" name="default_reserved_data_coding_scheme" /> <java-symbol type="dimen" name="text_size_small_material" /> <java-symbol type="attr" name="checkMarkGravity" /> <java-symbol type="layout" name="select_dialog_singlechoice_material" /> diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml index 9955c512686a..24172098491d 100644 --- a/core/tests/coretests/AndroidManifest.xml +++ b/core/tests/coretests/AndroidManifest.xml @@ -1270,10 +1270,8 @@ <action android:name="com.android.frameworks.coretests.activity.BROADCAST_REMOTE_DENIED" /> </intent-filter> </receiver> - <service android:name="android.app.activity.LocalService"> - <intent-filter> - <action android:name="com.android.frameworks.coretests.activity.SERVICE_LOCAL" /> - </intent-filter> + <service android:name="android.app.activity.ServiceTest$RemoteService" + android:process=":RemoteService"> <meta-data android:name="com.android.frameworks.coretests.string" android:value="foo" /> <meta-data android:name="com.android.frameworks.coretests.boolean" android:value="true" /> <meta-data android:name="com.android.frameworks.coretests.integer" android:value="100" /> @@ -1281,18 +1279,6 @@ <meta-data android:name="com.android.frameworks.coretests.float" android:value="100.1" /> <meta-data android:name="com.android.frameworks.coretests.reference" android:resource="@xml/metadata" /> </service> - <service android:name="android.app.activity.LocalDeniedService" - android:permission="com.android.frameworks.coretests.permission.TEST_DENIED"> - <intent-filter> - <action android:name="com.android.frameworks.coretests.activity.SERVICE_LOCAL_DENIED" /> - </intent-filter> - </service> - <service android:name="android.app.activity.LocalGrantedService" - android:permission="com.android.frameworks.coretests.permission.TEST_GRANTED"> - <intent-filter> - <action android:name="com.android.frameworks.coretests.activity.SERVICE_LOCAL_GRANTED" /> - </intent-filter> - </service> <service android:name="android.service.settings.suggestions.MockSuggestionService" diff --git a/core/tests/coretests/src/android/app/activity/LocalDeniedService.java b/core/tests/coretests/src/android/app/activity/LocalDeniedService.java deleted file mode 100644 index 3bdac22d9f1f..000000000000 --- a/core/tests/coretests/src/android/app/activity/LocalDeniedService.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2006 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.activity; - -public class LocalDeniedService extends LocalService -{ -} - diff --git a/core/tests/coretests/src/android/app/activity/LocalGrantedService.java b/core/tests/coretests/src/android/app/activity/LocalGrantedService.java deleted file mode 100644 index 7ab0fb4d372c..000000000000 --- a/core/tests/coretests/src/android/app/activity/LocalGrantedService.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2006 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.activity; - -public class LocalGrantedService extends LocalService -{ -} - diff --git a/core/tests/coretests/src/android/app/activity/LocalReceiver.java b/core/tests/coretests/src/android/app/activity/LocalReceiver.java index bfd543fdbe12..7f813390552c 100644 --- a/core/tests/coretests/src/android/app/activity/LocalReceiver.java +++ b/core/tests/coretests/src/android/app/activity/LocalReceiver.java @@ -23,9 +23,9 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.ReceiverCallNotAllowedException; import android.content.ServiceConnection; -import android.os.RemoteException; import android.os.IBinder; import android.os.Parcel; +import android.os.RemoteException; public class LocalReceiver extends BroadcastReceiver { public LocalReceiver() { @@ -52,7 +52,7 @@ public class LocalReceiver extends BroadcastReceiver { public void onServiceDisconnected(ComponentName name) { } }; - context.bindService(new Intent(context, LocalService.class), sc, 0); + context.bindService(new Intent(context, ServiceTest.RemoteService.class), sc, 0); context.unbindService(sc); } catch (ReceiverCallNotAllowedException e) { //resultString = "This is the correct behavior but not yet implemented"; diff --git a/core/tests/coretests/src/android/app/activity/LocalService.java b/core/tests/coretests/src/android/app/activity/LocalService.java deleted file mode 100644 index c31ca4b30a76..000000000000 --- a/core/tests/coretests/src/android/app/activity/LocalService.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (C) 2006 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.activity; - -import android.app.Service; -import android.content.Intent; -import android.os.Binder; -import android.os.Bundle; -import android.os.RemoteException; -import android.os.IBinder; -import android.os.Parcel; -import android.util.Log; - -public class LocalService extends Service { - private final IBinder mBinder = new Binder() { - - @Override - protected boolean onTransact(int code, Parcel data, Parcel reply, - int flags) throws RemoteException { - if (code == ServiceTest.SET_REPORTER_CODE) { - data.enforceInterface(ServiceTest.SERVICE_LOCAL); - mReportObject = data.readStrongBinder(); - return true; - } else { - return super.onTransact(code, data, reply, flags); - } - } - - }; - - private IBinder mReportObject; - private int mStartCount = 1; - - public LocalService() { - } - - @Override - public void onStart(Intent intent, int startId) { - //Log.i("LocalService", "onStart: " + intent); - if (intent.getExtras() != null) { - mReportObject = intent.getExtras().getIBinder(ServiceTest.REPORT_OBJ_NAME); - if (mReportObject != null) { - try { - Parcel data = Parcel.obtain(); - data.writeInterfaceToken(ServiceTest.SERVICE_LOCAL); - data.writeInt(mStartCount); - mStartCount++; - mReportObject.transact( - ServiceTest.STARTED_CODE, data, null, 0); - data.recycle(); - } catch (RemoteException e) { - } - } - } - } - - @Override - public void onDestroy() { - Log.i("LocalService", "onDestroy: mReportObject=" + mReportObject); - if (mReportObject != null) { - try { - Parcel data = Parcel.obtain(); - data.writeInterfaceToken(ServiceTest.SERVICE_LOCAL); - mReportObject.transact( - ServiceTest.DESTROYED_CODE, data, null, 0); - data.recycle(); - } catch (RemoteException e) { - } - } - } - - @Override - public IBinder onBind(Intent intent) { - Log.i("LocalService", "onBind: " + intent); - return mBinder; - } - - @Override - public boolean onUnbind(Intent intent) { - Log.i("LocalService", "onUnbind: " + intent); - if (mReportObject != null) { - try { - Parcel data = Parcel.obtain(); - data.writeInterfaceToken(ServiceTest.SERVICE_LOCAL); - mReportObject.transact( - ServiceTest.UNBIND_CODE, data, null, 0); - data.recycle(); - } catch (RemoteException e) { - } - } - return true; - } - - @Override - public void onRebind(Intent intent) { - Log.i("LocalService", "onUnbind: " + intent); - if (mReportObject != null) { - try { - Parcel data = Parcel.obtain(); - data.writeInterfaceToken(ServiceTest.SERVICE_LOCAL); - mReportObject.transact( - ServiceTest.REBIND_CODE, data, null, 0); - data.recycle(); - } catch (RemoteException e) { - } - } - } -} diff --git a/core/tests/coretests/src/android/app/activity/MetaDataTest.java b/core/tests/coretests/src/android/app/activity/MetaDataTest.java index cf27878e897e..be6e276d2806 100644 --- a/core/tests/coretests/src/android/app/activity/MetaDataTest.java +++ b/core/tests/coretests/src/android/app/activity/MetaDataTest.java @@ -125,7 +125,7 @@ public class MetaDataTest extends AndroidTestCase { @SmallTest public void testServiceWithData() throws Exception { - ComponentName cn = new ComponentName(mContext, LocalService.class); + ComponentName cn = new ComponentName(mContext, ServiceTest.RemoteService.class); ServiceInfo si = mContext.getPackageManager().getServiceInfo( cn, PackageManager.GET_META_DATA); diff --git a/core/tests/coretests/src/android/app/activity/ServiceTest.java b/core/tests/coretests/src/android/app/activity/ServiceTest.java index 9d2aebd1e6cd..c89f37db7fed 100644 --- a/core/tests/coretests/src/android/app/activity/ServiceTest.java +++ b/core/tests/coretests/src/android/app/activity/ServiceTest.java @@ -16,453 +16,250 @@ package android.app.activity; +import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.notNullValue; +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsNot.not; + +import android.app.ActivityManager; +import android.app.ActivityManager.RunningServiceInfo; +import android.app.Service; +import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.content.ServiceConnection; import android.os.Binder; -import android.os.Bundle; +import android.os.Handler; import android.os.IBinder; import android.os.Parcel; +import android.os.Process; import android.os.RemoteException; import androidx.test.filters.MediumTest; -import androidx.test.filters.Suppress; - -// These test binders purport to support an interface whose canonical -// interface name is ServiceTest.SERVICE_LOCAL -// Temporarily suppress, this test is causing unit test suite run to fail -// TODO: remove this suppress -@Suppress -public class ServiceTest extends ActivityTestsBase { - - public static final String SERVICE_LOCAL = - "com.android.frameworks.coretests.activity.SERVICE_LOCAL"; - public static final String SERVICE_LOCAL_GRANTED = - "com.android.frameworks.coretests.activity.SERVICE_LOCAL_GRANTED"; - public static final String SERVICE_LOCAL_DENIED = - "com.android.frameworks.coretests.activity.SERVICE_LOCAL_DENIED"; - - public static final String REPORT_OBJ_NAME = "report"; - - public static final int STARTED_CODE = 1; - public static final int DESTROYED_CODE = 2; - public static final int SET_REPORTER_CODE = 3; - public static final int UNBIND_CODE = 4; - public static final int REBIND_CODE = 5; - - public static final int STATE_START_1 = 0; - public static final int STATE_START_2 = 1; - public static final int STATE_UNBIND = 2; - public static final int STATE_DESTROY = 3; - public static final int STATE_REBIND = 4; - public static final int STATE_UNBIND_ONLY = 5; - public int mStartState; - - public IBinder mStartReceiver = new Binder() { - @Override - protected boolean onTransact(int code, Parcel data, Parcel reply, - int flags) throws RemoteException { - //Log.i("ServiceTest", "Received code " + code + " in state " + mStartState); - if (code == STARTED_CODE) { - data.enforceInterface(SERVICE_LOCAL); - int count = data.readInt(); - if (mStartState == STATE_START_1) { - if (count == 1) { - finishGood(); - } else { - finishBad("onStart() again on an object when it should have been the first time"); - } - } else if (mStartState == STATE_START_2) { - if (count == 2) { - finishGood(); - } else { - finishBad("onStart() the first time on an object when it should have been the second time"); - } - } else { - finishBad("onStart() was called when not expected (state="+mStartState+")"); - } - return true; - } else if (code == DESTROYED_CODE) { - data.enforceInterface(SERVICE_LOCAL); - if (mStartState == STATE_DESTROY) { - finishGood(); - } else { - finishBad("onDestroy() was called when not expected (state="+mStartState+")"); - } - return true; - } else if (code == UNBIND_CODE) { - data.enforceInterface(SERVICE_LOCAL); - if (mStartState == STATE_UNBIND) { - mStartState = STATE_DESTROY; - } else if (mStartState == STATE_UNBIND_ONLY) { - finishGood(); - } else { - finishBad("onUnbind() was called when not expected (state="+mStartState+")"); - } - return true; - } else if (code == REBIND_CODE) { - data.enforceInterface(SERVICE_LOCAL); - if (mStartState == STATE_REBIND) { - finishGood(); - } else { - finishBad("onRebind() was called when not expected (state="+mStartState+")"); - } - return true; - } else { - return super.onTransact(code, data, reply, flags); - } - } - }; - public class EmptyConnection implements ServiceConnection { - public void onServiceConnected(ComponentName name, IBinder service) { - } +import junit.framework.TestCase; - public void onServiceDisconnected(ComponentName name) { - } - } +import org.junit.Test; - public class TestConnection implements ServiceConnection { - private final boolean mExpectDisconnect; - private final boolean mSetReporter; - private boolean mMonitor; - private int mCount; - - public TestConnection(boolean expectDisconnect, boolean setReporter) { - mExpectDisconnect = expectDisconnect; - mSetReporter = setReporter; - mMonitor = !setReporter; - } +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.function.Supplier; - void setMonitor(boolean v) { - mMonitor = v; - } - - public void onServiceConnected(ComponentName name, IBinder service) { - if (mSetReporter) { - Parcel data = Parcel.obtain(); - data.writeInterfaceToken(SERVICE_LOCAL); - data.writeStrongBinder(mStartReceiver); - try { - service.transact(SET_REPORTER_CODE, data, null, 0); - } catch (RemoteException e) { - finishBad("DeadObjectException when sending reporting object"); - } - data.recycle(); - } - - if (mMonitor) { - mCount++; - if (mStartState == STATE_START_1) { - if (mCount == 1) { - finishGood(); - } else { - finishBad("onServiceConnected() again on an object when it should have been the first time"); - } - } else if (mStartState == STATE_START_2) { - if (mCount == 2) { - finishGood(); - } else { - finishBad("onServiceConnected() the first time on an object when it should have been the second time"); - } - } else { - finishBad("onServiceConnected() called unexpectedly"); - } - } - } - - public void onServiceDisconnected(ComponentName name) { - if (mMonitor) { - if (mStartState == STATE_DESTROY) { - if (mExpectDisconnect) { - finishGood(); - } else { - finishBad("onServiceDisconnected() when it shouldn't have been"); - } - } else { - finishBad("onServiceDisconnected() called unexpectedly"); - } - } +/** + * Test for verifying the behavior of {@link Service}. + * <p> + * Tests related to internal behavior are usually placed here, e.g. the restart delay may be + * different depending on the current amount of restarting services. + * <p> + * Build/Install/Run: + * atest FrameworksCoreTests:ServiceTest + */ +@MediumTest +public class ServiceTest extends TestCase { + private static final String ACTION_SERVICE_STARTED = RemoteService.class.getName() + "_STARTED"; + private static final String EXTRA_START_CODE = "start_code"; + private static final String EXTRA_PID = "pid"; + + private static final long TIMEOUT_SEC = 5; + private static final int NOT_STARTED = -1; + + private final Context mContext = getInstrumentation().getContext(); + private final Intent mServiceIntent = new Intent(mContext, RemoteService.class); + private TestConnection mCurrentConnection; + + @Override + public void tearDown() { + mContext.stopService(mServiceIntent); + if (mCurrentConnection != null) { + mContext.unbindService(mCurrentConnection); + mCurrentConnection = null; } } - void startExpectResult(Intent service) { - startExpectResult(service, new Bundle()); + @Test + public void testRestart_stickyStartedService_restarted() { + testRestartStartedService(Service.START_STICKY, true /* shouldRestart */); } - void startExpectResult(Intent service, Bundle bundle) { - bundle.putIBinder(REPORT_OBJ_NAME, mStartReceiver); - boolean success = false; - try { - //Log.i("foo", "STATE_START_1"); - mStartState = STATE_START_1; - getContext().startService(new Intent(service).putExtras(bundle)); - waitForResultOrThrow(5 * 1000, "service to start first time"); - //Log.i("foo", "STATE_START_2"); - mStartState = STATE_START_2; - getContext().startService(new Intent(service).putExtras(bundle)); - waitForResultOrThrow(5 * 1000, "service to start second time"); - success = true; - } finally { - if (!success) { - try { - getContext().stopService(service); - } catch (Exception e) { - // eat - } - } - } - //Log.i("foo", "STATE_DESTROY"); - mStartState = STATE_DESTROY; - getContext().stopService(service); - waitForResultOrThrow(5 * 1000, "service to be destroyed"); + @Test + public void testRestart_redeliveryStartedService_restarted() { + testRestartStartedService(Service.START_FLAG_REDELIVERY, true /* shouldRestart */); } - void startExpectNoPermission(Intent service) { - try { - getContext().startService(service); - fail("Expected security exception when starting " + service); - } catch (SecurityException e) { - // expected - } + @Test + public void testRestart_notStickyStartedService_notRestarted() { + testRestartStartedService(Service.START_NOT_STICKY, false /* shouldRestart */); } - void bindExpectResult(Intent service) { - TestConnection conn = new TestConnection(true, false); - TestConnection conn2 = new TestConnection(false, false); - boolean success = false; - try { - // Expect to see the TestConnection connected. - mStartState = STATE_START_1; - getContext().bindService(service, conn, 0); - getContext().startService(service); - waitForResultOrThrow(5 * 1000, "existing connection to receive service"); - - // Expect to see the second TestConnection connected. - getContext().bindService(service, conn2, 0); - waitForResultOrThrow(5 * 1000, "new connection to receive service"); - - getContext().unbindService(conn2); - success = true; - } finally { - if (!success) { - try { - getContext().stopService(service); - getContext().unbindService(conn); - getContext().unbindService(conn2); - } catch (Exception e) { - // eat - } - } - } - - // Expect to see the TestConnection disconnected. - mStartState = STATE_DESTROY; - getContext().stopService(service); - waitForResultOrThrow(5 * 1000, "existing connection to lose service"); - - getContext().unbindService(conn); - - conn = new TestConnection(true, true); - success = false; - try { - // Expect to see the TestConnection connected. - conn.setMonitor(true); - mStartState = STATE_START_1; - getContext().bindService(service, conn, 0); - getContext().startService(service); - waitForResultOrThrow(5 * 1000, "existing connection to receive service"); - - success = true; - } finally { - if (!success) { - try { - getContext().stopService(service); - getContext().unbindService(conn); - } catch (Exception e) { - // eat - } - } - } + private void testRestartStartedService(int startFlag, boolean shouldRestart) { + final int servicePid = startService(startFlag); + assertThat(servicePid, not(NOT_STARTED)); - // Expect to see the service unbind and then destroyed. - conn.setMonitor(false); - mStartState = STATE_UNBIND; - getContext().stopService(service); - waitForResultOrThrow(5 * 1000, "existing connection to lose service"); - - getContext().unbindService(conn); - - conn = new TestConnection(true, true); - success = false; - try { - // Expect to see the TestConnection connected. - conn.setMonitor(true); - mStartState = STATE_START_1; - getContext().bindService(service, conn, 0); - getContext().startService(service); - waitForResultOrThrow(5 * 1000, "existing connection to receive service"); - - success = true; - } finally { - if (!success) { - try { - getContext().stopService(service); - getContext().unbindService(conn); - } catch (Exception e) { - // eat - } - } - } - - // Expect to see the service unbind but not destroyed. - conn.setMonitor(false); - mStartState = STATE_UNBIND_ONLY; - getContext().unbindService(conn); - waitForResultOrThrow(5 * 1000, "existing connection to unbind service"); - - // Expect to see the service rebound. - mStartState = STATE_REBIND; - getContext().bindService(service, conn, 0); - waitForResultOrThrow(5 * 1000, "existing connection to rebind service"); + final int restartedServicePid = waitForServiceStarted( + () -> Process.killProcess(servicePid)); + assertThat(restartedServicePid, shouldRestart ? not(NOT_STARTED) : is(NOT_STARTED)); + } - // Expect to see the service unbind and then destroyed. - mStartState = STATE_UNBIND; - getContext().stopService(service); - waitForResultOrThrow(5 * 1000, "existing connection to lose service"); + @Test + public void testRestart_boundService_restarted() { + final int servicePid = bindService(Context.BIND_AUTO_CREATE); + assertThat(servicePid, not(NOT_STARTED)); - getContext().unbindService(conn); + Process.killProcess(servicePid); + // The service should be restarted and the connection will receive onServiceConnected again. + assertThat(mCurrentConnection.takePid(), not(NOT_STARTED)); } - void bindAutoExpectResult(Intent service) { - TestConnection conn = new TestConnection(false, true); - boolean success = false; - try { - conn.setMonitor(true); - mStartState = STATE_START_1; - getContext().bindService( - service, conn, Context.BIND_AUTO_CREATE); - waitForResultOrThrow(5 * 1000, "connection to start and receive service"); - success = true; - } finally { - if (!success) { - try { - getContext().unbindService(conn); - } catch (Exception e) { - // eat + @Test + public void testRestart_boundNotStickyStartedService_restarted() { + final ActivityManager am = mContext.getSystemService(ActivityManager.class); + final Supplier<RunningServiceInfo> serviceInfoGetter = () -> { + for (RunningServiceInfo rs : am.getRunningServices(Integer.MAX_VALUE)) { + if (mServiceIntent.getComponent().equals(rs.service)) { + return rs; } } - } - mStartState = STATE_UNBIND; - getContext().unbindService(conn); - waitForResultOrThrow(5 * 1000, "disconnecting from service"); - } - - void bindExpectNoPermission(Intent service) { - TestConnection conn = new TestConnection(false, false); - try { - getContext().bindService(service, conn, Context.BIND_AUTO_CREATE); - fail("Expected security exception when binding " + service); - } catch (SecurityException e) { - // expected - } finally { - getContext().unbindService(conn); - } - } - - - @MediumTest - public void testLocalStartClass() throws Exception { - startExpectResult(new Intent(getContext(), LocalService.class)); - } - - @MediumTest - public void testLocalStartAction() throws Exception { - startExpectResult(new Intent(SERVICE_LOCAL)); - } - - @MediumTest - public void testLocalBindClass() throws Exception { - bindExpectResult(new Intent(getContext(), LocalService.class)); - } - - @MediumTest - public void testLocalBindAction() throws Exception { - bindExpectResult(new Intent(SERVICE_LOCAL)); - } - - @MediumTest - public void testLocalBindAutoClass() throws Exception { - bindAutoExpectResult(new Intent(getContext(), LocalService.class)); + return null; + }; + + final int servicePid = bindService(Context.BIND_AUTO_CREATE); + assertThat(servicePid, not(NOT_STARTED)); + assertThat(startService(Service.START_NOT_STICKY), is(servicePid)); + + RunningServiceInfo info = serviceInfoGetter.get(); + assertThat(info, notNullValue()); + assertThat(info.started, is(true)); + + Process.killProcess(servicePid); + // The service will be restarted for connection but the started state should be gone. + final int restartedServicePid = mCurrentConnection.takePid(); + assertThat(restartedServicePid, not(NOT_STARTED)); + + info = serviceInfoGetter.get(); + assertThat(info, notNullValue()); + assertThat(info.started, is(false)); + assertThat(info.clientCount, is(1)); } - @MediumTest - public void testLocalBindAutoAction() throws Exception { - bindAutoExpectResult(new Intent(SERVICE_LOCAL)); - } + @Test + public void testRestart_notStickyStartedNoAutoCreateBoundService_notRestarted() { + final int servicePid = startService(Service.START_NOT_STICKY); + assertThat(servicePid, not(NOT_STARTED)); + assertThat(bindService(0 /* flags */), is(servicePid)); - @MediumTest - public void testLocalStartClassPermissionGranted() throws Exception { - startExpectResult(new Intent(getContext(), LocalGrantedService.class)); + Process.killProcess(servicePid); + assertThat(mCurrentConnection.takePid(), is(NOT_STARTED)); } - @MediumTest - public void testLocalStartActionPermissionGranted() throws Exception { - startExpectResult(new Intent(SERVICE_LOCAL_GRANTED)); + /** @return The pid of the started service. */ + private int startService(int code) { + return waitForServiceStarted( + () -> mContext.startService(mServiceIntent.putExtra(EXTRA_START_CODE, code))); } - @MediumTest - public void testLocalBindClassPermissionGranted() throws Exception { - bindExpectResult(new Intent(getContext(), LocalGrantedService.class)); - } + /** @return The pid of the started service. */ + private int waitForServiceStarted(Runnable serviceTrigger) { + final CompletableFuture<Integer> pidResult = new CompletableFuture<>(); + mContext.registerReceiver(new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + pidResult.complete(intent.getIntExtra(EXTRA_PID, NOT_STARTED)); + mContext.unregisterReceiver(this); + } + }, new IntentFilter(ACTION_SERVICE_STARTED)); - @MediumTest - public void testLocalBindActionPermissionGranted() throws Exception { - bindExpectResult(new Intent(SERVICE_LOCAL_GRANTED)); + serviceTrigger.run(); + try { + return pidResult.get(TIMEOUT_SEC, TimeUnit.SECONDS); + } catch (ExecutionException | InterruptedException | TimeoutException ignored) { + } + return NOT_STARTED; } - @MediumTest - public void testLocalBindAutoClassPermissionGranted() throws Exception { - bindAutoExpectResult(new Intent(getContext(), LocalGrantedService.class)); + /** @return The pid of the bound service. */ + private int bindService(int flags) { + mCurrentConnection = new TestConnection(); + assertThat(mContext.bindService(mServiceIntent, mCurrentConnection, flags), is(true)); + return mCurrentConnection.takePid(); } - @MediumTest - public void testLocalBindAutoActionPermissionGranted() throws Exception { - bindAutoExpectResult(new Intent(SERVICE_LOCAL_GRANTED)); - } + private static class TestConnection implements ServiceConnection { + private CompletableFuture<Integer> mServicePid = new CompletableFuture<>(); + + /** + * @return The pid of the connected service. It is only valid once after + * {@link #onServiceConnected} is called. + */ + int takePid() { + try { + return mServicePid.get(TIMEOUT_SEC, TimeUnit.SECONDS); + } catch (ExecutionException | InterruptedException | TimeoutException ignored) { + } finally { + mServicePid = new CompletableFuture<>(); + } + return NOT_STARTED; + } - @MediumTest - public void testLocalStartClassPermissionDenied() throws Exception { - startExpectNoPermission(new Intent(getContext(), LocalDeniedService.class)); - } + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + final Parcel data = Parcel.obtain(); + final Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(RemoteService.DESCRIPTOR); + try { + service.transact(RemoteService.TRANSACTION_GET_PID, data, reply, 0 /* flags */); + reply.readException(); + mServicePid.complete(reply.readInt()); + } catch (RemoteException e) { + mServicePid.complete(NOT_STARTED); + } finally { + data.recycle(); + reply.recycle(); + } + } - @MediumTest - public void testLocalStartActionPermissionDenied() throws Exception { - startExpectNoPermission(new Intent(SERVICE_LOCAL_DENIED)); + @Override + public void onServiceDisconnected(ComponentName name) { + } } - @MediumTest - public void testLocalBindClassPermissionDenied() throws Exception { - bindExpectNoPermission(new Intent(getContext(), LocalDeniedService.class)); - } + public static class RemoteService extends Service { + static final String DESCRIPTOR = RemoteService.class.getName(); + static final int TRANSACTION_GET_PID = Binder.FIRST_CALL_TRANSACTION; - @MediumTest - public void testLocalBindActionPermissionDenied() throws Exception { - bindExpectNoPermission(new Intent(SERVICE_LOCAL_DENIED)); - } + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + new Handler().post(() -> { + final Intent responseIntent = new Intent(ACTION_SERVICE_STARTED); + responseIntent.putExtra(EXTRA_PID, Process.myPid()); + sendBroadcast(responseIntent); + }); + if (intent != null && intent.hasExtra(EXTRA_START_CODE)) { + return intent.getIntExtra(EXTRA_START_CODE, Service.START_NOT_STICKY); + } + return super.onStartCommand(intent, flags, startId); + } - @MediumTest - public void testLocalUnbindTwice() throws Exception { - EmptyConnection conn = new EmptyConnection(); - getContext().bindService( - new Intent(SERVICE_LOCAL_GRANTED), conn, 0); - getContext().unbindService(conn); - try { - getContext().unbindService(conn); - fail("No exception thrown on second unbind"); - } catch (IllegalArgumentException e) { - //Log.i("foo", "Unbind exception", e); + @Override + public IBinder onBind(Intent intent) { + return new Binder() { + @Override + protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) + throws RemoteException { + if (code == TRANSACTION_GET_PID) { + data.enforceInterface(DESCRIPTOR); + reply.writeNoException(); + reply.writeInt(Process.myPid()); + return true; + } + return super.onTransact(code, data, reply, flags); + } + }; } } } diff --git a/core/tests/coretests/src/android/os/ProcessTest.java b/core/tests/coretests/src/android/os/ProcessTest.java index b749e715316a..9de450196fa0 100644 --- a/core/tests/coretests/src/android/os/ProcessTest.java +++ b/core/tests/coretests/src/android/os/ProcessTest.java @@ -29,8 +29,10 @@ public class ProcessTest extends TestCase { assertEquals(Process.BLUETOOTH_UID, Process.getUidForName("bluetooth")); assertEquals(Process.FIRST_APPLICATION_UID, Process.getUidForName("u0_a0")); assertEquals(UserHandle.getUid(1, Process.SYSTEM_UID), Process.getUidForName("u1_system")); - assertEquals(UserHandle.getUid(2, Process.FIRST_ISOLATED_UID), + assertEquals(UserHandle.getUid(2, Process.FIRST_APP_ZYGOTE_ISOLATED_UID), Process.getUidForName("u2_i0")); + assertEquals(UserHandle.getUid(2, Process.FIRST_ISOLATED_UID), + Process.getUidForName("u2_i9000")); assertEquals(UserHandle.getUid(3, Process.FIRST_APPLICATION_UID + 100), Process.getUidForName("u3_a100")); } diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java index 1e558287e21b..337663e33cd0 100644 --- a/core/tests/coretests/src/android/view/InsetsControllerTest.java +++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java @@ -145,6 +145,7 @@ public class InsetsControllerTest { InsetsSourceControl ime = controls[2]; InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { + mController.getSourceConsumer(TYPE_IME).onWindowFocusGained(); // since there is no focused view, forcefully make IME visible. mController.applyImeVisibility(true /* setVisible */); mController.show(Type.all()); @@ -160,6 +161,7 @@ public class InsetsControllerTest { assertFalse(mController.getSourceConsumer(navBar.getType()).isVisible()); assertFalse(mController.getSourceConsumer(topBar.getType()).isVisible()); assertFalse(mController.getSourceConsumer(ime.getType()).isVisible()); + mController.getSourceConsumer(TYPE_IME).onWindowFocusLost(); }); InstrumentationRegistry.getInstrumentation().waitForIdleSync(); } @@ -172,12 +174,14 @@ public class InsetsControllerTest { controls[0] = ime; mController.onControlsChanged(controls); InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { + mController.getSourceConsumer(TYPE_IME).onWindowFocusGained(); mController.applyImeVisibility(true); mController.cancelExistingAnimation(); assertTrue(mController.getSourceConsumer(ime.getType()).isVisible()); mController.applyImeVisibility(false); mController.cancelExistingAnimation(); assertFalse(mController.getSourceConsumer(ime.getType()).isVisible()); + mController.getSourceConsumer(TYPE_IME).onWindowFocusLost(); }); InstrumentationRegistry.getInstrumentation().waitForIdleSync(); } diff --git a/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java b/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java index 971e143927b3..e5fe2d021d9a 100644 --- a/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java +++ b/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java @@ -18,8 +18,10 @@ package android.view; import static android.view.InsetsState.TYPE_TOP_BAR; +import static junit.framework.TestCase.assertFalse; +import static junit.framework.TestCase.assertTrue; + import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; @@ -40,6 +42,7 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; +import org.mockito.Mockito; import org.mockito.MockitoAnnotations; /** @@ -60,6 +63,7 @@ public class InsetsSourceConsumerTest { private SurfaceSession mSession = new SurfaceSession(); private SurfaceControl mLeash; @Mock Transaction mMockTransaction; + private InsetsSource mSpyInsetsSource; @Before public void setup() { @@ -77,7 +81,11 @@ public class InsetsSourceConsumerTest { } catch (BadTokenException e) { // activity isn't running, lets ignore BadTokenException. } - mConsumer = new InsetsSourceConsumer(TYPE_TOP_BAR, new InsetsState(), + InsetsState state = new InsetsState(); + mSpyInsetsSource = Mockito.spy(new InsetsSource(TYPE_TOP_BAR)); + state.addSource(mSpyInsetsSource); + + mConsumer = new InsetsSourceConsumer(TYPE_TOP_BAR, state, () -> mMockTransaction, new InsetsController(viewRootImpl)); }); instrumentation.waitForIdleSync(); @@ -88,14 +96,15 @@ public class InsetsSourceConsumerTest { @Test public void testHide() { mConsumer.hide(); - verify(mMockTransaction).hide(eq(mLeash)); + assertFalse("Consumer should not be visible", mConsumer.isVisible()); + verify(mSpyInsetsSource).setVisible(eq(false)); } @Test public void testShow() { - mConsumer.hide(); mConsumer.show(); - verify(mMockTransaction, atLeastOnce()).show(eq(mLeash)); + assertTrue("Consumer should be visible", mConsumer.isVisible()); + verify(mSpyInsetsSource).setVisible(eq(true)); } @Test diff --git a/libs/androidfw/ApkAssets.cpp b/libs/androidfw/ApkAssets.cpp index 9f4a6193b434..cf2ef3070385 100644 --- a/libs/androidfw/ApkAssets.cpp +++ b/libs/androidfw/ApkAssets.cpp @@ -116,6 +116,7 @@ std::unique_ptr<const ApkAssets> ApkAssets::LoadImpl( if (result != 0) { LOG(ERROR) << "Failed to open APK '" << path << "' " << ::ErrorCodeString(result); + ::CloseArchive(unmanaged_handle); return {}; } diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp index 8a035dbbc0f5..535386920265 100644 --- a/libs/androidfw/ResourceTypes.cpp +++ b/libs/androidfw/ResourceTypes.cpp @@ -7402,12 +7402,12 @@ void ResTable::print_value(const Package* pkg, const Res_value& value) const print_complex(value.data, true); printf("\n"); } else if (value.dataType >= Res_value::TYPE_FIRST_COLOR_INT - || value.dataType <= Res_value::TYPE_LAST_COLOR_INT) { + && value.dataType <= Res_value::TYPE_LAST_COLOR_INT) { printf("(color) #%08x\n", value.data); } else if (value.dataType == Res_value::TYPE_INT_BOOLEAN) { printf("(boolean) %s\n", value.data ? "true" : "false"); } else if (value.dataType >= Res_value::TYPE_FIRST_INT - || value.dataType <= Res_value::TYPE_LAST_INT) { + && value.dataType <= Res_value::TYPE_LAST_INT) { printf("(int) 0x%08x or %d\n", value.data, value.data); } else { printf("(unknown type) t=0x%02x d=0x%08x (s=0x%04x r=0x%02x)\n", diff --git a/libs/hwui/DamageAccumulator.cpp b/libs/hwui/DamageAccumulator.cpp index 2d2df52073f4..b39f4f20dc0d 100644 --- a/libs/hwui/DamageAccumulator.cpp +++ b/libs/hwui/DamageAccumulator.cpp @@ -130,7 +130,7 @@ static inline void mapRect(const Matrix4* matrix, const SkRect& in, SkRect* out) // calculations. Just give up and expand to DIRTY_MIN/DIRTY_MAX temp.set(DIRTY_MIN, DIRTY_MIN, DIRTY_MAX, DIRTY_MAX); } - out->join(RECT_ARGS(temp)); + out->join({RECT_ARGS(temp)}); } void DamageAccumulator::applyMatrix4Transform(DirtyStack* frame) { @@ -145,7 +145,7 @@ static inline void applyMatrix(const SkMatrix* transform, SkRect* rect) { // Don't attempt to calculate damage for a perspective transform // as the numbers this works with can break the perspective // calculations. Just give up and expand to DIRTY_MIN/DIRTY_MAX - rect->set(DIRTY_MIN, DIRTY_MIN, DIRTY_MAX, DIRTY_MAX); + rect->setLTRB(DIRTY_MIN, DIRTY_MIN, DIRTY_MAX, DIRTY_MAX); } } } @@ -209,7 +209,7 @@ void DamageAccumulator::applyRenderNodeTransform(DirtyStack* frame) { // Perform clipping if (props.getClipDamageToBounds() && !frame->pendingDirty.isEmpty()) { - if (!frame->pendingDirty.intersect(0, 0, props.getWidth(), props.getHeight())) { + if (!frame->pendingDirty.intersect(SkRect::MakeIWH(props.getWidth(), props.getHeight()))) { frame->pendingDirty.setEmpty(); } } @@ -233,7 +233,7 @@ void DamageAccumulator::applyRenderNodeTransform(DirtyStack* frame) { } void DamageAccumulator::dirty(float left, float top, float right, float bottom) { - mHead->pendingDirty.join(left, top, right, bottom); + mHead->pendingDirty.join({left, top, right, bottom}); } void DamageAccumulator::peekAtDirty(SkRect* dest) const { diff --git a/libs/hwui/DisplayListOps.in b/libs/hwui/DisplayListOps.in index 2deb5657c877..4a252afc1df3 100644 --- a/libs/hwui/DisplayListOps.in +++ b/libs/hwui/DisplayListOps.in @@ -49,3 +49,4 @@ X(DrawVertices) X(DrawAtlas) X(DrawShadowRec) X(DrawVectorDrawable) +X(DrawWebView) diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp index c8eb1ca55910..c0df2faf120a 100644 --- a/libs/hwui/RecordingCanvas.cpp +++ b/libs/hwui/RecordingCanvas.cpp @@ -16,6 +16,7 @@ #include "RecordingCanvas.h" +#include "pipeline/skia/FunctorDrawable.h" #include "VectorDrawable.h" #include "SkAndroidFrameworkUtils.h" @@ -496,6 +497,16 @@ struct DrawVectorDrawable final : Op { SkPaint paint; BitmapPalette palette; }; +struct DrawWebView final : Op { + static const auto kType = Type::DrawWebView; + DrawWebView(skiapipeline::FunctorDrawable* drawable) : drawable(sk_ref_sp(drawable)) {} + sk_sp<skiapipeline::FunctorDrawable> drawable; + // We can't invoke SkDrawable::draw directly, because VkFunctorDrawable expects + // SkDrawable::onSnapGpuDrawHandler callback instead of SkDrawable::onDraw. + // SkCanvas::drawDrawable/SkGpuDevice::drawDrawable has the logic to invoke + // onSnapGpuDrawHandler. + void draw(SkCanvas* c, const SkMatrix&) const { c->drawDrawable(drawable.get()); } +}; } template <typename T, typename... Args> @@ -680,6 +691,9 @@ void DisplayListData::drawShadowRec(const SkPath& path, const SkDrawShadowRec& r void DisplayListData::drawVectorDrawable(VectorDrawableRoot* tree) { this->push<DrawVectorDrawable>(0, tree); } +void DisplayListData::drawWebView(skiapipeline::FunctorDrawable* drawable) { + this->push<DrawWebView>(0, drawable); +} typedef void (*draw_fn)(const void*, SkCanvas*, const SkMatrix&); typedef void (*void_fn)(const void*); @@ -986,5 +1000,9 @@ void RecordingCanvas::drawVectorDrawable(VectorDrawableRoot* tree) { fDL->drawVectorDrawable(tree); } +void RecordingCanvas::drawWebView(skiapipeline::FunctorDrawable* drawable) { + fDL->drawWebView(drawable); +} + } // namespace uirenderer } // namespace android diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h index 16ec877002f7..a79b7c00ba04 100644 --- a/libs/hwui/RecordingCanvas.h +++ b/libs/hwui/RecordingCanvas.h @@ -36,6 +36,10 @@ namespace android { namespace uirenderer { +namespace skiapipeline { +class FunctorDrawable; +} + enum class DisplayListOpType : uint8_t { #define X(T) T, #include "DisplayListOps.in" @@ -119,6 +123,7 @@ private: SkBlendMode, const SkRect*, const SkPaint*); void drawShadowRec(const SkPath&, const SkDrawShadowRec&); void drawVectorDrawable(VectorDrawableRoot* tree); + void drawWebView(skiapipeline::FunctorDrawable*); template <typename T, typename... Args> void* push(size_t, Args&&...); @@ -203,6 +208,7 @@ public: void onDrawShadowRec(const SkPath&, const SkDrawShadowRec&) override; void drawVectorDrawable(VectorDrawableRoot* tree); + void drawWebView(skiapipeline::FunctorDrawable*); /** * If "isClipMayBeComplex" returns false, it is guaranteed the current clip is a rectangle. diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp index a1be5b72a5c5..2ba6fbe76de1 100644 --- a/libs/hwui/hwui/Bitmap.cpp +++ b/libs/hwui/hwui/Bitmap.cpp @@ -361,7 +361,7 @@ void Bitmap::getSkBitmap(SkBitmap* outBitmap) { void Bitmap::getBounds(SkRect* bounds) const { SkASSERT(bounds); - bounds->set(0, 0, SkIntToScalar(width()), SkIntToScalar(height())); + bounds->setIWH(width(), height()); } #ifdef __ANDROID__ // Layoutlib does not support hardware acceleration diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp index 0db5133037b0..d67cf8c9c73f 100644 --- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp +++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp @@ -158,7 +158,7 @@ void SkiaRecordingCanvas::drawWebViewFunctor(int functor) { functorDrawable = mDisplayList->allocateDrawable<GLFunctorDrawable>(functor, asSkCanvas()); } mDisplayList->mChildFunctors.push_back(functorDrawable); - drawDrawable(functorDrawable); + mRecorder.drawWebView(functorDrawable); #endif } diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index 88a0c6ea3085..aad15ab9b0df 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -726,7 +726,7 @@ SkRect CanvasContext::computeDirtyRect(const Frame& frame, SkRect* dirty) { // New surface needs a full draw dirty->setEmpty(); } else { - if (!dirty->isEmpty() && !dirty->intersect(0, 0, frame.width(), frame.height())) { + if (!dirty->isEmpty() && !dirty->intersect(SkRect::MakeIWH(frame.width(), frame.height()))) { ALOGW("Dirty " RECT_STRING " doesn't intersect with 0 0 %d %d ?", SK_RECT_ARGS(*dirty), frame.width(), frame.height()); dirty->setEmpty(); @@ -735,7 +735,7 @@ SkRect CanvasContext::computeDirtyRect(const Frame& frame, SkRect* dirty) { } if (dirty->isEmpty()) { - dirty->set(0, 0, frame.width(), frame.height()); + dirty->setIWH(frame.width(), frame.height()); } // At this point dirty is the area of the window to update. However, @@ -751,7 +751,7 @@ SkRect CanvasContext::computeDirtyRect(const Frame& frame, SkRect* dirty) { if (frame.bufferAge() > (int)mSwapHistory.size()) { // We don't have enough history to handle this old of a buffer // Just do a full-draw - dirty->set(0, 0, frame.width(), frame.height()); + dirty->setIWH(frame.width(), frame.height()); } else { // At this point we haven't yet added the latest frame // to the damage history (happens below) diff --git a/libs/hwui/tests/common/scenes/RectGridAnimation.cpp b/libs/hwui/tests/common/scenes/RectGridAnimation.cpp index d5ecfaff4f0c..80b5cc191089 100644 --- a/libs/hwui/tests/common/scenes/RectGridAnimation.cpp +++ b/libs/hwui/tests/common/scenes/RectGridAnimation.cpp @@ -37,7 +37,7 @@ public: SkRegion region; for (int xOffset = 0; xOffset < 200; xOffset += 2) { for (int yOffset = 0; yOffset < 200; yOffset += 2) { - region.op(xOffset, yOffset, xOffset + 1, yOffset + 1, SkRegion::kUnion_Op); + region.op({xOffset, yOffset, xOffset + 1, yOffset + 1}, SkRegion::kUnion_Op); } } diff --git a/location/java/android/location/GnssCapabilities.java b/location/java/android/location/GnssCapabilities.java index 36fe8dab5dea..2e2f98432d2e 100644 --- a/location/java/android/location/GnssCapabilities.java +++ b/location/java/android/location/GnssCapabilities.java @@ -16,6 +16,7 @@ package android.location; +import android.annotation.NonNull; import android.annotation.SystemApi; /** @@ -164,6 +165,7 @@ public final class GnssCapabilities { return hasCapability(MEASUREMENT_CORRECTIONS_REFLECTING_PLANE); } + @NonNull @Override public String toString() { StringBuilder sb = new StringBuilder("GnssCapabilities: ( "); diff --git a/location/java/android/location/GnssMeasurementCorrections.java b/location/java/android/location/GnssMeasurementCorrections.java index 3e32c21da23b..a23213ff260c 100644 --- a/location/java/android/location/GnssMeasurementCorrections.java +++ b/location/java/android/location/GnssMeasurementCorrections.java @@ -176,6 +176,7 @@ public final class GnssMeasurementCorrections implements Parcelable { } }; + @NonNull @Override public String toString() { final String format = " %-29s = %s\n"; diff --git a/location/java/android/location/GnssReflectingPlane.java b/location/java/android/location/GnssReflectingPlane.java index 9d05287f6b76..1acdd1ecce0b 100644 --- a/location/java/android/location/GnssReflectingPlane.java +++ b/location/java/android/location/GnssReflectingPlane.java @@ -107,6 +107,7 @@ public final class GnssReflectingPlane implements Parcelable { } }; + @NonNull @Override public String toString() { final String format = " %-29s = %s\n"; diff --git a/location/java/android/location/GnssSingleSatCorrection.java b/location/java/android/location/GnssSingleSatCorrection.java index e9019097e327..aeca562fced2 100644 --- a/location/java/android/location/GnssSingleSatCorrection.java +++ b/location/java/android/location/GnssSingleSatCorrection.java @@ -268,6 +268,7 @@ public final class GnssSingleSatCorrection implements Parcelable { } }; + @NonNull @Override public String toString() { final String format = " %-29s = %s\n"; diff --git a/location/java/android/location/GpsClock.java b/location/java/android/location/GpsClock.java index 52ba60e36ffd..f1237662a559 100644 --- a/location/java/android/location/GpsClock.java +++ b/location/java/android/location/GpsClock.java @@ -16,6 +16,7 @@ package android.location; +import android.annotation.NonNull; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; @@ -437,6 +438,7 @@ public class GpsClock implements Parcelable { return 0; } + @NonNull @Override public String toString() { final String format = " %-15s = %s\n"; diff --git a/location/java/android/location/GpsMeasurement.java b/location/java/android/location/GpsMeasurement.java index 51718b85103a..27a81899bedc 100644 --- a/location/java/android/location/GpsMeasurement.java +++ b/location/java/android/location/GpsMeasurement.java @@ -16,6 +16,7 @@ package android.location; +import android.annotation.NonNull; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; @@ -1244,6 +1245,7 @@ public class GpsMeasurement implements Parcelable { return 0; } + @NonNull @Override public String toString() { final String format = " %-29s = %s\n"; diff --git a/location/java/android/location/GpsMeasurementsEvent.java b/location/java/android/location/GpsMeasurementsEvent.java index 1cd1fb4e3cb2..d69158d335f4 100644 --- a/location/java/android/location/GpsMeasurementsEvent.java +++ b/location/java/android/location/GpsMeasurementsEvent.java @@ -140,6 +140,7 @@ public class GpsMeasurementsEvent implements Parcelable { parcel.writeTypedArray(measurementsArray, flags); } + @NonNull @Override public String toString() { StringBuilder builder = new StringBuilder("[ GpsMeasurementsEvent:\n\n"); diff --git a/location/java/android/location/GpsNavigationMessage.java b/location/java/android/location/GpsNavigationMessage.java index 77f011374dab..6eeea2623a8b 100644 --- a/location/java/android/location/GpsNavigationMessage.java +++ b/location/java/android/location/GpsNavigationMessage.java @@ -290,6 +290,7 @@ public class GpsNavigationMessage implements Parcelable { return 0; } + @NonNull @Override public String toString() { final String format = " %-15s = %s\n"; diff --git a/location/java/android/location/GpsNavigationMessageEvent.java b/location/java/android/location/GpsNavigationMessageEvent.java index 2aa685cca757..f60e5c71ab16 100644 --- a/location/java/android/location/GpsNavigationMessageEvent.java +++ b/location/java/android/location/GpsNavigationMessageEvent.java @@ -109,6 +109,7 @@ public class GpsNavigationMessageEvent implements Parcelable { parcel.writeParcelable(mNavigationMessage, flags); } + @NonNull @Override public String toString() { StringBuilder builder = new StringBuilder("[ GpsNavigationMessageEvent:\n\n"); diff --git a/location/java/android/location/LocationRequest.java b/location/java/android/location/LocationRequest.java index a05d8501bc1f..0902acf176d4 100644 --- a/location/java/android/location/LocationRequest.java +++ b/location/java/android/location/LocationRequest.java @@ -734,6 +734,7 @@ public final class LocationRequest implements Parcelable { } } + @NonNull @Override public String toString() { StringBuilder s = new StringBuilder(); diff --git a/location/lib/Android.bp b/location/lib/Android.bp index b15cc5ccd656..ff6921d3e1c2 100644 --- a/location/lib/Android.bp +++ b/location/lib/Android.bp @@ -16,13 +16,12 @@ java_sdk_library { name: "com.android.location.provider", - srcs: ["java/**/*.java"], + srcs: [ + "java/**/*.java", + ":framework-srcs", + ], libs: [ "androidx.annotation_annotation", ], api_packages: ["com.android.location.provider"], - srcs_lib: "framework-minus-apex", - // TODO(b/70046217): remove core/java and android below. It was added to provide definitions for - // types like android.os.Bundle - srcs_lib_whitelist_pkgs: ["android", "com.android.internal.location"], } diff --git a/media/Android.bp b/media/Android.bp index ef322397deb3..a59b3e76faed 100644 --- a/media/Android.bp +++ b/media/Android.bp @@ -45,13 +45,6 @@ filegroup { } filegroup { - name: "updatable-media-srcs-without-aidls", - srcs : [ - ":mediasession2-srcs-without-aidls", - ], -} - -filegroup { name: "mediasession2-srcs", srcs: [ "apex/java/android/media/Controller2Link.java", @@ -71,19 +64,6 @@ filegroup { } filegroup { - name: "mediasession2-srcs-without-aidls", - srcs: [ - ":mediasession2-srcs", - ], - exclude_srcs: [ - "apex/java/android/media/IMediaController2.aidl", - "apex/java/android/media/IMediaSession2.aidl", - "apex/java/android/media/IMediaSession2Service.aidl", - ], - path: "apex/java", -} - -filegroup { name: "mediaplayer2-srcs", srcs: [ "apex/java/android/media/CloseGuard.java", @@ -113,21 +93,21 @@ metalava_updatable_media_args = " --error UnhiddenSystemApi " + droidstubs { name: "updatable-media-stubs", srcs: [ - ":updatable-media-srcs-without-aidls", + ":updatable-media-srcs", ":framework-media-annotation-srcs", ], args: metalava_updatable_media_args, - // Ideally, sdk_version here should be "current_system", but "current - 1" is used - // to avoid dependency cycle with framework. - sdk_version: "28", + aidl: { + // TODO(b/135922046) remove this + include_dirs: ["frameworks/base/core/java"], + }, + sdk_version: "system_current", } java_library { name: "updatable_media_stubs", srcs: [":updatable-media-stubs"], - // Ideally, sdk_version here should be "current_system", but "current - 1" is used - // to avoid dependency cycle with framework. - sdk_version: "28", + sdk_version: "system_current", } java_library { diff --git a/media/java/android/media/AudioFocusInfo.java b/media/java/android/media/AudioFocusInfo.java index ee89509951df..675cf7360b82 100644 --- a/media/java/android/media/AudioFocusInfo.java +++ b/media/java/android/media/AudioFocusInfo.java @@ -17,6 +17,7 @@ package android.media; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.TestApi; import android.os.Parcel; @@ -155,7 +156,7 @@ public final class AudioFocusInfo implements Parcelable { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (this == obj) return true; if (obj == null) diff --git a/media/java/android/media/audiopolicy/AudioProductStrategy.java b/media/java/android/media/audiopolicy/AudioProductStrategy.java index e456dad88fa4..2799d46cbb47 100644 --- a/media/java/android/media/audiopolicy/AudioProductStrategy.java +++ b/media/java/android/media/audiopolicy/AudioProductStrategy.java @@ -299,6 +299,7 @@ public final class AudioProductStrategy implements Parcelable { } }; + @NonNull @Override public String toString() { StringBuilder s = new StringBuilder(); diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java index 6fd3342fc84e..92fb31bd4de8 100644 --- a/media/java/android/media/session/MediaSessionManager.java +++ b/media/java/android/media/session/MediaSessionManager.java @@ -1006,7 +1006,7 @@ public final class MediaSessionManager { * @return {@code true} if equals, {@code false} otherwise */ @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (!(obj instanceof RemoteUserInfo)) { return false; } diff --git a/media/java/android/media/tv/TvContentRating.java b/media/java/android/media/tv/TvContentRating.java index 6197c707c752..9e671b1177cd 100644 --- a/media/java/android/media/tv/TvContentRating.java +++ b/media/java/android/media/tv/TvContentRating.java @@ -179,6 +179,10 @@ import java.util.Objects; * <td>TV content rating system for Canada (French)</td> * </tr> * <tr> + * <td>DTMB</td> + * <td>DTMB content rating system</td> + * </tr> + * <tr> * <td>DVB</td> * <td>DVB content rating system</td> * </tr> @@ -199,10 +203,18 @@ import java.util.Objects; * <td>TV content rating system for South Korea</td> * </tr> * <tr> + * <td>NZ_TV</td> + * <td>TV content rating system for New Zealand</td> + * </tr> + * <tr> * <td>SG_TV</td> * <td>TV content rating system for Singapore</td> * </tr> * <tr> + * <td>TH_TV</td> + * <td>TV content rating system for Thailand</td> + * </tr> + * <tr> * <td>US_MV</td> * <td>Movie content rating system for the United States</td> * </tr> @@ -356,6 +368,67 @@ import java.util.Objects; * <td>Only to be viewed by adults</td> * </tr> * <tr> + * <td valign="top" rowspan="15">DTMB</td> + * <td>DTMB_4</td> + * <td>Recommended for ages 4 and over</td> + * </tr> + * <tr> + * <td>DTMB_5</td> + * <td>Recommended for ages 5 and over</td> + * </tr> + * <tr> + * <td>DTMB_6</td> + * <td>Recommended for ages 6 and over</td> + * </tr> + * <tr> + * <td>DTMB_7</td> + * <td>Recommended for ages 7 and over</td> + * </tr> + * <tr> + * <td>DTMB_8</td> + * <td>Recommended for ages 8 and over</td> + * </tr> + * <tr> + * <td>DTMB_9</td> + * <td>Recommended for ages 9 and over</td> + * </tr> + * <tr> + * <td>DTMB_10</td> + * <td>Recommended for ages 10 and over</td> + * </tr> + * <tr> + * <td>DTMB_11</td> + * <td>Recommended for ages 11 and over</td> + * </tr> + * <tr> + * <td>DTMB_12</td> + * <td>Recommended for ages 12 and over</td> + * </tr> + * <tr> + * <td>DTMB_13</td> + * <td>Recommended for ages 13 and over</td> + * </tr> + * <tr> + * <td>DTMB_14</td> + * <td>Recommended for ages 14 and over</td> + * </tr> + * <tr> + * <td>DTMB_15</td> + * <td>Recommended for ages 15 and over</td> + * </tr> + * <tr> + * <td>DTMB_16</td> + * <td>Recommended for ages 16 and over</td> + * </tr> + * <tr> + * <td>DTMB_17</td> + * <td>Recommended for ages 17 and over</td> + * </tr> + * <tr> + * <td>DTMB_18</td> + * <td>Recommended for ages 18 and over</td> + * </tr> + * <tr> * <td valign="top" rowspan="15">DVB</td> * <td>DVB_4</td> * <td>Recommended for ages 4 and over</td> @@ -648,6 +721,22 @@ import java.util.Objects; * <td>For adults only</td> * </tr> * <tr> + * <td valign="top" rowspan="3">NZ_TV</td> + * <td>NZ_TV_G</td> + * <td>Programmes which exclude material likely to be unsuitable for children. Programmes + * may not necessarily be designed for child viewers but should not contain material likely + * to alarm or distress them.</td> + * </tr> + * <tr> + * <td>NZ_TV_PGR</td> + * <td>Programmes containing material more suited for mature audiences but not necessarily + * unsuitable for child viewers when subject to the guidance of a parent or an adult.</td> + * </tr> + * <tr> + * <td>NZ_TV_AO</td> + * <td>Programmes containing adult themes and directed primarily at mature audiences.</td> + * </tr> + * <tr> * <td valign="top" rowspan="6">SG_TV</td> * <td>SG_TV_G</td> * <td>Suitable for all ages</td> @@ -674,6 +763,31 @@ import java.util.Objects; * <td>Suitable for adults aged 21 and above</td> * </tr> * <tr> + * <td valign="top" rowspan="6">TH_TV</td> + * <td>TH_TV_4</td> + * <td>Suitable for audiences 3 to 5 years of age</td> + * </tr> + * <tr> + * <td>TH_TV_6</td> + * <td>Suitable for audiences 6 to 12 years of age</td> + * </tr> + * <tr> + * <td>TH_TV_10</td> + * <td>Suitable for all audiences</td> + * </tr> + * <tr> + * <td>TH_TV_13</td> + * <td>Parental guidance suggested for viewers age below 13</td> + * </tr> + * <tr> + * <td>TH_TV_18</td> + * <td>Parental guidance suggested for viewers age below 18</td> + * </tr> + * <tr> + * <td>TH_TV_19</td> + * <td>Not suitable for children and teenagers</td> + * </tr> + * <tr> * <td valign="top" rowspan="5">US_MV</td> * <td>US_MV_G</td> * <td>General audiences</td> diff --git a/media/java/android/media/tv/TvInputHardwareInfo.java b/media/java/android/media/tv/TvInputHardwareInfo.java index 5b316bedd134..b12f7c551288 100644 --- a/media/java/android/media/tv/TvInputHardwareInfo.java +++ b/media/java/android/media/tv/TvInputHardwareInfo.java @@ -19,12 +19,14 @@ package android.media.tv; import static java.lang.annotation.RetentionPolicy.SOURCE; import android.annotation.IntDef; +import android.annotation.NonNull; import android.annotation.SystemApi; import android.hardware.tv.input.V1_0.Constants; import android.media.AudioManager; import android.os.Parcel; import android.os.Parcelable; import android.util.Log; + import java.lang.annotation.Retention; /** @@ -141,6 +143,7 @@ public final class TvInputHardwareInfo implements Parcelable { return mCableConnectionStatus; } + @NonNull @Override public String toString() { StringBuilder b = new StringBuilder(128); diff --git a/media/java/android/media/tv/TvStreamConfig.java b/media/java/android/media/tv/TvStreamConfig.java index f012b46a4a62..7ea93b4f2b23 100644 --- a/media/java/android/media/tv/TvStreamConfig.java +++ b/media/java/android/media/tv/TvStreamConfig.java @@ -16,6 +16,8 @@ package android.media.tv; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; @@ -87,6 +89,7 @@ public class TvStreamConfig implements Parcelable { return mGeneration; } + @NonNull @Override public String toString() { return "TvStreamConfig {mStreamId=" + mStreamId + ";" + "mType=" + mType + ";mGeneration=" @@ -163,7 +166,7 @@ public class TvStreamConfig implements Parcelable { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (obj == null) return false; if (!(obj instanceof TvStreamConfig)) return false; diff --git a/media/java/android/media/tv/TvTrackInfo.java b/media/java/android/media/tv/TvTrackInfo.java index e09eeb8537c1..ea00d6eff12e 100644 --- a/media/java/android/media/tv/TvTrackInfo.java +++ b/media/java/android/media/tv/TvTrackInfo.java @@ -394,6 +394,7 @@ public final class TvTrackInfo implements Parcelable { * * @param encrypted The encryption status of the track. */ + @NonNull public Builder setEncrypted(boolean encrypted) { mEncrypted = encrypted; return this; diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp index 8d420e2c5598..cbc820b6fde0 100644 --- a/media/jni/android_media_MediaCodec.cpp +++ b/media/jni/android_media_MediaCodec.cpp @@ -743,8 +743,8 @@ status_t JMediaCodec::getCodecInfo(JNIEnv *env, jobject *codecInfoObject) const } status_t JMediaCodec::getMetrics(JNIEnv *, MediaAnalyticsItem * &reply) const { - - status_t status = mCodec->getMetrics(reply); + mediametrics_handle_t reply2 = MediaAnalyticsItem::convert(reply); + status_t status = mCodec->getMetrics(reply2); return status; } @@ -1848,7 +1848,7 @@ android_media_MediaCodec_native_getMetrics(JNIEnv *env, jobject thiz) } // get what we have for the metrics from the codec - MediaAnalyticsItem *item = NULL; + MediaAnalyticsItem *item = 0; status_t err = codec->getMetrics(env, item); if (err != OK) { @@ -1860,7 +1860,7 @@ android_media_MediaCodec_native_getMetrics(JNIEnv *env, jobject thiz) // housekeeping delete item; - item = NULL; + item = 0; return mybundle; } diff --git a/media/jni/android_media_MediaCodecList.cpp b/media/jni/android_media_MediaCodecList.cpp index 923d1d253c6e..307d80dc15c0 100644 --- a/media/jni/android_media_MediaCodecList.cpp +++ b/media/jni/android_media_MediaCodecList.cpp @@ -26,6 +26,7 @@ #include <utils/Vector.h> +#include <mutex> #include <vector> #include "android_runtime/AndroidRuntime.h" diff --git a/media/lib/signer/Android.bp b/media/lib/signer/Android.bp index 338ec12a9e28..85a007f427b8 100644 --- a/media/lib/signer/Android.bp +++ b/media/lib/signer/Android.bp @@ -16,8 +16,9 @@ java_sdk_library { name: "com.android.mediadrm.signer", - srcs: ["java/**/*.java"], + srcs: [ + "java/**/*.java", + ":framework-srcs", + ], api_packages: ["com.android.mediadrm.signer"], - srcs_lib: "framework-minus-apex", - srcs_lib_whitelist_pkgs: ["android.media"], } diff --git a/mime/Android.bp b/mime/Android.bp deleted file mode 100644 index 9303755ba73d..000000000000 --- a/mime/Android.bp +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (C) 2019 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. - -java_library { - name: "mimemap", - visibility: [ - "//cts/tests/tests/mimemap:__subpackages__", - "//frameworks/base:__subpackages__", - ], - - srcs: [ - "java/android/content/type/MimeMapImpl.java", - ], - - java_resources: [ - ":debian.mime.types", - ":android.mime.types", - ], - - sdk_version: "core_platform", -} - -filegroup { - name: "android.mime.types", - visibility: [ - "//visibility:private", - ], - path: "java-res/", - srcs: [ - "java-res/android.mime.types", - ], -} diff --git a/mime/java-res/android.mime.types b/mime/java-res/android.mime.types deleted file mode 100644 index 1ca912e8510b..000000000000 --- a/mime/java-res/android.mime.types +++ /dev/null @@ -1,146 +0,0 @@ - -############################################################################### -# -# Android-specific MIME type <-> extension mappings -# -# Each line below defines an mapping from one MIME type to the first of the -# listed extensions, and from listed extension back to the MIME type. -# A mapping overrides any previous mapping _from_ that same MIME type or -# extension (put() semantics), unless that MIME type / extension is prefixed with '?' -# (putIfAbsent() semantics). -# -# -############################################################################### -# -# EXAMPLES -# -# A line of the form: -# -# ?mime ext1 ?ext2 ext3 -# -# affects the current mappings along the lines of the following pseudo code: -# -# mimeToExt.putIfAbsent("mime", "ext1"); -# extToMime.put("ext1", "mime"); -# extToMime.putIfAbsent("ext2", "mime"); -# extToMime.put("ext3", "mime"); -# -# The line: -# -# ?text/plain txt -# -# leaves any earlier mapping for "text/plain" untouched, or maps that MIME type -# to the file extension ".txt" if there is no earlier mapping. The line also -# sets the mapping from file extension ".txt" to be the MIME type "text/plain", -# regardless of whether a previous mapping existed. -# -############################################################################### - - -# File extensions that Android wants to override to point to the given MIME type. -# -# After processing a line of the form: -# ?<mimeType> <extension1> <extension2> -# If <mimeType> was not already mapped to an extension then it will be -# mapped to <extension1>. -# <extension1> and <extension2> are mapped (or remapped) to <mimeType>. - -?application/epub+zip epub -?application/pkix-cert cer -?application/rss+xml rss -?application/vnd.android.ota ota -?application/vnd.apple.mpegurl m3u8 -?application/vnd.ms-pki.stl stl -?application/vnd.ms-powerpoint pot -?application/vnd.ms-wpl wpl -?application/vnd.stardivision.impress sdp -?application/vnd.stardivision.writer vor -?application/vnd.youtube.yt yt -?application/x-android-drm-fl fl -?application/x-flac flac -?application/x-font pcf -?application/x-mpegurl m3u m3u8 -?application/x-pem-file pem -?application/x-pkcs12 p12 pfx -?application/x-webarchive webarchive -?application/x-webarchive-xml webarchivexml -?application/x-x509-server-cert crt -?application/x-x509-user-cert crt - -?audio/3gpp 3gpp -?audio/aac-adts aac -?audio/imelody imy -?audio/midi rtttl xmf -?audio/mobile-xmf mxmf -?audio/mp4 m4a -?audio/mpegurl m3u -?audio/sp-midi smf -?audio/x-matroska mka -?audio/x-pn-realaudio ra - -?image/bmp bmp -?image/heic heic -?image/heic-sequence heics -?image/heif heif hif -?image/heif-sequence heifs -?image/ico cur -?image/webp webp -?image/x-adobe-dng dng -?image/x-fuji-raf raf -?image/x-icon ico -?image/x-nikon-nrw nrw -?image/x-panasonic-rw2 rw2 -?image/x-pentax-pef pef -?image/x-samsung-srw srw -?image/x-sony-arw arw - -?text/comma-separated-values csv -?text/plain diff po -?text/rtf rtf -?text/text phps -?text/xml xml -?text/x-vcard vcf - -?video/3gpp2 3gpp2 3g2 -?video/3gpp 3gpp -?video/avi avi -?video/m4v m4v -?video/mp2p mpeg -?video/mp2t m2ts mts -?video/mp2ts ts -?video/vnd.youtube.yt yt -?video/x-webex wrf - -# Optional additions that should not override any previous mapping. - -?application/x-wifi-config ?xml - -# Special cases where Android has a strong opinion about mappings, so we -# define them very last and make them override in both directions (no "?"). -# -# Lines here are of the form: -# <mimeType> <extension1> <extension2> ... -# -# After processing each line, -# <mimeType> is mapped to <extension1> -# <extension1>, <extension2>, ... are all mapped to <mimeType> -# This overrides any mappings for this <mimeType> / for these extensions -# that may have been defined earlier. - -application/pgp-signature pgp -application/x-x509-ca-cert crt -audio/aac aac -audio/basic snd -audio/flac flac -audio/midi rtx -audio/mpeg mp3 m4a m4r -audio/x-mpegurl m3u m3u8 -image/jpeg jpg -image/x-ms-bmp bmp -text/plain txt -text/x-c++hdr hpp -text/x-c++src cpp -video/3gpp 3gpp -video/mpeg mpeg -video/quicktime mov -video/x-matroska mkv diff --git a/mime/java/android/content/type/MimeMapImpl.java b/mime/java/android/content/type/MimeMapImpl.java deleted file mode 100644 index c904ea3f9b60..000000000000 --- a/mime/java/android/content/type/MimeMapImpl.java +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.content.type; - -import libcore.net.MimeMap; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.regex.Pattern; - -/** - * Default implementation of {@link MimeMap}, a bidirectional mapping between - * MIME types and file extensions. - * - * This default mapping is loaded from data files that start with some mappings - * recognized by IANA plus some custom extensions and overrides. - * - * @hide - */ -public class MimeMapImpl extends MimeMap { - - /** - * Creates and returns a new {@link MimeMapImpl} instance that implements. - * Android's default mapping between MIME types and extensions. - */ - public static MimeMapImpl createDefaultInstance() { - return parseFromResources("/mime.types", "/android.mime.types"); - } - - private static final Pattern SPLIT_PATTERN = Pattern.compile("\\s+"); - - /** - * Note: These maps only contain lowercase keys/values, regarded as the - * {@link #toLowerCase(String) canonical form}. - * - * <p>This is the case for both extensions and MIME types. The mime.types - * data file contains examples of mixed-case MIME types, but some applications - * use the lowercase version of these same types. RFC 2045 section 2 states - * that MIME types are case insensitive. - */ - private final Map<String, String> mMimeTypeToExtension; - private final Map<String, String> mExtensionToMimeType; - - public MimeMapImpl(Map<String, String> mimeTypeToExtension, - Map<String, String> extensionToMimeType) { - this.mMimeTypeToExtension = new HashMap<>(mimeTypeToExtension); - for (Map.Entry<String, String> entry : mimeTypeToExtension.entrySet()) { - checkValidMimeType(entry.getKey()); - checkValidExtension(entry.getValue()); - } - this.mExtensionToMimeType = new HashMap<>(extensionToMimeType); - for (Map.Entry<String, String> entry : extensionToMimeType.entrySet()) { - checkValidExtension(entry.getKey()); - checkValidMimeType(entry.getValue()); - } - } - - private static void checkValidMimeType(String s) { - if (MimeMap.isNullOrEmpty(s) || !s.equals(MimeMap.toLowerCase(s))) { - throw new IllegalArgumentException("Invalid MIME type: " + s); - } - } - - private static void checkValidExtension(String s) { - if (MimeMap.isNullOrEmpty(s) || !s.equals(MimeMap.toLowerCase(s))) { - throw new IllegalArgumentException("Invalid extension: " + s); - } - } - - static MimeMapImpl parseFromResources(String... resourceNames) { - Map<String, String> mimeTypeToExtension = new HashMap<>(); - Map<String, String> extensionToMimeType = new HashMap<>(); - for (String resourceName : resourceNames) { - parseTypes(mimeTypeToExtension, extensionToMimeType, resourceName); - } - return new MimeMapImpl(mimeTypeToExtension, extensionToMimeType); - } - - /** - * An element of a *mime.types file: A MIME type or an extension, with an optional - * prefix of "?" (if not overriding an earlier value). - */ - private static class Element { - public final boolean keepExisting; - public final String s; - - Element(boolean keepExisting, String value) { - this.keepExisting = keepExisting; - this.s = toLowerCase(value); - if (value.isEmpty()) { - throw new IllegalArgumentException(); - } - } - - public String toString() { - return keepExisting ? ("?" + s) : s; - } - } - - private static String maybePut(Map<String, String> map, Element keyElement, String value) { - if (keyElement.keepExisting) { - return map.putIfAbsent(keyElement.s, value); - } else { - return map.put(keyElement.s, value); - } - } - - private static void parseTypes(Map<String, String> mimeTypeToExtension, - Map<String, String> extensionToMimeType, String resource) { - try (BufferedReader r = new BufferedReader( - new InputStreamReader(MimeMapImpl.class.getResourceAsStream(resource)))) { - String line; - while ((line = r.readLine()) != null) { - int commentPos = line.indexOf('#'); - if (commentPos >= 0) { - line = line.substring(0, commentPos); - } - line = line.trim(); - // The first time a MIME type is encountered it is mapped to the first extension - // listed in its line. The first time an extension is encountered it is mapped - // to the MIME type. - // - // When encountering a previously seen MIME type or extension, then by default - // the later ones override earlier mappings (put() semantics); however if a MIME - // type or extension is prefixed with '?' then any earlier mapping _from_ that - // MIME type / extension is kept (putIfAbsent() semantics). - final String[] split = SPLIT_PATTERN.split(line); - if (split.length <= 1) { - // Need mimeType + at least one extension to make a mapping. - // "mime.types" files may also contain lines with just a mimeType without - // an extension but we skip them as they provide no mapping info. - continue; - } - List<Element> lineElements = new ArrayList<>(split.length); - for (String s : split) { - boolean keepExisting = s.startsWith("?"); - if (keepExisting) { - s = s.substring(1); - } - if (s.isEmpty()) { - throw new IllegalArgumentException("Invalid entry in '" + line + "'"); - } - lineElements.add(new Element(keepExisting, s)); - } - - // MIME type -> first extension (one mapping) - // This will override any earlier mapping from this MIME type to another - // extension, unless this MIME type was prefixed with '?'. - Element mimeElement = lineElements.get(0); - List<Element> extensionElements = lineElements.subList(1, lineElements.size()); - String firstExtension = extensionElements.get(0).s; - maybePut(mimeTypeToExtension, mimeElement, firstExtension); - - // extension -> MIME type (one or more mappings). - // This will override any earlier mapping from this extension to another - // MIME type, unless this extension was prefixed with '?'. - for (Element extensionElement : extensionElements) { - maybePut(extensionToMimeType, extensionElement, mimeElement.s); - } - } - } catch (IOException | RuntimeException e) { - throw new RuntimeException("Failed to parse " + resource, e); - } - } - - @Override - protected String guessExtensionFromLowerCaseMimeType(String mimeType) { - return mMimeTypeToExtension.get(mimeType); - } - - @Override - protected String guessMimeTypeFromLowerCaseExtension(String extension) { - return mExtensionToMimeType.get(extension); - } -} diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarTrustAgentUnlockDialogHelper.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarTrustAgentUnlockDialogHelper.java index 78bb1bcf24a8..013c63b834ff 100644 --- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarTrustAgentUnlockDialogHelper.java +++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarTrustAgentUnlockDialogHelper.java @@ -192,23 +192,28 @@ class CarTrustAgentUnlockDialogHelper extends BroadcastReceiver{ } } - // Set button text based on security lock type + // Set button text based on screen lock type private void setButtonText() { LockPatternUtils lockPatternUtils = new LockPatternUtils(mContext); int passwordQuality = lockPatternUtils.getActivePasswordQuality(mUid); switch (passwordQuality) { // PIN + case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC: case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX: + mButton.setText(R.string.unlock_dialog_button_text_pin); + break; // Pattern case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING: mButton.setText(R.string.unlock_dialog_button_text_pattern); break; // Password - case DevicePolicyManager.PASSWORD_QUALITY_MANAGED: + case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC: + case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC: + case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX: mButton.setText(R.string.unlock_dialog_button_text_password); break; default: - Log.e(TAG, "Encountered unexpected security type when attempting to set " + Log.e(TAG, "Encountered unexpected screen lock type when attempting to set " + "button text:" + passwordQuality); } } diff --git a/packages/SettingsLib/Android.bp b/packages/SettingsLib/Android.bp index 7760e0ef7246..9c8345dafbc8 100644 --- a/packages/SettingsLib/Android.bp +++ b/packages/SettingsLib/Android.bp @@ -24,6 +24,8 @@ android_library { "SettingsLibProgressBar", "SettingsLibAdaptiveIcon", "SettingsLibRadioButtonPreference", + "WifiTrackerLib", + "SettingsLibDisplayDensityUtils", ], // ANDROIDMK TRANSLATION ERROR: unsupported assignment to LOCAL_SHARED_JAVA_LIBRARIES diff --git a/packages/SettingsLib/DisplayDensityUtils/Android.bp b/packages/SettingsLib/DisplayDensityUtils/Android.bp new file mode 100644 index 000000000000..27d0cb5ad48c --- /dev/null +++ b/packages/SettingsLib/DisplayDensityUtils/Android.bp @@ -0,0 +1,7 @@ +android_library { + name: "SettingsLibDisplayDensityUtils", + + srcs: ["src/**/*.java"], + + min_sdk_version: "21", +} diff --git a/packages/SettingsLib/DisplayDensityUtils/AndroidManifest.xml b/packages/SettingsLib/DisplayDensityUtils/AndroidManifest.xml new file mode 100644 index 000000000000..0a4e2bb34409 --- /dev/null +++ b/packages/SettingsLib/DisplayDensityUtils/AndroidManifest.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2019 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. + --> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.settingslib.display"> + +</manifest> diff --git a/packages/SettingsLib/DisplayDensityUtils/src/com/android/settingslib/display/DisplayDensityConfiguration.java b/packages/SettingsLib/DisplayDensityUtils/src/com/android/settingslib/display/DisplayDensityConfiguration.java new file mode 100644 index 000000000000..284a9025de64 --- /dev/null +++ b/packages/SettingsLib/DisplayDensityUtils/src/com/android/settingslib/display/DisplayDensityConfiguration.java @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2019 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.settingslib.display; + +import android.os.AsyncTask; +import android.os.RemoteException; +import android.os.UserHandle; +import android.util.Log; +import android.view.IWindowManager; +import android.view.WindowManagerGlobal; + +/** Utility methods for controlling the display density. */ +public class DisplayDensityConfiguration { + private static final String LOG_TAG = "DisplayDensityConfig"; + + /** + * Returns the default density for the specified display. + * + * @param displayId the identifier of the display + * @return the default density of the specified display, or {@code -1} if the display does not + * exist or the density could not be obtained + */ + static int getDefaultDisplayDensity(int displayId) { + try { + final IWindowManager wm = WindowManagerGlobal.getWindowManagerService(); + return wm.getInitialDisplayDensity(displayId); + } catch (RemoteException exc) { + return -1; + } + } + + /** + * Asynchronously applies display density changes to the specified display. + * + * <p>The change will be applied to the user specified by the value of {@link + * UserHandle#myUserId()} at the time the method is called. + * + * @param displayId the identifier of the display to modify + */ + public static void clearForcedDisplayDensity(final int displayId) { + final int userId = UserHandle.myUserId(); + AsyncTask.execute( + () -> { + try { + final IWindowManager wm = WindowManagerGlobal.getWindowManagerService(); + wm.clearForcedDisplayDensityForUser(displayId, userId); + } catch (RemoteException exc) { + Log.w(LOG_TAG, "Unable to clear forced display density setting"); + } + }); + } + + /** + * Asynchronously applies display density changes to the specified display. + * + * <p>The change will be applied to the user specified by the value of {@link + * UserHandle#myUserId()} at the time the method is called. + * + * @param displayId the identifier of the display to modify + * @param density the density to force for the specified display + */ + public static void setForcedDisplayDensity(final int displayId, final int density) { + final int userId = UserHandle.myUserId(); + AsyncTask.execute( + () -> { + try { + final IWindowManager wm = WindowManagerGlobal.getWindowManagerService(); + wm.setForcedDisplayDensityForUser(displayId, density, userId); + } catch (RemoteException exc) { + Log.w(LOG_TAG, "Unable to save forced display density setting"); + } + }); + } +} diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml index eb6160a47fce..75344c45acb3 100644 --- a/packages/SettingsLib/res/values-te/strings.xml +++ b/packages/SettingsLib/res/values-te/strings.xml @@ -376,7 +376,7 @@ <string name="daltonizer_mode_protanomaly" msgid="8424148009038666065">"ప్రొటానోమలీ (ఎరుపు-ఆకుపచ్చ రంగు)"</string> <string name="daltonizer_mode_tritanomaly" msgid="481725854987912389">"ట్రైటనోమలీ (నీలం-పసుపు రంగు)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"రంగు సవరణ"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ఈ లక్షణం ప్రయోగాత్మకమైనది మరియు పనితీరుపై ప్రభావం చూపవచ్చు."</string> + <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ఈ ఫీచర్ ప్రయోగాత్మకమైనది, పనితీరుపై ప్రభావం చూపవచ్చు."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> ద్వారా భర్తీ చేయబడింది"</string> <string name="power_remaining_settings_home_page" msgid="4845022416859002011">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="6123167166221295462">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> సమయం మిగిలి ఉంది"</string> diff --git a/packages/SettingsLib/src/com/android/settingslib/datetime/ZoneGetter.java b/packages/SettingsLib/src/com/android/settingslib/datetime/ZoneGetter.java index 99d48d3957b6..aac7fc3c927a 100644 --- a/packages/SettingsLib/src/com/android/settingslib/datetime/ZoneGetter.java +++ b/packages/SettingsLib/src/com/android/settingslib/datetime/ZoneGetter.java @@ -34,11 +34,14 @@ import androidx.core.text.TextDirectionHeuristicsCompat; import com.android.settingslib.R; +import libcore.timezone.CountryTimeZones; +import libcore.timezone.CountryTimeZones.TimeZoneMapping; import libcore.timezone.TimeZoneFinder; import org.xmlpull.v1.XmlPullParserException; import java.util.ArrayList; +import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.HashSet; @@ -387,7 +390,21 @@ public class ZoneGetter { @VisibleForTesting public List<String> lookupTimeZoneIdsByCountry(String country) { - return TimeZoneFinder.getInstance().lookupTimeZoneIdsByCountry(country); + final CountryTimeZones countryTimeZones = + TimeZoneFinder.getInstance().lookupCountryTimeZones(country); + if (countryTimeZones == null) { + return null; + } + final List<TimeZoneMapping> mappings = countryTimeZones.getTimeZoneMappings(); + return extractTimeZoneIds(mappings); + } + + private static List<String> extractTimeZoneIds(List<TimeZoneMapping> timeZoneMappings) { + final List<String> zoneIds = new ArrayList<>(timeZoneMappings.size()); + for (TimeZoneMapping timeZoneMapping : timeZoneMappings) { + zoneIds.add(timeZoneMapping.timeZoneId); + } + return Collections.unmodifiableList(zoneIds); } } } diff --git a/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaManager.java index 008943c99033..12d054e307ba 100644 --- a/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaManager.java @@ -126,10 +126,13 @@ public class BluetoothMediaManager extends MediaManager implements BluetoothCall return; } - final List<Long> devicesHiSyncIds = new ArrayList<>(); final List<BluetoothDevice> devices = hapProfile.getConnectableDevices(); - for (BluetoothDevice device : devices) { + // Only add master HearingAid device, ignore sub + if (mCachedBluetoothDeviceManager.isSubDevice(device)) { + Log.w(TAG, "Sub hearingAid device: " + device.getName()); + continue; + } final CachedBluetoothDevice cachedDevice = mCachedBluetoothDeviceManager.findDevice(device); @@ -142,13 +145,8 @@ public class BluetoothMediaManager extends MediaManager implements BluetoothCall + ", is connected : " + cachedDevice.isConnected() + ", is preferred : " + hapProfile.isPreferred(device)); - final long hiSyncId = hapProfile.getHiSyncId(device); - - // device with same hiSyncId should not be shown in the UI. - // So do not add it into connectedDevices. - if (!devicesHiSyncIds.contains(hiSyncId) && hapProfile.isPreferred(device) + if (hapProfile.isPreferred(device) && BluetoothDevice.BOND_BONDED == cachedDevice.getBondState()) { - devicesHiSyncIds.add(hiSyncId); addMediaDevice(cachedDevice); } } @@ -284,9 +282,8 @@ public class BluetoothMediaManager extends MediaManager implements BluetoothCall + activeDevice + ", profile : " + bluetoothProfile); if (BluetoothProfile.HEARING_AID == bluetoothProfile) { - if (activeDevice != null) { - dispatchConnectedDeviceChanged(MediaDeviceUtils.getId(activeDevice)); - } + dispatchConnectedDeviceChanged(activeDevice == null + ? PhoneMediaDevice.ID : MediaDeviceUtils.getId(activeDevice)); } else if (BluetoothProfile.A2DP == bluetoothProfile) { // When active device change to Hearing Aid, // BluetoothEventManager also send onActiveDeviceChanged() to notify that active device @@ -304,12 +301,16 @@ public class BluetoothMediaManager extends MediaManager implements BluetoothCall private MediaDevice findActiveHearingAidDevice() { final HearingAidProfile hearingAidProfile = mProfileManager.getHearingAidProfile(); - if (hearingAidProfile != null) { - final List<BluetoothDevice> activeDevices = hearingAidProfile.getActiveDevices(); - for (BluetoothDevice btDevice : activeDevices) { - if (btDevice != null) { - return findMediaDevice(MediaDeviceUtils.getId(btDevice)); - } + if (hearingAidProfile == null) { + Log.e(TAG, "findActiveHearingAidDevice: hearingAidProfile == null"); + return null; + } + final List<BluetoothDevice> activeDevices = hearingAidProfile.getActiveDevices(); + for (BluetoothDevice btDevice : activeDevices) { + final MediaDevice mediaDevice = + findMediaDevice(Long.toString(hearingAidProfile.getHiSyncId(btDevice))); + if (mediaDevice != null) { + return mediaDevice; } } return null; diff --git a/packages/SettingsLib/src/com/android/settingslib/media/MediaDeviceUtils.java b/packages/SettingsLib/src/com/android/settingslib/media/MediaDeviceUtils.java index f181150de513..4b8e706c0d0c 100644 --- a/packages/SettingsLib/src/com/android/settingslib/media/MediaDeviceUtils.java +++ b/packages/SettingsLib/src/com/android/settingslib/media/MediaDeviceUtils.java @@ -32,6 +32,9 @@ public class MediaDeviceUtils { * @return CachedBluetoothDevice address */ public static String getId(CachedBluetoothDevice cachedDevice) { + if (cachedDevice.isHearingAidDevice()) { + return Long.toString(cachedDevice.getHiSyncId()); + } return cachedDevice.getAddress(); } diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/LongPressWifiEntryPreference.java b/packages/SettingsLib/src/com/android/settingslib/wifi/LongPressWifiEntryPreference.java new file mode 100644 index 000000000000..503d60c87bb9 --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/wifi/LongPressWifiEntryPreference.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2019 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.settingslib.wifi; + +import android.content.Context; + +import androidx.fragment.app.Fragment; +import androidx.preference.PreferenceViewHolder; + +import com.android.wifitrackerlib.WifiEntry; + +/** + * WifiEntryPreference that can be long pressed. + */ +public class LongPressWifiEntryPreference extends WifiEntryPreference { + + private final Fragment mFragment; + + public LongPressWifiEntryPreference(Context context, WifiEntry wifiEntry, Fragment fragment) { + super(context, wifiEntry); + mFragment = fragment; + } + + @Override + public void onBindViewHolder(final PreferenceViewHolder view) { + super.onBindViewHolder(view); + if (mFragment != null) { + view.itemView.setOnCreateContextMenuListener(mFragment); + view.itemView.setTag(this); + view.itemView.setLongClickable(true); + } + } +} diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiEntryPreference.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiEntryPreference.java new file mode 100644 index 000000000000..22f47f1c6585 --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiEntryPreference.java @@ -0,0 +1,238 @@ +/* + * Copyright (C) 2019 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.settingslib.wifi; + +import android.annotation.Nullable; +import android.content.Context; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.StateListDrawable; +import android.text.TextUtils; +import android.view.View; +import android.widget.ImageView; + +import androidx.annotation.NonNull; +import androidx.annotation.VisibleForTesting; +import androidx.preference.Preference; +import androidx.preference.PreferenceViewHolder; + +import com.android.settingslib.R; +import com.android.settingslib.Utils; +import com.android.wifitrackerlib.WifiEntry; + +/** + * Preference to display a WifiEntry in a wifi picker. + */ +public class WifiEntryPreference extends Preference implements WifiEntry.WifiEntryCallback { + + private static final int[] STATE_SECURED = { + R.attr.state_encrypted + }; + + private static final int[] STATE_METERED = { + R.attr.state_metered + }; + + private static final int[] FRICTION_ATTRS = { + R.attr.wifi_friction + }; + + // These values must be kept within [WifiEntry.WIFI_LEVEL_MIN, WifiEntry.WIFI_LEVEL_MAX] + private static final int[] WIFI_CONNECTION_STRENGTH = { + R.string.accessibility_no_wifi, + R.string.accessibility_wifi_one_bar, + R.string.accessibility_wifi_two_bars, + R.string.accessibility_wifi_three_bars, + R.string.accessibility_wifi_signal_full + }; + + // StateListDrawable to display secured lock / metered "$" icon + @Nullable private final StateListDrawable mFrictionSld; + private final IconInjector mIconInjector; + private WifiEntry mWifiEntry; + private int mLevel = -1; + private CharSequence mContentDescription; + + public WifiEntryPreference(@NonNull Context context, @NonNull WifiEntry wifiEntry) { + this(context, wifiEntry, new IconInjector(context)); + } + + @VisibleForTesting + WifiEntryPreference(@NonNull Context context, @NonNull WifiEntry wifiEntry, + @NonNull IconInjector iconInjector) { + super(context); + + setLayoutResource(R.layout.preference_access_point); + setWidgetLayoutResource(R.layout.access_point_friction_widget); + mFrictionSld = getFrictionStateListDrawable(); + mWifiEntry = wifiEntry; + mWifiEntry.setListener(this); + mIconInjector = iconInjector; + refresh(); + } + + public WifiEntry getWifiEntry() { + return mWifiEntry; + } + + @Override + public void onBindViewHolder(final PreferenceViewHolder view) { + super.onBindViewHolder(view); + final Drawable drawable = getIcon(); + if (drawable != null) { + drawable.setLevel(mLevel); + } + + view.itemView.setContentDescription(mContentDescription); + + final ImageView frictionImageView = (ImageView) view.findViewById(R.id.friction_icon); + bindFrictionImage(frictionImageView); + + // Turn off divider + view.findViewById(R.id.two_target_divider).setVisibility(View.INVISIBLE); + } + + /** + * Updates the title and summary; may indirectly call notifyChanged(). + */ + public void refresh() { + setTitle(mWifiEntry.getTitle()); + final int level = mWifiEntry.getLevel(); + if (level != mLevel) { + mLevel = level; + updateIcon(mLevel); + notifyChanged(); + } + + setSummary(mWifiEntry.getSummary()); + mContentDescription = buildContentDescription(); + } + + /** + * Indicates the state of the WifiEntry has changed and clients may retrieve updates through + * the WifiEntry getter methods. + */ + public void onUpdated() { + // TODO(b/70983952): Fill this method in + refresh(); + } + + /** + * Result of the connect request indicated by the WifiEntry.CONNECT_STATUS constants. + */ + public void onConnectResult(int status) { + // TODO(b/70983952): Fill this method in + } + + /** + * Result of the disconnect request indicated by the WifiEntry.DISCONNECT_STATUS constants. + */ + public void onDisconnectResult(int status) { + // TODO(b/70983952): Fill this method in + } + + /** + * Result of the forget request indicated by the WifiEntry.FORGET_STATUS constants. + */ + public void onForgetResult(int status) { + // TODO(b/70983952): Fill this method in + } + + private void updateIcon(int level) { + if (level == -1) { + setIcon(null); + return; + } + + final Drawable drawable = mIconInjector.getIcon(level); + if (drawable != null) { + drawable.setTintList(Utils.getColorAttr(getContext(), + android.R.attr.colorControlNormal)); + setIcon(drawable); + } else { + setIcon(null); + } + } + + @Nullable + private StateListDrawable getFrictionStateListDrawable() { + TypedArray frictionSld; + try { + frictionSld = getContext().getTheme().obtainStyledAttributes(FRICTION_ATTRS); + } catch (Resources.NotFoundException e) { + // Fallback for platforms that do not need friction icon resources. + frictionSld = null; + } + return frictionSld != null ? (StateListDrawable) frictionSld.getDrawable(0) : null; + } + + /** + * Binds the friction icon drawable using a StateListDrawable. + * + * <p>Friction icons will be rebound when notifyChange() is called, and therefore + * do not need to be managed in refresh()</p>. + */ + private void bindFrictionImage(ImageView frictionImageView) { + if (frictionImageView == null || mFrictionSld == null) { + return; + } + if ((mWifiEntry.getSecurity() != WifiEntry.SECURITY_NONE) + && (mWifiEntry.getSecurity() != WifiEntry.SECURITY_OWE) + && (mWifiEntry.getSecurity() != WifiEntry.SECURITY_OWE_TRANSITION)) { + mFrictionSld.setState(STATE_SECURED); + } else if (mWifiEntry.isMetered()) { + mFrictionSld.setState(STATE_METERED); + } + frictionImageView.setImageDrawable(mFrictionSld.getCurrent()); + } + + /** + * Helper method to generate content description string. + */ + @VisibleForTesting + CharSequence buildContentDescription() { + final Context context = getContext(); + + CharSequence contentDescription = getTitle(); + final CharSequence summary = getSummary(); + if (!TextUtils.isEmpty(summary)) { + contentDescription = TextUtils.concat(contentDescription, ",", summary); + } + int level = mWifiEntry.getLevel(); + if (level >= 0 && level < WIFI_CONNECTION_STRENGTH.length) { + contentDescription = TextUtils.concat(contentDescription, ",", + context.getString(WIFI_CONNECTION_STRENGTH[level])); + } + return TextUtils.concat(contentDescription, ",", + mWifiEntry.getSecurity() == WifiEntry.SECURITY_NONE + ? context.getString(R.string.accessibility_wifi_security_type_none) + : context.getString(R.string.accessibility_wifi_security_type_secured)); + } + + + static class IconInjector { + private final Context mContext; + + IconInjector(Context context) { + mContext = context; + } + + public Drawable getIcon(int level) { + return mContext.getDrawable(Utils.getWifiIconResource(level)); + } + } +} diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/BluetoothMediaManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/BluetoothMediaManagerTest.java index 030bab6a2034..f27cef9620c5 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/BluetoothMediaManagerTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/BluetoothMediaManagerTest.java @@ -428,20 +428,21 @@ public class BluetoothMediaManagerTest { @Test public void onActiveDeviceChanged_hearingAidDeviceIsActive_returnHearingAidDeviceId() { + final Long hiSyncId = Integer.toUnsignedLong(12345); final BluetoothDevice bluetoothDevice = mock(BluetoothDevice.class); final List<BluetoothDevice> devices = new ArrayList<>(); devices.add(bluetoothDevice); final BluetoothMediaDevice bluetoothMediaDevice = mock(BluetoothMediaDevice.class); mMediaManager.mMediaDevices.add(bluetoothMediaDevice); - when(bluetoothDevice.getAddress()).thenReturn(TEST_ADDRESS); + when(mHapProfile.getHiSyncId(bluetoothDevice)).thenReturn(hiSyncId); when(mHapProfile.getActiveDevices()).thenReturn(devices); - when(bluetoothMediaDevice.getId()).thenReturn(TEST_ADDRESS); + when(bluetoothMediaDevice.getId()).thenReturn(Long.toString(hiSyncId)); mMediaManager.registerCallback(mCallback); mMediaManager.onActiveDeviceChanged(null, BluetoothProfile.A2DP); - verify(mCallback).onConnectedDeviceChanged(TEST_ADDRESS); + verify(mCallback).onConnectedDeviceChanged(Long.toString(hiSyncId)); } @Test diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiEntryPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiEntryPreferenceTest.java new file mode 100644 index 000000000000..752a5498a077 --- /dev/null +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiEntryPreferenceTest.java @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2019 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.settingslib.wifi; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.graphics.drawable.Drawable; + +import com.android.wifitrackerlib.WifiEntry; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; + +import java.util.ArrayList; +import java.util.List; + +@RunWith(RobolectricTestRunner.class) +public class WifiEntryPreferenceTest { + + private Context mContext; + + @Mock + private WifiEntry mMockWifiEntry; + @Mock + private WifiEntryPreference.IconInjector mMockIconInjector; + + @Mock + private Drawable mMockDrawable0; + @Mock + private Drawable mMockDrawable1; + @Mock + private Drawable mMockDrawable2; + @Mock + private Drawable mMockDrawable3; + @Mock + private Drawable mMockDrawable4; + + private static final String MOCK_TITLE = "title"; + private static final String MOCK_SUMMARY = "summary"; + + + @Before + public void setUp() { + mContext = RuntimeEnvironment.application; + + MockitoAnnotations.initMocks(this); + + when(mMockWifiEntry.getTitle()).thenReturn(MOCK_TITLE); + when(mMockWifiEntry.getSummary()).thenReturn(MOCK_SUMMARY); + + when(mMockIconInjector.getIcon(0)).thenReturn(mMockDrawable0); + when(mMockIconInjector.getIcon(1)).thenReturn(mMockDrawable1); + when(mMockIconInjector.getIcon(2)).thenReturn(mMockDrawable2); + when(mMockIconInjector.getIcon(3)).thenReturn(mMockDrawable3); + when(mMockIconInjector.getIcon(4)).thenReturn(mMockDrawable4); + } + + @Test + public void constructor_shouldSetWifiEntryTitleAndSummary() { + final WifiEntryPreference pref = + new WifiEntryPreference(mContext, mMockWifiEntry, mMockIconInjector); + + assertThat(pref.getTitle()).isEqualTo(MOCK_TITLE); + assertThat(pref.getSummary()).isEqualTo(MOCK_SUMMARY); + } + + @Test + public void constructor_shouldSetIcon() { + when(mMockWifiEntry.getLevel()).thenReturn(0); + + final WifiEntryPreference pref = + new WifiEntryPreference(mContext, mMockWifiEntry, mMockIconInjector); + + assertThat(pref.getIcon()).isEqualTo(mMockDrawable0); + } + + @Test + public void titleChanged_refresh_shouldUpdateTitle() { + final WifiEntryPreference pref = + new WifiEntryPreference(mContext, mMockWifiEntry, mMockIconInjector); + final String updatedTitle = "updated title"; + when(mMockWifiEntry.getTitle()).thenReturn(updatedTitle); + + pref.refresh(); + + assertThat(pref.getTitle()).isEqualTo(updatedTitle); + } + + @Test + public void summaryChanged_refresh_shouldUpdateSummary() { + final WifiEntryPreference pref = + new WifiEntryPreference(mContext, mMockWifiEntry, mMockIconInjector); + final String updatedSummary = "updated summary"; + when(mMockWifiEntry.getSummary()).thenReturn(updatedSummary); + + pref.refresh(); + + assertThat(pref.getSummary()).isEqualTo(updatedSummary); + } + + @Test + public void levelChanged_refresh_shouldUpdateLevelIcon() { + final List<Drawable> iconList = new ArrayList<>(); + final WifiEntryPreference pref = + new WifiEntryPreference(mContext, mMockWifiEntry, mMockIconInjector); + + when(mMockWifiEntry.getLevel()).thenReturn(0); + pref.refresh(); + iconList.add(pref.getIcon()); + when(mMockWifiEntry.getLevel()).thenReturn(1); + pref.refresh(); + iconList.add(pref.getIcon()); + when(mMockWifiEntry.getLevel()).thenReturn(2); + pref.refresh(); + iconList.add(pref.getIcon()); + when(mMockWifiEntry.getLevel()).thenReturn(3); + pref.refresh(); + iconList.add(pref.getIcon()); + when(mMockWifiEntry.getLevel()).thenReturn(4); + pref.refresh(); + iconList.add(pref.getIcon()); + when(mMockWifiEntry.getLevel()).thenReturn(-1); + pref.refresh(); + iconList.add(pref.getIcon()); + + assertThat(iconList).containsExactly(mMockDrawable0, mMockDrawable1, + mMockDrawable2, mMockDrawable3, mMockDrawable4, null); + } +} diff --git a/packages/SettingsProvider/Android.bp b/packages/SettingsProvider/Android.bp index e54b847f167d..681b4940a3c3 100644 --- a/packages/SettingsProvider/Android.bp +++ b/packages/SettingsProvider/Android.bp @@ -11,7 +11,7 @@ android_app { ], static_libs: [ "junit", - "SettingsLib", + "SettingsLibDisplayDensityUtils", ], platform_apis: true, certificate: "platform", @@ -24,13 +24,17 @@ android_test { // because this test is not an instrumentation test. (because the target runs in the system process.) srcs: [ "test/**/*.java", + "src/android/provider/settings/backup/*", + "src/android/provider/settings/validators/*", "src/com/android/providers/settings/SettingsBackupAgent.java", "src/com/android/providers/settings/SettingsState.java", "src/com/android/providers/settings/SettingsHelper.java", ], static_libs: [ "androidx.test.rules", - "SettingsLib", + "SettingsLibDisplayDensityUtils", + "platform-test-annotations", + "truth-prebuilt", ], libs: [ "android.test.base", diff --git a/packages/SettingsProvider/TEST_MAPPING b/packages/SettingsProvider/TEST_MAPPING new file mode 100644 index 000000000000..890510ffebe3 --- /dev/null +++ b/packages/SettingsProvider/TEST_MAPPING @@ -0,0 +1,15 @@ +{ + "presubmit": [ + { + "name": "SettingsProviderTest" + }, + { + "name": "CtsProviderTestCases", + "options": [ + { + "include-filter": "android.provider.cts.settings." + } + ] + } + ] +} diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java new file mode 100644 index 000000000000..0c49f635f5bd --- /dev/null +++ b/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2019 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.provider.settings.backup; + +import android.provider.Settings; + +/** Information related to the backup of Global settings */ +public class GlobalSettings { + + /** + * These keys may be mentioned in the SETTINGS_TO_BACKUP arrays in SystemSettings + * and SecureSettings as well. This is because those tables drive both backup and + * restore, and restore needs to properly whitelist keys that used to live + * in those namespaces. + * + * NOTE: Settings are backed up and restored in the order they appear + * in this array. If you have one setting depending on another, + * make sure that they are ordered appropriately. + * + * NOTE: This table should only be used for settings which should be restored + * between different types of devices + * {@see #Settings.Secure.DEVICE_SPECIFIC_SETTINGS_TO_BACKUP} + * + * NOTE: All settings which are backed up should have a corresponding validator. + */ + public static final String[] SETTINGS_TO_BACKUP = { + Settings.Global.APPLY_RAMPING_RINGER, + Settings.Global.BUGREPORT_IN_POWER_MENU, + Settings.Global.STAY_ON_WHILE_PLUGGED_IN, + Settings.Global.APP_AUTO_RESTRICTION_ENABLED, + Settings.Global.AUTO_TIME, + Settings.Global.AUTO_TIME_ZONE, + Settings.Global.POWER_SOUNDS_ENABLED, + Settings.Global.DOCK_SOUNDS_ENABLED, + Settings.Global.CHARGING_SOUNDS_ENABLED, + Settings.Global.USB_MASS_STORAGE_ENABLED, + Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, + Settings.Global.WIFI_WAKEUP_ENABLED, + Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, + Settings.Global.USE_OPEN_WIFI_PACKAGE, + Settings.Global.WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED, + Settings.Global.EMERGENCY_TONE, + Settings.Global.CALL_AUTO_RETRY, + Settings.Global.DOCK_AUDIO_MEDIA_ENABLED, + Settings.Global.ENABLE_AUTOMATIC_SYSTEM_SERVER_HEAP_DUMPS, + Settings.Global.ENCODED_SURROUND_OUTPUT, + Settings.Global.ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS, + Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, + Settings.Global.LOW_POWER_MODE_STICKY_AUTO_DISABLE_ENABLED, + Settings.Global.LOW_POWER_MODE_STICKY_AUTO_DISABLE_LEVEL, + Settings.Global.BLUETOOTH_ON, + Settings.Global.PRIVATE_DNS_MODE, + Settings.Global.PRIVATE_DNS_SPECIFIER, + Settings.Global.SOFT_AP_TIMEOUT_ENABLED, + Settings.Global.ZEN_DURATION, + Settings.Global.CHARGING_VIBRATION_ENABLED, + Settings.Global.AWARE_ALLOWED, + }; +} diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java new file mode 100644 index 000000000000..8c2e43170cc2 --- /dev/null +++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2019 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.provider.settings.backup; + +import android.annotation.UnsupportedAppUsage; +import android.provider.Settings; + +/** Information relating to the Secure settings which should be backed up */ +public class SecureSettings { + + /** + * NOTE: Settings are backed up and restored in the order they appear + * in this array. If you have one setting depending on another, + * make sure that they are ordered appropriately. + */ + @UnsupportedAppUsage + public static final String[] SETTINGS_TO_BACKUP = { + Settings.Secure.BUGREPORT_IN_POWER_MENU, // moved to global + Settings.Secure.ALLOW_MOCK_LOCATION, + Settings.Secure.USB_MASS_STORAGE_ENABLED, // moved to global + Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, + Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER, + Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, + Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, + Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED, + Settings.Secure.AUTOFILL_SERVICE, + Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, + Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, + Settings.Secure.ENABLED_VR_LISTENERS, + Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES, + Settings.Secure.TOUCH_EXPLORATION_ENABLED, + Settings.Secure.ACCESSIBILITY_ENABLED, + Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, + Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT, + Settings.Secure.ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, + Settings.Secure.ACCESSIBILITY_SHORTCUT_ENABLED, + Settings.Secure.ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN, + Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED, + Settings.Secure.ACCESSIBILITY_CAPTIONING_PRESET, + Settings.Secure.ACCESSIBILITY_CAPTIONING_ENABLED, + Settings.Secure.ACCESSIBILITY_CAPTIONING_LOCALE, + Settings.Secure.ACCESSIBILITY_CAPTIONING_BACKGROUND_COLOR, + Settings.Secure.ACCESSIBILITY_CAPTIONING_FOREGROUND_COLOR, + Settings.Secure.ACCESSIBILITY_CAPTIONING_EDGE_TYPE, + Settings.Secure.ACCESSIBILITY_CAPTIONING_EDGE_COLOR, + Settings.Secure.ACCESSIBILITY_CAPTIONING_TYPEFACE, + Settings.Secure.ACCESSIBILITY_CAPTIONING_FONT_SCALE, + Settings.Secure.ACCESSIBILITY_CAPTIONING_WINDOW_COLOR, + Settings.Secure.TTS_DEFAULT_RATE, + Settings.Secure.TTS_DEFAULT_PITCH, + Settings.Secure.TTS_DEFAULT_SYNTH, + Settings.Secure.TTS_ENABLED_PLUGINS, + Settings.Secure.TTS_DEFAULT_LOCALE, + Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, + Settings.Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, // moved to global + Settings.Secure.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY, // moved to global + Settings.Secure.WIFI_NUM_OPEN_NETWORKS_KEPT, // moved to global + Settings.Secure.MOUNT_PLAY_NOTIFICATION_SND, + Settings.Secure.MOUNT_UMS_AUTOSTART, + Settings.Secure.MOUNT_UMS_PROMPT, + Settings.Secure.MOUNT_UMS_NOTIFY_ENABLED, + Settings.Secure.DOUBLE_TAP_TO_WAKE, + Settings.Secure.WAKE_GESTURE_ENABLED, + Settings.Secure.LONG_PRESS_TIMEOUT, + Settings.Secure.CAMERA_GESTURE_DISABLED, + Settings.Secure.ACCESSIBILITY_AUTOCLICK_ENABLED, + Settings.Secure.ACCESSIBILITY_AUTOCLICK_DELAY, + Settings.Secure.ACCESSIBILITY_LARGE_POINTER_ICON, + Settings.Secure.PREFERRED_TTY_MODE, + Settings.Secure.ENHANCED_VOICE_PRIVACY_ENABLED, + Settings.Secure.TTY_MODE_ENABLED, + Settings.Secure.RTT_CALLING_MODE, + Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR, + Settings.Secure.NIGHT_DISPLAY_CUSTOM_START_TIME, + Settings.Secure.NIGHT_DISPLAY_CUSTOM_END_TIME, + Settings.Secure.NIGHT_DISPLAY_COLOR_TEMPERATURE, + Settings.Secure.NIGHT_DISPLAY_AUTO_MODE, + Settings.Secure.DISPLAY_WHITE_BALANCE_ENABLED, + Settings.Secure.SYNC_PARENT_SOUNDS, + Settings.Secure.CAMERA_DOUBLE_TWIST_TO_FLIP_ENABLED, + Settings.Secure.CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, + Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, + Settings.Secure.QS_TILES, + Settings.Secure.DOZE_ENABLED, + Settings.Secure.DOZE_ALWAYS_ON, + Settings.Secure.DOZE_PICK_UP_GESTURE, + Settings.Secure.DOZE_DOUBLE_TAP_GESTURE, + Settings.Secure.DOZE_TAP_SCREEN_GESTURE, + Settings.Secure.DOZE_WAKE_LOCK_SCREEN_GESTURE, + Settings.Secure.DOZE_WAKE_DISPLAY_GESTURE, + Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT, + Settings.Secure.AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN, + Settings.Secure.FACE_UNLOCK_KEYGUARD_ENABLED, + Settings.Secure.SHOW_MEDIA_WHEN_BYPASSING, + Settings.Secure.FACE_UNLOCK_DISMISSES_KEYGUARD, + Settings.Secure.FACE_UNLOCK_APP_ENABLED, + Settings.Secure.FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION, + Settings.Secure.ASSIST_GESTURE_ENABLED, + Settings.Secure.ASSIST_GESTURE_SILENCE_ALERTS_ENABLED, + Settings.Secure.ASSIST_GESTURE_WAKE_ENABLED, + Settings.Secure.VR_DISPLAY_MODE, + Settings.Secure.NOTIFICATION_BADGING, + Settings.Secure.NOTIFICATION_BUBBLES, + Settings.Secure.NOTIFICATION_DISMISS_RTL, + Settings.Secure.QS_AUTO_ADDED_TILES, + Settings.Secure.SCREENSAVER_ENABLED, + Settings.Secure.SCREENSAVER_COMPONENTS, + Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK, + Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP, + Settings.Secure.LOCKDOWN_IN_POWER_MENU, + Settings.Secure.SHOW_FIRST_CRASH_DIALOG_DEV_OPTION, + Settings.Secure.VOLUME_HUSH_GESTURE, + Settings.Secure.MANUAL_RINGER_TOGGLE_COUNT, + Settings.Secure.HUSH_GESTURE_USED, + Settings.Secure.IN_CALL_NOTIFICATION_ENABLED, + Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, + Settings.Secure.LOCK_SCREEN_CUSTOM_CLOCK_FACE, + Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, + Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, + Settings.Secure.SHOW_NOTIFICATION_SNOOZE, + Settings.Secure.ZEN_DURATION, + Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, + Settings.Secure.SHOW_ZEN_SETTINGS_SUGGESTION, + Settings.Secure.ZEN_SETTINGS_UPDATED, + Settings.Secure.ZEN_SETTINGS_SUGGESTION_VIEWED, + Settings.Secure.CHARGING_SOUNDS_ENABLED, + Settings.Secure.CHARGING_VIBRATION_ENABLED, + Settings.Secure.ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS, + Settings.Secure.ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS, + Settings.Secure.NOTIFICATION_NEW_INTERRUPTION_MODEL, + Settings.Secure.TRUST_AGENTS_EXTEND_UNLOCK, + Settings.Secure.UI_NIGHT_MODE, + Settings.Secure.LOCK_SCREEN_WHEN_TRUST_LOST, + Settings.Secure.SKIP_GESTURE, + Settings.Secure.SKIP_DIRECTION, + Settings.Secure.SILENCE_GESTURE, + Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES, + Settings.Secure.NAVIGATION_MODE, + Settings.Secure.AWARE_ENABLED, + Settings.Secure.SKIP_GESTURE_COUNT, + Settings.Secure.SKIP_TOUCH_COUNT, + Settings.Secure.SILENCE_ALARMS_GESTURE_COUNT, + Settings.Secure.SILENCE_CALL_GESTURE_COUNT, + Settings.Secure.SILENCE_TIMER_GESTURE_COUNT, + Settings.Secure.SILENCE_ALARMS_TOUCH_COUNT, + Settings.Secure.SILENCE_CALL_TOUCH_COUNT, + Settings.Secure.SILENCE_TIMER_TOUCH_COUNT, + Settings.Secure.DARK_MODE_DIALOG_SEEN, + Settings.Secure.GLOBAL_ACTIONS_PANEL_ENABLED, + Settings.Secure.AWARE_LOCK_ENABLED + }; +} diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java new file mode 100644 index 000000000000..89b19de8dfcb --- /dev/null +++ b/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2019 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.provider.settings.backup; + +import android.annotation.UnsupportedAppUsage; +import android.provider.Settings; + +/** Information about the system settings to back up */ +public class SystemSettings { + + /** + * Settings to backup. + * + * NOTE: Settings are backed up and restored in the order they appear + * in this array. If you have one setting depending on another, + * make sure that they are ordered appropriately. + */ + @UnsupportedAppUsage + public static final String[] SETTINGS_TO_BACKUP = { + Settings.System.STAY_ON_WHILE_PLUGGED_IN, // moved to global + Settings.System.WIFI_USE_STATIC_IP, + Settings.System.WIFI_STATIC_IP, + Settings.System.WIFI_STATIC_GATEWAY, + Settings.System.WIFI_STATIC_NETMASK, + Settings.System.WIFI_STATIC_DNS1, + Settings.System.WIFI_STATIC_DNS2, + Settings.System.BLUETOOTH_DISCOVERABILITY, + Settings.System.BLUETOOTH_DISCOVERABILITY_TIMEOUT, + Settings.System.FONT_SCALE, + Settings.System.DIM_SCREEN, + Settings.System.SCREEN_OFF_TIMEOUT, + Settings.System.SCREEN_BRIGHTNESS_MODE, + Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, + Settings.System.SCREEN_BRIGHTNESS_FOR_VR, + Settings.System.ADAPTIVE_SLEEP, + Settings.System.VIBRATE_INPUT_DEVICES, + Settings.System.MODE_RINGER_STREAMS_AFFECTED, + Settings.System.TEXT_AUTO_REPLACE, + Settings.System.TEXT_AUTO_CAPS, + Settings.System.TEXT_AUTO_PUNCTUATE, + Settings.System.TEXT_SHOW_PASSWORD, + Settings.System.AUTO_TIME, // moved to global + Settings.System.AUTO_TIME_ZONE, // moved to global + Settings.System.TIME_12_24, + Settings.System.DATE_FORMAT, + Settings.System.DTMF_TONE_WHEN_DIALING, + Settings.System.DTMF_TONE_TYPE_WHEN_DIALING, + Settings.System.HEARING_AID, + Settings.System.TTY_MODE, + Settings.System.MASTER_MONO, + Settings.System.MASTER_BALANCE, + Settings.System.SOUND_EFFECTS_ENABLED, + Settings.System.HAPTIC_FEEDBACK_ENABLED, + Settings.System.POWER_SOUNDS_ENABLED, // moved to global + Settings.System.DOCK_SOUNDS_ENABLED, // moved to global + Settings.System.LOCKSCREEN_SOUNDS_ENABLED, + Settings.System.SHOW_WEB_SUGGESTIONS, + Settings.System.SIP_CALL_OPTIONS, + Settings.System.SIP_RECEIVE_CALLS, + Settings.System.POINTER_SPEED, + Settings.System.VIBRATE_WHEN_RINGING, + Settings.System.RINGTONE, + Settings.System.LOCK_TO_APP_ENABLED, + Settings.System.NOTIFICATION_SOUND, + Settings.System.ACCELEROMETER_ROTATION, + Settings.System.SHOW_BATTERY_PERCENT, + Settings.System.NOTIFICATION_VIBRATION_INTENSITY, + Settings.System.RING_VIBRATION_INTENSITY, + Settings.System.HAPTIC_FEEDBACK_INTENSITY, + Settings.System.DISPLAY_COLOR_MODE, + Settings.System.ALARM_ALERT, + Settings.System.NOTIFICATION_LIGHT_PULSE, + }; +} diff --git a/core/java/android/provider/settings/validators/ComponentNameListValidator.java b/packages/SettingsProvider/src/android/provider/settings/validators/ComponentNameListValidator.java index b6b867a5d513..b6b867a5d513 100644 --- a/core/java/android/provider/settings/validators/ComponentNameListValidator.java +++ b/packages/SettingsProvider/src/android/provider/settings/validators/ComponentNameListValidator.java diff --git a/core/java/android/provider/settings/validators/DiscreteValueValidator.java b/packages/SettingsProvider/src/android/provider/settings/validators/DiscreteValueValidator.java index 183651f77f5a..183651f77f5a 100644 --- a/core/java/android/provider/settings/validators/DiscreteValueValidator.java +++ b/packages/SettingsProvider/src/android/provider/settings/validators/DiscreteValueValidator.java diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java new file mode 100644 index 000000000000..9be636d69daa --- /dev/null +++ b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2019 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.provider.settings.validators; + +import static android.provider.settings.validators.SettingsValidators.ANY_INTEGER_VALIDATOR; +import static android.provider.settings.validators.SettingsValidators.ANY_STRING_VALIDATOR; +import static android.provider.settings.validators.SettingsValidators.BOOLEAN_VALIDATOR; +import static android.provider.settings.validators.SettingsValidators.PACKAGE_NAME_VALIDATOR; +import static android.provider.settings.validators.SettingsValidators.PERCENTAGE_INTEGER_VALIDATOR; + +import android.media.AudioFormat; +import android.os.BatteryManager; +import android.provider.Settings.Global; +import android.text.TextUtils; +import android.util.ArrayMap; + +import java.util.Map; + +/** + * Validators for Global settings + */ +public class GlobalSettingsValidators { + /** + * All settings in {@link Global.SETTINGS_TO_BACKUP} array *must* have a non-null validator, + * otherwise they won't be restored. + */ + public static final Map<String, Validator> VALIDATORS = new ArrayMap<>(); + + static { + VALIDATORS.put(Global.APPLY_RAMPING_RINGER, BOOLEAN_VALIDATOR); + VALIDATORS.put(Global.BUGREPORT_IN_POWER_MENU, BOOLEAN_VALIDATOR); + VALIDATORS.put( + Global.STAY_ON_WHILE_PLUGGED_IN, + value -> { + try { + int val = Integer.parseInt(value); + return (val == 0) + || (val == BatteryManager.BATTERY_PLUGGED_AC) + || (val == BatteryManager.BATTERY_PLUGGED_USB) + || (val == BatteryManager.BATTERY_PLUGGED_WIRELESS) + || (val + == (BatteryManager.BATTERY_PLUGGED_AC + | BatteryManager.BATTERY_PLUGGED_USB)) + || (val + == (BatteryManager.BATTERY_PLUGGED_AC + | BatteryManager.BATTERY_PLUGGED_WIRELESS)) + || (val + == (BatteryManager.BATTERY_PLUGGED_USB + | BatteryManager.BATTERY_PLUGGED_WIRELESS)) + || (val + == (BatteryManager.BATTERY_PLUGGED_AC + | BatteryManager.BATTERY_PLUGGED_USB + | BatteryManager.BATTERY_PLUGGED_WIRELESS)); + } catch (NumberFormatException e) { + return false; + } + }); + VALIDATORS.put(Global.AUTO_TIME, BOOLEAN_VALIDATOR); + VALIDATORS.put(Global.AUTO_TIME_ZONE, BOOLEAN_VALIDATOR); + VALIDATORS.put(Global.POWER_SOUNDS_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Global.DOCK_SOUNDS_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Global.CHARGING_SOUNDS_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Global.USB_MASS_STORAGE_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put( + Global.NETWORK_RECOMMENDATIONS_ENABLED, + new DiscreteValueValidator(new String[] {"-1", "0", "1"})); + VALIDATORS.put(Global.WIFI_WAKEUP_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, BOOLEAN_VALIDATOR); + VALIDATORS.put( + Global.USE_OPEN_WIFI_PACKAGE, + value -> (value == null) || PACKAGE_NAME_VALIDATOR.validate(value)); + VALIDATORS.put(Global.WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED, ANY_STRING_VALIDATOR); + VALIDATORS.put( + Global.EMERGENCY_TONE, new DiscreteValueValidator(new String[] {"0", "1", "2"})); + VALIDATORS.put(Global.CALL_AUTO_RETRY, BOOLEAN_VALIDATOR); + VALIDATORS.put(Global.DOCK_AUDIO_MEDIA_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put( + Global.ENABLE_AUTOMATIC_SYSTEM_SERVER_HEAP_DUMPS, + new DiscreteValueValidator(new String[] {"0", "1"})); + VALIDATORS.put( + Global.ENCODED_SURROUND_OUTPUT, + new DiscreteValueValidator(new String[] {"0", "1", "2", "3"})); + VALIDATORS.put( + Global.ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS, + value -> { + try { + String[] surroundFormats = TextUtils.split(value, ","); + for (String format : surroundFormats) { + int audioFormat = Integer.valueOf(format); + boolean isSurroundFormat = false; + for (int sf : AudioFormat.SURROUND_SOUND_ENCODING) { + if (sf == audioFormat) { + isSurroundFormat = true; + break; + } + } + if (!isSurroundFormat) { + return false; + } + } + return true; + } catch (NumberFormatException e) { + return false; + } + }); + VALIDATORS.put( + Global.LOW_POWER_MODE_STICKY_AUTO_DISABLE_LEVEL, + new InclusiveIntegerRangeValidator(0, 100)); + VALIDATORS.put( + Global.LOW_POWER_MODE_STICKY_AUTO_DISABLE_ENABLED, + new DiscreteValueValidator(new String[] {"0", "1"})); + VALIDATORS.put(Global.LOW_POWER_MODE_TRIGGER_LEVEL, PERCENTAGE_INTEGER_VALIDATOR); + VALIDATORS.put(Global.LOW_POWER_MODE_TRIGGER_LEVEL_MAX, PERCENTAGE_INTEGER_VALIDATOR); + VALIDATORS.put( + Global.AUTOMATIC_POWER_SAVE_MODE, + new DiscreteValueValidator(new String[] {"0", "1"})); + VALIDATORS.put( + Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD, PERCENTAGE_INTEGER_VALIDATOR); + VALIDATORS.put(Global.BLUETOOTH_ON, BOOLEAN_VALIDATOR); + VALIDATORS.put(Global.PRIVATE_DNS_MODE, ANY_STRING_VALIDATOR); + VALIDATORS.put(Global.PRIVATE_DNS_SPECIFIER, ANY_STRING_VALIDATOR); + VALIDATORS.put(Global.SOFT_AP_TIMEOUT_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Global.WIFI_SCAN_THROTTLE_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Global.APP_AUTO_RESTRICTION_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Global.ZEN_DURATION, ANY_INTEGER_VALIDATOR); + VALIDATORS.put(Global.CHARGING_VIBRATION_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Global.DEVICE_PROVISIONING_MOBILE_DATA_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Global.REQUIRE_PASSWORD_TO_DECRYPT, BOOLEAN_VALIDATOR); + VALIDATORS.put(Global.DEVICE_DEMO_MODE, BOOLEAN_VALIDATOR); + VALIDATORS.put(Global.WIFI_PNO_FREQUENCY_CULLING_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Global.WIFI_PNO_RECENCY_SORTING_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Global.WIFI_LINK_PROBING_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Global.AWARE_ALLOWED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Global.POWER_BUTTON_LONG_PRESS, new InclusiveIntegerRangeValidator(0, 5)); + VALIDATORS.put( + Global.POWER_BUTTON_VERY_LONG_PRESS, new InclusiveIntegerRangeValidator(0, 1)); + } +} diff --git a/core/java/android/provider/settings/validators/InclusiveFloatRangeValidator.java b/packages/SettingsProvider/src/android/provider/settings/validators/InclusiveFloatRangeValidator.java index 38400ac676a8..1a0b88c1c150 100644 --- a/core/java/android/provider/settings/validators/InclusiveFloatRangeValidator.java +++ b/packages/SettingsProvider/src/android/provider/settings/validators/InclusiveFloatRangeValidator.java @@ -23,11 +23,11 @@ import android.annotation.Nullable; * * @hide */ -public final class InclusiveFloatRangeValidator implements Validator { +final class InclusiveFloatRangeValidator implements Validator { private final float mMin; private final float mMax; - public InclusiveFloatRangeValidator(float min, float max) { + InclusiveFloatRangeValidator(float min, float max) { mMin = min; mMax = max; } diff --git a/core/java/android/provider/settings/validators/InclusiveIntegerRangeValidator.java b/packages/SettingsProvider/src/android/provider/settings/validators/InclusiveIntegerRangeValidator.java index e53c252c7d35..f9f8ce851719 100644 --- a/core/java/android/provider/settings/validators/InclusiveIntegerRangeValidator.java +++ b/packages/SettingsProvider/src/android/provider/settings/validators/InclusiveIntegerRangeValidator.java @@ -23,11 +23,11 @@ import android.annotation.Nullable; * * @hide */ -public final class InclusiveIntegerRangeValidator implements Validator { +final class InclusiveIntegerRangeValidator implements Validator { private final int mMin; private final int mMax; - public InclusiveIntegerRangeValidator(int min, int max) { + InclusiveIntegerRangeValidator(int min, int max) { mMin = min; mMax = max; } diff --git a/core/java/android/provider/settings/validators/ListValidator.java b/packages/SettingsProvider/src/android/provider/settings/validators/ListValidator.java index a6001d2e10c1..a6001d2e10c1 100644 --- a/core/java/android/provider/settings/validators/ListValidator.java +++ b/packages/SettingsProvider/src/android/provider/settings/validators/ListValidator.java diff --git a/core/java/android/provider/settings/validators/PackageNameListValidator.java b/packages/SettingsProvider/src/android/provider/settings/validators/PackageNameListValidator.java index bc7fc13bdc6d..a883223f6f1b 100644 --- a/core/java/android/provider/settings/validators/PackageNameListValidator.java +++ b/packages/SettingsProvider/src/android/provider/settings/validators/PackageNameListValidator.java @@ -23,8 +23,8 @@ import static android.provider.settings.validators.SettingsValidators.PACKAGE_NA * * @hide */ -public final class PackageNameListValidator extends ListValidator { - public PackageNameListValidator(String separator) { +final class PackageNameListValidator extends ListValidator { + PackageNameListValidator(String separator) { super(separator); } diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java new file mode 100644 index 000000000000..f160edc6e446 --- /dev/null +++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java @@ -0,0 +1,231 @@ +/* + * Copyright (C) 2019 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.provider.settings.validators; + +import static android.provider.settings.validators.SettingsValidators.ANY_INTEGER_VALIDATOR; +import static android.provider.settings.validators.SettingsValidators.BOOLEAN_VALIDATOR; +import static android.provider.settings.validators.SettingsValidators.COLON_SEPARATED_COMPONENT_LIST_VALIDATOR; +import static android.provider.settings.validators.SettingsValidators.COLON_SEPARATED_PACKAGE_LIST_VALIDATOR; +import static android.provider.settings.validators.SettingsValidators.COMMA_SEPARATED_COMPONENT_LIST_VALIDATOR; +import static android.provider.settings.validators.SettingsValidators.COMPONENT_NAME_VALIDATOR; +import static android.provider.settings.validators.SettingsValidators.JSON_OBJECT_VALIDATOR; +import static android.provider.settings.validators.SettingsValidators.LOCALE_VALIDATOR; +import static android.provider.settings.validators.SettingsValidators.NON_NEGATIVE_INTEGER_VALIDATOR; +import static android.provider.settings.validators.SettingsValidators.NULLABLE_COMPONENT_NAME_VALIDATOR; +import static android.provider.settings.validators.SettingsValidators.PACKAGE_NAME_VALIDATOR; +import static android.provider.settings.validators.SettingsValidators.TILE_LIST_VALIDATOR; +import static android.provider.settings.validators.SettingsValidators.TTS_LIST_VALIDATOR; + +import android.provider.Settings.Secure; +import android.util.ArrayMap; + +import java.util.Map; + +/** + * Validators for the Secure Settings. + */ +public class SecureSettingsValidators { + /** + * All settings in {@link Secure.SETTINGS_TO_BACKUP} and {@link + * Secure.DEVICE_SPECIFIC_SETTINGS_TO_BACKUP} array *must* have a non-null validator, otherwise + * they won't be restored. + */ + public static final Map<String, Validator> VALIDATORS = new ArrayMap<>(); + + static { + VALIDATORS.put(Secure.BUGREPORT_IN_POWER_MENU, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.ALLOW_MOCK_LOCATION, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.USB_MASS_STORAGE_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put( + Secure.ACCESSIBILITY_DISPLAY_DALTONIZER, + new DiscreteValueValidator(new String[] {"-1", "0", "11", "12", "13"})); + VALIDATORS.put(Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put( + Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.AUTOFILL_SERVICE, NULLABLE_COMPONENT_NAME_VALIDATOR); + VALIDATORS.put( + Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, + new InclusiveFloatRangeValidator(1.0f, Float.MAX_VALUE)); + VALIDATORS.put( + Secure.ENABLED_ACCESSIBILITY_SERVICES, COLON_SEPARATED_COMPONENT_LIST_VALIDATOR); + VALIDATORS.put(Secure.ENABLED_VR_LISTENERS, COLON_SEPARATED_COMPONENT_LIST_VALIDATOR); + VALIDATORS.put( + Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES, + COLON_SEPARATED_COMPONENT_LIST_VALIDATOR); + VALIDATORS.put(Secure.TOUCH_EXPLORATION_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.ACCESSIBILITY_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put( + Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, NULLABLE_COMPONENT_NAME_VALIDATOR); + // technically either ComponentName or class name, but there's proper value + // validation at callsites, so allow any non-null string + VALIDATORS.put(Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT, value -> value != null); + VALIDATORS.put(Secure.ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.ACCESSIBILITY_SHORTCUT_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put( + Secure.ACCESSIBILITY_CAPTIONING_PRESET, + new DiscreteValueValidator(new String[] {"-1", "0", "1", "2", "3", "4"})); + VALIDATORS.put(Secure.ACCESSIBILITY_CAPTIONING_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.ACCESSIBILITY_CAPTIONING_LOCALE, LOCALE_VALIDATOR); + VALIDATORS.put(Secure.ACCESSIBILITY_CAPTIONING_BACKGROUND_COLOR, ANY_INTEGER_VALIDATOR); + VALIDATORS.put(Secure.ACCESSIBILITY_CAPTIONING_FOREGROUND_COLOR, ANY_INTEGER_VALIDATOR); + VALIDATORS.put( + Secure.ACCESSIBILITY_CAPTIONING_EDGE_TYPE, + new DiscreteValueValidator(new String[] {"0", "1", "2"})); + VALIDATORS.put(Secure.ACCESSIBILITY_CAPTIONING_EDGE_COLOR, ANY_INTEGER_VALIDATOR); + VALIDATORS.put( + Secure.ACCESSIBILITY_CAPTIONING_TYPEFACE, + new DiscreteValueValidator( + new String[] {"DEFAULT", "MONOSPACE", "SANS_SERIF", "SERIF"})); + VALIDATORS.put( + Secure.ACCESSIBILITY_CAPTIONING_FONT_SCALE, + new InclusiveFloatRangeValidator(0.5f, 2.0f)); + VALIDATORS.put(Secure.ACCESSIBILITY_CAPTIONING_WINDOW_COLOR, ANY_INTEGER_VALIDATOR); + VALIDATORS.put(Secure.TTS_DEFAULT_RATE, NON_NEGATIVE_INTEGER_VALIDATOR); + VALIDATORS.put(Secure.TTS_DEFAULT_PITCH, NON_NEGATIVE_INTEGER_VALIDATOR); + VALIDATORS.put(Secure.TTS_DEFAULT_SYNTH, PACKAGE_NAME_VALIDATOR); + VALIDATORS.put(Secure.TTS_ENABLED_PLUGINS, new PackageNameListValidator(" ")); + VALIDATORS.put(Secure.TTS_DEFAULT_LOCALE, TTS_LIST_VALIDATOR); + VALIDATORS.put(Secure.SHOW_IME_WITH_HARD_KEYBOARD, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY, NON_NEGATIVE_INTEGER_VALIDATOR); + VALIDATORS.put(Secure.WIFI_NUM_OPEN_NETWORKS_KEPT, NON_NEGATIVE_INTEGER_VALIDATOR); + VALIDATORS.put(Secure.MOUNT_PLAY_NOTIFICATION_SND, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.MOUNT_UMS_AUTOSTART, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.MOUNT_UMS_PROMPT, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.MOUNT_UMS_NOTIFY_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.DOUBLE_TAP_TO_WAKE, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.WAKE_GESTURE_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.LONG_PRESS_TIMEOUT, NON_NEGATIVE_INTEGER_VALIDATOR); + VALIDATORS.put(Secure.CAMERA_GESTURE_DISABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.ACCESSIBILITY_AUTOCLICK_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.ACCESSIBILITY_AUTOCLICK_DELAY, NON_NEGATIVE_INTEGER_VALIDATOR); + VALIDATORS.put(Secure.ACCESSIBILITY_LARGE_POINTER_ICON, BOOLEAN_VALIDATOR); + VALIDATORS.put( + Secure.PREFERRED_TTY_MODE, + new DiscreteValueValidator(new String[] {"0", "1", "2", "3"})); + VALIDATORS.put(Secure.ENHANCED_VOICE_PRIVACY_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.TTY_MODE_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.RTT_CALLING_MODE, BOOLEAN_VALIDATOR); + VALIDATORS.put( + Secure.INCALL_POWER_BUTTON_BEHAVIOR, + new DiscreteValueValidator(new String[] {"1", "2"})); + VALIDATORS.put(Secure.NIGHT_DISPLAY_CUSTOM_START_TIME, NON_NEGATIVE_INTEGER_VALIDATOR); + VALIDATORS.put(Secure.NIGHT_DISPLAY_CUSTOM_END_TIME, NON_NEGATIVE_INTEGER_VALIDATOR); + VALIDATORS.put(Secure.NIGHT_DISPLAY_COLOR_TEMPERATURE, NON_NEGATIVE_INTEGER_VALIDATOR); + VALIDATORS.put(Secure.NIGHT_DISPLAY_AUTO_MODE, new InclusiveIntegerRangeValidator(0, 2)); + VALIDATORS.put(Secure.DISPLAY_WHITE_BALANCE_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.SYNC_PARENT_SOUNDS, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.CAMERA_DOUBLE_TWIST_TO_FLIP_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.QS_TILES, TILE_LIST_VALIDATOR); + VALIDATORS.put(Secure.DOZE_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.DOZE_ALWAYS_ON, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.DOZE_PICK_UP_GESTURE, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.DOZE_DOUBLE_TAP_GESTURE, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.DOZE_TAP_SCREEN_GESTURE, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.DOZE_WAKE_LOCK_SCREEN_GESTURE, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.DOZE_WAKE_DISPLAY_GESTURE, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.NFC_PAYMENT_DEFAULT_COMPONENT, COMPONENT_NAME_VALIDATOR); + VALIDATORS.put( + Secure.AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN, NON_NEGATIVE_INTEGER_VALIDATOR); + VALIDATORS.put(Secure.FACE_UNLOCK_KEYGUARD_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.FACE_UNLOCK_DISMISSES_KEYGUARD, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.SHOW_MEDIA_WHEN_BYPASSING, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.FACE_UNLOCK_APP_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.ASSIST_GESTURE_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.ASSIST_GESTURE_SILENCE_ALERTS_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.ASSIST_GESTURE_WAKE_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.VR_DISPLAY_MODE, new DiscreteValueValidator(new String[] {"0", "1"})); + VALIDATORS.put(Secure.NOTIFICATION_BADGING, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.NOTIFICATION_BUBBLES, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.NOTIFICATION_DISMISS_RTL, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.QS_AUTO_ADDED_TILES, TILE_LIST_VALIDATOR); + VALIDATORS.put(Secure.SCREENSAVER_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.SCREENSAVER_COMPONENTS, COMMA_SEPARATED_COMPONENT_LIST_VALIDATOR); + VALIDATORS.put(Secure.SCREENSAVER_ACTIVATE_ON_DOCK, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.SCREENSAVER_ACTIVATE_ON_SLEEP, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.LOCKDOWN_IN_POWER_MENU, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.SHOW_FIRST_CRASH_DIALOG_DEV_OPTION, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.VOLUME_HUSH_GESTURE, NON_NEGATIVE_INTEGER_VALIDATOR); + VALIDATORS.put( + Secure.ENABLED_NOTIFICATION_LISTENERS, + COLON_SEPARATED_COMPONENT_LIST_VALIDATOR); // legacy restore setting + VALIDATORS.put( + Secure.ENABLED_NOTIFICATION_ASSISTANT, + COLON_SEPARATED_COMPONENT_LIST_VALIDATOR); // legacy restore setting + VALIDATORS.put( + Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES, + COLON_SEPARATED_PACKAGE_LIST_VALIDATOR); // legacy restore setting + VALIDATORS.put(Secure.HUSH_GESTURE_USED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.MANUAL_RINGER_TOGGLE_COUNT, NON_NEGATIVE_INTEGER_VALIDATOR); + VALIDATORS.put(Secure.IN_CALL_NOTIFICATION_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.SHOW_NOTIFICATION_SNOOZE, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.ZEN_DURATION, ANY_INTEGER_VALIDATOR); + VALIDATORS.put(Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.SHOW_ZEN_SETTINGS_SUGGESTION, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.ZEN_SETTINGS_UPDATED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.ZEN_SETTINGS_SUGGESTION_VIEWED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.CHARGING_SOUNDS_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.CHARGING_VIBRATION_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put( + Secure.ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS, NON_NEGATIVE_INTEGER_VALIDATOR); + VALIDATORS.put( + Secure.ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS, NON_NEGATIVE_INTEGER_VALIDATOR); + VALIDATORS.put(Secure.USER_SETUP_COMPLETE, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.ASSIST_GESTURE_SETUP_COMPLETE, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.NOTIFICATION_NEW_INTERRUPTION_MODEL, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.TRUST_AGENTS_EXTEND_UNLOCK, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.LOCK_SCREEN_CUSTOM_CLOCK_FACE, JSON_OBJECT_VALIDATOR); + VALIDATORS.put(Secure.LOCK_SCREEN_WHEN_TRUST_LOST, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.SKIP_GESTURE, BOOLEAN_VALIDATOR); + /* + * Only used if FeatureFlag "settings_skip_direction_mutable" is enabled. + * If feature flag is disabled, should assume SKIP_DIRECTION = 0. + * 0 / false = right to left to advance to next + * 1 / true = left to right to advance to next + */ + VALIDATORS.put(Secure.SKIP_DIRECTION, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.SILENCE_GESTURE, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES, JSON_OBJECT_VALIDATOR); + VALIDATORS.put( + Secure.NAVIGATION_MODE, new DiscreteValueValidator(new String[] {"0", "1", "2"})); + VALIDATORS.put(Secure.AWARE_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.SKIP_GESTURE_COUNT, NON_NEGATIVE_INTEGER_VALIDATOR); + VALIDATORS.put(Secure.SKIP_TOUCH_COUNT, NON_NEGATIVE_INTEGER_VALIDATOR); + VALIDATORS.put(Secure.SILENCE_ALARMS_GESTURE_COUNT, NON_NEGATIVE_INTEGER_VALIDATOR); + VALIDATORS.put(Secure.SILENCE_TIMER_GESTURE_COUNT, NON_NEGATIVE_INTEGER_VALIDATOR); + VALIDATORS.put(Secure.SILENCE_CALL_GESTURE_COUNT, NON_NEGATIVE_INTEGER_VALIDATOR); + VALIDATORS.put(Secure.SILENCE_ALARMS_TOUCH_COUNT, NON_NEGATIVE_INTEGER_VALIDATOR); + VALIDATORS.put(Secure.SILENCE_TIMER_TOUCH_COUNT, NON_NEGATIVE_INTEGER_VALIDATOR); + VALIDATORS.put(Secure.SILENCE_CALL_TOUCH_COUNT, NON_NEGATIVE_INTEGER_VALIDATOR); + VALIDATORS.put(Secure.ODI_CAPTIONS_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.DARK_MODE_DIALOG_SEEN, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.UI_NIGHT_MODE, new InclusiveIntegerRangeValidator(0, 2)); + VALIDATORS.put(Secure.GLOBAL_ACTIONS_PANEL_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.AWARE_LOCK_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.DISPLAY_DENSITY_FORCED, NON_NEGATIVE_INTEGER_VALIDATOR); + } +} diff --git a/core/java/android/provider/settings/validators/SettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SettingsValidators.java index 562c638d0b5a..224042ca755d 100644 --- a/core/java/android/provider/settings/validators/SettingsValidators.java +++ b/packages/SettingsProvider/src/android/provider/settings/validators/SettingsValidators.java @@ -24,6 +24,7 @@ import android.text.TextUtils; import org.json.JSONException; import org.json.JSONObject; +import java.text.SimpleDateFormat; import java.util.Locale; /** @@ -180,4 +181,27 @@ public class SettingsValidators { public static final Validator TTS_LIST_VALIDATOR = new TTSListValidator(); public static final Validator TILE_LIST_VALIDATOR = new TileListValidator(); + + static final Validator DATE_FORMAT_VALIDATOR = value -> { + try { + new SimpleDateFormat(value); + return true; + } catch (IllegalArgumentException | NullPointerException e) { + return false; + } + }; + + static final Validator COLON_SEPARATED_COMPONENT_LIST_VALIDATOR = + new ComponentNameListValidator(":"); + + static final Validator COLON_SEPARATED_PACKAGE_LIST_VALIDATOR = + new PackageNameListValidator(":"); + + static final Validator COMMA_SEPARATED_COMPONENT_LIST_VALIDATOR = + new ComponentNameListValidator(","); + + static final Validator PERCENTAGE_INTEGER_VALIDATOR = + new InclusiveIntegerRangeValidator(0, 100); + + static final Validator VIBRATION_INTENSITY_VALIDATOR = new InclusiveIntegerRangeValidator(0, 3); } diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java new file mode 100644 index 000000000000..94ab0f11927d --- /dev/null +++ b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java @@ -0,0 +1,220 @@ +/* + * Copyright (C) 2019 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.provider.settings.validators; + +import static android.provider.settings.validators.SettingsValidators.BOOLEAN_VALIDATOR; +import static android.provider.settings.validators.SettingsValidators.COMPONENT_NAME_VALIDATOR; +import static android.provider.settings.validators.SettingsValidators.DATE_FORMAT_VALIDATOR; +import static android.provider.settings.validators.SettingsValidators.LENIENT_IP_ADDRESS_VALIDATOR; +import static android.provider.settings.validators.SettingsValidators.NON_NEGATIVE_INTEGER_VALIDATOR; +import static android.provider.settings.validators.SettingsValidators.URI_VALIDATOR; +import static android.provider.settings.validators.SettingsValidators.VIBRATION_INTENSITY_VALIDATOR; + +import android.annotation.Nullable; +import android.annotation.UnsupportedAppUsage; +import android.content.ComponentName; +import android.hardware.display.ColorDisplayManager; +import android.os.BatteryManager; +import android.provider.Settings.System; +import android.util.ArrayMap; + +import java.util.Map; + +/** + * Validators for System settings + */ +public class SystemSettingsValidators { + /** + * These are all public system settings + * + * <p>All settings in {@link System.SETTINGS_TO_BACKUP} array *must* have a non-null validator, + * otherwise they won't be restored. + */ + @UnsupportedAppUsage + public static final Map<String, Validator> VALIDATORS = new ArrayMap<>(); + + static { + VALIDATORS.put( + System.STAY_ON_WHILE_PLUGGED_IN, + value -> { + try { + int val = Integer.parseInt(value); + return (val == 0) + || (val == BatteryManager.BATTERY_PLUGGED_AC) + || (val == BatteryManager.BATTERY_PLUGGED_USB) + || (val == BatteryManager.BATTERY_PLUGGED_WIRELESS) + || (val + == (BatteryManager.BATTERY_PLUGGED_AC + | BatteryManager.BATTERY_PLUGGED_USB)) + || (val + == (BatteryManager.BATTERY_PLUGGED_AC + | BatteryManager.BATTERY_PLUGGED_WIRELESS)) + || (val + == (BatteryManager.BATTERY_PLUGGED_USB + | BatteryManager.BATTERY_PLUGGED_WIRELESS)) + || (val + == (BatteryManager.BATTERY_PLUGGED_AC + | BatteryManager.BATTERY_PLUGGED_USB + | BatteryManager.BATTERY_PLUGGED_WIRELESS)); + } catch (NumberFormatException e) { + return false; + } + }); + VALIDATORS.put(System.END_BUTTON_BEHAVIOR, new InclusiveIntegerRangeValidator(0, 3)); + VALIDATORS.put(System.WIFI_USE_STATIC_IP, BOOLEAN_VALIDATOR); + VALIDATORS.put(System.BLUETOOTH_DISCOVERABILITY, new InclusiveIntegerRangeValidator(0, 2)); + VALIDATORS.put(System.BLUETOOTH_DISCOVERABILITY_TIMEOUT, NON_NEGATIVE_INTEGER_VALIDATOR); + VALIDATORS.put( + System.NEXT_ALARM_FORMATTED, + new Validator() { + private static final int MAX_LENGTH = 1000; + + @Override + public boolean validate(String value) { + // TODO: No idea what the correct format is. + return value == null || value.length() < MAX_LENGTH; + } + }); + VALIDATORS.put( + System.FONT_SCALE, + value -> { + try { + return Float.parseFloat(value) >= 0; + } catch (NumberFormatException | NullPointerException e) { + return false; + } + }); + VALIDATORS.put(System.DIM_SCREEN, BOOLEAN_VALIDATOR); + VALIDATORS.put( + System.DISPLAY_COLOR_MODE, + new Validator() { + @Override + public boolean validate(@Nullable String value) { + // Assume the actual validation that this device can properly handle this + // kind of + // color mode further down in ColorDisplayManager / ColorDisplayService. + try { + final int setting = Integer.parseInt(value); + final boolean isInFrameworkRange = + setting >= ColorDisplayManager.COLOR_MODE_NATURAL + && setting <= ColorDisplayManager.COLOR_MODE_AUTOMATIC; + final boolean isInVendorRange = + setting >= ColorDisplayManager.VENDOR_COLOR_MODE_RANGE_MIN + && setting + <= ColorDisplayManager + .VENDOR_COLOR_MODE_RANGE_MAX; + return isInFrameworkRange || isInVendorRange; + } catch (NumberFormatException | NullPointerException e) { + return false; + } + } + }); + VALIDATORS.put(System.SCREEN_OFF_TIMEOUT, NON_NEGATIVE_INTEGER_VALIDATOR); + VALIDATORS.put(System.SCREEN_BRIGHTNESS_FOR_VR, new InclusiveIntegerRangeValidator(0, 255)); + VALIDATORS.put(System.SCREEN_BRIGHTNESS_MODE, BOOLEAN_VALIDATOR); + VALIDATORS.put(System.ADAPTIVE_SLEEP, BOOLEAN_VALIDATOR); + VALIDATORS.put(System.MODE_RINGER_STREAMS_AFFECTED, NON_NEGATIVE_INTEGER_VALIDATOR); + VALIDATORS.put(System.MUTE_STREAMS_AFFECTED, NON_NEGATIVE_INTEGER_VALIDATOR); + VALIDATORS.put(System.VIBRATE_ON, BOOLEAN_VALIDATOR); + VALIDATORS.put(System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_VALIDATOR); + VALIDATORS.put(System.RING_VIBRATION_INTENSITY, VIBRATION_INTENSITY_VALIDATOR); + VALIDATORS.put(System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_VALIDATOR); + VALIDATORS.put(System.RINGTONE, URI_VALIDATOR); + VALIDATORS.put(System.NOTIFICATION_SOUND, URI_VALIDATOR); + VALIDATORS.put(System.ALARM_ALERT, URI_VALIDATOR); + VALIDATORS.put(System.TEXT_AUTO_REPLACE, BOOLEAN_VALIDATOR); + VALIDATORS.put(System.TEXT_AUTO_CAPS, BOOLEAN_VALIDATOR); + VALIDATORS.put(System.TEXT_AUTO_PUNCTUATE, BOOLEAN_VALIDATOR); + VALIDATORS.put(System.TEXT_SHOW_PASSWORD, BOOLEAN_VALIDATOR); + VALIDATORS.put(System.AUTO_TIME, BOOLEAN_VALIDATOR); + VALIDATORS.put(System.AUTO_TIME_ZONE, BOOLEAN_VALIDATOR); + VALIDATORS.put(System.SHOW_GTALK_SERVICE_STATUS, BOOLEAN_VALIDATOR); + VALIDATORS.put( + System.WALLPAPER_ACTIVITY, + new Validator() { + private static final int MAX_LENGTH = 1000; + + @Override + public boolean validate(String value) { + if (value != null && value.length() > MAX_LENGTH) { + return false; + } + return ComponentName.unflattenFromString(value) != null; + } + }); + VALIDATORS.put( + System.TIME_12_24, new DiscreteValueValidator(new String[] {"12", "24", null})); + VALIDATORS.put(System.DATE_FORMAT, DATE_FORMAT_VALIDATOR); + VALIDATORS.put(System.SETUP_WIZARD_HAS_RUN, BOOLEAN_VALIDATOR); + VALIDATORS.put(System.ACCELEROMETER_ROTATION, BOOLEAN_VALIDATOR); + VALIDATORS.put(System.USER_ROTATION, new InclusiveIntegerRangeValidator(0, 3)); + VALIDATORS.put(System.DTMF_TONE_WHEN_DIALING, BOOLEAN_VALIDATOR); + VALIDATORS.put(System.SOUND_EFFECTS_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(System.HAPTIC_FEEDBACK_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(System.POWER_SOUNDS_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(System.DOCK_SOUNDS_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(System.SHOW_WEB_SUGGESTIONS, BOOLEAN_VALIDATOR); + VALIDATORS.put(System.WIFI_USE_STATIC_IP, BOOLEAN_VALIDATOR); + VALIDATORS.put(System.ADVANCED_SETTINGS, BOOLEAN_VALIDATOR); + VALIDATORS.put(System.SCREEN_AUTO_BRIGHTNESS_ADJ, new InclusiveFloatRangeValidator(-1, 1)); + VALIDATORS.put(System.VIBRATE_INPUT_DEVICES, BOOLEAN_VALIDATOR); + VALIDATORS.put(System.MASTER_MONO, BOOLEAN_VALIDATOR); + VALIDATORS.put(System.MASTER_BALANCE, new InclusiveFloatRangeValidator(-1.f, 1.f)); + VALIDATORS.put(System.NOTIFICATIONS_USE_RING_VOLUME, BOOLEAN_VALIDATOR); + VALIDATORS.put(System.VIBRATE_IN_SILENT, BOOLEAN_VALIDATOR); + VALIDATORS.put(System.MEDIA_BUTTON_RECEIVER, COMPONENT_NAME_VALIDATOR); + VALIDATORS.put(System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY, BOOLEAN_VALIDATOR); + VALIDATORS.put(System.VIBRATE_WHEN_RINGING, BOOLEAN_VALIDATOR); + VALIDATORS.put(System.DTMF_TONE_TYPE_WHEN_DIALING, BOOLEAN_VALIDATOR); + VALIDATORS.put(System.HEARING_AID, BOOLEAN_VALIDATOR); + VALIDATORS.put(System.TTY_MODE, new InclusiveIntegerRangeValidator(0, 3)); + VALIDATORS.put(System.NOTIFICATION_LIGHT_PULSE, BOOLEAN_VALIDATOR); + VALIDATORS.put(System.POINTER_LOCATION, BOOLEAN_VALIDATOR); + VALIDATORS.put(System.SHOW_TOUCHES, BOOLEAN_VALIDATOR); + VALIDATORS.put(System.WINDOW_ORIENTATION_LISTENER_LOG, BOOLEAN_VALIDATOR); + VALIDATORS.put(System.LOCKSCREEN_SOUNDS_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(System.LOCKSCREEN_DISABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(System.SIP_RECEIVE_CALLS, BOOLEAN_VALIDATOR); + VALIDATORS.put( + System.SIP_CALL_OPTIONS, + new DiscreteValueValidator(new String[] {"SIP_ALWAYS", "SIP_ADDRESS_ONLY"})); + VALIDATORS.put(System.SIP_ALWAYS, BOOLEAN_VALIDATOR); + VALIDATORS.put(System.SIP_ADDRESS_ONLY, BOOLEAN_VALIDATOR); + VALIDATORS.put(System.SIP_ASK_ME_EACH_TIME, BOOLEAN_VALIDATOR); + VALIDATORS.put(System.POINTER_SPEED, new InclusiveFloatRangeValidator(-7, 7)); + VALIDATORS.put(System.LOCK_TO_APP_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put( + System.EGG_MODE, + new Validator() { + @Override + public boolean validate(@Nullable String value) { + try { + return Long.parseLong(value) >= 0; + } catch (NumberFormatException e) { + return false; + } + } + }); + VALIDATORS.put(System.WIFI_STATIC_IP, LENIENT_IP_ADDRESS_VALIDATOR); + VALIDATORS.put(System.WIFI_STATIC_GATEWAY, LENIENT_IP_ADDRESS_VALIDATOR); + VALIDATORS.put(System.WIFI_STATIC_NETMASK, LENIENT_IP_ADDRESS_VALIDATOR); + VALIDATORS.put(System.WIFI_STATIC_DNS1, LENIENT_IP_ADDRESS_VALIDATOR); + VALIDATORS.put(System.WIFI_STATIC_DNS2, LENIENT_IP_ADDRESS_VALIDATOR); + VALIDATORS.put(System.SHOW_BATTERY_PERCENT, BOOLEAN_VALIDATOR); + VALIDATORS.put(System.NOTIFICATION_LIGHT_PULSE, BOOLEAN_VALIDATOR); + } +} diff --git a/core/java/android/provider/settings/validators/TTSListValidator.java b/packages/SettingsProvider/src/android/provider/settings/validators/TTSListValidator.java index 6c73471a8e8e..6c73471a8e8e 100644 --- a/core/java/android/provider/settings/validators/TTSListValidator.java +++ b/packages/SettingsProvider/src/android/provider/settings/validators/TTSListValidator.java diff --git a/core/java/android/provider/settings/validators/TileListValidator.java b/packages/SettingsProvider/src/android/provider/settings/validators/TileListValidator.java index c69644252bcd..c69644252bcd 100644 --- a/core/java/android/provider/settings/validators/TileListValidator.java +++ b/packages/SettingsProvider/src/android/provider/settings/validators/TileListValidator.java diff --git a/core/java/android/provider/settings/validators/Validator.java b/packages/SettingsProvider/src/android/provider/settings/validators/Validator.java index 393a03ddf916..393a03ddf916 100644 --- a/core/java/android/provider/settings/validators/Validator.java +++ b/packages/SettingsProvider/src/android/provider/settings/validators/Validator.java diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java index 36e945fe30b6..f545fa65fb90 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java @@ -34,6 +34,12 @@ import android.os.Build; import android.os.ParcelFileDescriptor; import android.os.UserHandle; import android.provider.Settings; +import android.provider.settings.backup.GlobalSettings; +import android.provider.settings.backup.SecureSettings; +import android.provider.settings.backup.SystemSettings; +import android.provider.settings.validators.GlobalSettingsValidators; +import android.provider.settings.validators.SecureSettingsValidators; +import android.provider.settings.validators.SystemSettingsValidators; import android.provider.settings.validators.Validator; import android.util.ArrayMap; import android.util.ArraySet; @@ -45,7 +51,7 @@ import android.view.Display; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; import com.android.internal.widget.LockPatternUtils; -import com.android.settingslib.display.DisplayDensityUtils; +import com.android.settingslib.display.DisplayDensityConfiguration; import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; @@ -542,7 +548,7 @@ public class SettingsBackupAgent extends BackupAgentHelper { Cursor cursor = getContentResolver().query(Settings.System.CONTENT_URI, PROJECTION, null, null, null); try { - return extractRelevantValues(cursor, Settings.System.SETTINGS_TO_BACKUP); + return extractRelevantValues(cursor, SystemSettings.SETTINGS_TO_BACKUP); } finally { cursor.close(); } @@ -552,7 +558,7 @@ public class SettingsBackupAgent extends BackupAgentHelper { Cursor cursor = getContentResolver().query(Settings.Secure.CONTENT_URI, PROJECTION, null, null, null); try { - return extractRelevantValues(cursor, Settings.Secure.SETTINGS_TO_BACKUP); + return extractRelevantValues(cursor, SecureSettings.SETTINGS_TO_BACKUP); } finally { cursor.close(); } @@ -562,7 +568,7 @@ public class SettingsBackupAgent extends BackupAgentHelper { Cursor cursor = getContentResolver().query(Settings.Global.CONTENT_URI, PROJECTION, null, null, null); try { - return extractRelevantValues(cursor, Settings.Global.SETTINGS_TO_BACKUP); + return extractRelevantValues(cursor, GlobalSettings.SETTINGS_TO_BACKUP); } finally { cursor.close(); } @@ -633,18 +639,18 @@ public class SettingsBackupAgent extends BackupAgentHelper { final String[] whitelist; Map<String, Validator> validators = null; if (contentUri.equals(Settings.Secure.CONTENT_URI)) { - whitelist = ArrayUtils.concatElements(String.class, Settings.Secure.SETTINGS_TO_BACKUP, + whitelist = ArrayUtils.concatElements(String.class, SecureSettings.SETTINGS_TO_BACKUP, Settings.Secure.LEGACY_RESTORE_SETTINGS, Settings.Secure.DEVICE_SPECIFIC_SETTINGS_TO_BACKUP); - validators = Settings.Secure.VALIDATORS; + validators = SecureSettingsValidators.VALIDATORS; } else if (contentUri.equals(Settings.System.CONTENT_URI)) { - whitelist = ArrayUtils.concatElements(String.class, Settings.System.SETTINGS_TO_BACKUP, + whitelist = ArrayUtils.concatElements(String.class, SystemSettings.SETTINGS_TO_BACKUP, Settings.System.LEGACY_RESTORE_SETTINGS); - validators = Settings.System.VALIDATORS; + validators = SystemSettingsValidators.VALIDATORS; } else if (contentUri.equals(Settings.Global.CONTENT_URI)) { - whitelist = ArrayUtils.concatElements(String.class, Settings.Global.SETTINGS_TO_BACKUP, + whitelist = ArrayUtils.concatElements(String.class, GlobalSettings.SETTINGS_TO_BACKUP, Settings.Global.LEGACY_RESTORE_SETTINGS); - validators = Settings.Global.VALIDATORS; + validators = GlobalSettingsValidators.VALIDATORS; } else { throw new IllegalArgumentException("Unknown URI: " + contentUri); } @@ -1035,7 +1041,8 @@ public class SettingsBackupAgent extends BackupAgentHelper { if (previousDensity == null || previousDensity != newDensity) { // From nothing to something is a change. - DisplayDensityUtils.setForcedDisplayDensity(Display.DEFAULT_DISPLAY, newDensity); + DisplayDensityConfiguration.setForcedDisplayDensity( + Display.DEFAULT_DISPLAY, newDensity); } } diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java index e492e28f6172..4d71e72b59d6 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java @@ -70,6 +70,7 @@ import android.provider.DeviceConfig; import android.provider.Settings; import android.provider.Settings.Global; import android.provider.Settings.Secure; +import android.provider.settings.validators.SystemSettingsValidators; import android.provider.settings.validators.Validator; import android.text.TextUtils; import android.util.ArrayMap; @@ -1717,7 +1718,7 @@ public class SettingsProvider extends ContentProvider { } private void validateSystemSettingValue(String name, String value) { - Validator validator = Settings.System.VALIDATORS.get(name); + Validator validator = SystemSettingsValidators.VALIDATORS.get(name); if (validator != null && !validator.validate(value)) { throw new IllegalArgumentException("Invalid value: " + value + " for setting: " + name); diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java index eef780ac2efa..d7eb7e955d8c 100644 --- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java +++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java @@ -18,15 +18,16 @@ package android.provider; import static com.google.android.collect.Sets.newHashSet; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.empty; -import static org.hamcrest.Matchers.is; +import static junit.framework.Assert.assertTrue; import static java.lang.reflect.Modifier.isFinal; import static java.lang.reflect.Modifier.isPublic; import static java.lang.reflect.Modifier.isStatic; import android.platform.test.annotations.Presubmit; +import android.provider.settings.backup.GlobalSettings; +import android.provider.settings.backup.SecureSettings; +import android.provider.settings.backup.SystemSettings; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; @@ -727,45 +728,43 @@ public class SettingsBackupTest { public void systemSettingsBackedUpOrBlacklisted() { checkSettingsBackedUpOrBlacklisted( getCandidateSettings(Settings.System.class), - newHashSet(Settings.System.SETTINGS_TO_BACKUP), + newHashSet(SystemSettings.SETTINGS_TO_BACKUP), BACKUP_BLACKLISTED_SYSTEM_SETTINGS); } @Test public void globalSettingsBackedUpOrBlacklisted() { checkSettingsBackedUpOrBlacklisted( - getCandidateSettings(Settings.Global.class), - newHashSet(Settings.Global.SETTINGS_TO_BACKUP), - BACKUP_BLACKLISTED_GLOBAL_SETTINGS); + getCandidateSettings(Settings.Global.class), + newHashSet(GlobalSettings.SETTINGS_TO_BACKUP), + BACKUP_BLACKLISTED_GLOBAL_SETTINGS); } @Test public void secureSettingsBackedUpOrBlacklisted() { HashSet<String> keys = new HashSet<String>(); - Collections.addAll(keys, Settings.Secure.SETTINGS_TO_BACKUP); + Collections.addAll(keys, SecureSettings.SETTINGS_TO_BACKUP); Collections.addAll(keys, Settings.Secure.DEVICE_SPECIFIC_SETTINGS_TO_BACKUP); checkSettingsBackedUpOrBlacklisted( getCandidateSettings(Settings.Secure.class), keys, - BACKUP_BLACKLISTED_SECURE_SETTINGS); + BACKUP_BLACKLISTED_SECURE_SETTINGS); } private static void checkSettingsBackedUpOrBlacklisted( Set<String> settings, Set<String> settingsToBackup, Set<String> blacklist) { Set<String> settingsNotBackedUp = difference(settings, settingsToBackup); Set<String> settingsNotBackedUpOrBlacklisted = difference(settingsNotBackedUp, blacklist); - assertThat( + assertTrue( "Settings not backed up or blacklisted", - settingsNotBackedUpOrBlacklisted, - is(empty())); + settingsNotBackedUpOrBlacklisted.isEmpty()); - assertThat( - "blacklisted settings backed up", - intersect(settingsToBackup, blacklist), - is(empty())); + assertTrue( + "blacklisted settings backed up", intersect(settingsToBackup, blacklist).isEmpty()); } - private static Set<String> getCandidateSettings(Class<? extends Settings.NameValueTable> clazz) { + private static Set<String> getCandidateSettings( + Class<? extends Settings.NameValueTable> clazz) { HashSet<String> result = new HashSet<String>(); for (Field field : clazz.getDeclaredFields()) { if (looksLikeValidSetting(field)) { diff --git a/core/tests/coretests/src/android/provider/settings/validators/SettingsValidatorsTest.java b/packages/SettingsProvider/test/src/android/provider/settings/validators/SettingsValidatorsTest.java index 5f042d3dce0f..a3b08359860c 100644 --- a/core/tests/coretests/src/android/provider/settings/validators/SettingsValidatorsTest.java +++ b/packages/SettingsProvider/test/src/android/provider/settings/validators/SettingsValidatorsTest.java @@ -24,6 +24,9 @@ import static org.junit.Assert.fail; import android.platform.test.annotations.Presubmit; import android.provider.Settings; +import android.provider.settings.backup.GlobalSettings; +import android.provider.settings.backup.SecureSettings; +import android.provider.settings.backup.SystemSettings; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; @@ -218,7 +221,7 @@ public class SettingsValidatorsTest { @Test public void dateFormatValidator_onNullValue_returnsFalse() { - assertFalse(Settings.System.DATE_FORMAT_VALIDATOR.validate(null)); + assertFalse(SettingsValidators.DATE_FORMAT_VALIDATOR.validate(null)); } @Test @@ -238,18 +241,18 @@ public class SettingsValidatorsTest { @Test public void testJSONObjectValidator_onNullValue_returnsFalse() { - assertThat(SettingsValidators.JSON_OBJECT_VALIDATOR.validate(null)).isFalse(); + assertFalse(SettingsValidators.JSON_OBJECT_VALIDATOR.validate(null)); } @Test public void testJSONObjectValidator_onEmptyString_returnsFalse() { - assertThat(SettingsValidators.JSON_OBJECT_VALIDATOR.validate("")).isFalse(); + assertFalse(SettingsValidators.JSON_OBJECT_VALIDATOR.validate("")); } @Test public void ensureAllBackedUpSystemSettingsHaveValidators() { - String offenders = getOffenders(concat(Settings.System.SETTINGS_TO_BACKUP, - Settings.System.LEGACY_RESTORE_SETTINGS), Settings.System.VALIDATORS); + String offenders = getOffenders(concat(SystemSettings.SETTINGS_TO_BACKUP, + Settings.System.LEGACY_RESTORE_SETTINGS), SystemSettingsValidators.VALIDATORS); failIfOffendersPresent(offenders, "Settings.System"); } @@ -295,16 +298,16 @@ public class SettingsValidatorsTest { @Test public void ensureAllBackedUpGlobalSettingsHaveValidators() { - String offenders = getOffenders(concat(Settings.Global.SETTINGS_TO_BACKUP, - Settings.Global.LEGACY_RESTORE_SETTINGS), Settings.Global.VALIDATORS); + String offenders = getOffenders(concat(GlobalSettings.SETTINGS_TO_BACKUP, + Settings.Global.LEGACY_RESTORE_SETTINGS), GlobalSettingsValidators.VALIDATORS); failIfOffendersPresent(offenders, "Settings.Global"); } @Test public void ensureAllBackedUpSecureSettingsHaveValidators() { - String offenders = getOffenders(concat(Settings.Secure.SETTINGS_TO_BACKUP, - Settings.Secure.LEGACY_RESTORE_SETTINGS), Settings.Secure.VALIDATORS); + String offenders = getOffenders(concat(SecureSettings.SETTINGS_TO_BACKUP, + Settings.Secure.LEGACY_RESTORE_SETTINGS), SecureSettingsValidators.VALIDATORS); failIfOffendersPresent(offenders, "Settings.Secure"); } diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/BaseSettingsProviderTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/BaseSettingsProviderTest.java index 68efa6779f04..ce1da4a6ad7d 100644 --- a/packages/SettingsProvider/test/src/com/android/providers/settings/BaseSettingsProviderTest.java +++ b/packages/SettingsProvider/test/src/com/android/providers/settings/BaseSettingsProviderTest.java @@ -31,6 +31,8 @@ import androidx.test.runner.AndroidJUnit4; import libcore.io.Streams; +import org.junit.After; +import org.junit.Before; import org.junit.runner.RunWith; import java.io.FileInputStream; @@ -60,6 +62,20 @@ abstract class BaseSettingsProviderTest { private int mSecondaryUserId = Integer.MIN_VALUE; + @Before + public void setUp() { + Settings.Global.clearProviderForTest(); + Settings.Secure.clearProviderForTest(); + Settings.System.clearProviderForTest(); + } + + @After + public void tearDown() { + Settings.Global.clearProviderForTest(); + Settings.Secure.clearProviderForTest(); + Settings.System.clearProviderForTest(); + } + protected void setStringViaFrontEndApiSetting(int type, String name, String value, int userId) { ContentResolver contentResolver = getContext().getContentResolver(); diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/InstallNonMarketAppsDeprecationTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/InstallNonMarketAppsDeprecationTest.java index 863b0352913a..ff11f70b8ed1 100644 --- a/packages/SettingsProvider/test/src/com/android/providers/settings/InstallNonMarketAppsDeprecationTest.java +++ b/packages/SettingsProvider/test/src/com/android/providers/settings/InstallNonMarketAppsDeprecationTest.java @@ -84,8 +84,10 @@ public class InstallNonMarketAppsDeprecationTest extends BaseSettingsProviderTes return line.trim(); } + @Override @Before public void setUp() { + super.setUp(); mUm = (UserManager) getContext().getSystemService(Context.USER_SERVICE); mHasUserRestriction = mUm.hasUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES); mSystemSetUserRestriction = mUm.getUserRestrictionSource( @@ -145,8 +147,10 @@ public class InstallNonMarketAppsDeprecationTest extends BaseSettingsProviderTes assertTrue("Invalid value", value.equals("1") || value.equals("0")); } + @Override @After public void tearDown() { + super.tearDown(); if (!mHasUserRestriction || mSystemSetUserRestriction) { // The test may have modified the user restriction state. Restore it. mUm.setUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsBackupAgentTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsBackupAgentTest.java index cf8e1a5c2b14..12ca92f02e7a 100644 --- a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsBackupAgentTest.java +++ b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsBackupAgentTest.java @@ -64,8 +64,10 @@ public class SettingsBackupAgentTest extends BaseSettingsProviderTest { private TestFriendlySettingsBackupAgent mAgentUnderTest; private Context mContext; + @Override @Before public void setUp() { + super.setUp(); mContext = new ContextWithMockContentResolver(getContext()); mAgentUnderTest = new TestFriendlySettingsBackupAgent(); diff --git a/packages/SystemUI/res/drawable/ic_5g_e_mobiledata.xml b/packages/SystemUI/res/drawable/ic_5g_e_mobiledata.xml index fe1bb265880c..7c7c8c1e4729 100644 --- a/packages/SystemUI/res/drawable/ic_5g_e_mobiledata.xml +++ b/packages/SystemUI/res/drawable/ic_5g_e_mobiledata.xml @@ -16,16 +16,10 @@ <vector xmlns:android="http://schemas.android.com/apk/res/android" android:viewportWidth="22" android:viewportHeight="17" - android:width="22dp" - android:height="17dp"> + android:width="19.41dp" + android:height="15dp"> <path android:fillColor="#FFFFFFFF" - android:pathData="M1.22,8.49l0.43-4.96h4.33v1.17H2.67L2.44,7.41c0.41-0.29,0.85-0.43,1.33-0.43c0.77,0,1.38,0.3,1.83,0.9 s0.66,1.41,0.66,2.43c0,1.03-0.24,1.84-0.72,2.43s-1.14,0.88-1.98,0.88c-0.75,0-1.36-0.24-1.83-0.73s-0.74-1.16-0.81-2.02h1.13 c0.07,0.57,0.23,1,0.49,1.29c0.26,0.29,0.59,0.43,1.01,0.43c0.47,0,0.84-0.2,1.1-0.61c0.26-0.41,0.4-0.96,0.4-1.65 c0-0.65-0.14-1.18-0.43-1.59S3.96,8.11,3.47,8.11c-0.4,0-0.72,0.1-0.96,0.31L2.19,8.75L1.22,8.49z" /> - <path - android:fillColor="#FFFFFFFF" - android:pathData="M14.14,12.24l-0.22,0.27c-0.63,0.73-1.55,1.1-2.76,1.1c-1.08,0-1.92-0.36-2.53-1.07c-0.61-0.71-0.93-1.72-0.94-3.02V7.56 c0-1.39,0.28-2.44,0.84-3.13c0.56-0.7,1.39-1.04,2.51-1.04c0.95,0,1.69,0.26,2.23,0.79c0.54,0.53,0.83,1.28,0.89,2.26h-1.25 c-0.05-0.62-0.22-1.1-0.52-1.45c-0.29-0.35-0.74-0.52-1.34-0.52c-0.72,0-1.24,0.23-1.57,0.7C9.14,5.63,8.96,6.37,8.95,7.4v2.03 c0,1,0.19,1.77,0.57,2.31c0.38,0.54,0.93,0.8,1.65,0.8c0.67,0,1.19-0.16,1.54-0.49l0.18-0.17V9.59h-1.82V8.52h3.07V12.24z" /> - <path - android:fillColor="#FFFFFFFF" - android:pathData="M20.96,8.88h-3.52v3.53h4.1v1.07h-5.35V3.52h5.28V4.6h-4.03V7.8h3.52V8.88z" /> - + android:pathData="M 6.72 3.52 L 6.54 4.69 L 3.34 4.69 L 2.63 7.41 C 3.011 7.143 3.465 7 3.93 7 C 4.5 6.986 5.041 7.251 5.38 7.71 C 5.756 8.249 5.952 8.893 5.94 9.55 C 5.98 10.276 5.864 11.002 5.6 11.68 C 5.385 12.267 5.007 12.78 4.51 13.16 C 4.043 13.499 3.476 13.671 2.9 13.65 C 2.271 13.653 1.675 13.369 1.28 12.88 C 0.854 12.302 0.636 11.597 0.66 10.88 L 1.76 10.88 C 1.81 12 2.21 12.57 3 12.58 C 3.592 12.589 4.132 12.243 4.37 11.7 C 4.708 11.044 4.85 10.305 4.78 9.57 C 4.767 9.209 4.645 8.86 4.43 8.57 C 4.239 8.309 3.934 8.156 3.61 8.16 C 3.404 8.138 3.196 8.162 3 8.23 C 2.748 8.358 2.518 8.527 2.32 8.73 L 1.31 8.46 L 2.51 3.52 L 6.72 3.52 Z M 11.7 3.39 C 12.459 3.353 13.195 3.662 13.7 4.23 C 14.185 4.864 14.42 5.654 14.36 6.45 L 13.1 6.45 C 13.131 5.938 12.998 5.43 12.72 5 C 12.455 4.679 12.056 4.498 11.64 4.51 C 11.025 4.456 10.42 4.688 10 5.14 C 9.491 5.811 9.179 6.611 9.1 7.45 L 8.75 9.54 L 8.75 10.57 C 8.82 11.86 9.36 12.52 10.36 12.57 C 10.701 12.593 11.043 12.538 11.36 12.41 C 11.661 12.281 11.943 12.113 12.2 11.91 L 12.62 9.62 L 10.77 9.62 L 11 8.52 L 14 8.52 L 13.36 12.23 C 13.176 12.483 12.953 12.706 12.7 12.89 C 11.995 13.398 11.138 13.652 10.27 13.61 C 9.507 13.634 8.773 13.315 8.27 12.74 C 7.748 12.085 7.475 11.267 7.5 10.43 C 7.47 10.097 7.47 9.763 7.5 9.43 L 7.8 7.43 C 7.927 6.332 8.36 5.293 9.05 4.43 C 9.725 3.692 10.703 3.308 11.7 3.39 Z M 20.81 7.21 L 20.62 8.29 L 18.32 8.29 L 18.06 9.8 L 20.06 9.8 L 19.83 10.84 L 17.88 10.84 L 17.59 12.54 L 19.9 12.54 L 19.71 13.61 L 16.14 13.61 L 17.25 7.21 L 20.81 7.21 Z" /> + <path android:pathData="M 0 0 H 14 V 17 H 0 V 0 Z"/> </vector> diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java index 45126f35d864..107d5cce3f8e 100644 --- a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java +++ b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java @@ -19,6 +19,8 @@ package com.android.keyguard; import static android.telephony.PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE; import static android.telephony.PhoneStateListener.LISTEN_NONE; +import static com.android.systemui.DejankUtils.whitelistIpcs; + import android.content.Context; import android.content.Intent; import android.content.IntentFilter; @@ -33,6 +35,8 @@ import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.Log; +import androidx.annotation.VisibleForTesting; + import com.android.internal.telephony.IccCardConstants; import com.android.internal.telephony.TelephonyIntents; import com.android.settingslib.WirelessUtils; @@ -42,8 +46,6 @@ import com.android.systemui.keyguard.WakefulnessLifecycle; import java.util.List; import java.util.Objects; -import androidx.annotation.VisibleForTesting; - /** * Controller that generates text including the carrier names and/or the status of all the SIM * interfaces in the device. Through a callback, the updates can be retrieved either as a list or @@ -220,8 +222,9 @@ public class CarrierTextController { .getSystemService(Context.TELEPHONY_SERVICE)); if (callback != null) { mCarrierTextCallback = callback; - if (ConnectivityManager.from(mContext).isNetworkSupported( - ConnectivityManager.TYPE_MOBILE)) { + // TODO(b/140034799) + if (whitelistIpcs(() -> ConnectivityManager.from(mContext).isNetworkSupported( + ConnectivityManager.TYPE_MOBILE))) { mKeyguardUpdateMonitor = KeyguardUpdateMonitor.getInstance(mContext); mKeyguardUpdateMonitor.registerCallback(mCallback); mWakefulnessLifecycle.addObserver(mWakefulnessObserver); diff --git a/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java b/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java index 210b82d1d69c..979f3dc5ffe8 100644 --- a/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java +++ b/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java @@ -16,6 +16,8 @@ package com.android.keyguard; +import static com.android.systemui.DejankUtils.whitelistIpcs; + import android.app.ActivityOptions; import android.app.ActivityTaskManager; import android.content.Context; @@ -132,7 +134,7 @@ public class EmergencyButton extends Button { return false; } }); - updateEmergencyCallButton(); + whitelistIpcs(this::updateEmergencyCallButton); } @Override diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java index 169c97b1ce22..454f44674c66 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java @@ -15,6 +15,8 @@ */ package com.android.keyguard; +import static com.android.systemui.DejankUtils.whitelistIpcs; + import android.app.Activity; import android.app.AlertDialog; import android.app.admin.DevicePolicyManager; @@ -467,8 +469,8 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe * @param turningOff true if the device is being turned off */ void showPrimarySecurityScreen(boolean turningOff) { - SecurityMode securityMode = mSecurityModel.getSecurityMode( - KeyguardUpdateMonitor.getCurrentUser()); + SecurityMode securityMode = whitelistIpcs(() -> mSecurityModel.getSecurityMode( + KeyguardUpdateMonitor.getCurrentUser())); if (DEBUG) Log.v(TAG, "showPrimarySecurityScreen(turningOff=" + turningOff + ")"); showSecurityScreen(securityMode); } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java index 0cb6423008e5..16e9ffca7782 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java @@ -15,6 +15,8 @@ */ package com.android.keyguard; +import static com.android.systemui.DejankUtils.whitelistIpcs; + import android.app.admin.DevicePolicyManager; import android.content.Context; import android.telephony.SubscriptionManager; @@ -67,7 +69,9 @@ public class KeyguardSecurityModel { return SecurityMode.SimPin; } - final int security = mLockPatternUtils.getActivePasswordQuality(userId); + // TODO(b/140034863) + final int security = whitelistIpcs(() -> + mLockPatternUtils.getActivePasswordQuality(userId)); switch (security) { case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC: case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX: diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index 6da2a42ddfe1..aa1d8b4d5287 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -18,6 +18,8 @@ package com.android.keyguard; import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; +import static android.content.Intent.ACTION_USER_REMOVED; +import static android.content.Intent.ACTION_USER_STOPPED; import static android.content.Intent.ACTION_USER_UNLOCKED; import static android.os.BatteryManager.BATTERY_HEALTH_UNKNOWN; import static android.os.BatteryManager.BATTERY_STATUS_FULL; @@ -36,6 +38,7 @@ import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STR import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT; import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_TIMEOUT; import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN; +import static com.android.systemui.DejankUtils.whitelistIpcs; import android.annotation.AnyThread; import android.annotation.MainThread; @@ -161,6 +164,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { private static final int MSG_DEVICE_POLICY_MANAGER_STATE_CHANGED = 337; private static final int MSG_TELEPHONY_CAPABLE = 338; private static final int MSG_TIMEZONE_UPDATE = 339; + private static final int MSG_USER_STOPPED = 340; + private static final int MSG_USER_REMOVED = 341; /** Biometric authentication state: Not listening. */ private static final int BIOMETRIC_STATE_STOPPED = 0; @@ -374,7 +379,13 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { handleDreamingStateChanged(msg.arg1); break; case MSG_USER_UNLOCKED: - handleUserUnlocked(); + handleUserUnlocked(msg.arg1); + break; + case MSG_USER_STOPPED: + handleUserStopped(msg.arg1); + break; + case MSG_USER_REMOVED: + handleUserRemoved(msg.arg1); break; case MSG_ASSISTANT_STACK_CHANGED: setAssistantVisible((boolean) msg.obj); @@ -426,6 +437,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } }; + private SparseBooleanArray mUserIsUnlocked = new SparseBooleanArray(); private SparseBooleanArray mUserHasTrust = new SparseBooleanArray(); private SparseBooleanArray mUserTrustIsManaged = new SparseBooleanArray(); private SparseBooleanArray mUserFingerprintAuthenticated = new SparseBooleanArray(); @@ -997,9 +1009,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { private boolean isFaceDisabled(int userId) { final DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); - return dpm != null && (dpm.getKeyguardDisabledFeatures(null, userId) + // TODO(b/140035044) + return whitelistIpcs(() -> dpm != null && (dpm.getKeyguardDisabledFeatures(null, userId) & DevicePolicyManager.KEYGUARD_DISABLE_FACE) != 0 - || isSimPinSecure(); + || isSimPinSecure()); } @@ -1205,7 +1218,14 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { .equals(action)) { mHandler.sendEmptyMessage(MSG_DPM_STATE_CHANGED); } else if (ACTION_USER_UNLOCKED.equals(action)) { - mHandler.sendEmptyMessage(MSG_USER_UNLOCKED); + mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_UNLOCKED, + getSendingUserId(), 0)); + } else if (ACTION_USER_STOPPED.equals(action)) { + mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_STOPPED, + intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1), 0)); + } else if (ACTION_USER_REMOVED.equals(action)) { + mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_REMOVED, + intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1), 0)); } } }; @@ -1556,8 +1576,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } } - private void handleUserUnlocked() { + private void handleUserUnlocked(int userId) { checkIsHandlerThread(); + mUserIsUnlocked.put(userId, true); mNeedsSlowUnlockTransition = resolveNeedsSlowUnlockTransition(); for (int i = 0; i < mCallbacks.size(); i++) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); @@ -1567,6 +1588,16 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } } + private void handleUserStopped(int userId) { + checkIsHandlerThread(); + mUserIsUnlocked.put(userId, mUserManager.isUserUnlocked(userId)); + } + + private void handleUserRemoved(int userId) { + checkIsHandlerThread(); + mUserIsUnlocked.delete(userId); + } + @VisibleForTesting protected KeyguardUpdateMonitor(Context context) { mContext = context; @@ -1610,6 +1641,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { allUserFilter.addAction(ACTION_FACE_UNLOCK_STOPPED); allUserFilter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); allUserFilter.addAction(ACTION_USER_UNLOCKED); + allUserFilter.addAction(ACTION_USER_STOPPED); + allUserFilter.addAction(ACTION_USER_REMOVED); context.registerReceiverAsUser(mBroadcastAllReceiver, UserHandle.ALL, allUserFilter, null, mHandler); @@ -1664,6 +1697,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener); mUserManager = context.getSystemService(UserManager.class); mIsPrimaryUser = mUserManager.isPrimaryUser(); + int user = ActivityManager.getCurrentUser(); + mUserIsUnlocked.put(user, mUserManager.isUserUnlocked(user)); mDevicePolicyManager = context.getSystemService(DevicePolicyManager.class); mLogoutEnabled = mDevicePolicyManager.isLogoutEnabled(); updateAirplaneModeState(); @@ -1707,6 +1742,19 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } /** + * If a user is encrypted or not. + * This is NOT related to the lock screen being visible or not. + * + * @param userId The user. + * @return {@code true} when encrypted. + * @see UserManager#isUserUnlocked() + * @see Intent#ACTION_USER_UNLOCKED + */ + public boolean isUserUnlocked(int userId) { + return mUserIsUnlocked.get(userId); + } + + /** * Called whenever passive authentication is requested or aborted by a sensor. * * @param active If the interrupt started or ended. @@ -1884,9 +1932,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { * If face hardware is available, user has enrolled and enabled auth via setting. */ public boolean isFaceAuthEnabledForUser(int userId) { - return mFaceManager != null && mFaceManager.isHardwareDetected() + // TODO(b/140034352) + return whitelistIpcs(() -> mFaceManager != null && mFaceManager.isHardwareDetected() && mFaceManager.hasEnrolledTemplates(userId) - && mFaceSettingEnabledForUser.get(userId); + && mFaceSettingEnabledForUser.get(userId)); } private void stopListeningForFingerprint() { @@ -2294,7 +2343,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } private boolean resolveNeedsSlowUnlockTransition() { - if (mUserManager.isUserUnlocked(getCurrentUser())) { + if (isUserUnlocked(getCurrentUser())) { return false; } Intent homeIntent = new Intent(Intent.ACTION_MAIN) diff --git a/packages/SystemUI/src/com/android/keyguard/NumPadKey.java b/packages/SystemUI/src/com/android/keyguard/NumPadKey.java index 08691ec10d6a..1edb57eaaaa0 100644 --- a/packages/SystemUI/src/com/android/keyguard/NumPadKey.java +++ b/packages/SystemUI/src/com/android/keyguard/NumPadKey.java @@ -34,13 +34,14 @@ public class NumPadKey extends ViewGroup { // list of "ABC", etc per digit, starting with '0' static String sKlondike[]; + private final TextView mDigitText; + private final TextView mKlondikeText; + private final LockPatternUtils mLockPatternUtils; + private final PowerManager mPM; + private int mDigit = -1; private int mTextViewResId; private PasswordTextView mTextView; - private TextView mDigitText; - private TextView mKlondikeText; - private boolean mEnableHaptics; - private PowerManager mPM; private View.OnClickListener mListener = new View.OnClickListener() { @Override @@ -90,8 +91,7 @@ public class NumPadKey extends ViewGroup { setOnClickListener(mListener); setOnHoverListener(new LiftToActivateListener(context)); - mEnableHaptics = new LockPatternUtils(context).isTactileFeedbackEnabled(); - + mLockPatternUtils = new LockPatternUtils(context); mPM = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); LayoutInflater inflater = (LayoutInflater) getContext().getSystemService( Context.LAYOUT_INFLATER_SERVICE); @@ -162,7 +162,7 @@ public class NumPadKey extends ViewGroup { // Cause a VIRTUAL_KEY vibration public void doHapticKeyClick() { - if (mEnableHaptics) { + if (mLockPatternUtils.isTactileFeedbackEnabled()) { performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY, HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING | HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java index ffa69fa87436..ce61a00fefc3 100644 --- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java +++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java @@ -19,6 +19,7 @@ import static android.app.StatusBarManager.DISABLE2_SYSTEM_ICONS; import static android.app.StatusBarManager.DISABLE_NONE; import static android.provider.Settings.System.SHOW_BATTERY_PERCENT; +import static com.android.systemui.DejankUtils.whitelistIpcs; import static com.android.systemui.util.SysuiLifecycle.viewAttachLifecycle; import static java.lang.annotation.RetentionPolicy.SOURCE; @@ -382,9 +383,10 @@ public class BatteryMeterView extends LinearLayout implements private void updateShowPercent() { final boolean showing = mBatteryPercentView != null; - final boolean systemSetting = 0 != Settings.System + // TODO(b/140051051) + final boolean systemSetting = 0 != whitelistIpcs(() -> Settings.System .getIntForUser(getContext().getContentResolver(), - SHOW_BATTERY_PERCENT, 0, mUser); + SHOW_BATTERY_PERCENT, 0, mUser)); if ((mShowPercentAvailable && systemSetting && mShowPercentMode != MODE_OFF) || mShowPercentMode == MODE_ON || mShowPercentMode == MODE_ESTIMATE) { diff --git a/packages/SystemUI/src/com/android/systemui/ContextComponentHelper.java b/packages/SystemUI/src/com/android/systemui/ContextComponentHelper.java index 8fabe7aa9eb6..62826d806adc 100644 --- a/packages/SystemUI/src/com/android/systemui/ContextComponentHelper.java +++ b/packages/SystemUI/src/com/android/systemui/ContextComponentHelper.java @@ -16,10 +16,12 @@ package com.android.systemui; +import android.app.Service; + /** * Interface necessary to make Dagger happy. See {@link ContextComponentResolver}. */ public interface ContextComponentHelper { /** Turns a classname into an instance of the class or returns null. */ - <T> T resolve(String className); + Service resolveService(String className); } diff --git a/packages/SystemUI/src/com/android/systemui/ContextComponentResolver.java b/packages/SystemUI/src/com/android/systemui/ContextComponentResolver.java index 09bccd993f39..e8f019688997 100644 --- a/packages/SystemUI/src/com/android/systemui/ContextComponentResolver.java +++ b/packages/SystemUI/src/com/android/systemui/ContextComponentResolver.java @@ -16,6 +16,8 @@ package com.android.systemui; +import android.app.Service; + import java.util.Map; import javax.inject.Inject; @@ -25,21 +27,26 @@ import javax.inject.Provider; * Used during Service and Activity instantiation to make them injectable. */ public class ContextComponentResolver implements ContextComponentHelper { - private final Map<Class<?>, Provider<Object>> mCreators; + private final Map<Class<?>, Provider<Service>> mServiceCreators; @Inject - ContextComponentResolver(Map<Class<?>, Provider<Object>> creators) { - mCreators = creators; + ContextComponentResolver( + Map<Class<?>, Provider<Service>> serviceCreators) { + mServiceCreators = serviceCreators; } /** - * Looks up the class name to see if Dagger has an instance of it. + * Looks up the Service class name to see if Dagger has an instance of it. */ @Override - public <T> T resolve(String className) { - for (Map.Entry<Class<?>, Provider<Object>> p : mCreators.entrySet()) { + public Service resolveService(String className) { + return resolve(className, mServiceCreators); + } + + private <T> T resolve(String className, Map<Class<?>, Provider<T>> creators) { + for (Map.Entry<Class<?>, Provider<T>> p : creators.entrySet()) { if (p.getKey().getName().equals(className)) { - return (T) p.getValue().get(); + return p.getValue().get(); } } diff --git a/packages/SystemUI/src/com/android/systemui/DejankUtils.java b/packages/SystemUI/src/com/android/systemui/DejankUtils.java index bec8820a3053..97578e19ccd1 100644 --- a/packages/SystemUI/src/com/android/systemui/DejankUtils.java +++ b/packages/SystemUI/src/com/android/systemui/DejankUtils.java @@ -16,39 +16,200 @@ package com.android.systemui; +import static android.os.IBinder.FLAG_ONEWAY; + +import static com.android.settingslib.utils.ThreadUtils.isMainThread; + +import android.annotation.MainThread; +import android.os.Binder; +import android.os.Binder.ProxyTransactListener; +import android.os.Build; import android.os.Handler; +import android.os.IBinder; +import android.os.RemoteException; +import android.os.StrictMode; +import android.os.SystemProperties; import android.view.Choreographer; import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.util.Assert; import java.util.ArrayList; +import java.util.HashSet; +import java.util.Stack; +import java.util.function.Supplier; /** * Utility class for methods used to dejank the UI. */ public class DejankUtils { + public static final boolean STRICT_MODE_ENABLED = Build.IS_ENG + || SystemProperties.getBoolean("persist.sysui.strictmode", false); private static final Choreographer sChoreographer = Choreographer.getInstance(); private static final Handler sHandler = new Handler(); private static final ArrayList<Runnable> sPendingRunnables = new ArrayList<>(); + private static Stack<String> sBlockingIpcs = new Stack<>(); + private static boolean sTemporarilyIgnoreStrictMode; + private static final HashSet<String> sWhitelistedFrameworkClasses = new HashSet<>(); + private static final Object sLock = new Object(); + private static final ProxyTransactListener sProxy = new ProxyTransactListener() { + @Override + public Object onTransactStarted(IBinder binder, int transactionCode, int flags) { + synchronized (sLock) { + if ((flags & FLAG_ONEWAY) == FLAG_ONEWAY || sBlockingIpcs.empty() + || !isMainThread() || sTemporarilyIgnoreStrictMode) { + return null; + } + + try { + String description = binder.getInterfaceDescriptor(); + if (sWhitelistedFrameworkClasses.contains(description)) { + return null; + } + } catch (RemoteException e) { + e.printStackTrace(); + } + + StrictMode.noteSlowCall("IPC detected on critical path: " + sBlockingIpcs.peek()); + return null; + } + } + + @Override + public Object onTransactStarted(IBinder binder, int transactionCode) { + return null; + } + + @Override + public void onTransactEnded(Object o) { + + } + }; /** * Only for testing. */ private static boolean sImmediate; - private static final Runnable sAnimationCallbackRunnable = new Runnable() { - @Override - public void run() { - for (int i = 0; i < sPendingRunnables.size(); i++) { - sHandler.post(sPendingRunnables.get(i)); - } - sPendingRunnables.clear(); + static { + if (STRICT_MODE_ENABLED) { + // Common IPCs that are ok to block the main thread. + sWhitelistedFrameworkClasses.add("android.view.IWindowSession"); + sWhitelistedFrameworkClasses.add("com.android.internal.policy.IKeyguardStateCallback"); + sWhitelistedFrameworkClasses.add("android.os.IPowerManager"); + sWhitelistedFrameworkClasses.add("com.android.internal.statusbar.IStatusBarService"); + + Binder.setProxyTransactListener(sProxy); + StrictMode.ThreadPolicy.Builder builder = new StrictMode.ThreadPolicy.Builder() + .detectCustomSlowCalls() + .penaltyFlashScreen() + .penaltyLog(); + StrictMode.setThreadPolicy(builder.build()); + } + } + + private static final Runnable sAnimationCallbackRunnable = () -> { + for (int i = 0; i < sPendingRunnables.size(); i++) { + sHandler.post(sPendingRunnables.get(i)); } + sPendingRunnables.clear(); }; /** + * Enable blocking-binder-call {@link StrictMode} for a {@link Runnable}. + * + * @param runnable Target. + */ + @MainThread + public static void detectBlockingIpcs(Runnable runnable) { + if (STRICT_MODE_ENABLED && sBlockingIpcs.empty()) { + synchronized (sLock) { + sBlockingIpcs.push("detectBlockingIpcs"); + try { + runnable.run(); + } finally { + sBlockingIpcs.pop(); + } + } + } else { + runnable.run(); + } + } + + /** + * Enable blocking-binder-call {@link StrictMode}. + * + * @param tag A key. + * @see #detectBlockingIpcs(Runnable) + */ + @MainThread + public static void startDetectingBlockingIpcs(String tag) { + if (STRICT_MODE_ENABLED) { + synchronized (sLock) { + sBlockingIpcs.push(tag); + } + } + } + + /** + * Stop IPC detection for a specific tag. + * + * @param tag The key. + * @see #startDetectingBlockingIpcs(String) + */ + @MainThread + public static void stopDetectingBlockingIpcs(String tag) { + if (STRICT_MODE_ENABLED) { + synchronized (sLock) { + sBlockingIpcs.remove(tag); + } + } + } + + /** + * Temporarily ignore blocking binder calls for contents of this {@link Runnable}. + * + * @param runnable Target. + */ + @MainThread + public static void whitelistIpcs(Runnable runnable) { + if (STRICT_MODE_ENABLED && !sTemporarilyIgnoreStrictMode) { + synchronized (sLock) { + sTemporarilyIgnoreStrictMode = true; + try { + runnable.run(); + } finally { + sTemporarilyIgnoreStrictMode = false; + } + } + } else { + runnable.run(); + } + } + + /** + * @see #whitelistIpcs(Runnable) + */ + @MainThread + public static <T> T whitelistIpcs(Supplier<T> supplier) { + if (STRICT_MODE_ENABLED && !sTemporarilyIgnoreStrictMode) { + synchronized (sLock) { + sTemporarilyIgnoreStrictMode = true; + final T val; + try { + val = supplier.get(); + } finally { + sTemporarilyIgnoreStrictMode = false; + } + return val; + } + } else { + return supplier.get(); + } + } + + /** * Executes {@code r} after performTraversals. Use this do to CPU heavy work for which the * timing is not critical for animation. The work is then scheduled at the same time * RenderThread is doing its thing, leading to better parallelization. diff --git a/packages/SystemUI/src/com/android/systemui/ServiceBinder.java b/packages/SystemUI/src/com/android/systemui/ServiceBinder.java index 6282c6e5282f..131a0f8c81a9 100644 --- a/packages/SystemUI/src/com/android/systemui/ServiceBinder.java +++ b/packages/SystemUI/src/com/android/systemui/ServiceBinder.java @@ -16,6 +16,8 @@ package com.android.systemui; +import android.app.Service; + import com.android.systemui.doze.DozeService; import dagger.Binds; @@ -36,6 +38,5 @@ public abstract class ServiceBinder { @Binds @IntoMap @ClassKey(DozeService.class) - public abstract Object bindDozeService(DozeService service); - + public abstract Service bindDozeService(DozeService service); } diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java index 00ae99295768..6a59fa19b0eb 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java @@ -18,16 +18,25 @@ package com.android.systemui; import android.app.Application; import android.app.Service; +import android.content.ContentProvider; +import android.content.Context; import android.content.Intent; -import androidx.core.app.CoreComponentFactory; +import androidx.annotation.NonNull; +import androidx.core.app.AppComponentFactory; import javax.inject.Inject; /** * Implementation of AppComponentFactory that injects into constructors. + * + * This class sets up dependency injection when creating our application. + * + * Services support dependency injection into their constructors. + * + * ContentProviders support injection into member variables - _not_ constructors. */ -public class SystemUIAppComponentFactory extends CoreComponentFactory { +public class SystemUIAppComponentFactory extends AppComponentFactory { @Inject public ContextComponentHelper mComponentHelper; @@ -36,12 +45,14 @@ public class SystemUIAppComponentFactory extends CoreComponentFactory { super(); } + @NonNull @Override - public Application instantiateApplication(ClassLoader cl, String className) + public Application instantiateApplicationCompat( + @NonNull ClassLoader cl, @NonNull String className) throws InstantiationException, IllegalAccessException, ClassNotFoundException { - Application app = super.instantiateApplication(cl, className); - if (app instanceof SystemUIApplication) { - ((SystemUIApplication) app).setContextAvailableCallback( + Application app = super.instantiateApplicationCompat(cl, className); + if (app instanceof ContextProvider) { + ((ContextProvider) app).setContextAvailableCallback( context -> { SystemUIFactory.createFromConfig(context); SystemUIFactory.getInstance().getRootComponent().inject( @@ -53,24 +64,43 @@ public class SystemUIAppComponentFactory extends CoreComponentFactory { return app; } + @NonNull @Override - public Service instantiateService(ClassLoader cl, String className, Intent intent) + public ContentProvider instantiateProviderCompat( + @NonNull ClassLoader cl, @NonNull String className) throws InstantiationException, IllegalAccessException, ClassNotFoundException { - Service service = mComponentHelper.resolve(className); - if (service != null) { - return checkCompatWrapper(service); + + ContentProvider contentProvider = super.instantiateProviderCompat(cl, className); + if (contentProvider instanceof ContextProvider) { + ((ContextProvider) contentProvider).setContextAvailableCallback( + context -> { + SystemUIFactory.createFromConfig(context); + SystemUIFactory.getInstance().getRootComponent().inject( + contentProvider); + } + ); } - return super.instantiateService(cl, className, intent); + + return contentProvider; } - static <T> T checkCompatWrapper(T obj) { - if (obj instanceof CompatWrapped) { - T wrapper = (T) ((CompatWrapped) obj).getWrapper(); - if (wrapper != null) { - return wrapper; - } + @NonNull + @Override + public Service instantiateServiceCompat( + @NonNull ClassLoader cl, @NonNull String className, Intent intent) + throws InstantiationException, IllegalAccessException, ClassNotFoundException { + Service service = mComponentHelper.resolveService(className); + if (service != null) { + return service; } + return super.instantiateServiceCompat(cl, className, intent); + } + + interface ContextAvailableCallback { + void onContextAvailable(Context context); + } - return obj; + interface ContextProvider { + void setContextAvailableCallback(ContextAvailableCallback callback); } } diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java index f8449add6dce..aafc67ecd496 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java @@ -48,7 +48,8 @@ import java.util.Map; /** * Application class for SystemUI. */ -public class SystemUIApplication extends Application implements SysUiServiceProvider { +public class SystemUIApplication extends Application implements SysUiServiceProvider, + SystemUIAppComponentFactory.ContextProvider { public static final String TAG = "SystemUIService"; private static final boolean DEBUG = false; @@ -60,7 +61,7 @@ public class SystemUIApplication extends Application implements SysUiServiceProv private boolean mServicesStarted; private boolean mBootCompleted; private final Map<Class<?>, Object> mComponents = new HashMap<>(); - private ContextAvailableCallback mContextAvailableCallback; + private SystemUIAppComponentFactory.ContextAvailableCallback mContextAvailableCallback; @Override public void onCreate() { @@ -74,7 +75,6 @@ public class SystemUIApplication extends Application implements SysUiServiceProv // the theme set there. setTheme(R.style.Theme_SystemUI); - if (Process.myUserHandle().equals(UserHandle.SYSTEM)) { IntentFilter bootCompletedFilter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED); bootCompletedFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); @@ -291,11 +291,10 @@ public class SystemUIApplication extends Application implements SysUiServiceProv return mServices; } - void setContextAvailableCallback(ContextAvailableCallback callback) { + @Override + public void setContextAvailableCallback( + SystemUIAppComponentFactory.ContextAvailableCallback callback) { mContextAvailableCallback = callback; } - interface ContextAvailableCallback { - void onContextAvailable(Context context); - } } diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java index b67d7dff4d79..39617ecd2770 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java @@ -24,13 +24,13 @@ import android.os.Looper; import android.util.Log; import android.view.ViewGroup; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.colorextraction.ColorExtractor.GradientColors; import com.android.internal.util.function.TriConsumer; import com.android.internal.widget.LockPatternUtils; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.ViewMediatorCallback; import com.android.systemui.keyguard.DismissCallbackRegistry; -import com.android.systemui.model.SysUiState; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.KeyguardIndicationController; @@ -70,6 +70,10 @@ public class SystemUIFactory { } public static void createFromConfig(Context context) { + if (mFactory != null) { + return; + } + final String clsName = context.getString(R.string.config_systemUIFactoryComponent); if (clsName == null || clsName.length() == 0) { throw new RuntimeException("No SystemUIFactory component configured"); @@ -86,6 +90,11 @@ public class SystemUIFactory { } } + @VisibleForTesting + static void cleanup() { + mFactory = null; + } + public SystemUIFactory() {} private void init(Context context) { diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIRootComponent.java b/packages/SystemUI/src/com/android/systemui/SystemUIRootComponent.java index f18c8b2c3da6..ad04f18c6ec2 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIRootComponent.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIRootComponent.java @@ -16,6 +16,8 @@ package com.android.systemui; +import android.content.ContentProvider; + import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME; import com.android.systemui.fragments.FragmentService; @@ -76,7 +78,12 @@ public interface SystemUIRootComponent { boolean allowNotificationLongPressName(); /** - * Injects into the supplied argument. + * Member injection into the supplied argument. */ void inject(SystemUIAppComponentFactory factory); + + /** + * Member injection into the supplied argument. + */ + void inject(ContentProvider contentProvider); } diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java index 1e20b9922121..7a9feb7b26a6 100644 --- a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java +++ b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java @@ -16,6 +16,8 @@ package com.android.systemui.assist; +import static com.android.systemui.DejankUtils.whitelistIpcs; + import android.app.ActivityManager; import android.content.BroadcastReceiver; import android.content.ComponentName; @@ -368,8 +370,9 @@ final class AssistHandleReminderExpBehavior implements BehaviorController { long currentTimestamp = SystemClock.uptimeMillis(); mLearningTimeElapsed += currentTimestamp - mLastLearningTimestamp; mLastLearningTimestamp = currentTimestamp; - Settings.Secure.putLong( - mContext.getContentResolver(), LEARNING_TIME_ELAPSED_KEY, mLearningTimeElapsed); + // TODO(b/140034473) + whitelistIpcs(() -> Settings.Secure.putLong( + mContext.getContentResolver(), LEARNING_TIME_ELAPSED_KEY, mLearningTimeElapsed)); mIsLearned = mLearningCount >= getLearningCount() || mLearningTimeElapsed >= getLearningTimeMs(); diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java index ac32d4dfb2b4..c4feac1d1a26 100644 --- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java +++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java @@ -1,5 +1,7 @@ package com.android.systemui.assist; +import static com.android.systemui.DejankUtils.whitelistIpcs; + import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; @@ -374,7 +376,8 @@ public class AssistManager implements ConfigurationChangedReceiver { } public boolean canVoiceAssistBeLaunchedFromKeyguard() { - return mAssistUtils.activeServiceSupportsLaunchFromKeyguard(); + // TODO(b/140051519) + return whitelistIpcs(() -> mAssistUtils.activeServiceSupportsLaunchFromKeyguard()); } public ComponentName getVoiceInteractorComponentName() { @@ -442,7 +445,8 @@ public class AssistManager implements ConfigurationChangedReceiver { } public void onLockscreenShown() { - mAssistUtils.onLockscreenShown(); + // TODO(b/140052478) + whitelistIpcs(mAssistUtils::onLockscreenShown); } public long getAssistHandleShowAndGoRemainingDurationMs() { diff --git a/packages/SystemUI/src/com/android/systemui/assist/PhenotypeHelper.java b/packages/SystemUI/src/com/android/systemui/assist/PhenotypeHelper.java index b3f57afc0753..c21a717dc8cf 100644 --- a/packages/SystemUI/src/com/android/systemui/assist/PhenotypeHelper.java +++ b/packages/SystemUI/src/com/android/systemui/assist/PhenotypeHelper.java @@ -16,6 +16,8 @@ package com.android.systemui.assist; +import static com.android.systemui.DejankUtils.whitelistIpcs; + import android.provider.DeviceConfig; import androidx.annotation.Nullable; @@ -27,20 +29,24 @@ public class PhenotypeHelper { public PhenotypeHelper() {} public long getLong(String name, long defaultValue) { - return DeviceConfig.getLong(DeviceConfig.NAMESPACE_SYSTEMUI, name, defaultValue); + return whitelistIpcs(() -> + DeviceConfig.getLong(DeviceConfig.NAMESPACE_SYSTEMUI, name, defaultValue)); } public int getInt(String name, int defaultValue) { - return DeviceConfig.getInt(DeviceConfig.NAMESPACE_SYSTEMUI, name, defaultValue); + return whitelistIpcs(() -> + DeviceConfig.getInt(DeviceConfig.NAMESPACE_SYSTEMUI, name, defaultValue)); } @Nullable public String getString(String name, @Nullable String defaultValue) { - return DeviceConfig.getString(DeviceConfig.NAMESPACE_SYSTEMUI, name, defaultValue); + return whitelistIpcs(() -> + DeviceConfig.getString(DeviceConfig.NAMESPACE_SYSTEMUI, name, defaultValue)); } public boolean getBoolean(String name, boolean defaultValue) { - return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI, name, defaultValue); + return whitelistIpcs(() -> + DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI, name, defaultValue)); } public void addOnPropertiesChangedListener( diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/BiometricDialogView.java b/packages/SystemUI/src/com/android/systemui/biometrics/ui/BiometricDialogView.java index 2b4dde55ef72..290475562893 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/BiometricDialogView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/BiometricDialogView.java @@ -18,8 +18,14 @@ package com.android.systemui.biometrics.ui; import static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE; +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.AnimatorSet; +import android.animation.ValueAnimator; +import android.annotation.IntDef; import android.app.admin.DevicePolicyManager; import android.content.Context; +import android.graphics.Outline; import android.graphics.PixelFormat; import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; @@ -38,6 +44,7 @@ import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.view.ViewOutlineProvider; import android.view.WindowManager; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; @@ -71,6 +78,7 @@ public abstract class BiometricDialogView extends LinearLayout implements Biomet public static final String KEY_ERROR_TEXT_STRING = "key_error_text_string"; public static final String KEY_ERROR_TEXT_IS_TEMPORARY = "key_error_text_is_temporary"; public static final String KEY_ERROR_TEXT_COLOR = "key_error_text_color"; + public static final String KEY_DIALOG_SIZE = "key_dialog_size"; private static final int ANIMATION_DURATION_SHOW = 250; // ms private static final int ANIMATION_DURATION_AWAY = 350; // ms @@ -83,8 +91,18 @@ public abstract class BiometricDialogView extends LinearLayout implements Biomet protected static final int STATE_PENDING_CONFIRMATION = 3; protected static final int STATE_AUTHENTICATED = 4; - @VisibleForTesting - final WakefulnessLifecycle mWakefulnessLifecycle; + // Dialog layout/animation + private static final int IMPLICIT_Y_PADDING = 16; // dp + private static final int GROW_DURATION = 150; // ms + private static final int TEXT_ANIMATE_DISTANCE = 32; // dp + @VisibleForTesting static final int SIZE_UNKNOWN = 0; + @VisibleForTesting static final int SIZE_SMALL = 1; + @VisibleForTesting static final int SIZE_GROWING = 2; + @VisibleForTesting static final int SIZE_BIG = 3; + @IntDef({SIZE_UNKNOWN, SIZE_SMALL, SIZE_GROWING, SIZE_BIG}) + @interface DialogSize {} + + @VisibleForTesting final WakefulnessLifecycle mWakefulnessLifecycle; private final AccessibilityManager mAccessibilityManager; private final IBinder mWindowToken = new Binder(); private final Interpolator mLinearOutSlowIn; @@ -95,25 +113,18 @@ public abstract class BiometricDialogView extends LinearLayout implements Biomet private final int mErrorColor; private final float mDialogWidth; protected final DialogViewCallback mCallback; + private final DialogOutlineProvider mOutlineProvider = new DialogOutlineProvider(); protected final ViewGroup mLayout; protected final LinearLayout mDialog; - @VisibleForTesting - final TextView mTitleText; - @VisibleForTesting - final TextView mSubtitleText; - @VisibleForTesting - final TextView mDescriptionText; - @VisibleForTesting - final ImageView mBiometricIcon; - @VisibleForTesting - final TextView mErrorText; - @VisibleForTesting - final Button mPositiveButton; - @VisibleForTesting - final Button mNegativeButton; - @VisibleForTesting - final Button mTryAgainButton; + @VisibleForTesting final TextView mTitleText; + @VisibleForTesting final TextView mSubtitleText; + @VisibleForTesting final TextView mDescriptionText; + @VisibleForTesting final ImageView mBiometricIcon; + @VisibleForTesting final TextView mErrorText; + @VisibleForTesting final Button mPositiveButton; + @VisibleForTesting final Button mNegativeButton; + @VisibleForTesting final Button mTryAgainButton; protected final int mTextColor; @@ -126,6 +137,8 @@ public abstract class BiometricDialogView extends LinearLayout implements Biomet private boolean mSkipIntro; protected boolean mRequireConfirmation; private int mUserId; // used to determine if we should show work background + private @DialogSize int mSize; + private float mIconOriginalY; private boolean mCompletedAnimatingIn; private boolean mPendingDismissDialog; @@ -137,6 +150,7 @@ public abstract class BiometricDialogView extends LinearLayout implements Biomet protected abstract boolean shouldGrayAreaDismissDialog(); protected abstract void handleResetMessage(); protected abstract void updateIcon(int oldState, int newState); + protected abstract boolean supportsSmallDialog(); private final Runnable mShowAnimationRunnable = new Runnable() { @Override @@ -166,6 +180,30 @@ public abstract class BiometricDialogView extends LinearLayout implements Biomet } }; + private final class DialogOutlineProvider extends ViewOutlineProvider { + + float mY; + + @Override + public void getOutline(View view, Outline outline) { + outline.setRoundRect( + 0 /* left */, + (int) mY, /* top */ + mDialog.getWidth() /* right */, + mDialog.getBottom(), /* bottom */ + getResources().getDimension(R.dimen.biometric_dialog_corner_size)); + } + + int calculateSmall() { + final float padding = Utils.dpToPixels(mContext, IMPLICIT_Y_PADDING); + return mDialog.getHeight() - mBiometricIcon.getHeight() - 2 * (int) padding; + } + + void setOutlineY(float y) { + mY = y; + } + } + protected Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { @@ -346,7 +384,6 @@ public abstract class BiometricDialogView extends LinearLayout implements Biomet mWakefulnessLifecycle.addObserver(mWakefulnessObserver); final ImageView backgroundView = mLayout.findViewById(R.id.background); - if (mUserManager.isManagedProfile(mUserId)) { final Drawable image = getResources().getDrawable(R.drawable.work_challenge_background, mContext.getTheme()); @@ -428,6 +465,42 @@ public abstract class BiometricDialogView extends LinearLayout implements Biomet mSkipIntro = false; } + /** + * Do small/big layout here instead of onAttachedToWindow, since: + * 1) We need the big layout to be measured, etc for small -> big animation + * 2) We need the dialog measurements to know where to move the biometric icon to + * + * BiometricDialogView already sets the views to their default big state, so here we only + * need to hide the ones that are unnecessary. + */ + @Override + public void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + + if (mIconOriginalY == 0) { + mIconOriginalY = mBiometricIcon.getY(); + } + + // UNKNOWN means size hasn't been set yet. First time we create the dialog. + // onLayout can happen when visibility of views change (during animation, etc). + if (getSize() != SIZE_UNKNOWN) { + // Probably not the cleanest way to do this, but since dialog is big by default, + // and small dialogs can persist across orientation changes, we need to set it to + // small size here again. + if (getSize() == SIZE_SMALL) { + updateSize(SIZE_SMALL); + } + return; + } + + // If we don't require confirmation, show the small dialog first (until errors occur). + if (!requiresConfirmation() && supportsSmallDialog()) { + updateSize(SIZE_SMALL); + } else { + updateSize(SIZE_BIG); + } + } + @Override public void onDetachedFromWindow() { super.onDetachedFromWindow(); @@ -435,6 +508,133 @@ public abstract class BiometricDialogView extends LinearLayout implements Biomet mWakefulnessLifecycle.removeObserver(mWakefulnessObserver); } + @VisibleForTesting + void updateSize(@DialogSize int newSize) { + final float padding = Utils.dpToPixels(mContext, IMPLICIT_Y_PADDING); + final float iconSmallPositionY = mDialog.getHeight() - mBiometricIcon.getHeight() - padding; + + if (newSize == SIZE_SMALL) { + if (!supportsSmallDialog()) { + Log.e(TAG, "Small dialog unsupported"); + return; + } + + // These fields are required and/or always hold a spot on the UI, so should be set to + // INVISIBLE so they keep their position + mTitleText.setVisibility(View.INVISIBLE); + mErrorText.setVisibility(View.INVISIBLE); + mNegativeButton.setVisibility(View.INVISIBLE); + + // These fields are optional, so set them to gone or invisible depending on their + // usage. If they're empty, they're already set to GONE in BiometricDialogView. + if (!TextUtils.isEmpty(mSubtitleText.getText())) { + mSubtitleText.setVisibility(View.INVISIBLE); + } + if (!TextUtils.isEmpty(mDescriptionText.getText())) { + mDescriptionText.setVisibility(View.INVISIBLE); + } + + // Move the biometric icon to the small spot + mBiometricIcon.setY(iconSmallPositionY); + + // Clip the dialog to the small size + mDialog.setOutlineProvider(mOutlineProvider); + mOutlineProvider.setOutlineY(mOutlineProvider.calculateSmall()); + + mDialog.setClipToOutline(true); + mDialog.invalidateOutline(); + + mSize = newSize; + announceAccessibilityEvent(); + } else if (mSize == SIZE_SMALL && newSize == SIZE_BIG) { + mSize = SIZE_GROWING; + + // Animate the outline + final ValueAnimator outlineAnimator = + ValueAnimator.ofFloat(mOutlineProvider.calculateSmall(), 0); + outlineAnimator.addUpdateListener((animation) -> { + final float y = (float) animation.getAnimatedValue(); + mOutlineProvider.setOutlineY(y); + mDialog.invalidateOutline(); + }); + + // Animate the icon back to original big position + final ValueAnimator iconAnimator = + ValueAnimator.ofFloat(iconSmallPositionY, mIconOriginalY); + iconAnimator.addUpdateListener((animation) -> { + final float y = (float) animation.getAnimatedValue(); + mBiometricIcon.setY(y); + }); + + // Animate the error text so it slides up with the icon + final ValueAnimator textSlideAnimator = + ValueAnimator.ofFloat(Utils.dpToPixels(mContext, TEXT_ANIMATE_DISTANCE), 0); + textSlideAnimator.addUpdateListener((animation) -> { + final float y = (float) animation.getAnimatedValue(); + mErrorText.setTranslationY(y); + }); + + // Opacity animator for things that should fade in (title, subtitle, details, negative + // button) + final ValueAnimator opacityAnimator = ValueAnimator.ofFloat(0, 1); + opacityAnimator.addUpdateListener((animation) -> { + final float opacity = (float) animation.getAnimatedValue(); + + // These fields are required and/or always hold a spot on the UI + mTitleText.setAlpha(opacity); + mErrorText.setAlpha(opacity); + mNegativeButton.setAlpha(opacity); + mTryAgainButton.setAlpha(opacity); + + // These fields are optional, so only animate them if they're supposed to be showing + if (!TextUtils.isEmpty(mSubtitleText.getText())) { + mSubtitleText.setAlpha(opacity); + } + if (!TextUtils.isEmpty(mDescriptionText.getText())) { + mDescriptionText.setAlpha(opacity); + } + }); + + // Choreograph together + final AnimatorSet as = new AnimatorSet(); + as.setDuration(GROW_DURATION); + as.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animation) { + super.onAnimationStart(animation); + // Set the visibility of opacity-animating views back to VISIBLE + mTitleText.setVisibility(View.VISIBLE); + mErrorText.setVisibility(View.VISIBLE); + mNegativeButton.setVisibility(View.VISIBLE); + mTryAgainButton.setVisibility(View.VISIBLE); + + if (!TextUtils.isEmpty(mSubtitleText.getText())) { + mSubtitleText.setVisibility(View.VISIBLE); + } + if (!TextUtils.isEmpty(mDescriptionText.getText())) { + mDescriptionText.setVisibility(View.VISIBLE); + } + } + + @Override + public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + mSize = SIZE_BIG; + } + }); + as.play(outlineAnimator).with(iconAnimator).with(opacityAnimator) + .with(textSlideAnimator); + as.start(); + } else if (mSize == SIZE_BIG) { + mDialog.setClipToOutline(false); + mDialog.invalidateOutline(); + + mBiometricIcon.setY(mIconOriginalY); + + mSize = newSize; + } + } + private void setDismissesDialog(View v) { v.setClickable(true); v.setOnClickListener(v1 -> { @@ -599,6 +799,12 @@ public abstract class BiometricDialogView extends LinearLayout implements Biomet */ @Override public void onError(String error) { + // All error messages will cause the dialog to go from small -> big. Error messages + // are messages such as lockout, auth failed, etc. + if (mSize == SIZE_SMALL) { + updateSize(SIZE_BIG); + } + updateState(STATE_ERROR); showTemporaryMessage(error); showTryAgainButton(false /* show */); @@ -619,11 +825,16 @@ public abstract class BiometricDialogView extends LinearLayout implements Biomet bundle.putCharSequence(KEY_ERROR_TEXT_STRING, mErrorText.getText()); bundle.putBoolean(KEY_ERROR_TEXT_IS_TEMPORARY, mHandler.hasMessages(MSG_RESET_MESSAGE)); bundle.putInt(KEY_ERROR_TEXT_COLOR, mErrorText.getCurrentTextColor()); + bundle.putInt(KEY_DIALOG_SIZE, mSize); } @Override public void restoreState(Bundle bundle) { mRestoredState = bundle; + + // Keep in mind that this happens before onAttachedToWindow() + mSize = bundle.getInt(KEY_DIALOG_SIZE); + final int tryAgainVisibility = bundle.getInt(KEY_TRY_AGAIN_VISIBILITY); mTryAgainButton.setVisibility(tryAgainVisibility); final int confirmVisibility = bundle.getInt(KEY_CONFIRM_VISIBILITY); @@ -678,7 +889,28 @@ public abstract class BiometricDialogView extends LinearLayout implements Biomet mState = newState; } + protected @DialogSize int getSize() { + return mSize; + } + protected void showTryAgainButton(boolean show) { + if (show && getSize() == SIZE_SMALL) { + // Do not call super, we will nicely animate the alpha together with the rest + // of the elements in here. + updateSize(SIZE_BIG); + } else { + if (show) { + mTryAgainButton.setVisibility(View.VISIBLE); + } else { + mTryAgainButton.setVisibility(View.GONE); + announceAccessibilityEvent(); + } + } + + if (show) { + mPositiveButton.setVisibility(View.GONE); + announceAccessibilityEvent(); + } } protected void onDialogAnimatedIn() { diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/FaceDialogView.java b/packages/SystemUI/src/com/android/systemui/biometrics/ui/FaceDialogView.java index bd8714812ab4..9e4fe24aec40 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/FaceDialogView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/FaceDialogView.java @@ -16,24 +16,15 @@ package com.android.systemui.biometrics.ui; -import android.animation.Animator; -import android.animation.AnimatorListenerAdapter; -import android.animation.AnimatorSet; -import android.animation.ValueAnimator; import android.content.Context; -import android.graphics.Outline; import android.graphics.drawable.Animatable2; import android.graphics.drawable.AnimatedVectorDrawable; import android.graphics.drawable.Drawable; import android.hardware.biometrics.BiometricPrompt; import android.os.Bundle; -import android.text.TextUtils; -import android.util.DisplayMetrics; import android.util.Log; import android.view.View; -import android.view.ViewOutlineProvider; -import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.R; import com.android.systemui.biometrics.DialogViewCallback; @@ -45,23 +36,11 @@ import com.android.systemui.biometrics.DialogViewCallback; public class FaceDialogView extends BiometricDialogView { private static final String TAG = "FaceDialogView"; - private static final String KEY_DIALOG_SIZE = "key_dialog_size"; + private static final String KEY_DIALOG_ANIMATED_IN = "key_dialog_animated_in"; private static final int HIDE_DIALOG_DELAY = 500; // ms - private static final int IMPLICIT_Y_PADDING = 16; // dp - private static final int GROW_DURATION = 150; // ms - private static final int TEXT_ANIMATE_DISTANCE = 32; // dp - - private static final int SIZE_UNKNOWN = 0; - @VisibleForTesting - static final int SIZE_SMALL = 1; - private static final int SIZE_GROWING = 2; - private static final int SIZE_BIG = 3; - - private int mSize; - private float mIconOriginalY; - private DialogOutlineProvider mOutlineProvider = new DialogOutlineProvider(); + private IconController mIconController; private boolean mDialogAnimatedIn; @@ -125,30 +104,6 @@ public class FaceDialogView extends BiometricDialogView { } } - private final class DialogOutlineProvider extends ViewOutlineProvider { - - float mY; - - @Override - public void getOutline(View view, Outline outline) { - outline.setRoundRect( - 0 /* left */, - (int) mY, /* top */ - mDialog.getWidth() /* right */, - mDialog.getBottom(), /* bottom */ - getResources().getDimension(R.dimen.biometric_dialog_corner_size)); - } - - int calculateSmall() { - final float padding = dpToPixels(IMPLICIT_Y_PADDING); - return mDialog.getHeight() - mBiometricIcon.getHeight() - 2 * (int) padding; - } - - void setOutlineY(float y) { - mY = y; - } - } - private final Runnable mErrorToIdleAnimationRunnable = () -> { updateState(STATE_IDLE); mErrorText.setVisibility(View.INVISIBLE); @@ -160,132 +115,9 @@ public class FaceDialogView extends BiometricDialogView { mIconController = new IconController(); } - @VisibleForTesting - void updateSize(int newSize) { - final float padding = dpToPixels(IMPLICIT_Y_PADDING); - final float iconSmallPositionY = mDialog.getHeight() - mBiometricIcon.getHeight() - padding; - - if (newSize == SIZE_SMALL) { - // These fields are required and/or always hold a spot on the UI, so should be set to - // INVISIBLE so they keep their position - mTitleText.setVisibility(View.INVISIBLE); - mErrorText.setVisibility(View.INVISIBLE); - mNegativeButton.setVisibility(View.INVISIBLE); - - // These fields are optional, so set them to gone or invisible depending on their - // usage. If they're empty, they're already set to GONE in BiometricDialogView. - if (!TextUtils.isEmpty(mSubtitleText.getText())) { - mSubtitleText.setVisibility(View.INVISIBLE); - } - if (!TextUtils.isEmpty(mDescriptionText.getText())) { - mDescriptionText.setVisibility(View.INVISIBLE); - } - - // Move the biometric icon to the small spot - mBiometricIcon.setY(iconSmallPositionY); - - // Clip the dialog to the small size - mDialog.setOutlineProvider(mOutlineProvider); - mOutlineProvider.setOutlineY(mOutlineProvider.calculateSmall()); - - mDialog.setClipToOutline(true); - mDialog.invalidateOutline(); - - mSize = newSize; - announceAccessibilityEvent(); - } else if (mSize == SIZE_SMALL && newSize == SIZE_BIG) { - mSize = SIZE_GROWING; - - // Animate the outline - final ValueAnimator outlineAnimator = - ValueAnimator.ofFloat(mOutlineProvider.calculateSmall(), 0); - outlineAnimator.addUpdateListener((animation) -> { - final float y = (float) animation.getAnimatedValue(); - mOutlineProvider.setOutlineY(y); - mDialog.invalidateOutline(); - }); - - // Animate the icon back to original big position - final ValueAnimator iconAnimator = - ValueAnimator.ofFloat(iconSmallPositionY, mIconOriginalY); - iconAnimator.addUpdateListener((animation) -> { - final float y = (float) animation.getAnimatedValue(); - mBiometricIcon.setY(y); - }); - - // Animate the error text so it slides up with the icon - final ValueAnimator textSlideAnimator = - ValueAnimator.ofFloat(dpToPixels(TEXT_ANIMATE_DISTANCE), 0); - textSlideAnimator.addUpdateListener((animation) -> { - final float y = (float) animation.getAnimatedValue(); - mErrorText.setTranslationY(y); - }); - - // Opacity animator for things that should fade in (title, subtitle, details, negative - // button) - final ValueAnimator opacityAnimator = ValueAnimator.ofFloat(0, 1); - opacityAnimator.addUpdateListener((animation) -> { - final float opacity = (float) animation.getAnimatedValue(); - - // These fields are required and/or always hold a spot on the UI - mTitleText.setAlpha(opacity); - mErrorText.setAlpha(opacity); - mNegativeButton.setAlpha(opacity); - mTryAgainButton.setAlpha(opacity); - - // These fields are optional, so only animate them if they're supposed to be showing - if (!TextUtils.isEmpty(mSubtitleText.getText())) { - mSubtitleText.setAlpha(opacity); - } - if (!TextUtils.isEmpty(mDescriptionText.getText())) { - mDescriptionText.setAlpha(opacity); - } - }); - - // Choreograph together - final AnimatorSet as = new AnimatorSet(); - as.setDuration(GROW_DURATION); - as.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationStart(Animator animation) { - super.onAnimationStart(animation); - // Set the visibility of opacity-animating views back to VISIBLE - mTitleText.setVisibility(View.VISIBLE); - mErrorText.setVisibility(View.VISIBLE); - mNegativeButton.setVisibility(View.VISIBLE); - mTryAgainButton.setVisibility(View.VISIBLE); - - if (!TextUtils.isEmpty(mSubtitleText.getText())) { - mSubtitleText.setVisibility(View.VISIBLE); - } - if (!TextUtils.isEmpty(mDescriptionText.getText())) { - mDescriptionText.setVisibility(View.VISIBLE); - } - } - - @Override - public void onAnimationEnd(Animator animation) { - super.onAnimationEnd(animation); - mSize = SIZE_BIG; - } - }); - as.play(outlineAnimator).with(iconAnimator).with(opacityAnimator) - .with(textSlideAnimator); - as.start(); - } else if (mSize == SIZE_BIG) { - mDialog.setClipToOutline(false); - mDialog.invalidateOutline(); - - mBiometricIcon.setY(mIconOriginalY); - - mSize = newSize; - } - } - @Override public void onSaveState(Bundle bundle) { super.onSaveState(bundle); - bundle.putInt(KEY_DIALOG_SIZE, mSize); bundle.putBoolean(KEY_DIALOG_ANIMATED_IN, mDialogAnimatedIn); } @@ -300,57 +132,9 @@ public class FaceDialogView extends BiometricDialogView { @Override public void restoreState(Bundle bundle) { super.restoreState(bundle); - // Keep in mind that this happens before onAttachedToWindow() - mSize = bundle.getInt(KEY_DIALOG_SIZE); mDialogAnimatedIn = bundle.getBoolean(KEY_DIALOG_ANIMATED_IN); } - /** - * Do small/big layout here instead of onAttachedToWindow, since: - * 1) We need the big layout to be measured, etc for small -> big animation - * 2) We need the dialog measurements to know where to move the biometric icon to - * - * BiometricDialogView already sets the views to their default big state, so here we only - * need to hide the ones that are unnecessary. - */ - @Override - public void onLayout(boolean changed, int left, int top, int right, int bottom) { - super.onLayout(changed, left, top, right, bottom); - - if (mIconOriginalY == 0) { - mIconOriginalY = mBiometricIcon.getY(); - } - - // UNKNOWN means size hasn't been set yet. First time we create the dialog. - // onLayout can happen when visibility of views change (during animation, etc). - if (mSize != SIZE_UNKNOWN) { - // Probably not the cleanest way to do this, but since dialog is big by default, - // and small dialogs can persist across orientation changes, we need to set it to - // small size here again. - if (mSize == SIZE_SMALL) { - updateSize(SIZE_SMALL); - } - return; - } - - // If we don't require confirmation, show the small dialog first (until errors occur). - if (!requiresConfirmation()) { - updateSize(SIZE_SMALL); - } else { - updateSize(SIZE_BIG); - } - } - - @Override - public void onError(String error) { - super.onError(error); - // All error messages will cause the dialog to go from small -> big. Error messages - // are messages such as lockout, auth failed, etc. - if (mSize == SIZE_SMALL) { - updateSize(SIZE_BIG); - } - } - @Override public void onAuthenticationFailed(String message) { super.onAuthenticationFailed(message); @@ -358,27 +142,6 @@ public class FaceDialogView extends BiometricDialogView { } @Override - public void showTryAgainButton(boolean show) { - if (show && mSize == SIZE_SMALL) { - // Do not call super, we will nicely animate the alpha together with the rest - // of the elements in here. - updateSize(SIZE_BIG); - } else { - if (show) { - mTryAgainButton.setVisibility(View.VISIBLE); - } else { - mTryAgainButton.setVisibility(View.GONE); - announceAccessibilityEvent(); - } - } - - if (show) { - mPositiveButton.setVisibility(View.GONE); - announceAccessibilityEvent(); - } - } - - @Override protected int getHintStringResourceId() { return 0; } @@ -462,6 +225,11 @@ public class FaceDialogView extends BiometricDialogView { } @Override + protected boolean supportsSmallDialog() { + return true; + } + + @Override public void onDialogAnimatedIn() { super.onDialogAnimatedIn(); mDialogAnimatedIn = true; @@ -475,19 +243,11 @@ public class FaceDialogView extends BiometricDialogView { @Override protected boolean shouldGrayAreaDismissDialog() { - if (mSize == SIZE_SMALL) { + if (getSize() == SIZE_SMALL) { return false; } return true; } - private float dpToPixels(float dp) { - return dp * ((float) mContext.getResources().getDisplayMetrics().densityDpi - / DisplayMetrics.DENSITY_DEFAULT); - } - private float pixelsToDp(float pixels) { - return pixels / ((float) mContext.getResources().getDisplayMetrics().densityDpi - / DisplayMetrics.DENSITY_DEFAULT); - } } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/FingerprintDialogView.java b/packages/SystemUI/src/com/android/systemui/biometrics/ui/FingerprintDialogView.java index e597080f89fd..292588024646 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/FingerprintDialogView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/FingerprintDialogView.java @@ -80,6 +80,11 @@ public class FingerprintDialogView extends BiometricDialogView { } } + @Override + protected boolean supportsSmallDialog() { + return false; + } + protected boolean shouldAnimateForTransition(int oldState, int newState) { if (newState == STATE_ERROR) { return true; diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/Utils.java b/packages/SystemUI/src/com/android/systemui/biometrics/ui/Utils.java new file mode 100644 index 000000000000..028b1aa5b513 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/Utils.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2019 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.biometrics.ui; + +import android.content.Context; +import android.util.DisplayMetrics; + +public class Utils { + static float dpToPixels(Context context, float dp) { + return dp * ((float) context.getResources().getDisplayMetrics().densityDpi + / DisplayMetrics.DENSITY_DEFAULT); + } + + static float pixelsToDp(Context context, float pixels) { + return pixels / ((float) context.getResources().getDisplayMetrics().densityDpi + / DisplayMetrics.DENSITY_DEFAULT); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java index 41203348d7a0..efac147fc6b9 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java @@ -35,6 +35,7 @@ import com.android.systemui.plugins.FalsingPlugin; import com.android.systemui.plugins.PluginListener; import com.android.systemui.shared.plugins.PluginManager; import com.android.systemui.util.AsyncSensorManager; +import com.android.systemui.util.DeviceConfigProxy; import java.io.PrintWriter; @@ -51,18 +52,23 @@ import javax.inject.Singleton; public class FalsingManagerProxy implements FalsingManager { private FalsingManager mInternalFalsingManager; - private final Handler mMainHandler; + private DeviceConfig.OnPropertiesChangedListener mDeviceConfigListener; + private final DeviceConfigProxy mDeviceConfig; private boolean mBrightlineEnabled; @Inject FalsingManagerProxy(Context context, PluginManager pluginManager, - @Named(MAIN_HANDLER_NAME) Handler handler) { - mMainHandler = handler; + @Named(MAIN_HANDLER_NAME) Handler handler, DeviceConfigProxy deviceConfig) { + mDeviceConfig = deviceConfig; + mDeviceConfigListener = + properties -> onDeviceConfigPropertiesChanged(context, properties.getNamespace()); setupFalsingManager(context); - DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_SYSTEMUI, - command -> mMainHandler.post(command), - properties -> onDeviceConfigPropertiesChanged(context, properties.getNamespace()) + mDeviceConfig.addOnPropertiesChangedListener( + DeviceConfig.NAMESPACE_SYSTEMUI, + handler::post, + mDeviceConfigListener ); + final PluginListener<FalsingPlugin> mPluginListener = new PluginListener<FalsingPlugin>() { public void onPluginConnected(FalsingPlugin plugin, Context context) { FalsingManager pluginFalsingManager = plugin.getFalsingManager(context); @@ -91,9 +97,8 @@ public class FalsingManagerProxy implements FalsingManager { /** * Chooses the FalsingManager implementation. */ - @VisibleForTesting - public void setupFalsingManager(Context context) { - boolean brightlineEnabled = DeviceConfig.getBoolean( + private void setupFalsingManager(Context context) { + boolean brightlineEnabled = mDeviceConfig.getBoolean( DeviceConfig.NAMESPACE_SYSTEMUI, BRIGHTLINE_FALSING_MANAGER_ENABLED, true); if (brightlineEnabled == mBrightlineEnabled && mInternalFalsingManager != null) { return; @@ -109,10 +114,10 @@ public class FalsingManagerProxy implements FalsingManager { mInternalFalsingManager = new BrightLineFalsingManager( new FalsingDataProvider(context.getResources().getDisplayMetrics()), Dependency.get(AsyncSensorManager.class), - KeyguardUpdateMonitor.getInstance(context) + KeyguardUpdateMonitor.getInstance(context), + mDeviceConfig ); } - } /** @@ -305,6 +310,7 @@ public class FalsingManagerProxy implements FalsingManager { @Override public void cleanup() { + mDeviceConfig.removeOnPropertiesChangedListener(mDeviceConfigListener); mInternalFalsingManager.cleanup(); } } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java index 9e0b7025ddf8..9e646b627bd2 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java @@ -33,6 +33,7 @@ import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitorCallback; import com.android.systemui.classifier.Classifier; import com.android.systemui.plugins.FalsingManager; +import com.android.systemui.util.DeviceConfigProxy; import java.io.PrintWriter; import java.util.ArrayList; @@ -88,7 +89,8 @@ public class BrightLineFalsingManager implements FalsingManager { public BrightLineFalsingManager( FalsingDataProvider falsingDataProvider, SensorManager sensorManager, - KeyguardUpdateMonitor keyguardUpdateMonitor) { + KeyguardUpdateMonitor keyguardUpdateMonitor, + DeviceConfigProxy deviceConfigProxy) { mKeyguardUpdateMonitor = keyguardUpdateMonitor; mDataProvider = falsingDataProvider; mSensorManager = sensorManager; @@ -96,15 +98,16 @@ public class BrightLineFalsingManager implements FalsingManager { mMetricsLogger = new MetricsLogger(); mClassifiers = new ArrayList<>(); - DistanceClassifier distanceClassifier = new DistanceClassifier(mDataProvider); - ProximityClassifier proximityClassifier = new ProximityClassifier(distanceClassifier, - mDataProvider); + DistanceClassifier distanceClassifier = + new DistanceClassifier(mDataProvider, deviceConfigProxy); + ProximityClassifier proximityClassifier = + new ProximityClassifier(distanceClassifier, mDataProvider, deviceConfigProxy); mClassifiers.add(new PointerCountClassifier(mDataProvider)); mClassifiers.add(new TypeClassifier(mDataProvider)); - mClassifiers.add(new DiagonalClassifier(mDataProvider)); + mClassifiers.add(new DiagonalClassifier(mDataProvider, deviceConfigProxy)); mClassifiers.add(distanceClassifier); mClassifiers.add(proximityClassifier); - mClassifiers.add(new ZigZagClassifier(mDataProvider)); + mClassifiers.add(new ZigZagClassifier(mDataProvider, deviceConfigProxy)); } private void registerSensors() { diff --git a/packages/SystemUI/src/com/android/systemui/classifier/brightline/DiagonalClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/brightline/DiagonalClassifier.java index cc6645415fd8..9c03b915000e 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/brightline/DiagonalClassifier.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/brightline/DiagonalClassifier.java @@ -23,6 +23,8 @@ import static com.android.systemui.classifier.Classifier.RIGHT_AFFORDANCE; import android.provider.DeviceConfig; +import com.android.systemui.util.DeviceConfigProxy; + /** * False on swipes that are too close to 45 degrees. * @@ -42,14 +44,14 @@ class DiagonalClassifier extends FalsingClassifier { private final float mHorizontalAngleRange; private final float mVerticalAngleRange; - DiagonalClassifier(FalsingDataProvider dataProvider) { + DiagonalClassifier(FalsingDataProvider dataProvider, DeviceConfigProxy deviceConfigProxy) { super(dataProvider); - mHorizontalAngleRange = DeviceConfig.getFloat( + mHorizontalAngleRange = deviceConfigProxy.getFloat( DeviceConfig.NAMESPACE_SYSTEMUI, BRIGHTLINE_FALSING_DIAGONAL_HORIZONTAL_ANGLE_RANGE, HORIZONTAL_ANGLE_RANGE); - mVerticalAngleRange = DeviceConfig.getFloat( + mVerticalAngleRange = deviceConfigProxy.getFloat( DeviceConfig.NAMESPACE_SYSTEMUI, BRIGHTLINE_FALSING_DIAGONAL_VERTICAL_ANGLE_RANGE, VERTICAL_ANGLE_RANGE); diff --git a/packages/SystemUI/src/com/android/systemui/classifier/brightline/DistanceClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/brightline/DistanceClassifier.java index a6a617dc51de..0954f9e6e672 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/brightline/DistanceClassifier.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/brightline/DistanceClassifier.java @@ -27,6 +27,8 @@ import android.provider.DeviceConfig; import android.view.MotionEvent; import android.view.VelocityTracker; +import com.android.systemui.util.DeviceConfigProxy; + import java.util.List; /** @@ -50,35 +52,35 @@ class DistanceClassifier extends FalsingClassifier { private boolean mDistanceDirty; private DistanceVectors mCachedDistance; - DistanceClassifier(FalsingDataProvider dataProvider) { + DistanceClassifier(FalsingDataProvider dataProvider, DeviceConfigProxy deviceConfigProxy) { super(dataProvider); - mVelocityToDistanceMultiplier = DeviceConfig.getFloat( + mVelocityToDistanceMultiplier = deviceConfigProxy.getFloat( DeviceConfig.NAMESPACE_SYSTEMUI, BRIGHTLINE_FALSING_DISTANCE_VELOCITY_TO_DISTANCE, VELOCITY_TO_DISTANCE); - float horizontalFlingThresholdIn = DeviceConfig.getFloat( + float horizontalFlingThresholdIn = deviceConfigProxy.getFloat( DeviceConfig.NAMESPACE_SYSTEMUI, BRIGHTLINE_FALSING_DISTANCE_HORIZONTAL_FLING_THRESHOLD_IN, HORIZONTAL_FLING_THRESHOLD_DISTANCE_IN); - float verticalFlingThresholdIn = DeviceConfig.getFloat( + float verticalFlingThresholdIn = deviceConfigProxy.getFloat( DeviceConfig.NAMESPACE_SYSTEMUI, BRIGHTLINE_FALSING_DISTANCE_VERTICAL_FLING_THRESHOLD_IN, VERTICAL_FLING_THRESHOLD_DISTANCE_IN); - float horizontalSwipeThresholdIn = DeviceConfig.getFloat( + float horizontalSwipeThresholdIn = deviceConfigProxy.getFloat( DeviceConfig.NAMESPACE_SYSTEMUI, BRIGHTLINE_FALSING_DISTANCE_HORIZONTAL_SWIPE_THRESHOLD_IN, HORIZONTAL_SWIPE_THRESHOLD_DISTANCE_IN); - float verticalSwipeThresholdIn = DeviceConfig.getFloat( + float verticalSwipeThresholdIn = deviceConfigProxy.getFloat( DeviceConfig.NAMESPACE_SYSTEMUI, BRIGHTLINE_FALSING_DISTANCE_VERTICAL_SWIPE_THRESHOLD_IN, VERTICAL_SWIPE_THRESHOLD_DISTANCE_IN); - float screenFractionMaxDistance = DeviceConfig.getFloat( + float screenFractionMaxDistance = deviceConfigProxy.getFloat( DeviceConfig.NAMESPACE_SYSTEMUI, BRIGHTLINE_FALSING_DISTANCE_SCREEN_FRACTION_MAX_DISTANCE, SCREEN_FRACTION_MAX_DISTANCE); diff --git a/packages/SystemUI/src/com/android/systemui/classifier/brightline/ProximityClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/brightline/ProximityClassifier.java index 2644bf9f26ce..182704726129 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/brightline/ProximityClassifier.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/brightline/ProximityClassifier.java @@ -24,6 +24,8 @@ import android.hardware.SensorEvent; import android.provider.DeviceConfig; import android.view.MotionEvent; +import com.android.systemui.util.DeviceConfigProxy; + /** * False touch if proximity sensor is covered for more than a certain percentage of the gesture. @@ -44,11 +46,11 @@ class ProximityClassifier extends FalsingClassifier { private float mPercentNear; ProximityClassifier(DistanceClassifier distanceClassifier, - FalsingDataProvider dataProvider) { + FalsingDataProvider dataProvider, DeviceConfigProxy deviceConfigProxy) { super(dataProvider); this.mDistanceClassifier = distanceClassifier; - mPercentCoveredThreshold = DeviceConfig.getFloat( + mPercentCoveredThreshold = deviceConfigProxy.getFloat( DeviceConfig.NAMESPACE_SYSTEMUI, BRIGHTLINE_FALSING_PROXIMITY_PERCENT_COVERED_THRESHOLD, PERCENT_COVERED_THRESHOLD); diff --git a/packages/SystemUI/src/com/android/systemui/classifier/brightline/ZigZagClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/brightline/ZigZagClassifier.java index 82ae30ac4bdf..a0da988b27b5 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/brightline/ZigZagClassifier.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/brightline/ZigZagClassifier.java @@ -25,6 +25,8 @@ import android.graphics.Point; import android.provider.DeviceConfig; import android.view.MotionEvent; +import com.android.systemui.util.DeviceConfigProxy; + import java.util.ArrayList; import java.util.List; @@ -48,25 +50,25 @@ class ZigZagClassifier extends FalsingClassifier { private final float mMaxXSecondaryDeviance; private final float mMaxYSecondaryDeviance; - ZigZagClassifier(FalsingDataProvider dataProvider) { + ZigZagClassifier(FalsingDataProvider dataProvider, DeviceConfigProxy deviceConfigProxy) { super(dataProvider); - mMaxXPrimaryDeviance = DeviceConfig.getFloat( + mMaxXPrimaryDeviance = deviceConfigProxy.getFloat( DeviceConfig.NAMESPACE_SYSTEMUI, BRIGHTLINE_FALSING_ZIGZAG_X_PRIMARY_DEVIANCE, MAX_X_PRIMARY_DEVIANCE); - mMaxYPrimaryDeviance = DeviceConfig.getFloat( + mMaxYPrimaryDeviance = deviceConfigProxy.getFloat( DeviceConfig.NAMESPACE_SYSTEMUI, BRIGHTLINE_FALSING_ZIGZAG_Y_PRIMARY_DEVIANCE, MAX_Y_PRIMARY_DEVIANCE); - mMaxXSecondaryDeviance = DeviceConfig.getFloat( + mMaxXSecondaryDeviance = deviceConfigProxy.getFloat( DeviceConfig.NAMESPACE_SYSTEMUI, BRIGHTLINE_FALSING_ZIGZAG_X_SECONDARY_DEVIANCE, MAX_X_SECONDARY_DEVIANCE); - mMaxYSecondaryDeviance = DeviceConfig.getFloat( + mMaxYSecondaryDeviance = deviceConfigProxy.getFloat( DeviceConfig.NAMESPACE_SYSTEMUI, BRIGHTLINE_FALSING_ZIGZAG_Y_SECONDARY_DEVIANCE, MAX_Y_SECONDARY_DEVIANCE); diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index 36c3cc68be85..4016b5999775 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -25,6 +25,7 @@ import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOM import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW; import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT; import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_TIMEOUT; +import static com.android.systemui.DejankUtils.whitelistIpcs; import android.app.ActivityManager; import android.app.ActivityTaskManager; @@ -643,26 +644,29 @@ public class KeyguardViewMediator extends SystemUI { @Override public int getBouncerPromptReason() { - int currentUser = ActivityManager.getCurrentUser(); - boolean trust = mTrustManager.isTrustUsuallyManaged(currentUser); - boolean biometrics = mUpdateMonitor.isUnlockingWithBiometricsPossible(currentUser); - boolean any = trust || biometrics; - KeyguardUpdateMonitor.StrongAuthTracker strongAuthTracker = - mUpdateMonitor.getStrongAuthTracker(); - int strongAuth = strongAuthTracker.getStrongAuthForUser(currentUser); - - if (any && !strongAuthTracker.hasUserAuthenticatedSinceBoot()) { - return KeyguardSecurityView.PROMPT_REASON_RESTART; - } else if (any && (strongAuth & STRONG_AUTH_REQUIRED_AFTER_TIMEOUT) != 0) { - return KeyguardSecurityView.PROMPT_REASON_TIMEOUT; - } else if (any && (strongAuth & STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW) != 0) { - return KeyguardSecurityView.PROMPT_REASON_DEVICE_ADMIN; - } else if (trust && (strongAuth & SOME_AUTH_REQUIRED_AFTER_USER_REQUEST) != 0) { - return KeyguardSecurityView.PROMPT_REASON_USER_REQUEST; - } else if (any && (strongAuth & STRONG_AUTH_REQUIRED_AFTER_LOCKOUT) != 0) { - return KeyguardSecurityView.PROMPT_REASON_AFTER_LOCKOUT; - } - return KeyguardSecurityView.PROMPT_REASON_NONE; + // TODO(b/140053364) + return whitelistIpcs(() -> { + int currentUser = ActivityManager.getCurrentUser(); + boolean trust = mTrustManager.isTrustUsuallyManaged(currentUser); + boolean biometrics = mUpdateMonitor.isUnlockingWithBiometricsPossible(currentUser); + boolean any = trust || biometrics; + KeyguardUpdateMonitor.StrongAuthTracker strongAuthTracker = + mUpdateMonitor.getStrongAuthTracker(); + int strongAuth = strongAuthTracker.getStrongAuthForUser(currentUser); + + if (any && !strongAuthTracker.hasUserAuthenticatedSinceBoot()) { + return KeyguardSecurityView.PROMPT_REASON_RESTART; + } else if (any && (strongAuth & STRONG_AUTH_REQUIRED_AFTER_TIMEOUT) != 0) { + return KeyguardSecurityView.PROMPT_REASON_TIMEOUT; + } else if (any && (strongAuth & STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW) != 0) { + return KeyguardSecurityView.PROMPT_REASON_DEVICE_ADMIN; + } else if (trust && (strongAuth & SOME_AUTH_REQUIRED_AFTER_USER_REQUEST) != 0) { + return KeyguardSecurityView.PROMPT_REASON_USER_REQUEST; + } else if (any && (strongAuth & STRONG_AUTH_REQUIRED_AFTER_LOCKOUT) != 0) { + return KeyguardSecurityView.PROMPT_REASON_AFTER_LOCKOUT; + } + return KeyguardSecurityView.PROMPT_REASON_NONE; + }); } @Override @@ -2172,18 +2176,21 @@ public class KeyguardViewMediator extends SystemUI { } private void notifyDefaultDisplayCallbacks(boolean showing) { - int size = mKeyguardStateCallbacks.size(); - for (int i = size - 1; i >= 0; i--) { - IKeyguardStateCallback callback = mKeyguardStateCallbacks.get(i); - try { - callback.onShowingStateChanged(showing); - } catch (RemoteException e) { - Slog.w(TAG, "Failed to call onShowingStateChanged", e); - if (e instanceof DeadObjectException) { - mKeyguardStateCallbacks.remove(callback); + // TODO(b/140053364) + whitelistIpcs(() -> { + int size = mKeyguardStateCallbacks.size(); + for (int i = size - 1; i >= 0; i--) { + IKeyguardStateCallback callback = mKeyguardStateCallbacks.get(i); + try { + callback.onShowingStateChanged(showing); + } catch (RemoteException e) { + Slog.w(TAG, "Failed to call onShowingStateChanged", e); + if (e instanceof DeadObjectException) { + mKeyguardStateCallbacks.remove(callback); + } } } - } + }); updateInputRestrictedLocked(); mUiOffloadThread.submit(() -> { mTrustManager.reportKeyguardShowingChanged(); diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSCarrierGroup.java b/packages/SystemUI/src/com/android/systemui/qs/QSCarrierGroup.java index 4571ef3ef4ef..8c21dde8ad03 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSCarrierGroup.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSCarrierGroup.java @@ -16,6 +16,7 @@ package com.android.systemui.qs; +import static com.android.systemui.DejankUtils.whitelistIpcs; import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT; import android.content.Context; @@ -109,7 +110,8 @@ public class QSCarrierGroup extends LinearLayout implements return; } mListening = listening; - updateListeners(); + // TODO(b/140053526) + whitelistIpcs(this::updateListeners); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java index f1e9c8714776..37113cfac2f3 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java @@ -16,6 +16,7 @@ package com.android.systemui.qs; +import static com.android.systemui.DejankUtils.whitelistIpcs; import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT; import android.content.Context; @@ -164,7 +165,9 @@ public class QuickQSPanel extends QSPanel { }; public static int getNumQuickTiles(Context context) { - return Dependency.get(TunerService.class).getValue(NUM_QUICK_TILES, mDefaultMaxTiles); + // TODO(b/140052679) + return whitelistIpcs(() -> + Dependency.get(TunerService.class).getValue(NUM_QUICK_TILES, mDefaultMaxTiles)); } void setDisabledByPolicy(boolean disabled) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java index bba64d96c0f3..9178fda2b549 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java @@ -16,6 +16,8 @@ package com.android.systemui.statusbar; +import static com.android.systemui.DejankUtils.whitelistIpcs; + import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.app.admin.DevicePolicyManager; @@ -234,7 +236,8 @@ public class KeyguardIndicationController implements StateListener, return; } - if (!mDozing && mDevicePolicyManager.isDeviceManaged()) { + // TODO(b/140053632) + if (!mDozing && whitelistIpcs(mDevicePolicyManager::isDeviceManaged)) { final CharSequence organizationName = mDevicePolicyManager.getDeviceOwnerOrganizationName(); if (organizationName != null) { @@ -381,7 +384,7 @@ public class KeyguardIndicationController implements StateListener, int userId = KeyguardUpdateMonitor.getCurrentUser(); String trustGrantedIndication = getTrustGrantedIndication(); String trustManagedIndication = getTrustManagedIndication(); - if (!mUserManager.isUserUnlocked(userId)) { + if (!mKeyguardUpdateMonitor.isUserUnlocked(userId)) { mTextView.switchIndication(com.android.internal.R.string.lockscreen_storage_locked); mTextView.setTextColor(mInitialTextColorState); } else if (!TextUtils.isEmpty(mTransientIndication)) { @@ -753,6 +756,13 @@ public class KeyguardIndicationController implements StateListener, } @Override + public void onUserSwitchComplete(int userId) { + if (mVisible) { + updateIndication(false); + } + } + + @Override public void onUserUnlocked() { if (mVisible) { updateIndication(false); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java index 802a7d29a7a5..107b24cbd83a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java @@ -17,6 +17,8 @@ package com.android.systemui.statusbar; import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED; +import static com.android.systemui.DejankUtils.whitelistIpcs; + import android.app.ActivityManager; import android.app.KeyguardManager; import android.app.Notification; @@ -323,8 +325,9 @@ public class NotificationLockscreenUserManagerImpl implements } private boolean hideSilentNotificationsOnLockscreen() { - return Settings.Secure.getInt(mContext.getContentResolver(), - Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, 1) == 0; + // TODO(b/140058091) + return whitelistIpcs(() -> Settings.Secure.getInt(mContext.getContentResolver(), + Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, 1) == 0); } private void setShowLockscreenNotifications(boolean show) { @@ -515,8 +518,9 @@ public class NotificationLockscreenUserManagerImpl implements for (int i = currentProfiles.size() - 1; i >= 0; i--) { final int userId = currentProfiles.valueAt(i).id; boolean isProfilePublic = devicePublic; - boolean needsSeparateChallenge = mLockPatternUtils.isSeparateProfileChallengeEnabled( - userId); + // TODO(b/140058091) + boolean needsSeparateChallenge = whitelistIpcs(() -> + mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)); if (!devicePublic && userId != getCurrentUserId() && needsSeparateChallenge && isSecure(userId)) { // Keyguard.isDeviceLocked is updated asynchronously, assume that all profiles diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java index f0eeb046bc44..4422a81874c6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java @@ -24,6 +24,7 @@ import android.view.View; import android.view.animation.Interpolator; import com.android.internal.annotations.GuardedBy; +import com.android.systemui.DejankUtils; import com.android.systemui.Dumpable; import com.android.systemui.Interpolators; import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener; @@ -137,6 +138,8 @@ public class StatusBarStateControllerImpl implements SysuiStatusBarStateControll recordHistoricalState(state, mState); synchronized (mListeners) { + String tag = getClass().getSimpleName() + "#setState(" + state + ")"; + DejankUtils.startDetectingBlockingIpcs(tag); for (RankedListener rl : new ArrayList<>(mListeners)) { rl.mListener.onStatePreChange(mState, state); } @@ -149,6 +152,7 @@ public class StatusBarStateControllerImpl implements SysuiStatusBarStateControll for (RankedListener rl : new ArrayList<>(mListeners)) { rl.mListener.onStatePostChange(); } + DejankUtils.stopDetectingBlockingIpcs(tag); } return true; @@ -178,9 +182,12 @@ public class StatusBarStateControllerImpl implements SysuiStatusBarStateControll mIsDozing = isDozing; synchronized (mListeners) { + String tag = getClass().getSimpleName() + "#setIsDozing"; + DejankUtils.startDetectingBlockingIpcs(tag); for (RankedListener rl : new ArrayList<>(mListeners)) { rl.mListener.onDozingChanged(isDozing); } + DejankUtils.stopDetectingBlockingIpcs(tag); } return true; @@ -220,9 +227,12 @@ public class StatusBarStateControllerImpl implements SysuiStatusBarStateControll mDozeAmount = dozeAmount; float interpolatedAmount = mDozeInterpolator.getInterpolation(dozeAmount); synchronized (mListeners) { + String tag = getClass().getSimpleName() + "#setDozeAmount"; + DejankUtils.startDetectingBlockingIpcs(tag); for (RankedListener rl : new ArrayList<>(mListeners)) { rl.mListener.onDozeAmountChanged(mDozeAmount, interpolatedAmount); } + DejankUtils.stopDetectingBlockingIpcs(tag); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java index f8fef7d4778c..00321744f75a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java @@ -499,10 +499,10 @@ public class NotificationEntryManager implements if (rankingMap == null) { return; } - NotificationListenerService.Ranking tmpRanking = new NotificationListenerService.Ranking(); + NotificationListenerService.Ranking ranking = new NotificationListenerService.Ranking(); for (NotificationEntry pendingNotification : mPendingNotifications.values()) { - rankingMap.getRanking(pendingNotification.key, tmpRanking); - pendingNotification.populateFromRanking(tmpRanking); + rankingMap.getRanking(pendingNotification.key, ranking); + pendingNotification.setRanking(ranking); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java index 00092929fd49..727e245ae38b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java @@ -213,7 +213,7 @@ public class NotificationData { StatusBarNotification notification) { updateRanking(ranking); final StatusBarNotification oldNotification = entry.notification; - entry.notification = notification; + entry.setNotification(notification); mGroupManager.onEntryUpdated(entry, oldNotification); } @@ -325,14 +325,6 @@ public class NotificationData { return NotificationManager.IMPORTANCE_UNSPECIFIED; } - public String getOverrideGroupKey(String key) { - if (mRankingMap != null) { - getRanking(key, mTmpRanking); - return mTmpRanking.getOverrideGroupKey(); - } - return null; - } - public List<SnoozeCriterion> getSnoozeCriteria(String key) { if (mRankingMap != null) { getRanking(key, mTmpRanking); @@ -365,23 +357,25 @@ public class NotificationData { return false; } - private void updateRankingAndSort(RankingMap ranking) { - if (ranking != null) { - mRankingMap = ranking; + private void updateRankingAndSort(RankingMap rankingMap) { + if (rankingMap != null) { + mRankingMap = rankingMap; synchronized (mEntries) { final int len = mEntries.size(); for (int i = 0; i < len; i++) { NotificationEntry entry = mEntries.valueAt(i); - if (!getRanking(entry.key, mTmpRanking)) { + Ranking newRanking = new Ranking(); + if (!getRanking(entry.key, newRanking)) { continue; } + entry.setRanking(newRanking); + final StatusBarNotification oldSbn = entry.notification.cloneLight(); - final String overrideGroupKey = getOverrideGroupKey(entry.key); + final String overrideGroupKey = newRanking.getOverrideGroupKey(); if (!Objects.equals(oldSbn.getOverrideGroupKey(), overrideGroupKey)) { entry.notification.setOverrideGroupKey(overrideGroupKey); mGroupManager.onEntryUpdated(entry, oldSbn); } - entry.populateFromRanking(mTmpRanking); entry.setIsHighPriority(isHighPriority(entry.notification)); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java index fe8854168288..6178488cf43a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java @@ -38,7 +38,7 @@ import android.graphics.drawable.Icon; import android.os.Bundle; import android.os.Parcelable; import android.os.SystemClock; -import android.service.notification.NotificationListenerService; +import android.service.notification.NotificationListenerService.Ranking; import android.service.notification.SnoozeCriterion; import android.service.notification.StatusBarNotification; import android.text.TextUtils; @@ -88,6 +88,8 @@ public final class NotificationEntry { private static final int COLOR_INVALID = 1; public final String key; public StatusBarNotification notification; + private Ranking mRanking; + public NotificationChannel channel; public long lastAudiblyAlertedMs; public boolean noisy; @@ -103,7 +105,7 @@ public final class NotificationEntry { private long lastFullScreenIntentLaunchTime = NOT_LAUNCHED_YET; public CharSequence remoteInputText; public List<SnoozeCriterion> snoozeCriteria; - public int userSentiment = NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL; + public int userSentiment = Ranking.USER_SENTIMENT_NEUTRAL; /** Smart Actions provided by the NotificationAssistantService. */ @NonNull public List<Notification.Action> systemGeneratedSmartActions = Collections.emptyList(); @@ -181,21 +183,80 @@ public final class NotificationEntry { private boolean mAutoHeadsUp; private boolean mPulseSupressed; - public NotificationEntry(StatusBarNotification n) { - this(n, null); + public NotificationEntry( + StatusBarNotification sbn, + @NonNull Ranking ranking) { + this(sbn, ranking, false); } - public NotificationEntry( - StatusBarNotification n, - @Nullable NotificationListenerService.Ranking ranking) { - this.key = n.getKey(); - this.notification = n; + private NotificationEntry( + StatusBarNotification sbn, + Ranking ranking, + boolean isTest) { + this.key = sbn.getKey(); + this.notification = sbn; + + // TODO: Update tests to no longer need to pass null ranking if (ranking != null) { - populateFromRanking(ranking); + setRanking(ranking); + } else if (!isTest) { + throw new IllegalArgumentException("Ranking cannot be null"); + } + } + + /** + * Method for old tests that build NotificationEntries with a ranking. + * + * @deprecated New tests should pass a ranking object as well. + */ + @VisibleForTesting + @Deprecated + public static NotificationEntry buildForTest(StatusBarNotification sbn) { + // TODO START here this will NPE on all tests + return new NotificationEntry(sbn, null, true); + } + + /** The key for this notification. Guaranteed to be immutable and unique */ + public String key() { + return key; + } + + /** + * The StatusBarNotification that represents one half of a NotificationEntry (the other half + * being the Ranking). This object is swapped out whenever a notification is updated. + */ + public StatusBarNotification sbn() { + return notification; + } + + /** + * Should only be called by NotificationEntryManager and friends. + * TODO: Make this package-private + */ + public void setNotification(StatusBarNotification sbn) { + if (!sbn.getKey().equals(key)) { + throw new IllegalArgumentException("New key " + sbn.getKey() + + " doesn't match existing key " + key); } + notification = sbn; } - public void populateFromRanking(@NonNull NotificationListenerService.Ranking ranking) { + /** + * The Ranking that represents one half of a NotificationEntry (the other half being the + * StatusBarNotification). This object is swapped out whenever a the ranking is updated (which + * generally occurs whenever anything changes in the notification list). + */ + public Ranking ranking() { + return mRanking; + } + + /** + * Should only be called by NotificationEntryManager and friends. + * TODO: Make this package-private + */ + public void setRanking(@NonNull Ranking ranking) { + mRanking = ranking; + channel = ranking.getChannel(); lastAudiblyAlertedMs = ranking.getLastAudiblyAlertedMillis(); importance = ranking.getImportance(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java index 80d36a1a4e54..ab9162ace817 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java @@ -76,7 +76,6 @@ import com.android.systemui.plugins.IntentButtonProvider; import com.android.systemui.plugins.IntentButtonProvider.IntentButton; import com.android.systemui.plugins.IntentButtonProvider.IntentButton.IconState; import com.android.systemui.statusbar.KeyguardAffordanceView; -import com.android.systemui.statusbar.KeyguardIndicationController; import com.android.systemui.statusbar.policy.AccessibilityController; import com.android.systemui.statusbar.policy.ExtensionController; import com.android.systemui.statusbar.policy.ExtensionController.Extension; @@ -117,6 +116,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL private static final int DOZE_ANIMATION_STAGGER_DELAY = 48; private static final int DOZE_ANIMATION_ELEMENT_DURATION = 250; + private final UnlockMethodCache mUnlockMethodCache; private KeyguardAffordanceView mRightAffordanceView; private KeyguardAffordanceView mLeftAffordanceView; private ViewGroup mIndicationArea; @@ -129,7 +129,6 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL private View mCameraPreview; private ActivityStarter mActivityStarter; - private UnlockMethodCache mUnlockMethodCache; private LockPatternUtils mLockPatternUtils; private FlashlightController mFlashlightController; private PreviewInflater mPreviewInflater; @@ -185,6 +184,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL public KeyguardBottomAreaView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); + mUnlockMethodCache = UnlockMethodCache.getInstance(getContext()); } private AccessibilityDelegate mAccessibilityDelegate = new AccessibilityDelegate() { @@ -242,8 +242,6 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL mBurnInYOffset = getResources().getDimensionPixelSize( R.dimen.default_burn_in_prevention_offset); updateCameraVisibility(); - mUnlockMethodCache = UnlockMethodCache.getInstance(getContext()); - mUnlockMethodCache.addListener(this); setClipChildren(false); setClipToPadding(false); inflateCameraPreview(); @@ -281,11 +279,13 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL getContext().registerReceiverAsUser(mDevicePolicyReceiver, UserHandle.ALL, filter, null, null); KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateMonitorCallback); + mUnlockMethodCache.addListener(this); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); + mUnlockMethodCache.removeListener(this); mAccessibilityController.removeStateChangedCallback(this); mRightExtension.destroy(); mLeftExtension.destroy(); @@ -804,11 +804,11 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL @Override public IconState getIcon() { - ResolveInfo resolved = resolveCameraIntent(); boolean isCameraDisabled = (mStatusBar != null) && !mStatusBar.isCameraAllowedByAdmin(); - mIconState.isVisible = !isCameraDisabled && resolved != null + mIconState.isVisible = !isCameraDisabled && getResources().getBoolean(R.bool.config_keyguardShowCameraAffordance) - && mUserSetupComplete; + && mUserSetupComplete + && resolveCameraIntent() != null; mIconState.drawable = mContext.getDrawable(R.drawable.ic_camera_alt_24dp); mIconState.contentDescription = mContext.getString(R.string.accessibility_camera_button); @@ -820,7 +820,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext); boolean canSkipBouncer = updateMonitor.getUserCanSkipBouncer( KeyguardUpdateMonitor.getCurrentUser()); - boolean secure = mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser()); + boolean secure = mUnlockMethodCache.isMethodSecure(); return (secure && !canSkipBouncer) ? SECURE_CAMERA_INTENT : INSECURE_CAMERA_INTENT; } } 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 dc9b373de688..2e7ba045c272 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java @@ -17,6 +17,7 @@ package com.android.systemui.statusbar.phone; import static com.android.keyguard.KeyguardSecurityModel.SecurityMode; +import static com.android.systemui.DejankUtils.whitelistIpcs; import static com.android.systemui.plugins.ActivityStarter.OnDismissAction; import android.content.Context; @@ -468,12 +469,15 @@ public class KeyguardBouncer { * notifications on Keyguard, like SIM PIN/PUK. */ public boolean needsFullscreenBouncer() { - ensureView(); - if (mKeyguardView != null) { - SecurityMode mode = mKeyguardView.getSecurityMode(); - return mode == SecurityMode.SimPin || mode == SecurityMode.SimPuk; - } - return false; + // TODO(b/140059518) + return whitelistIpcs(() -> { + ensureView(); + if (mKeyguardView != null) { + SecurityMode mode = mKeyguardView.getSecurityMode(); + return mode == SecurityMode.SimPin || mode == SecurityMode.SimPuk; + } + return false; + }); } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java index 1d4d0bd17f01..dcc31075a2ac 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java @@ -16,6 +16,8 @@ package com.android.systemui.statusbar.phone; +import static com.android.systemui.DejankUtils.whitelistIpcs; + import android.app.admin.DevicePolicyManager; import android.content.Context; import android.os.UserManager; @@ -98,25 +100,30 @@ public class MultiUserSwitch extends FrameLayout implements View.OnClickListener // Short-circuiting from UserManager. Needs to be extracted because of SystemUI boolean flag // qs_show_user_switcher_for_single_user - // The default in UserManager is to show the switcher. We want to not show it unless the - // user explicitly requests it in Settings - final boolean userSwitcherEnabled = Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.USER_SWITCHER_ENABLED, 0) != 0; - // TODO(b/138661450) Move IPC calls to background - if (!userSwitcherEnabled - || !UserManager.supportsMultipleUsers() - || UserManager.isDeviceInDemoMode(mContext) - || mUserManager.hasUserRestriction(UserManager.DISALLOW_USER_SWITCH)) { - return false; - } + return whitelistIpcs(() -> { + // The default in UserManager is to show the switcher. We want to not show it unless the + // user explicitly requests it in Settings + final boolean userSwitcherEnabled = Settings.Global.getInt( + mContext.getContentResolver(), + Settings.Global.USER_SWITCHER_ENABLED, 0) != 0; + + if (!userSwitcherEnabled + || !UserManager.supportsMultipleUsers() + || UserManager.isDeviceInDemoMode(mContext) + || mUserManager.hasUserRestriction(UserManager.DISALLOW_USER_SWITCH)) { + return false; + } - final boolean guestEnabled = !mContext.getSystemService(DevicePolicyManager.class) - .getGuestUserDisabled(null); - return mUserSwitcherController.getSwitchableUserCount() > 1 - // If we cannot add guests even if they are enabled, do not show - || (guestEnabled && !mUserManager.hasUserRestriction(UserManager.DISALLOW_ADD_USER)) - || mContext.getResources().getBoolean(R.bool.qs_show_user_switcher_for_single_user); + final boolean guestEnabled = !mContext.getSystemService(DevicePolicyManager.class) + .getGuestUserDisabled(null); + return mUserSwitcherController.getSwitchableUserCount() > 1 + // If we cannot add guests even if they are enabled, do not show + || (guestEnabled && !mUserManager.hasUserRestriction( + UserManager.DISALLOW_ADD_USER)) + || mContext.getResources().getBoolean( + R.bool.qs_show_user_switcher_for_single_user); + }); } private void registerListener() { @@ -167,7 +174,8 @@ public class MultiUserSwitch extends FrameLayout implements View.OnClickListener private void refreshContentDescription() { String currentUser = null; - if (mUserManager.isUserSwitcherEnabled() + // TODO(b/138661450) + if (whitelistIpcs(mUserManager::isUserSwitcherEnabled) && mUserSwitcherController != null) { currentUser = mUserSwitcherController.getCurrentUserName(mContext); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java index c76cdcb85c34..248bc75ef856 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -666,6 +666,7 @@ public class NotificationPanelView extends PanelView implements @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + DejankUtils.startDetectingBlockingIpcs("NVP#onLayout"); super.onLayout(changed, left, top, right, bottom); setIsFullWidth(mNotificationStackScroller.getWidth() == getWidth()); @@ -712,6 +713,7 @@ public class NotificationPanelView extends PanelView implements mExpandAfterLayoutRunnable.run(); mExpandAfterLayoutRunnable = null; } + DejankUtils.stopDetectingBlockingIpcs("NVP#onLayout"); } private void updateGestureExclusionRect() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index 4c5b4649613f..9fc3e476579a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -25,6 +25,7 @@ import static android.app.StatusBarManager.WindowVisibleState; import static android.app.StatusBarManager.windowStateToString; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY; +import static com.android.systemui.DejankUtils.whitelistIpcs; import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME; import static com.android.systemui.Dependency.BG_HANDLER; import static com.android.systemui.Dependency.MAIN_HANDLER; @@ -131,6 +132,7 @@ import com.android.keyguard.ViewMediatorCallback; import com.android.systemui.ActivityIntentHelper; import com.android.systemui.ActivityStarterDelegate; import com.android.systemui.AutoReinflateContainer; +import com.android.systemui.DejankUtils; import com.android.systemui.DemoMode; import com.android.systemui.Dependency; import com.android.systemui.Dumpable; @@ -3680,16 +3682,21 @@ public class StatusBar extends SystemUI implements DemoMode, @Override public void onStartedGoingToSleep() { + String tag = "StatusBar#onStartedGoingToSleep"; + DejankUtils.startDetectingBlockingIpcs(tag); updateNotificationPanelTouchState(); notifyHeadsUpGoingToSleep(); dismissVolumeDialog(); mWakeUpCoordinator.setFullyAwake(false); mBypassHeadsUpNotifier.setFullyAwake(false); mKeyguardBypassController.onStartedGoingToSleep(); + DejankUtils.stopDetectingBlockingIpcs(tag); } @Override public void onStartedWakingUp() { + String tag = "StatusBar#onStartedWakingUp"; + DejankUtils.startDetectingBlockingIpcs(tag); mDeviceInteractive = true; mWakeUpCoordinator.setWakingUp(true); if (!mKeyguardBypassController.getBypassEnabled()) { @@ -3704,6 +3711,7 @@ public class StatusBar extends SystemUI implements DemoMode, // once we fully woke up. updateNotificationPanelTouchState(); mPulseExpansionHandler.onStartedWakingUp(); + DejankUtils.stopDetectingBlockingIpcs(tag); } @Override @@ -3854,18 +3862,20 @@ public class StatusBar extends SystemUI implements DemoMode, } boolean isCameraAllowedByAdmin() { - if (mDevicePolicyManager.getCameraDisabled(null, - mLockscreenUserManager.getCurrentUserId())) { - return false; - } else if (mStatusBarKeyguardViewManager == null || - (isKeyguardShowing() && isKeyguardSecure())) { - // Check if the admin has disabled the camera specifically for the keyguard - return (mDevicePolicyManager. - getKeyguardDisabledFeatures(null, mLockscreenUserManager.getCurrentUserId()) - & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) == 0; - } - - return true; + // TODO(b/140060745) + return whitelistIpcs(() -> { + if (mDevicePolicyManager.getCameraDisabled(null, + mLockscreenUserManager.getCurrentUserId())) { + return false; + } else if (mStatusBarKeyguardViewManager == null + || (isKeyguardShowing() && isKeyguardSecure())) { + // Check if the admin has disabled the camera specifically for the keyguard + return (mDevicePolicyManager.getKeyguardDisabledFeatures(null, + mLockscreenUserManager.getCurrentUserId()) + & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) == 0; + } + return true; + }); } private boolean isGoingToSleep() { 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 0ef981bdb3de..e85b147f7a34 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java @@ -18,6 +18,7 @@ package com.android.systemui.statusbar.phone; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; +import static com.android.systemui.DejankUtils.whitelistIpcs; import static com.android.systemui.statusbar.NotificationRemoteInputManager.ENABLE_REMOTE_INPUT; import android.app.ActivityManager; @@ -370,12 +371,14 @@ public class StatusBarWindowController implements Callback, Dumpable, Configurat mWindowManager.updateViewLayout(mStatusBarView, mLp); } if (mHasTopUi != mHasTopUiChanged) { - try { - mActivityManager.setHasTopUi(mHasTopUiChanged); - } catch (RemoteException e) { - Log.e(TAG, "Failed to call setHasTopUi", e); - } - mHasTopUi = mHasTopUiChanged; + whitelistIpcs(() -> { + try { + mActivityManager.setHasTopUi(mHasTopUiChanged); + } catch (RemoteException e) { + Log.e(TAG, "Failed to call setHasTopUi", e); + } + mHasTopUi = mHasTopUiChanged; + }); } notifyStateChangedCallbacks(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java index 6789930ab76e..7a81ed419fff 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java @@ -65,8 +65,6 @@ import com.android.systemui.R; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.DragDownHelper; -import com.android.systemui.statusbar.StatusBarState; -import com.android.systemui.statusbar.notification.DynamicPrivacyController; import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout; import com.android.systemui.statusbar.phone.ScrimController.ScrimVisibility; import com.android.systemui.tuner.TunerService; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java index b1d6ca6e5580..24ecd148043f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java @@ -27,6 +27,7 @@ import android.os.Trace; import com.android.internal.widget.LockPatternUtils; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitorCallback; +import com.android.systemui.DejankUtils; import java.io.PrintWriter; import java.util.ArrayList; @@ -133,15 +134,20 @@ public class UnlockMethodCache { mTrusted = trusted; mTrustManaged = trustManaged; mFaceAuthEnabled = faceAuthEnabled; + Trace.endSection(); notifyListeners(); + } else { + Trace.endSection(); } - Trace.endSection(); } private void notifyListeners() { + String tag = "UnlockMethodCache#notifyListeners"; + DejankUtils.startDetectingBlockingIpcs(tag); for (OnUnlockMethodChangedListener listener : mListeners) { listener.onUnlockMethodStateChanged(); } + DejankUtils.stopDetectingBlockingIpcs(tag); } public void dump(PrintWriter pw) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java index abe3f2c18891..fc6e5e22c2e8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java @@ -18,12 +18,12 @@ package com.android.systemui.statusbar.policy; import static com.android.systemui.statusbar.policy.NetworkControllerImpl.TAG; import android.content.Context; -import android.text.format.DateFormat; import android.util.Log; import com.android.systemui.statusbar.policy.NetworkController.SignalCallback; import java.io.PrintWriter; +import java.text.SimpleDateFormat; import java.util.BitSet; @@ -254,6 +254,8 @@ public abstract class SignalController<T extends SignalController.State, } static class State { + // No locale as it's only used for logging purposes + private static SimpleDateFormat sSDF = new SimpleDateFormat("MM-dd HH:mm:ss.SSS"); boolean connected; boolean enabled; boolean activityIn; @@ -301,7 +303,7 @@ public abstract class SignalController<T extends SignalController.State, .append("activityOut=").append(activityOut).append(',') .append("activityDormant=").append(activityDormant).append(',') .append("rssi=").append(rssi).append(',') - .append("lastModified=").append(DateFormat.format("MM-dd HH:mm:ss", time)); + .append("lastModified=").append(sSDF.format(time)); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java index 395add76dda4..2e1e52049419 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java @@ -17,6 +17,7 @@ package com.android.systemui.statusbar.policy; import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; +import static com.android.systemui.DejankUtils.whitelistIpcs; import static com.android.systemui.Dependency.MAIN_HANDLER_NAME; import android.app.ActivityManager; @@ -313,9 +314,10 @@ public class UserSwitcherController implements Dumpable { // adb shell settings put system enable_fullscreen_user_switcher 1 # Turn it on. // Restart SystemUI or adb reboot. final int DEFAULT = -1; + // TODO(b/140061064) final int overrideUseFullscreenUserSwitcher = - Settings.System.getInt(mContext.getContentResolver(), - "enable_fullscreen_user_switcher", DEFAULT); + whitelistIpcs(() -> Settings.System.getInt(mContext.getContentResolver(), + "enable_fullscreen_user_switcher", DEFAULT)); if (overrideUseFullscreenUserSwitcher != DEFAULT) { return overrideUseFullscreenUserSwitcher != 0; } diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java index aa4dcc0ca2ae..a55e2cf38e39 100644 --- a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java +++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java @@ -34,6 +34,7 @@ import android.util.ArrayMap; import android.util.ArraySet; import com.android.internal.util.ArrayUtils; +import com.android.systemui.DejankUtils; import com.android.systemui.DemoMode; import com.android.systemui.qs.QSTileHost; import com.android.systemui.settings.CurrentUserTracker; @@ -189,7 +190,8 @@ public class TunerServiceImpl extends TunerService { mContentResolver.registerContentObserver(uri, false, mObserver, mCurrentUser); } // Send the first state. - String value = Settings.Secure.getStringForUser(mContentResolver, key, mCurrentUser); + String value = DejankUtils.whitelistIpcs(() -> Settings.Secure + .getStringForUser(mContentResolver, key, mCurrentUser)); tunable.onTuningChanged(key, value); } diff --git a/packages/SystemUI/src/com/android/systemui/util/DeviceConfigProxy.java b/packages/SystemUI/src/com/android/systemui/util/DeviceConfigProxy.java new file mode 100644 index 000000000000..3a2172ae0fae --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/util/DeviceConfigProxy.java @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2019 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.util; + +import android.annotation.CallbackExecutor; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.content.Context; +import android.provider.DeviceConfig; +import android.provider.Settings; + +import java.util.concurrent.Executor; + +import javax.inject.Inject; + +/** + * Wrapper around DeviceConfig useful for testing. + */ +public class DeviceConfigProxy { + @Inject + public DeviceConfigProxy() { + } + + /** + * Wrapped version of {@link DeviceConfig#addOnPropertiesChangedListener}. + */ + public void addOnPropertiesChangedListener( + @NonNull String namespace, + @NonNull @CallbackExecutor Executor executor, + @NonNull DeviceConfig.OnPropertiesChangedListener onPropertiesChangedListener) { + DeviceConfig.addOnPropertiesChangedListener( + namespace, executor, onPropertiesChangedListener); + } + + /** + * Wrapped version of {@link DeviceConfig#enforceReadPermission}. + */ + public void enforceReadPermission(Context context, String namespace) { + DeviceConfig.enforceReadPermission(context, namespace); + } + + /** + * Wrapped version of {@link DeviceConfig#getBoolean}. + */ + public boolean getBoolean( + @NonNull String namespace, @NonNull String name, boolean defaultValue) { + return DeviceConfig.getBoolean(namespace, name, defaultValue); + } + + /** + * Wrapped version of {@link DeviceConfig#getFloat}. + */ + public float getFloat( + @NonNull String namespace, @NonNull String name, float defaultValue) { + return DeviceConfig.getFloat(namespace, name, defaultValue); + } + + /** + * Wrapped version of {@link DeviceConfig#getInt}. + */ + public int getInt(@NonNull String namespace, @NonNull String name, int defaultValue) { + return DeviceConfig.getInt(namespace, name, defaultValue); + } + + /** + * Wrapped version of {@link DeviceConfig#getLong}. + */ + public long getLong(@NonNull String namespace, @NonNull String name, long defaultValue) { + return DeviceConfig.getLong(namespace, name, defaultValue); + + } + + /** + * Wrapped version of {@link DeviceConfig#getProperty}. + */ + public String getProperty(@NonNull String namespace, @NonNull String name) { + return DeviceConfig.getProperty(namespace, name); + } + + /** + * Wrapped version of {@link DeviceConfig#getString}. + */ + public String getString( + @NonNull String namespace, @NonNull String name, @Nullable String defaultValue) { + return DeviceConfig.getString(namespace, name, defaultValue); + } + + /** + * Wrapped version of {@link DeviceConfig#removeOnPropertiesChangedListener}. + * + * Like {@link #addOnPropertiesChangedListener}, this operates on a callback type that + * wraps the original callback type provided by {@link DeviceConfig}. + */ + public void removeOnPropertiesChangedListener( + @NonNull DeviceConfig.OnPropertiesChangedListener onPropertiesChangedListener) { + DeviceConfig.removeOnPropertiesChangedListener(onPropertiesChangedListener); + } + + /** + * Wrapped version of {@link DeviceConfig#resetToDefaults}. + */ + public void resetToDefaults(@Settings.ResetMode int resetMode, + @Nullable String namespace) { + DeviceConfig.resetToDefaults(resetMode, namespace); + } + + /** + * Wrapped version of {@link DeviceConfig#setProperty}. + */ + public boolean setProperty( + @NonNull String namespace, + @NonNull String name, + @Nullable String value, + boolean makeDefault) { + return DeviceConfig.setProperty(namespace, name, value, makeDefault); + } +} diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java index a3cb6c05ca7a..fce79c373c36 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java @@ -477,6 +477,16 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { assertThat(listToVerify.get(0)).isEqualTo(TEST_SUBSCRIPTION_2); } + @Test + public void testIsUserUnlocked() { + // mUserManager will report the user as unlocked on @Before + assertThat(mKeyguardUpdateMonitor.isUserUnlocked(KeyguardUpdateMonitor.getCurrentUser())) + .isTrue(); + // Invalid user should not be unlocked. + int randomUser = 99; + assertThat(mKeyguardUpdateMonitor.isUserUnlocked(randomUser)).isFalse(); + } + private Intent putPhoneInfo(Intent intent, Bundle data, Boolean simInited) { int subscription = simInited ? 1/* mock subid=1 */ : SubscriptionManager.DUMMY_SUBSCRIPTION_ID_BASE; diff --git a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java index 8a6ee12d7068..ccd2138ced54 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java @@ -392,18 +392,18 @@ public class ForegroundServiceControllerTest extends SysuiTestCase { } private void entryRemoved(StatusBarNotification notification) { - mEntryListener.onEntryRemoved(new NotificationEntry(notification), + mEntryListener.onEntryRemoved(NotificationEntry.buildForTest(notification), null, false); } private void entryAdded(StatusBarNotification notification, int importance) { - NotificationEntry entry = new NotificationEntry(notification); + NotificationEntry entry = NotificationEntry.buildForTest(notification); entry.importance = importance; mEntryListener.onPendingEntryAdded(entry); } private void entryUpdated(StatusBarNotification notification, int importance) { - NotificationEntry entry = new NotificationEntry(notification); + NotificationEntry entry = NotificationEntry.buildForTest(notification); entry.importance = importance; mEntryListener.onPostEntryUpdated(entry); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/SysuiBaseFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/SysuiBaseFragmentTest.java index 256cfb28d4de..a245d4112798 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/SysuiBaseFragmentTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/SysuiBaseFragmentTest.java @@ -42,7 +42,7 @@ public abstract class SysuiBaseFragmentTest extends BaseFragmentTest { public final DexmakerShareClassLoaderRule mDexmakerShareClassLoaderRule = new DexmakerShareClassLoaderRule(); - protected final TestableDependency mDependency = new TestableDependency(mContext); + protected TestableDependency mDependency; protected SysuiTestableContext mSysuiContext; private Instrumentation mRealInstrumentation; @@ -53,6 +53,7 @@ public abstract class SysuiBaseFragmentTest extends BaseFragmentTest { @Before public void SysuiSetup() { SystemUIFactory.createFromConfig(mContext); + mDependency = new TestableDependency(mContext); // TODO: Figure out another way to give reference to a SysuiTestableContext. mSysuiContext = (SysuiTestableContext) mContext; @@ -69,6 +70,7 @@ public abstract class SysuiBaseFragmentTest extends BaseFragmentTest { public void SysuiTeardown() { InstrumentationRegistry.registerInstance(mRealInstrumentation, InstrumentationRegistry.getArguments()); + SystemUIFactory.cleanup(); } @Override diff --git a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java index 8d93f967be4f..e4f33e25a341 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java +++ b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java @@ -55,12 +55,13 @@ public abstract class SysuiTestCase { @Rule public final DexmakerShareClassLoaderRule mDexmakerShareClassLoaderRule = new DexmakerShareClassLoaderRule(); - public TestableDependency mDependency = new TestableDependency(mContext); + public TestableDependency mDependency; private Instrumentation mRealInstrumentation; @Before public void SysuiSetup() throws Exception { SystemUIFactory.createFromConfig(mContext); + mDependency = new TestableDependency(mContext); mRealInstrumentation = InstrumentationRegistry.getInstrumentation(); Instrumentation inst = spy(mRealInstrumentation); @@ -82,6 +83,7 @@ public abstract class SysuiTestCase { InstrumentationRegistry.getArguments()); // Reset the assert's main looper. Assert.sMainLooper = Looper.getMainLooper(); + SystemUIFactory.cleanup(); } protected LeakCheck getLeakCheck() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java index 815a70ae3026..3eea853ef2bc 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java @@ -878,7 +878,7 @@ public class BubbleDataTest extends SysuiTestCase { when(sbn.getNotification()).thenReturn(notification); // NotificationEntry -> StatusBarNotification -> Notification -> BubbleMetadata - return new NotificationEntry(sbn); + return NotificationEntry.buildForTest(sbn); } private void setCurrentTime(long time) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingManagerProxyTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingManagerProxyTest.java index 7ea6493da83d..2073ae17784c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingManagerProxyTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingManagerProxyTest.java @@ -31,6 +31,8 @@ import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; import com.android.systemui.classifier.brightline.BrightLineFalsingManager; import com.android.systemui.shared.plugins.PluginManager; +import com.android.systemui.util.DeviceConfigProxy; +import com.android.systemui.util.DeviceConfigProxyFake; import org.junit.After; import org.junit.Before; @@ -45,8 +47,9 @@ import org.mockito.MockitoAnnotations; public class FalsingManagerProxyTest extends SysuiTestCase { @Mock PluginManager mPluginManager; - private boolean mDefaultConfigValue; private Handler mHandler; + private FalsingManagerProxy mProxy; + private DeviceConfigProxy mDeviceConfig; private TestableLooper mTestableLooper; @Before @@ -54,50 +57,47 @@ public class FalsingManagerProxyTest extends SysuiTestCase { MockitoAnnotations.initMocks(this); mTestableLooper = TestableLooper.get(this); mHandler = new Handler(mTestableLooper.getLooper()); - mDefaultConfigValue = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI, - BRIGHTLINE_FALSING_MANAGER_ENABLED, false); - // In case it runs on a device where it's been set to true, set it to false by hand. - DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI, + mDeviceConfig = new DeviceConfigProxyFake(); + mDeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI, BRIGHTLINE_FALSING_MANAGER_ENABLED, "false", false); } @After public void tearDown() { - DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI, - BRIGHTLINE_FALSING_MANAGER_ENABLED, mDefaultConfigValue ? "true" : "false", false); + if (mProxy != null) { + mProxy.cleanup(); + } } @Test public void test_brightLineFalsingManagerDisabled() { - FalsingManagerProxy proxy = new FalsingManagerProxy(getContext(), mPluginManager, mHandler); - - assertThat(proxy.getInternalFalsingManager(), instanceOf(FalsingManagerImpl.class)); + mProxy = new FalsingManagerProxy(getContext(), mPluginManager, mHandler, mDeviceConfig); + assertThat(mProxy.getInternalFalsingManager(), instanceOf(FalsingManagerImpl.class)); } @Test - public void test_brightLineFalsingManagerEnabled() { - DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI, + public void test_brightLineFalsingManagerEnabled() throws InterruptedException { + mDeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI, BRIGHTLINE_FALSING_MANAGER_ENABLED, "true", false); - FalsingManagerProxy proxy = new FalsingManagerProxy(getContext(), mPluginManager, mHandler); - - assertThat(proxy.getInternalFalsingManager(), instanceOf(BrightLineFalsingManager.class)); + mTestableLooper.processAllMessages(); + mProxy = new FalsingManagerProxy(getContext(), mPluginManager, mHandler, mDeviceConfig); + assertThat(mProxy.getInternalFalsingManager(), instanceOf(BrightLineFalsingManager.class)); } @Test - public void test_brightLineFalsingManagerToggled() { - FalsingManagerProxy proxy = new FalsingManagerProxy(getContext(), mPluginManager, mHandler); - assertThat(proxy.getInternalFalsingManager(), instanceOf(FalsingManagerImpl.class)); + public void test_brightLineFalsingManagerToggled() throws InterruptedException { + mProxy = new FalsingManagerProxy(getContext(), mPluginManager, mHandler, mDeviceConfig); + assertThat(mProxy.getInternalFalsingManager(), instanceOf(FalsingManagerImpl.class)); - DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI, + mDeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI, BRIGHTLINE_FALSING_MANAGER_ENABLED, "true", false); mTestableLooper.processAllMessages(); - proxy.setupFalsingManager(getContext()); - assertThat(proxy.getInternalFalsingManager(), instanceOf(BrightLineFalsingManager.class)); + assertThat(mProxy.getInternalFalsingManager(), + instanceOf(BrightLineFalsingManager.class)); - DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI, + mDeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI, BRIGHTLINE_FALSING_MANAGER_ENABLED, "false", false); mTestableLooper.processAllMessages(); - proxy.setupFalsingManager(getContext()); - assertThat(proxy.getInternalFalsingManager(), instanceOf(FalsingManagerImpl.class)); + assertThat(mProxy.getInternalFalsingManager(), instanceOf(FalsingManagerImpl.class)); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/DiagonalClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/DiagonalClassifierTest.java index b45d3f2855ee..afe4200a3a43 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/DiagonalClassifierTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/DiagonalClassifierTest.java @@ -28,6 +28,8 @@ import android.testing.TestableLooper; import androidx.test.filters.SmallTest; +import com.android.systemui.util.DeviceConfigProxyFake; + import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -58,7 +60,7 @@ public class DiagonalClassifierTest extends ClassifierTest { public void setup() { super.setup(); MockitoAnnotations.initMocks(this); - mClassifier = new DiagonalClassifier(mDataProvider); + mClassifier = new DiagonalClassifier(mDataProvider, new DeviceConfigProxyFake()); } @After diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/DistanceClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/DistanceClassifierTest.java index 805bb91591e5..f0f5fc719272 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/DistanceClassifierTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/DistanceClassifierTest.java @@ -24,6 +24,8 @@ import android.testing.TestableLooper; import androidx.test.filters.SmallTest; +import com.android.systemui.util.DeviceConfigProxyFake; + import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -41,7 +43,7 @@ public class DistanceClassifierTest extends ClassifierTest { public void setup() { super.setup(); mDataProvider = getDataProvider(); - mClassifier = new DistanceClassifier(mDataProvider); + mClassifier = new DistanceClassifier(mDataProvider, new DeviceConfigProxyFake()); } @After diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/ProximityClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/ProximityClassifierTest.java index a6cabbf49458..c76fe74b1af7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/ProximityClassifierTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/ProximityClassifierTest.java @@ -31,6 +31,8 @@ import android.view.MotionEvent; import androidx.test.filters.SmallTest; +import com.android.systemui.util.DeviceConfigProxyFake; + import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -60,7 +62,8 @@ public class ProximityClassifierTest extends ClassifierTest { MockitoAnnotations.initMocks(this); when(mDataProvider.getInteractionType()).thenReturn(GENERIC); when(mDistanceClassifier.isLongSwipe()).thenReturn(false); - mClassifier = new ProximityClassifier(mDistanceClassifier, mDataProvider); + mClassifier = new ProximityClassifier( + mDistanceClassifier, mDataProvider, new DeviceConfigProxyFake()); } @After diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/ZigZagClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/ZigZagClassifierTest.java index fb4c1ec11faa..387c0daad399 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/ZigZagClassifierTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/ZigZagClassifierTest.java @@ -24,6 +24,8 @@ import android.testing.TestableLooper; import androidx.test.filters.SmallTest; +import com.android.systemui.util.DeviceConfigProxyFake; + import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -41,7 +43,7 @@ public class ZigZagClassifierTest extends ClassifierTest { @Before public void setup() { super.setup(); - mClassifier = new ZigZagClassifier(getDataProvider()); + mClassifier = new ZigZagClassifier(getDataProvider(), new DeviceConfigProxyFake()); } @After diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/DismissCallbackRegistryTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/DismissCallbackRegistryTest.java index d35fc30da6c4..7fa1dbeafced 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/DismissCallbackRegistryTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/DismissCallbackRegistryTest.java @@ -38,12 +38,13 @@ import org.mockito.MockitoAnnotations; @RunWith(AndroidJUnit4.class) public class DismissCallbackRegistryTest extends SysuiTestCase { - private final DismissCallbackRegistry mDismissCallbackRegistry = new DismissCallbackRegistry(); + private DismissCallbackRegistry mDismissCallbackRegistry; private @Mock IKeyguardDismissCallback mMockCallback; private @Mock IKeyguardDismissCallback mMockCallback2; @Before public void setUp() throws Exception { + mDismissCallbackRegistry = new DismissCallbackRegistry(); MockitoAnnotations.initMocks(this); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java index 881cc3915880..e6f36e6abbfd 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java @@ -129,7 +129,7 @@ public class AlertingNotificationManagerTest extends SysuiTestCase { public void setUp() { mTestHandler = Handler.createAsync(Looper.myLooper()); mSbn = createNewNotification(0 /* id */); - mEntry = new NotificationEntry(mSbn); + mEntry = NotificationEntry.buildForTest(mSbn); mEntry.setRow(mRow); mAlertingNotificationManager = createAlertingNotificationManager(); @@ -180,7 +180,7 @@ public class AlertingNotificationManagerTest extends SysuiTestCase { public void testReleaseAllImmediately() { for (int i = 0; i < TEST_NUM_NOTIFICATIONS; i++) { StatusBarNotification sbn = createNewNotification(i); - NotificationEntry entry = new NotificationEntry(sbn); + NotificationEntry entry = NotificationEntry.buildForTest(sbn); entry.setRow(mRow); mAlertingNotificationManager.showNotification(entry); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java index daee55bd3d61..2427cfc77f39 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java @@ -268,12 +268,18 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase { public void unlockMethodCache_listenerUpdatesIndication() { createController(); String restingIndication = "Resting indication"; + + mController.setVisible(true); + assertThat(mTextView.getText()).isEqualTo( + mContext.getString(com.android.internal.R.string.lockscreen_storage_locked)); + when(mKeyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(true); + when(mKeyguardUpdateMonitor.isUserUnlocked(anyInt())).thenReturn(true); mController.setRestingIndication(restingIndication); - mController.setVisible(true); assertThat(mTextView.getText()).isEqualTo(mController.getTrustGrantedIndication()); reset(mKeyguardUpdateMonitor); + when(mKeyguardUpdateMonitor.isUserUnlocked(anyInt())).thenReturn(true); when(mKeyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(false); mController.onUnlockMethodStateChanged(); assertThat(mTextView.getText()).isEqualTo(restingIndication); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationListenerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationListenerTest.java index 0800cb9c33f7..55ce8d60f2b4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationListenerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationListenerTest.java @@ -91,7 +91,7 @@ public class NotificationListenerTest extends SysuiTestCase { @Test public void testNotificationUpdateCallsUpdateNotification() { - when(mNotificationData.get(mSbn.getKey())).thenReturn(new NotificationEntry(mSbn)); + when(mNotificationData.get(mSbn.getKey())).thenReturn(NotificationEntry.buildForTest(mSbn)); mListener.onNotificationPosted(mSbn, mRanking); TestableLooper.get(this).processAllMessages(); verify(mEntryManager).updateNotification(mSbn, mRanking); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java index da25eed4a24e..99d09f18eca6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java @@ -30,7 +30,6 @@ import com.android.systemui.statusbar.NotificationRemoteInputManager.SmartReplyH import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; -import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.phone.ShadeController; import com.google.android.collect.Sets; @@ -81,7 +80,7 @@ public class NotificationRemoteInputManagerTest extends SysuiTestCase { Handler.createAsync(Looper.myLooper())); mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID, 0, new Notification(), UserHandle.CURRENT, null, 0); - mEntry = new NotificationEntry(mSbn); + mEntry = NotificationEntry.buildForTest(mSbn); mEntry.setRow(mRow); mRemoteInputManager.setUpWithPresenterForTest(mCallback, @@ -176,7 +175,7 @@ public class NotificationRemoteInputManagerTest extends SysuiTestCase { // Setup a notification entry with 1 remote input. StatusBarNotification newSbn = mRemoteInputManager.rebuildNotificationWithRemoteInput(mEntry, "A Reply", false); - NotificationEntry entry = new NotificationEntry(newSbn); + NotificationEntry entry = NotificationEntry.buildForTest(newSbn); // Try rebuilding to add another reply. newSbn = mRemoteInputManager.rebuildNotificationWithRemoteInput(entry, "Reply 2", true); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java index 7063ddf3e653..99428ec50181 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java @@ -50,7 +50,6 @@ import com.android.systemui.statusbar.notification.row.NotificationContentInflat import com.android.systemui.statusbar.phone.HeadsUpManagerPhone; import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.phone.NotificationGroupManager; -import com.android.systemui.statusbar.policy.HeadsUpManager; /** * A helper class to create {@link ExpandableNotificationRow} (for both individual and group @@ -307,7 +306,7 @@ public class NotificationTestHelper { userHandle, null /* overrideGroupKey */, System.currentTimeMillis()); - NotificationEntry entry = new NotificationEntry(sbn); + NotificationEntry entry = NotificationEntry.buildForTest(sbn); entry.setRow(row); entry.createIcons(mContext, sbn); entry.channel = new NotificationChannel( diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java index 58fb53aae7bb..54d8688857fa 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java @@ -119,7 +119,7 @@ public class NotificationViewHierarchyManagerTest extends SysuiTestCase { private NotificationEntry createEntry() throws Exception { ExpandableNotificationRow row = mHelper.createRow(); - NotificationEntry entry = new NotificationEntry(row.getStatusBarNotification()); + NotificationEntry entry = NotificationEntry.buildForTest(row.getStatusBarNotification()); entry.setRow(row); return entry; } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java index 185723ffa09b..e54ea6a7c8f9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java @@ -97,7 +97,7 @@ public class SmartReplyControllerTest extends SysuiTestCase { mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID, 0, mNotification, new UserHandle(ActivityManager.getCurrentUser()), null, 0); - mEntry = new NotificationEntry(mSbn); + mEntry = NotificationEntry.buildForTest(mSbn); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java index 2ca1b0611cd6..36b143bdace7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java @@ -239,7 +239,7 @@ public class NotificationEntryManagerTest extends SysuiTestCase { .setContentText("Text"); mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID, 0, n.build(), new UserHandle(ActivityManager.getCurrentUser()), null, 0); - mEntry = new NotificationEntry(mSbn); + mEntry = NotificationEntry.buildForTest(mSbn); mEntry.expandedIcon = mock(StatusBarIconView.class); mEntryManager = new TestableNotificationEntryManager(mContext); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java index 6f7751b2e2a5..b5223161dae4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java @@ -195,12 +195,12 @@ public class NotificationFilterTest extends SysuiTestCase { // test should filter out hidden notifications: // hidden - NotificationEntry entry = new NotificationEntry(mMockStatusBarNotification); + NotificationEntry entry = NotificationEntry.buildForTest(mMockStatusBarNotification); entry.suspended = true; assertTrue(mNotificationFilter.shouldFilterOut(entry)); // not hidden - entry = new NotificationEntry(mMockStatusBarNotification); + entry = NotificationEntry.buildForTest(mMockStatusBarNotification); entry.suspended = false; assertFalse(mNotificationFilter.shouldFilterOut(entry)); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java index 311b81c2858e..e42d1558afa9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java @@ -234,7 +234,7 @@ public class NotificationListControllerTest extends SysuiTestCase { new UserHandle(ActivityManager.getCurrentUser()), null, 0); - return new NotificationEntry(notification); + return NotificationEntry.buildForTest(notification); } private static final String TEST_PACKAGE_NAME = "test"; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/VisualStabilityManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/VisualStabilityManagerTest.java index dd2630bc3417..49229ca050c3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/VisualStabilityManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/VisualStabilityManagerTest.java @@ -62,7 +62,7 @@ public class VisualStabilityManagerTest extends SysuiTestCase { mVisualStabilityManager.setUpWithPresenter(mock(NotificationPresenter.class)); mVisualStabilityManager.setVisibilityLocationProvider(mLocationProvider); - mEntry = new NotificationEntry(mock(StatusBarNotification.class)); + mEntry = NotificationEntry.buildForTest(mock(StatusBarNotification.class)); mEntry.setRow(mRow); when(mRow.getEntry()).thenReturn(mEntry); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationDataTest.java index e2d8e5698daf..ed719d99a980 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationDataTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationDataTest.java @@ -233,7 +233,7 @@ public class NotificationDataTest extends SysuiTestCase { Notification n = mMockStatusBarNotification.getNotification(); n.flags = Notification.FLAG_FOREGROUND_SERVICE; - NotificationEntry entry = new NotificationEntry(mMockStatusBarNotification); + NotificationEntry entry = NotificationEntry.buildForTest(mMockStatusBarNotification); entry.setRow(mRow); mNotificationData.add(entry); Bundle override = new Bundle(); @@ -252,7 +252,7 @@ public class NotificationDataTest extends SysuiTestCase { nb.setStyle(new Notification.MediaStyle().setMediaSession(mock(MediaSession.Token.class))); n = nb.build(); when(mMockStatusBarNotification.getNotification()).thenReturn(n); - NotificationEntry entry = new NotificationEntry(mMockStatusBarNotification); + NotificationEntry entry = NotificationEntry.buildForTest(mMockStatusBarNotification); entry.setRow(mRow); mNotificationData.add(entry); Bundle override = new Bundle(); @@ -266,7 +266,7 @@ public class NotificationDataTest extends SysuiTestCase { @Test public void testIsExemptFromDndVisualSuppression_system() { initStatusBarNotification(false); - NotificationEntry entry = new NotificationEntry(mMockStatusBarNotification); + NotificationEntry entry = NotificationEntry.buildForTest(mMockStatusBarNotification); entry.setRow(mRow); entry.mIsSystemNotification = true; mNotificationData.add(entry); @@ -281,7 +281,7 @@ public class NotificationDataTest extends SysuiTestCase { @Test public void testIsNotExemptFromDndVisualSuppression_hiddenCategories() { initStatusBarNotification(false); - NotificationEntry entry = new NotificationEntry(mMockStatusBarNotification); + NotificationEntry entry = NotificationEntry.buildForTest(mMockStatusBarNotification); entry.setRow(mRow); entry.mIsSystemNotification = true; Bundle override = new Bundle(); @@ -369,7 +369,7 @@ public class NotificationDataTest extends SysuiTestCase { StatusBarNotification sbn = new StatusBarNotification("pkg", "pkg", 0, "tag", 0, 0, notification, mContext.getUser(), "", 0); - NotificationEntry entry = new NotificationEntry(sbn); + NotificationEntry entry = NotificationEntry.buildForTest(sbn); entry.setHasSentReply(); assertTrue(entry.isLastMessageFromReply()); @@ -474,7 +474,7 @@ public class NotificationDataTest extends SysuiTestCase { .build(); StatusBarNotification aSbn = new StatusBarNotification("pkg", "pkg", 0, "tag", 0, 0, aN, mContext.getUser(), "", 0); - NotificationEntry a = new NotificationEntry(aSbn); + NotificationEntry a = NotificationEntry.buildForTest(aSbn); a.setRow(mock(ExpandableNotificationRow.class)); a.setIsHighPriority(false); @@ -488,7 +488,7 @@ public class NotificationDataTest extends SysuiTestCase { .build(); StatusBarNotification bSbn = new StatusBarNotification("pkg2", "pkg2", 0, "tag", 0, 0, bN, mContext.getUser(), "", 0); - NotificationEntry b = new NotificationEntry(bSbn); + NotificationEntry b = NotificationEntry.buildForTest(bSbn); b.setIsHighPriority(true); b.setRow(mock(ExpandableNotificationRow.class)); @@ -509,7 +509,7 @@ public class NotificationDataTest extends SysuiTestCase { .build(); StatusBarNotification aSbn = new StatusBarNotification("pkg", "pkg", 0, "tag", 0, 0, aN, mContext.getUser(), "", 0); - NotificationEntry a = new NotificationEntry(aSbn); + NotificationEntry a = NotificationEntry.buildForTest(aSbn); a.setRow(mock(ExpandableNotificationRow.class)); a.setIsHighPriority(false); @@ -523,7 +523,7 @@ public class NotificationDataTest extends SysuiTestCase { .build(); StatusBarNotification bSbn = new StatusBarNotification("pkg2", "pkg2", 0, "tag", 0, 0, bN, mContext.getUser(), "", 0); - NotificationEntry b = new NotificationEntry(bSbn); + NotificationEntry b = NotificationEntry.buildForTest(bSbn); b.setRow(mock(ExpandableNotificationRow.class)); b.setIsHighPriority(false); @@ -556,7 +556,7 @@ public class NotificationDataTest extends SysuiTestCase { override.putInt(OVERRIDE_IMPORTANCE, IMPORTANCE_DEFAULT); mNotificationData.rankingOverrides.put(sbn.getKey(), override); - NotificationEntry entry = new NotificationEntry(sbn); + NotificationEntry entry = NotificationEntry.buildForTest(sbn); entry.setRow(mRow); mNotificationData.add(entry); @@ -583,7 +583,7 @@ public class NotificationDataTest extends SysuiTestCase { override.putInt(OVERRIDE_IMPORTANCE, IMPORTANCE_LOW); mNotificationData.rankingOverrides.put(sbn.getKey(), override); - NotificationEntry entry = new NotificationEntry(sbn); + NotificationEntry entry = NotificationEntry.buildForTest(sbn); entry.setRow(mRow); mNotificationData.add(entry); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java index cca9f2834e93..57a6aae744f0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java @@ -23,6 +23,7 @@ import static org.mockito.Mockito.when; import android.app.Notification; import android.os.Bundle; +import android.service.notification.NotificationListenerService.Ranking; import android.service.notification.StatusBarNotification; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; @@ -59,7 +60,18 @@ public class NotificationEntryTest extends SysuiTestCase { mExtras = new Bundle(); mNotif.extras = mExtras; - mEntry = new NotificationEntry(mStatusBarNotification); + mEntry = NotificationEntry.buildForTest(mStatusBarNotification); + } + + @Test + public void testInitialization() { + final Ranking ranking = new Ranking(); + + final NotificationEntry entry = new NotificationEntry(mStatusBarNotification, ranking); + + assertEquals("key", entry.key()); + assertEquals(mStatusBarNotification, entry.sbn()); + assertEquals(ranking, entry.ranking()); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java index 5e587f848ece..ff3a2e224788 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java @@ -96,7 +96,7 @@ public class NotificationLoggerTest extends SysuiTestCase { StatusBarNotification sbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID, 0, new Notification(), UserHandle.CURRENT, null, 0); - mEntry = new NotificationEntry(sbn); + mEntry = NotificationEntry.buildForTest(sbn); mEntry.setRow(mRow); mLogger = new TestableNotificationLogger(mListener, Dependency.get(UiOffloadThread.class), diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java index 13b9d56e5a14..98e1692c2368 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java @@ -60,7 +60,7 @@ public class NotificationMenuRowTest extends LeakCheckedTest { public void setup() { injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES); mRow = mock(ExpandableNotificationRow.class); - NotificationEntry entry = new NotificationEntry( + NotificationEntry entry = NotificationEntry.buildForTest( mock(StatusBarNotification.class)); entry.channel = mock(NotificationChannel.class); when(mRow.getEntry()).thenReturn(entry); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java index 48934da9fb37..de3623f86c44 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java @@ -121,7 +121,7 @@ public class HeadsUpManagerPhoneTest extends AlertingNotificationManagerTest { @Test public void testCanRemoveImmediately_notTopEntry() { - NotificationEntry laterEntry = new NotificationEntry(createNewNotification(1)); + NotificationEntry laterEntry = NotificationEntry.buildForTest(createNewNotification(1)); laterEntry.setRow(mRow); mHeadsUpManager.showNotification(mEntry); mHeadsUpManager.showNotification(laterEntry); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java index 75aae017316c..33d3ac848f0f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java @@ -82,8 +82,7 @@ public class NavigationBarFragmentTest extends SysuiBaseFragmentTest { private FragmentController mControllerExternalDisplay; private SysuiTestableContext mSysuiTestableContextExternal; - private OverviewProxyService mOverviewProxyService = - mDependency.injectMockDependency(OverviewProxyService.class); + private OverviewProxyService mOverviewProxyService; private CommandQueue mCommandQueue; private SysUiState mMockSysUiState; @@ -115,6 +114,8 @@ public class NavigationBarFragmentTest extends SysuiBaseFragmentTest { public void setupFragment() throws Exception { setupSysuiDependency(); createRootView(); + mOverviewProxyService = + mDependency.injectMockDependency(OverviewProxyService.class); TestableLooper.get(this).runWithLooper(() -> { mHandler = new Handler(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarRotationContextTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarRotationContextTest.java index cf084287a7b7..d6b38ff4936f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarRotationContextTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarRotationContextTest.java @@ -30,7 +30,6 @@ import androidx.test.runner.AndroidJUnit4; import com.android.systemui.SysuiTestCase; import com.android.systemui.SysuiTestableContext; -import com.android.systemui.TestableDependency; import com.android.systemui.statusbar.policy.KeyButtonDrawable; import com.android.systemui.statusbar.policy.RotationLockController; @@ -50,7 +49,6 @@ public class NavigationBarRotationContextTest extends SysuiTestCase { @Rule public final SysuiTestableContext mContext = new SysuiTestableContext( InstrumentationRegistry.getContext(), getLeakCheck()); - private final TestableDependency mDependency = new TestableDependency(mContext); private RotationButtonController mRotationButtonController; private RotationButton mRotationButton; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelperTest.java index b1c3c83e938e..a0d264d81c7c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelperTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelperTest.java @@ -256,7 +256,7 @@ public class NotificationGroupAlertTransferHelperTest extends SysuiTestCase { StatusBarNotification oldNotification = childEntry.notification; StatusBarNotification newSbn = spy(childEntry.notification.clone()); doReturn("other_group").when(newSbn).getGroupKey(); - childEntry.notification = newSbn; + childEntry.setNotification(newSbn); mGroupManager.onEntryUpdated(childEntry, oldNotification); assertFalse(mGroupAlertTransferHelper.isAlertTransferPending(childEntry)); @@ -267,7 +267,7 @@ public class NotificationGroupAlertTransferHelperTest extends SysuiTestCase { NotificationEntry summaryEntry = mGroupTestHelper.createSummaryNotification(Notification.GROUP_ALERT_SUMMARY); NotificationEntry childEntry = - mGroupTestHelper.createChildNotification(Notification.GROUP_ALERT_SUMMARY); + mGroupTestHelper.createChildNotification(Notification.GROUP_ALERT_SUMMARY, 47); when(childEntry.getRow().isInflationFlagSet(mHeadsUpManager.getContentFlag())) .thenReturn(false); mHeadsUpManager.showNotification(summaryEntry); @@ -277,8 +277,9 @@ public class NotificationGroupAlertTransferHelperTest extends SysuiTestCase { // Update that child to a summary. StatusBarNotification oldNotification = childEntry.notification; - childEntry.notification = mGroupTestHelper.createSummaryNotification( - Notification.GROUP_ALERT_SUMMARY).notification; + childEntry.setNotification( + mGroupTestHelper.createSummaryNotification( + Notification.GROUP_ALERT_SUMMARY, 47).notification); mGroupManager.onEntryUpdated(childEntry, oldNotification); assertFalse(mGroupAlertTransferHelper.isAlertTransferPending(childEntry)); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupTestHelper.java index e6b9778eb59f..e33545bba7a2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupTestHelper.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupTestHelper.java @@ -45,11 +45,15 @@ public final class NotificationGroupTestHelper { } public NotificationEntry createSummaryNotification() { - return createSummaryNotification(Notification.GROUP_ALERT_ALL); + return createSummaryNotification(Notification.GROUP_ALERT_ALL, mId++); } public NotificationEntry createSummaryNotification(int groupAlertBehavior) { - return createEntry(true, groupAlertBehavior); + return createSummaryNotification(groupAlertBehavior, mId++); + } + + public NotificationEntry createSummaryNotification(int groupAlertBehavior, int id) { + return createEntry(id, true, groupAlertBehavior); } public NotificationEntry createChildNotification() { @@ -57,10 +61,14 @@ public final class NotificationGroupTestHelper { } public NotificationEntry createChildNotification(int groupAlertBehavior) { - return createEntry(false, groupAlertBehavior); + return createEntry(mId++, false, groupAlertBehavior); + } + + public NotificationEntry createChildNotification(int groupAlertBehavior, int id) { + return createEntry(id, false, groupAlertBehavior); } - public NotificationEntry createEntry(boolean isSummary, int groupAlertBehavior) { + public NotificationEntry createEntry(int id, boolean isSummary, int groupAlertBehavior) { Notification notif = new Notification.Builder(mContext, TEST_CHANNEL_ID) .setContentTitle("Title") .setSmallIcon(R.drawable.ic_person) @@ -71,7 +79,7 @@ public final class NotificationGroupTestHelper { StatusBarNotification sbn = new StatusBarNotification( TEST_PACKAGE_NAME /* pkg */, TEST_PACKAGE_NAME, - mId++, + id, null /* tag */, 0, /* uid */ 0 /* initialPid */, @@ -79,7 +87,7 @@ public final class NotificationGroupTestHelper { new UserHandle(ActivityManager.getCurrentUser()), null /* overrideGroupKey */, 0 /* postTime */); - NotificationEntry entry = new NotificationEntry(sbn); + NotificationEntry entry = NotificationEntry.buildForTest(sbn); ExpandableNotificationRow row = mock(ExpandableNotificationRow.class); entry.setRow(row); when(row.getEntry()).thenReturn(entry); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java index 186a8c7dcee1..45cd1e17ff93 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java @@ -86,7 +86,7 @@ public class StatusBarNotificationPresenterTest extends SysuiTestCase { Notification n = new Notification.Builder(getContext(), "a").build(); StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "a", 0, 0, n, UserHandle.of(0), null, 0); - NotificationEntry entry = new NotificationEntry(sbn); + NotificationEntry entry = NotificationEntry.buildForTest(sbn); mCommandQueue.disable(DEFAULT_DISPLAY, StatusBarManager.DISABLE_EXPAND, 0, false /* animate */); TestableLooper.get(this).processAllMessages(); @@ -100,7 +100,7 @@ public class StatusBarNotificationPresenterTest extends SysuiTestCase { Notification n = new Notification.Builder(getContext(), "a").build(); StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "a", 0, 0, n, UserHandle.of(0), null, 0); - NotificationEntry entry = new NotificationEntry(sbn); + NotificationEntry entry = NotificationEntry.buildForTest(sbn); mCommandQueue.disable(DEFAULT_DISPLAY, 0, StatusBarManager.DISABLE2_NOTIFICATION_SHADE, false /* animate */); TestableLooper.get(this).processAllMessages(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java index fa235bd46d7e..7fbf18367f61 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java @@ -418,7 +418,7 @@ public class StatusBarTest extends SysuiTestCase { .build(); StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "a", 0, 0, n, UserHandle.of(0), null, 0); - NotificationEntry entry = new NotificationEntry(sbn); + NotificationEntry entry = NotificationEntry.buildForTest(sbn); entry.importance = IMPORTANCE_HIGH; assertTrue(mNotificationInterruptionStateProvider.shouldHeadsUp(entry)); @@ -439,7 +439,7 @@ public class StatusBarTest extends SysuiTestCase { .build(); StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "a", 0, 0, n, UserHandle.of(0), null, 0); - NotificationEntry entry = new NotificationEntry(sbn); + NotificationEntry entry = NotificationEntry.buildForTest(sbn); entry.importance = IMPORTANCE_HIGH; assertFalse(mNotificationInterruptionStateProvider.shouldHeadsUp(entry)); @@ -456,7 +456,7 @@ public class StatusBarTest extends SysuiTestCase { Notification n = new Notification.Builder(getContext(), "a").build(); StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "a", 0, 0, n, UserHandle.of(0), null, 0); - NotificationEntry entry = new NotificationEntry(sbn); + NotificationEntry entry = NotificationEntry.buildForTest(sbn); entry.suppressedVisualEffects = SUPPRESSED_EFFECT_PEEK; entry.importance = IMPORTANCE_HIGH; @@ -474,7 +474,7 @@ public class StatusBarTest extends SysuiTestCase { Notification n = new Notification.Builder(getContext(), "a").build(); StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "a", 0, 0, n, UserHandle.of(0), null, 0); - NotificationEntry entry = new NotificationEntry(sbn); + NotificationEntry entry = NotificationEntry.buildForTest(sbn); entry.importance = IMPORTANCE_HIGH; assertTrue(mNotificationInterruptionStateProvider.shouldHeadsUp(entry)); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/InflatedSmartRepliesTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/InflatedSmartRepliesTest.java index 2462fb3ca589..bda0e39fb572 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/InflatedSmartRepliesTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/InflatedSmartRepliesTest.java @@ -88,7 +88,7 @@ public class InflatedSmartRepliesTest extends SysuiTestCase { when(mNotification.getAllowSystemGeneratedContextualActions()).thenReturn(true); when(mStatusBarNotification.getNotification()).thenReturn(mNotification); - mEntry = new NotificationEntry(mStatusBarNotification); + mEntry = NotificationEntry.buildForTest(mStatusBarNotification); when(mSmartReplyConstants.isEnabled()).thenReturn(true); mActionIcon = Icon.createWithResource(mContext, R.drawable.ic_person); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java index 0cb575483466..b59bac19629b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java @@ -140,7 +140,7 @@ public class SmartReplyViewTest extends SysuiTestCase { StatusBarNotification sbn = mock(StatusBarNotification.class); when(sbn.getNotification()).thenReturn(mNotification); when(sbn.getKey()).thenReturn(TEST_NOTIFICATION_KEY); - mEntry = new NotificationEntry(sbn); + mEntry = NotificationEntry.buildForTest(sbn); mActionIcon = Icon.createWithResource(mContext, R.drawable.ic_person); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/DeviceConfigProxyFake.java b/packages/SystemUI/tests/src/com/android/systemui/util/DeviceConfigProxyFake.java new file mode 100644 index 000000000000..426aba03d5d8 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/util/DeviceConfigProxyFake.java @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2019 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.util; + +import android.content.Context; +import android.provider.DeviceConfig; +import android.provider.DeviceConfig.OnPropertiesChangedListener; +import android.provider.DeviceConfig.Properties; +import android.util.Pair; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Executor; + +/** + * A Fake of {@link DeviceConfigProxy} useful for testing. + * + * No properties are set by default. No calls to {@link DeviceConfig} are made. Be sure to set any + * properties you rely on ahead of time in your test. + */ +public class DeviceConfigProxyFake extends DeviceConfigProxy { + + private List<Pair<Executor, OnPropertiesChangedListener>> mListeners = new ArrayList<>(); + private Map<String, Map<String, String>> mDefaultProperties = new HashMap<>(); + private Map<String, Map<String, String>> mProperties = new HashMap<>(); + + public DeviceConfigProxyFake() { + } + + @Override + public void addOnPropertiesChangedListener( + String namespace, Executor executor, + OnPropertiesChangedListener onPropertiesChangedListener) { + mListeners.add(Pair.create(executor, onPropertiesChangedListener)); + } + + @Override + public void removeOnPropertiesChangedListener( + OnPropertiesChangedListener onPropertiesChangedListener) { + mListeners.removeIf(listener -> { + if (listener == null) { + return false; + } + return listener.second.equals(onPropertiesChangedListener); + }); + } + + @Override + public boolean setProperty(String namespace, String name, String value, boolean makeDefault) { + setPropertyInternal(namespace, name, value, mProperties); + if (makeDefault) { + setPropertyInternal(namespace, name, value, mDefaultProperties); + } + + for (Pair<Executor, OnPropertiesChangedListener> listener : mListeners) { + listener.first.execute(() -> listener.second.onPropertiesChanged( + new Properties(namespace, mProperties.get(namespace)))); + } + return true; + } + + private void setPropertyInternal(String namespace, String name, String value, + Map<String, Map<String, String>> properties) { + properties.putIfAbsent(namespace, new HashMap<>()); + properties.get(namespace).put(name, value); + } + + @Override + public void enforceReadPermission(Context context, String namespace) { + // no-op + } + + private Properties propsForNamespaceAndName(String namespace, String name) { + if (mProperties.containsKey(namespace) && mProperties.get(namespace).containsKey(name)) { + return new Properties(namespace, mProperties.get(namespace)); + } + if (mDefaultProperties.containsKey(namespace)) { + return new Properties(namespace, mDefaultProperties.get(namespace)); + } + + return null; + } + + @Override + public boolean getBoolean(String namespace, String name, boolean defaultValue) { + Properties props = propsForNamespaceAndName(namespace, name); + if (props != null) { + return props.getBoolean(name, defaultValue); + } + + return defaultValue; + } + + @Override + public int getInt(String namespace, String name, int defaultValue) { + Properties props = propsForNamespaceAndName(namespace, name); + if (props != null) { + return props.getInt(name, defaultValue); + } + + return defaultValue; + } + + @Override + public long getLong(String namespace, String name, long defaultValue) { + Properties props = propsForNamespaceAndName(namespace, name); + if (props != null) { + return props.getLong(name, defaultValue); + } + + return defaultValue; + } + + @Override + public String getProperty(String namespace, String name) { + return getString(namespace, name, null); + } + + @Override + public String getString(String namespace, String name, String defaultValue) { + Properties props = propsForNamespaceAndName(namespace, name); + if (props != null) { + return props.getString(name, defaultValue); + } + + return defaultValue; + } + + @Override + public void resetToDefaults(int resetMode, String namespace) { + if (mProperties.containsKey(namespace)) { + mProperties.get(namespace).clear(); + } + } +} diff --git a/services/Android.bp b/services/Android.bp index 27f8d36894da..6953e862f68b 100644 --- a/services/Android.bp +++ b/services/Android.bp @@ -63,6 +63,5 @@ cc_library_shared { platform_compat_config { name: "services-platform-compat-config", - prefix: "services", src: ":services", } diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java index d8b7e3a25e04..a338b901d24c 100644 --- a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java +++ b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java @@ -66,12 +66,6 @@ public class TouchExplorer extends BaseEventStreamTransformation // Tag for logging received events. private static final String LOG_TAG = "TouchExplorer"; - // States this explorer can be in. - private static final int STATE_TOUCH_EXPLORING = 0x00000001; - private static final int STATE_DRAGGING = 0x00000002; - private static final int STATE_DELEGATING = 0x00000004; - private static final int STATE_GESTURE_DETECTING = 0x00000005; - // The maximum of the cosine between the vectors of two moving // pointers so they can be considered moving in the same direction. private static final float MAX_DRAGGING_ANGLE_COS = 0.525321989f; // cos(pi/4) @@ -248,7 +242,13 @@ public class TouchExplorer extends BaseEventStreamTransformation return; } - if (mState.isTouchExploring()) { + // TODO: extract the below functions into separate handlers for each state. + // Right now the number of functions and number of states make the code messy. + if (mState.isClear()) { + handleMotionEventStateClear(event, rawEvent, policyFlags); + } else if (mState.isTouchInteracting()) { + handleMotionEventStateTouchInteracting(event, rawEvent, policyFlags); + } else if (mState.isTouchExploring()) { handleMotionEventStateTouchExploring(event, rawEvent, policyFlags); } else if (mState.isDragging()) { handleMotionEventStateDragging(event, policyFlags); @@ -286,8 +286,8 @@ public class TouchExplorer extends BaseEventStreamTransformation @Override public void onDoubleTapAndHold(MotionEvent event, int policyFlags) { - // Ignore the event if we aren't touch exploring. - if (!mState.isTouchExploring()) { + // Ignore the event if we aren't touch interacting. + if (!mState.isTouchInteracting()) { return; } @@ -304,8 +304,7 @@ public class TouchExplorer extends BaseEventStreamTransformation @Override public boolean onDoubleTap(MotionEvent event, int policyFlags) { - // Ignore the event if we aren't touch exploring. - if (!mState.isTouchExploring()) { + if (!mState.isTouchInteracting()) { return false; } @@ -380,35 +379,26 @@ public class TouchExplorer extends BaseEventStreamTransformation } /** - * Handles a motion event in touch exploring state. - * - * @param event The event to be handled. - * @param rawEvent The raw (unmodified) motion event. - * @param policyFlags The policy flags associated with the event. + * Handles a motion event in the clear state i.e. no fingers are touching the screen. */ - private void handleMotionEventStateTouchExploring( + private void handleMotionEventStateClear( MotionEvent event, MotionEvent rawEvent, int policyFlags) { switch (event.getActionMasked()) { + // The only way to leave the clear state is for a pointer to go down. case MotionEvent.ACTION_DOWN: - handleActionDownStateTouchExploring(event, policyFlags); - break; - case MotionEvent.ACTION_POINTER_DOWN: - handleActionPointerDownStateTouchExploring(); - break; - case MotionEvent.ACTION_MOVE: - handleActionMoveStateTouchExploring(event, rawEvent, policyFlags); + handleActionDown(event, policyFlags); break; - case MotionEvent.ACTION_UP: - handleActionUpStateTouchExploring(event, policyFlags); + default: + // Some other nonsensical event. break; } } /** - * Handles ACTION_DOWN while in the default touch exploring state. This event represents the + * Handles ACTION_DOWN while in the clear or touch interacting states. This event represents the * first finger touching the screen. */ - private void handleActionDownStateTouchExploring(MotionEvent event, int policyFlags) { + private void handleActionDown(MotionEvent event, int policyFlags) { mAms.onTouchInteractionStart(); // If we still have not notified the user for the last @@ -418,13 +408,13 @@ public class TouchExplorer extends BaseEventStreamTransformation mSendHoverExitDelayed.cancel(); // If a touch exploration gesture is in progress send events for its end. - if (mState.isTouchExplorationInProgress()) { + if (mState.isTouchExploring()) { sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags); } // Avoid duplicated TYPE_TOUCH_INTERACTION_START event when 2nd tap of double // tap. - if (!mGestureDetector.firstTapDetected()) { + if (!mGestureDetector.firstTapDetected() && mState.isClear()) { mSendTouchExplorationEndDelayed.forceSendAndRemove(); mSendTouchInteractionEndDelayed.forceSendAndRemove(); sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_START); @@ -433,13 +423,15 @@ public class TouchExplorer extends BaseEventStreamTransformation mSendTouchInteractionEndDelayed.cancel(); } - if (!mGestureDetector.firstTapDetected() && !mState.isTouchExplorationInProgress()) { + if (!mGestureDetector.firstTapDetected() && !mState.isTouchExploring()) { if (!mSendHoverEnterAndMoveDelayed.isPending()) { - // Deliver hover enter with a delay to have a chance - // to detect what the user is trying to do. + // Queue a delayed transition to STATE_TOUCH_EXPLORING. + // If we do not detect that this is a gesture, delegation or drag the transition + // will fire by default. + // The idea is to avoid getting stuck in STATE_TOUCH_INTERACTING final int pointerId = mReceivedPointerTracker.getPrimaryPointerId(); final int pointerIdBits = (1 << pointerId); - mSendHoverEnterAndMoveDelayed.post(event, true, pointerIdBits, policyFlags); + mSendHoverEnterAndMoveDelayed.post(event, pointerIdBits, policyFlags); } else { // Cache the event until we discern exploration from gesturing. mSendHoverEnterAndMoveDelayed.addEvent(event); @@ -448,10 +440,64 @@ public class TouchExplorer extends BaseEventStreamTransformation } /** + * Handles a motion event in touch interacting state. + * + * @param event The event to be handled. + * @param rawEvent The raw (unmodified) motion event. + * @param policyFlags The policy flags associated with the event. + */ + private void handleMotionEventStateTouchInteracting( + MotionEvent event, MotionEvent rawEvent, int policyFlags) { + switch (event.getActionMasked()) { + case MotionEvent.ACTION_DOWN: + // Continue the previous interaction. + mSendTouchInteractionEndDelayed.cancel(); + handleActionDown(event, policyFlags); + break; + case MotionEvent.ACTION_POINTER_DOWN: + handleActionPointerDown(); + break; + case MotionEvent.ACTION_MOVE: + handleActionMoveStateTouchInteracting(event, rawEvent, policyFlags); + break; + case MotionEvent.ACTION_UP: + handleActionUp(event, policyFlags); + break; + } + } + + /** + * Handles a motion event in touch exploring state. + * + * @param event The event to be handled. + * @param rawEvent The raw (unmodified) motion event. + * @param policyFlags The policy flags associated with the event. + */ + private void handleMotionEventStateTouchExploring( + MotionEvent event, MotionEvent rawEvent, int policyFlags) { + switch (event.getActionMasked()) { + case MotionEvent.ACTION_DOWN: + // We should have already received ACTION_DOWN. Ignore. + break; + case MotionEvent.ACTION_POINTER_DOWN: + handleActionPointerDown(); + break; + case MotionEvent.ACTION_MOVE: + handleActionMoveStateTouchExploring(event, rawEvent, policyFlags); + break; + case MotionEvent.ACTION_UP: + handleActionUp(event, policyFlags); + break; + default: + break; + } + } + + /** * Handles ACTION_POINTER_DOWN when in the touch exploring state. This event represents an * additional finger touching the screen. */ - private void handleActionPointerDownStateTouchExploring() { + private void handleActionPointerDown() { // Another finger down means that if we have not started to deliver // hover events, we will not have to. The code for ACTION_MOVE will // decide what we will actually do next. @@ -459,10 +505,10 @@ public class TouchExplorer extends BaseEventStreamTransformation mSendHoverExitDelayed.cancel(); } /** - * Handles ACTION_MOVE while in the initial touch exploring state. This is where transitions to + * Handles ACTION_MOVE while in the touch interacting state. This is where transitions to * delegating and dragging states are handled. */ - private void handleActionMoveStateTouchExploring( + private void handleActionMoveStateTouchInteracting( MotionEvent event, MotionEvent rawEvent, int policyFlags) { final int pointerId = mReceivedPointerTracker.getPrimaryPointerId(); final int pointerIndex = event.findPointerIndex(pointerId); @@ -474,41 +520,14 @@ public class TouchExplorer extends BaseEventStreamTransformation if (mSendHoverEnterAndMoveDelayed.isPending()) { // Cache the event until we discern exploration from gesturing. mSendHoverEnterAndMoveDelayed.addEvent(event); - } else if (mState.isTouchExplorationInProgress()) { - sendTouchExplorationGestureStartAndHoverEnterIfNeeded(policyFlags); - sendMotionEvent( - event, MotionEvent.ACTION_HOVER_MOVE, pointerIdBits, policyFlags); } break; case 2: + // Make sure we don't have any pending transitions to touch exploration + mSendHoverEnterAndMoveDelayed.cancel(); + mSendHoverExitDelayed.cancel(); // More than one pointer so the user is not touch exploring // and now we have to decide whether to delegate or drag. - if (mSendHoverEnterAndMoveDelayed.isPending()) { - // We have not started sending events so cancel - // scheduled sending events. - mSendHoverEnterAndMoveDelayed.cancel(); - mSendHoverExitDelayed.cancel(); - } else if (mState.isTouchExplorationInProgress()) { - // If the user is touch exploring the second pointer may be - // performing a double tap to activate an item without need - // for the user to lift his exploring finger. - // It is *important* to use the distance traveled by the pointers - // on the screen which may or may not be magnified. - final float deltaX = - mReceivedPointerTracker.getReceivedPointerDownX(pointerId) - - rawEvent.getX(pointerIndex); - final float deltaY = - mReceivedPointerTracker.getReceivedPointerDownY(pointerId) - - rawEvent.getY(pointerIndex); - final double moveDelta = Math.hypot(deltaX, deltaY); - if (moveDelta < mDoubleTapSlop) { - break; - } - // We are sending events so send exit and gesture - // end since we transition to another state. - sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags); - } - // Remove move history before send injected non-move events event = MotionEvent.obtainNoHistory(event); if (isDraggingGesture(event)) { @@ -525,19 +544,6 @@ public class TouchExplorer extends BaseEventStreamTransformation } break; default: - // More than one pointer so the user is not touch exploring - // and now we have to decide whether to delegate or drag. - if (mSendHoverEnterAndMoveDelayed.isPending()) { - // We have not started sending events so cancel - // scheduled sending events. - mSendHoverEnterAndMoveDelayed.cancel(); - mSendHoverExitDelayed.cancel(); - } else { - // We are sending events so send exit and gesture - // end since we transition to another state. - sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags); - } - // More than two pointers are delegated to the view hierarchy. mState.startDelegating(); event = MotionEvent.obtainNoHistory(event); @@ -547,14 +553,13 @@ public class TouchExplorer extends BaseEventStreamTransformation } /** - * Handles ACTION_UP while in the initial touch exploring state. This event represents all - * fingers being lifted from the screen. + * Handles ACTION_UP while in the touch interacting state. This event represents all fingers + * being lifted from the screen. */ - private void handleActionUpStateTouchExploring(MotionEvent event, int policyFlags) { + private void handleActionUp(MotionEvent event, int policyFlags) { mAms.onTouchInteractionEnd(); final int pointerId = event.getPointerId(event.getActionIndex()); final int pointerIdBits = (1 << pointerId); - if (mSendHoverEnterAndMoveDelayed.isPending()) { // If we have not delivered the enter schedule an exit. mSendHoverExitDelayed.post(event, pointerIdBits, policyFlags); @@ -562,13 +567,69 @@ public class TouchExplorer extends BaseEventStreamTransformation // The user is touch exploring so we send events for end. sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags); } - if (!mSendTouchInteractionEndDelayed.isPending()) { mSendTouchInteractionEndDelayed.post(); } } /** + * Handles move events while touch exploring. this is also where we drag or delegate based on + * the number of fingers moving on the screen. + */ + private void handleActionMoveStateTouchExploring( + MotionEvent event, MotionEvent rawEvent, int policyFlags) { + final int pointerId = mReceivedPointerTracker.getPrimaryPointerId(); + final int pointerIdBits = (1 << pointerId); + final int pointerIndex = event.findPointerIndex(pointerId); + switch (event.getPointerCount()) { + case 1: + // Touch exploration. + sendTouchExplorationGestureStartAndHoverEnterIfNeeded(policyFlags); + sendMotionEvent(event, MotionEvent.ACTION_HOVER_MOVE, pointerIdBits, policyFlags); + break; + case 2: + if (mSendHoverEnterAndMoveDelayed.isPending()) { + // We have not started sending events so cancel + // scheduled sending events. + mSendHoverEnterAndMoveDelayed.cancel(); + mSendHoverExitDelayed.cancel(); + } + // If the user is touch exploring the second pointer may be + // performing a double tap to activate an item without need + // for the user to lift his exploring finger. + // It is *important* to use the distance traveled by the pointers + // on the screen which may or may not be magnified. + final float deltaX = + mReceivedPointerTracker.getReceivedPointerDownX(pointerId) + - rawEvent.getX(pointerIndex); + final float deltaY = + mReceivedPointerTracker.getReceivedPointerDownY(pointerId) + - rawEvent.getY(pointerIndex); + final double moveDelta = Math.hypot(deltaX, deltaY); + if (moveDelta > mDoubleTapSlop) { + // The user is trying to either delegate or drag. + handleActionMoveStateTouchInteracting(event, rawEvent, policyFlags); + } else { + // Otherwise the double tap will be handled by the gesture detector. + sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags); + } + break; + default: + // Three or more fingers is something other than touch exploration. + if (mSendHoverEnterAndMoveDelayed.isPending()) { + // We have not started sending events so cancel + // scheduled sending events. + mSendHoverEnterAndMoveDelayed.cancel(); + mSendHoverExitDelayed.cancel(); + } else { + sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags); + } + handleActionMoveStateTouchInteracting(event, rawEvent, policyFlags); + break; + } + } + + /** * Handles a motion event in dragging state. * * @param event The event to be handled. @@ -670,7 +731,6 @@ public class TouchExplorer extends BaseEventStreamTransformation // Send an event to the end of the drag gesture. sendMotionEvent(event, MotionEvent.ACTION_UP, pointerIdBits, policyFlags); } - mState.startTouchExploring(); } break; } } @@ -697,7 +757,6 @@ public class TouchExplorer extends BaseEventStreamTransformation mAms.onTouchInteractionEnd(); sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_END); - mState.startTouchExploring(); } break; default: { // Deliver the event. @@ -717,7 +776,6 @@ public class TouchExplorer extends BaseEventStreamTransformation } mExitGestureDetectionModeDelayed.cancel(); - mState.startTouchExploring(); } /** @@ -731,8 +789,13 @@ public class TouchExplorer extends BaseEventStreamTransformation AccessibilityEvent event = AccessibilityEvent.obtain(type); event.setWindowId(mAms.getActiveWindowId()); accessibilityManager.sendAccessibilityEvent(event); - mState.onInjectedAccessibilityEvent(type); + if (DEBUG) { + Slog.d( + LOG_TAG, + "Sending accessibility event" + AccessibilityEvent.eventTypeToString(type)); + } } + mState.onInjectedAccessibilityEvent(type); } /** @@ -915,6 +978,10 @@ public class TouchExplorer extends BaseEventStreamTransformation MAX_DRAGGING_ANGLE_COS); } + public TouchState getState() { + return mState; + } + /** * Class for delayed exiting from gesture detecting mode. */ @@ -947,8 +1014,7 @@ public class TouchExplorer extends BaseEventStreamTransformation private int mPointerIdBits; private int mPolicyFlags; - public void post(MotionEvent event, boolean touchExplorationInProgress, - int pointerIdBits, int policyFlags) { + public void post(MotionEvent event, int pointerIdBits, int policyFlags) { cancel(); addEvent(event); mPointerIdBits = pointerIdBits; diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/TouchState.java b/services/accessibility/java/com/android/server/accessibility/gestures/TouchState.java index 820c1a794635..17e969a1aa49 100644 --- a/services/accessibility/java/com/android/server/accessibility/gestures/TouchState.java +++ b/services/accessibility/java/com/android/server/accessibility/gestures/TouchState.java @@ -41,20 +41,33 @@ public class TouchState { public static final int ALL_POINTER_ID_BITS = 0xFFFFFFFF; // States that the touch explorer can be in. - public static final int STATE_TOUCH_EXPLORING = 0x00000001; - public static final int STATE_DRAGGING = 0x00000002; - public static final int STATE_DELEGATING = 0x00000003; - public static final int STATE_GESTURE_DETECTING = 0x00000004; - - @IntDef({STATE_TOUCH_EXPLORING, STATE_DRAGGING, STATE_DELEGATING, STATE_GESTURE_DETECTING}) + // In the clear state the user is not touching the screen. + public static final int STATE_CLEAR = 0; + // The user is touching the screen and we are trying to figure out their intent. + // This state gets its name from the TYPE_TOUCH_INTERACTION start and end accessibility events. + public static final int STATE_TOUCH_INTERACTING = 1; + // The user is explicitly exploring the screen. + public static final int STATE_TOUCH_EXPLORING = 2; + // the user is dragging with two fingers. + public static final int STATE_DRAGGING = 3; + // The user is performing some other two finger gesture which we pass through to the view + // hierarchy as a one-finger gesture e.g. two-finger scrolling. + public static final int STATE_DELEGATING = 4; + // The user is performing something that might be a gesture. + public static final int STATE_GESTURE_DETECTING = 5; + + @IntDef({ + STATE_CLEAR, + STATE_TOUCH_INTERACTING, + STATE_TOUCH_EXPLORING, + STATE_DRAGGING, + STATE_DELEGATING, + STATE_GESTURE_DETECTING + }) public @interface State {} // The current state of the touch explorer. - private int mState = STATE_TOUCH_EXPLORING; - // Whether touch exploration is in progress. - // TODO: Add separate states to represent intend detection and actual touch exploration so that - // only one variable describes the state. - private boolean mTouchExplorationInProgress; + private int mState = STATE_CLEAR; // Helper class to track received pointers. // Todo: collapse or hide this class so multiple classes don't modify it. private final ReceivedPointerTracker mReceivedPointerTracker; @@ -69,8 +82,7 @@ public class TouchState { /** Clears the internal shared state. */ public void clear() { - mState = STATE_TOUCH_EXPLORING; - mTouchExplorationInProgress = false; + setState(STATE_CLEAR); // Reset the pointer trackers. mReceivedPointerTracker.clear(); mInjectedPointerTracker.clear(); @@ -94,18 +106,33 @@ public class TouchState { mReceivedPointerTracker.onMotionEvent(rawEvent); } - /** - * Updates the state in response to an accessibility event being sent from TouchExplorer. - * - * @param type The event type. - */ public void onInjectedAccessibilityEvent(int type) { + // The below state transitions go here because the related events are often sent on a + // delay. + // This allows state to accurately reflect the state in the moment. + // TODO: replaced the delayed event senders with delayed state transitions + // so that state transitions trigger events rather than events triggering state + // transitions. switch (type) { + case AccessibilityEvent.TYPE_TOUCH_INTERACTION_START: + startTouchInteracting(); + break; + case AccessibilityEvent.TYPE_TOUCH_INTERACTION_END: + clear(); + break; case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START: - mTouchExplorationInProgress = true; + startTouchExploring(); break; case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END: - mTouchExplorationInProgress = false; + startTouchInteracting(); + break; + case AccessibilityEvent.TYPE_GESTURE_DETECTION_START: + startGestureDetecting(); + break; + case AccessibilityEvent.TYPE_GESTURE_DETECTION_END: + startTouchInteracting(); + break; + default: break; } } @@ -117,6 +144,7 @@ public class TouchState { /** Transitions to a new state. */ public void setState(@State int state) { + if (mState == state) return; if (DEBUG) { Slog.i(LOG_TAG, getStateSymbolicName(mState) + "->" + getStateSymbolicName(state)); } @@ -159,26 +187,32 @@ public class TouchState { setState(STATE_DRAGGING); } - public boolean isTouchExplorationInProgress() { - return mTouchExplorationInProgress; + public boolean isTouchInteracting() { + return mState == STATE_TOUCH_INTERACTING; } - public void setTouchExplorationInProgress(boolean touchExplorationInProgress) { - mTouchExplorationInProgress = touchExplorationInProgress; + /** + * Transitions to the touch interacting state, where we attempt to figure out what the user is + * doing. + */ + public void startTouchInteracting() { + setState(STATE_TOUCH_INTERACTING); } + public boolean isClear() { + return mState == STATE_CLEAR; + } /** Returns a string representation of the current state. */ public String toString() { - return "TouchState { " - + "mState: " - + getStateSymbolicName(mState) - + ", mTouchExplorationInProgress" - + mTouchExplorationInProgress - + " }"; + return "TouchState { " + "mState: " + getStateSymbolicName(mState) + " }"; } /** Returns a string representation of the specified state. */ public static String getStateSymbolicName(int state) { switch (state) { + case STATE_CLEAR: + return "STATE_CLEAR"; + case STATE_TOUCH_INTERACTING: + return "STATE_TOUCH_INTERACTING"; case STATE_TOUCH_EXPLORING: return "STATE_TOUCH_EXPLORING"; case STATE_DRAGGING: diff --git a/services/appprediction/java/com/android/server/appprediction/AppPredictionManagerService.java b/services/appprediction/java/com/android/server/appprediction/AppPredictionManagerService.java index d7e68f896c6c..5844f9873001 100644 --- a/services/appprediction/java/com/android/server/appprediction/AppPredictionManagerService.java +++ b/services/appprediction/java/com/android/server/appprediction/AppPredictionManagerService.java @@ -23,6 +23,7 @@ import static android.content.pm.PackageManager.PERMISSION_GRANTED; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.UserIdInt; import android.app.prediction.AppPredictionContext; import android.app.prediction.AppPredictionSessionId; import android.app.prediction.AppTargetEvent; @@ -61,7 +62,8 @@ public class AppPredictionManagerService extends public AppPredictionManagerService(Context context) { super(context, new FrameworkResourcesServiceNameResolver(context, - com.android.internal.R.string.config_defaultAppPredictionService), null); + com.android.internal.R.string.config_defaultAppPredictionService), null, + PACKAGE_UPDATE_POLICY_NO_REFRESH | PACKAGE_RESTART_POLICY_NO_REFRESH); mActivityTaskManagerInternal = LocalServices.getService(ActivityTaskManagerInternal.class); } @@ -80,6 +82,22 @@ public class AppPredictionManagerService extends getContext().enforceCallingPermission(MANAGE_APP_PREDICTIONS, TAG); } + @Override // from AbstractMasterSystemService + protected void onServicePackageUpdatedLocked(@UserIdInt int userId) { + final AppPredictionPerUserService service = peekServiceForUserLocked(userId); + if (service != null) { + service.onPackageUpdatedLocked(); + } + } + + @Override // from AbstractMasterSystemService + protected void onServicePackageRestartedLocked(@UserIdInt int userId) { + final AppPredictionPerUserService service = peekServiceForUserLocked(userId); + if (service != null) { + service.onPackageRestartedLocked(); + } + } + @Override protected int getMaximumTemporaryServiceDurationMs() { return MAX_TEMP_SERVICE_DURATION_MS; diff --git a/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java b/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java index 03c4542a50d4..4f49fb7578a1 100644 --- a/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java +++ b/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java @@ -251,6 +251,40 @@ public class AppPredictionPerUserService extends // Do nothing, eventually the system will bind to the remote service again... } + void onPackageUpdatedLocked() { + if (isDebug()) { + Slog.v(TAG, "onPackageUpdatedLocked()"); + } + destroyAndRebindRemoteService(); + } + + void onPackageRestartedLocked() { + if (isDebug()) { + Slog.v(TAG, "onPackageRestartedLocked()"); + } + destroyAndRebindRemoteService(); + } + + private void destroyAndRebindRemoteService() { + if (mRemoteService == null) { + return; + } + + if (isDebug()) { + Slog.d(TAG, "Destroying the old remote service."); + } + mRemoteService.destroy(); + mRemoteService = null; + + mRemoteService = getRemoteServiceLocked(); + if (mRemoteService != null) { + if (isDebug()) { + Slog.d(TAG, "Rebinding to the new remote service."); + } + mRemoteService.reconnect(); + } + } + /** * Called after the remote service connected, it's used to restore state from a 'zombie' * service (i.e., after it died). diff --git a/services/appprediction/java/com/android/server/appprediction/RemoteAppPredictionService.java b/services/appprediction/java/com/android/server/appprediction/RemoteAppPredictionService.java index c82e7a012fff..04e0e7f7102f 100644 --- a/services/appprediction/java/com/android/server/appprediction/RemoteAppPredictionService.java +++ b/services/appprediction/java/com/android/server/appprediction/RemoteAppPredictionService.java @@ -135,6 +135,13 @@ public class RemoteAppPredictionService extends } /** + * Schedules a request to bind to the remote service. + */ + public void reconnect() { + super.scheduleBind(); + } + + /** * Failure callback */ public interface RemoteAppPredictionServiceCallbacks diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java index 6b7c3e69e54e..c689ed1c64c7 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java @@ -212,8 +212,7 @@ public final class AutofillManagerService (u, s, t) -> onAugmentedServiceNameChanged(u, s, t)); if (mSupportedSmartSuggestionModes != AutofillManager.FLAG_SMART_SUGGESTION_OFF) { - final UserManager um = getContext().getSystemService(UserManager.class); - final List<UserInfo> users = um.getUsers(); + final List<UserInfo> users = getSupportedUsers(); for (int i = 0; i < users.size(); i++) { final int userId = users.get(i).id; // Must eager load the services so they bind to the augmented autofill service @@ -325,6 +324,11 @@ public final class AutofillManagerService } @Override // from SystemService + public boolean isSupported(UserInfo userInfo) { + return userInfo.isFull() || userInfo.isManagedProfile(); + } + + @Override // from SystemService public void onSwitchUser(int userHandle) { if (sDebug) Slog.d(TAG, "Hiding UI when user switched"); mUi.hideAll(null); diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java index 48f16acc864a..256ca500f5de 100644 --- a/services/autofill/java/com/android/server/autofill/Session.java +++ b/services/autofill/java/com/android/server/autofill/Session.java @@ -2419,6 +2419,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState Slog.v(TAG, "entered on virtual child " + id + ": " + virtualBounds); } + final boolean isSameViewEntered = Objects.equals(mCurrentViewId, viewState.id); // Update the view states first... mCurrentViewId = viewState.id; if (value != null) { @@ -2451,6 +2452,10 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState hideAugmentedAutofillLocked(viewState); } + if (isSameViewEntered) { + return; + } + // If the ViewState is ready to be displayed, onReady() will be called. viewState.update(value, virtualBounds, flags); break; diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java index 5c6258ffe4cb..c8dbb363bc36 100644 --- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java +++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java @@ -147,8 +147,7 @@ public final class ContentCaptureManagerService extends mRequestsHistory = null; } - final UserManager um = getContext().getSystemService(UserManager.class); - final List<UserInfo> users = um.getUsers(); + final List<UserInfo> users = getSupportedUsers(); for (int i = 0; i < users.size(); i++) { final int userId = users.get(i).id; final boolean disabled = !isEnabledBySettings(userId); @@ -174,6 +173,11 @@ public final class ContentCaptureManagerService extends } @Override // from SystemService + public boolean isSupported(UserInfo userInfo) { + return userInfo.isFull() || userInfo.isManagedProfile(); + } + + @Override // from SystemService public void onStart() { publishBinderService(CONTENT_CAPTURE_MANAGER_SERVICE, new ContentCaptureManagerServiceStub()); @@ -336,8 +340,7 @@ public final class ContentCaptureManagerService extends if (verbose) { Slog.v(mTag, "setDisabledByDeviceConfig(): explicitlyEnabled=" + explicitlyEnabled); } - final UserManager um = getContext().getSystemService(UserManager.class); - final List<UserInfo> users = um.getUsers(); + final List<UserInfo> users = getSupportedUsers(); final boolean newDisabledValue; diff --git a/services/core/Android.bp b/services/core/Android.bp index c838c6044e1d..16432212d8e2 100644 --- a/services/core/Android.bp +++ b/services/core/Android.bp @@ -53,7 +53,7 @@ java_library_static { "android.hardware.contexthub-V1.0-java", "android.hidl.manager-V1.2-java", "dnsresolver_aidl_interface-V2-java", - "netd_aidl_interface-V2-java", + "netd_aidl_interface-java", "netd_event_listener_interface-java", ], } diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index e67ccc42f1e2..2a2dc3d3cdb6 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -1102,7 +1102,7 @@ public class ConnectivityService extends IConnectivityManager.Stub mSettingsObserver = new SettingsObserver(mContext, mHandler); registerSettingsCallbacks(); - final DataConnectionStats dataConnectionStats = new DataConnectionStats(mContext); + final DataConnectionStats dataConnectionStats = new DataConnectionStats(mContext, mHandler); dataConnectionStats.startMonitoring(); mKeepaliveTracker = new KeepaliveTracker(mContext, mHandler); @@ -4551,7 +4551,7 @@ public class ConnectivityService extends IConnectivityManager.Stub Slog.w(TAG, "VPN for user " + user + " not ready yet. Skipping lockdown"); return false; } - setLockdownTracker(new LockdownVpnTracker(mContext, mNMS, this, vpn, profile)); + setLockdownTracker(new LockdownVpnTracker(mContext, this, mHandler, vpn, profile)); } else { setLockdownTracker(null); } diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java index 59e0a28f2ae1..9efaad848ccc 100644 --- a/services/core/java/com/android/server/NetworkManagementService.java +++ b/services/core/java/com/android/server/NetworkManagementService.java @@ -1008,11 +1008,15 @@ public class NetworkManagementService extends INetworkManagementService.Stub { @Override public void startTethering(String[] dhcpRange) { + startTetheringWithConfiguration(true, dhcpRange); + } + + @Override + public void startTetheringWithConfiguration(boolean usingLegacyDnsProxy, String[] dhcpRange) { mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); // an odd number of addrs will fail - try { - mNetdService.tetherStart(dhcpRange); + mNetdService.tetherStartWithConfiguration(usingLegacyDnsProxy, dhcpRange); } catch (RemoteException | ServiceSpecificException e) { throw new IllegalStateException(e); } diff --git a/services/core/java/com/android/server/PackageWatchdog.java b/services/core/java/com/android/server/PackageWatchdog.java index ea3dd3d4ba8d..73ec5614b2a3 100644 --- a/services/core/java/com/android/server/PackageWatchdog.java +++ b/services/core/java/com/android/server/PackageWatchdog.java @@ -131,6 +131,10 @@ public class PackageWatchdog { @GuardedBy("mLock") private long mUptimeAtLastStateSync; + private final Runnable mSyncRequests = this::syncRequests; + private final Runnable mSyncStateWithScheduledReason = this::syncStateWithScheduledReason; + private final Runnable mSaveToFile = this::saveToFile; + private PackageWatchdog(Context context) { // Needs to be constructed inline this(context, new AtomicFile( @@ -349,7 +353,7 @@ public class PackageWatchdog { // Must only run synchronous tasks as this runs on the ShutdownThread and no other // thread is guaranteed to run during shutdown. if (!mAllObservers.isEmpty()) { - mLongTaskHandler.removeCallbacks(this::saveToFileAsync); + mLongTaskHandler.removeCallbacks(mSaveToFile); pruneObserversLocked(); saveToFile(); Slog.i(TAG, "Last write to update package durations"); @@ -424,8 +428,8 @@ public class PackageWatchdog { * Serializes and syncs health check requests with the {@link ExplicitHealthCheckController}. */ private void syncRequestsAsync() { - mShortTaskHandler.removeCallbacks(this::syncRequests); - mShortTaskHandler.post(this::syncRequests); + mShortTaskHandler.removeCallbacks(mSyncRequests); + mShortTaskHandler.post(mSyncRequests); } /** @@ -569,14 +573,14 @@ public class PackageWatchdog { @GuardedBy("mLock") private void scheduleNextSyncStateLocked() { long durationMs = getNextStateSyncMillisLocked(); - mShortTaskHandler.removeCallbacks(this::syncStateWithScheduledReason); + mShortTaskHandler.removeCallbacks(mSyncStateWithScheduledReason); if (durationMs == Long.MAX_VALUE) { Slog.i(TAG, "Cancelling state sync, nothing to sync"); mUptimeAtLastStateSync = 0; } else { Slog.i(TAG, "Scheduling next state sync in " + durationMs + "ms"); mUptimeAtLastStateSync = SystemClock.uptimeMillis(); - mShortTaskHandler.postDelayed(this::syncStateWithScheduledReason, durationMs); + mShortTaskHandler.postDelayed(mSyncStateWithScheduledReason, durationMs); } } @@ -802,8 +806,8 @@ public class PackageWatchdog { } private void saveToFileAsync() { - if (!mLongTaskHandler.hasCallbacks(this::saveToFile)) { - mLongTaskHandler.post(this::saveToFile); + if (!mLongTaskHandler.hasCallbacks(mSaveToFile)) { + mLongTaskHandler.post(mSaveToFile); } } diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java index 4fab7c16c9ec..8367e89058cf 100644 --- a/services/core/java/com/android/server/StorageManagerService.java +++ b/services/core/java/com/android/server/StorageManagerService.java @@ -140,6 +140,7 @@ import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.Preconditions; import com.android.internal.widget.LockPatternUtils; import com.android.server.storage.AppFuseBridge; +import com.android.server.storage.StorageSessionController; import com.android.server.wm.ActivityTaskManagerInternal; import com.android.server.wm.ActivityTaskManagerInternal.ScreenObserver; @@ -498,6 +499,9 @@ class StorageManagerService extends IStorageManager.Stub private final StorageManagerInternalImpl mStorageManagerInternal = new StorageManagerInternalImpl(); + // Not guarded by a lock. + private final StorageSessionController mStorageSessionController; + class ObbState implements IBinder.DeathRecipient { public ObbState(String rawPath, String canonicalPath, int callingUid, IObbActionListener token, int nonce, String volId) { @@ -647,12 +651,20 @@ class StorageManagerService extends IStorageManager.Stub Slog.i(TAG, "Ignoring mount " + vol.getId() + " due to policy"); break; } - mount(vol); + + // TODO(b/135341433): Remove paranoid logging when FUSE is stable + Slog.i(TAG, "Mounting volume " + vol); + // TODO(b/135341433): Update to use new vold API that gets or mounts fuse fd + // Ensure that we can pass user of a volume to the new API + mStorageSessionController.onVolumeMounted(mCurrentUserId, mount(vol), vol); + Slog.i(TAG, "Mounted volume " + vol); + break; } case H_VOLUME_UNMOUNT: { final VolumeInfo vol = (VolumeInfo) msg.obj; unmount(vol); + mStorageSessionController.onVolumeUnmounted(mCurrentUserId, vol); break; } case H_VOLUME_BROADCAST: { @@ -733,6 +745,7 @@ class StorageManagerService extends IStorageManager.Stub } } mVold.onUserRemoved(userId); + mStorageSessionController.onUserRemoved(userId); } } catch (Exception e) { Slog.wtf(TAG, e); @@ -951,7 +964,10 @@ class StorageManagerService extends IStorageManager.Stub } try { + // TODO(b/135341433): Remove paranoid logging when FUSE is stable + Slog.i(TAG, "Resetting vold"); mVold.reset(); + Slog.i(TAG, "Reset vold"); // Tell vold about all existing and started users for (UserInfo user : users) { @@ -976,6 +992,7 @@ class StorageManagerService extends IStorageManager.Stub // staging area is ready so it's ready for zygote-forked apps to // bind mount against. try { + mStorageSessionController.onUserStarted(userId); mVold.onUserStarted(userId); mStoraged.onUserStarted(userId); } catch (Exception e) { @@ -1516,6 +1533,12 @@ class StorageManagerService extends IStorageManager.Stub // Add OBB Action Handler to StorageManagerService thread. mObbActionHandler = new ObbActionHandler(IoThread.get().getLooper()); + mStorageSessionController = new StorageSessionController(mContext, + userId -> { + Slog.i(TAG, "Storage session ended for user: " + userId + ". Resetting..."); + mHandler.obtainMessage(H_RESET).sendToTarget(); + }); + // Initialize the last-fstrim tracking if necessary File dataDir = Environment.getDataDirectory(); File systemDir = new File(dataDir, "system"); @@ -1814,11 +1837,18 @@ class StorageManagerService extends IStorageManager.Stub mount(vol); } - private void mount(VolumeInfo vol) { + private FileDescriptor mount(VolumeInfo vol) { try { - mVold.mount(vol.id, vol.mountFlags, vol.mountUserId); + // TODO(b/135341433): Now, emulated (and private?) volumes are shared across users + // This means the mountUserId on such volumes is USER_NULL. This breaks fuse which + // requires a valid user to mount a volume. Create individual volumes per user in vold + // and remove this property check + int userId = SystemProperties.getBoolean("persist.sys.fuse", false) + ? mCurrentUserId : vol.mountUserId; + return mVold.mount(vol.id, vol.mountFlags, userId); } catch (Exception e) { Slog.wtf(TAG, e); + return null; } } diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 7bc2e6d647be..8eb5d9bcb5b8 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -2318,9 +2318,8 @@ public final class ActiveServices { return true; } + /** @return {@code true} if the restart is scheduled. */ private final boolean scheduleServiceRestartLocked(ServiceRecord r, boolean allowCancel) { - boolean canceled = false; - if (mAm.mAtmInternal.isShuttingDown()) { Slog.w(TAG, "Not scheduling restart of crashed service " + r.shortInstanceName + " - system is shutting down"); @@ -2337,10 +2336,12 @@ public final class ActiveServices { final long now = SystemClock.uptimeMillis(); + final String reason; if ((r.serviceInfo.applicationInfo.flags &ApplicationInfo.FLAG_PERSISTENT) == 0) { long minDuration = mAm.mConstants.SERVICE_RESTART_DURATION; long resetTime = mAm.mConstants.SERVICE_RESET_RUN_DURATION; + boolean canceled = false; // Any delivered but not yet finished starts should be put back // on the pending list. @@ -2367,6 +2368,17 @@ public final class ActiveServices { r.deliveredStarts.clear(); } + if (allowCancel) { + final boolean shouldStop = r.canStopIfKilled(canceled); + if (shouldStop && !r.hasAutoCreateConnections()) { + // Nothing to restart. + return false; + } + reason = (r.startRequested && !shouldStop) ? "start-requested" : "connection"; + } else { + reason = "always"; + } + r.totalRestartCount++; if (r.restartDelay == 0) { r.restartCount++; @@ -2418,6 +2430,7 @@ public final class ActiveServices { r.restartCount = 0; r.restartDelay = 0; r.nextRestartTime = now; + reason = "persistent"; } if (!mRestartingServices.contains(r)) { @@ -2432,11 +2445,11 @@ public final class ActiveServices { mAm.mHandler.postAtTime(r.restarter, r.nextRestartTime); r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay; Slog.w(TAG, "Scheduling restart of crashed service " - + r.shortInstanceName + " in " + r.restartDelay + "ms"); + + r.shortInstanceName + " in " + r.restartDelay + "ms for " + reason); EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART, r.userId, r.shortInstanceName, r.restartDelay); - return canceled; + return true; } final void performServiceRestartLocked(ServiceRecord r) { @@ -3651,22 +3664,21 @@ public final class ActiveServices { || !mAm.mUserController.isUserRunning(sr.userId, 0)) { bringDownServiceLocked(sr); } else { - boolean canceled = scheduleServiceRestartLocked(sr, true); + final boolean scheduled = scheduleServiceRestartLocked(sr, true /* allowCancel */); // Should the service remain running? Note that in the // extreme case of so many attempts to deliver a command // that it failed we also will stop it here. - if (sr.startRequested && (sr.stopIfKilled || canceled)) { - if (sr.pendingStarts.size() == 0) { - sr.startRequested = false; - if (sr.tracker != null) { - sr.tracker.setStarted(false, mAm.mProcessStats.getMemFactorLocked(), - SystemClock.uptimeMillis()); - } - if (!sr.hasAutoCreateConnections()) { - // Whoops, no reason to restart! - bringDownServiceLocked(sr); - } + if (!scheduled) { + bringDownServiceLocked(sr); + } else if (sr.canStopIfKilled(false /* isStartCanceled */)) { + // Update to stopped state because the explicit start is gone. The service is + // scheduled to restart for other reason (e.g. connections) so we don't bring + // down it. + sr.startRequested = false; + if (sr.tracker != null) { + sr.tracker.setStarted(false, mAm.mProcessStats.getMemFactorLocked(), + SystemClock.uptimeMillis()); } } } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 84f5530f31bc..3dc33f844092 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -4644,7 +4644,7 @@ public class ActivityManagerService extends IActivityManager.Stub } boolean didSomething = mProcessList.killPackageProcessesLocked(packageName, appId, userId, - ProcessList.INVALID_ADJ, callerWillRestart, true /* allowRestart */, doit, + ProcessList.INVALID_ADJ, callerWillRestart, false /* allowRestart */, doit, evenPersistent, true /* setRemoved */, packageName == null ? ("stop user " + userId) : ("stop " + packageName)); @@ -5268,7 +5268,7 @@ public class ActivityManagerService extends IActivityManager.Stub storageManager.commitChanges(); } catch (Exception e) { PowerManager pm = (PowerManager) - mInjector.getContext().getSystemService(Context.POWER_SERVICE); + mContext.getSystemService(Context.POWER_SERVICE); pm.reboot("Checkpoint commit failed"); } @@ -8285,8 +8285,13 @@ public class ActivityManagerService extends IActivityManager.Stub if (shareDescription != null) { triggerShellBugreport.putExtra(EXTRA_DESCRIPTION, shareDescription); } - // Send broadcast to shell to trigger bugreport using Bugreport API - mContext.sendBroadcast(triggerShellBugreport); + final long identity = Binder.clearCallingIdentity(); + try { + // Send broadcast to shell to trigger bugreport using Bugreport API + mContext.sendBroadcast(triggerShellBugreport); + } finally { + Binder.restoreCallingIdentity(identity); + } } else { SystemProperties.set("dumpstate.options", type); SystemProperties.set("ctl.start", "bugreport"); @@ -9154,10 +9159,10 @@ public class ActivityManagerService extends IActivityManager.Stub } t.traceEnd(); } - // Automotive will re-start system user as background (so its unlocked), then start a - // full user as foreground. Hence, we need to skip some steps that would otherwise be - // done twice. - // TODO(b/138956267): this workdound shouldn't be necessary once we move the + + // On Automotive, at this point the system user has already been started and unlocked, + // and some of the tasks we do here have already been done. So skip those in that case. + // TODO(b/132262830): this workdound shouldn't be necessary once we move the // headless-user start logic to UserManager-land final boolean bootingSystemUser = currentUserId == UserHandle.USER_SYSTEM; @@ -13919,9 +13924,9 @@ public class ActivityManagerService extends IActivityManager.Stub // Remove published content providers. for (int i = app.pubProviders.size() - 1; i >= 0; i--) { ContentProviderRecord cpr = app.pubProviders.valueAt(i); - final boolean always = app.bad || !allowRestart; - boolean inLaunching = removeDyingProviderLocked(app, cpr, always); - if ((inLaunching || always) && cpr.hasConnectionOrHandle()) { + final boolean alwaysRemove = app.bad || !allowRestart; + final boolean inLaunching = removeDyingProviderLocked(app, cpr, alwaysRemove); + if (!alwaysRemove && inLaunching && cpr.hasConnectionOrHandle()) { // We left the provider in the launching list, need to // restart it. restart = true; diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java index 8619ad5d3357..8c038aaab0b5 100644 --- a/services/core/java/com/android/server/am/ServiceRecord.java +++ b/services/core/java/com/android/server/am/ServiceRecord.java @@ -19,9 +19,7 @@ package com.android.server.am; import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; -import android.app.INotificationManager; import android.app.Notification; -import android.app.NotificationManager; import android.app.PendingIntent; import android.content.ComponentName; import android.content.Context; @@ -33,7 +31,6 @@ import android.net.Uri; import android.os.Binder; import android.os.Build; import android.os.IBinder; -import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; import android.provider.Settings; @@ -623,6 +620,14 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN } } + /** + * @return {@code true} if the killed service which was started by {@link Context#startService} + * has no reason to start again. Note this condition doesn't consider the bindings. + */ + boolean canStopIfKilled(boolean isStartCanceled) { + return startRequested && (stopIfKilled || isStartCanceled) && pendingStarts.isEmpty(); + } + void updateHasBindingWhitelistingBgActivityStarts() { boolean hasWhitelistingBinding = false; for (int conni = connections.size() - 1; conni >= 0; conni--) { diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java index 2b4cc3cc3bd5..5fe72ddfaf91 100644 --- a/services/core/java/com/android/server/am/UserController.java +++ b/services/core/java/com/android/server/am/UserController.java @@ -1755,9 +1755,10 @@ class UserController implements Handler.Callback { for (int i = 0; i < startedUsers.size(); i++) { UserState uss = startedUsers.valueAt(i); if (systemUserFinishedBooting && uss.mHandle.isSystem()) { - // Automotive will re-start system user as background, which in turn will call - // finishUserboot(). Hence, we need to check it here to avoid calling it twice. - // TODO(b/138956267): this workdound shouldn't be necessary once we move the + // On Automotive, at this point the system user has already been started and + // unlocked, and some of the tasks we do here have already been done. So skip those + // in that case. + // TODO(b/132262830): this workdound shouldn't be necessary once we move the // headless-user start logic to UserManager-land Slog.d(TAG, "sendBootCompleted(): skipping on non-current system user"); continue; diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java index 6d6a148c105d..cc8e3f097450 100644 --- a/services/core/java/com/android/server/appop/AppOpsService.java +++ b/services/core/java/com/android/server/appop/AppOpsService.java @@ -2973,28 +2973,49 @@ public class AppOpsService extends IAppOpsService.Stub { out.startTag(null, "app-ops"); out.attribute(null, "v", String.valueOf(CURRENT_VERSION)); + SparseArray<SparseIntArray> uidStatesClone; synchronized (this) { + uidStatesClone = new SparseArray<>(mUidStates.size()); + final int uidStateCount = mUidStates.size(); - for (int i = 0; i < uidStateCount; i++) { - UidState uidState = mUidStates.valueAt(i); - if (uidState.opModes != null && uidState.opModes.size() > 0) { - out.startTag(null, "uid"); - out.attribute(null, "n", Integer.toString(uidState.uid)); - SparseIntArray uidOpModes = uidState.opModes; - final int opCount = uidOpModes.size(); - for (int j = 0; j < opCount; j++) { - final int op = uidOpModes.keyAt(j); - final int mode = uidOpModes.valueAt(j); - out.startTag(null, "op"); - out.attribute(null, "n", Integer.toString(op)); - out.attribute(null, "m", Integer.toString(mode)); - out.endTag(null, "op"); + for (int uidStateNum = 0; uidStateNum < uidStateCount; uidStateNum++) { + UidState uidState = mUidStates.valueAt(uidStateNum); + int uid = mUidStates.keyAt(uidStateNum); + + SparseIntArray opModes = uidState.opModes; + if (opModes != null && opModes.size() > 0) { + uidStatesClone.put(uid, new SparseIntArray(opModes.size())); + + final int opCount = opModes.size(); + for (int opCountNum = 0; opCountNum < opCount; opCountNum++) { + uidStatesClone.get(uid).put( + opModes.keyAt(opCountNum), + opModes.valueAt(opCountNum)); } - out.endTag(null, "uid"); } } } + final int uidStateCount = uidStatesClone.size(); + for (int uidStateNum = 0; uidStateNum < uidStateCount; uidStateNum++) { + SparseIntArray opModes = uidStatesClone.valueAt(uidStateNum); + if (opModes != null && opModes.size() > 0) { + out.startTag(null, "uid"); + out.attribute(null, "n", + Integer.toString(uidStatesClone.keyAt(uidStateNum))); + final int opCount = opModes.size(); + for (int opCountNum = 0; opCountNum < opCount; opCountNum++) { + final int op = opModes.keyAt(opCountNum); + final int mode = opModes.valueAt(opCountNum); + out.startTag(null, "op"); + out.attribute(null, "n", Integer.toString(op)); + out.attribute(null, "m", Integer.toString(mode)); + out.endTag(null, "op"); + } + out.endTag(null, "uid"); + } + } + if (allOps != null) { String lastPkg = null; for (int i=0; i<allOps.size(); i++) { diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java index 24e6a75e6844..4af3627427d2 100644 --- a/services/core/java/com/android/server/biometrics/BiometricService.java +++ b/services/core/java/com/android/server/biometrics/BiometricService.java @@ -514,7 +514,6 @@ public class BiometricService extends SystemService { } public boolean getFaceEnabledForApps(int userId) { - Slog.e(TAG, "getFaceEnabledForApps: " + userId, new Exception()); if (!mFaceEnabledForApps.containsKey(userId)) { onChange(true /* selfChange */, FACE_UNLOCK_APP_ENABLED, userId); } diff --git a/services/core/java/com/android/server/compat/CompatConfig.java b/services/core/java/com/android/server/compat/CompatConfig.java index 044e41789bb2..027e2fb5ccaa 100644 --- a/services/core/java/com/android/server/compat/CompatConfig.java +++ b/services/core/java/com/android/server/compat/CompatConfig.java @@ -47,11 +47,10 @@ import javax.xml.datatype.DatatypeConfigurationException; public final class CompatConfig { private static final String TAG = "CompatConfig"; - private static final String CONFIG_FILE_SUFFIX = "platform_compat_config.xml"; private static final CompatConfig sInstance = new CompatConfig().initConfigFromLib( Environment.buildPath( - Environment.getRootDirectory(), "etc", "sysconfig")); + Environment.getRootDirectory(), "etc", "compatconfig")); @GuardedBy("mChanges") private final LongSparseArray<CompatChange> mChanges = new LongSparseArray<>(); @@ -212,10 +211,9 @@ public final class CompatConfig { return this; } for (File f : libraryDir.listFiles()) { + Slog.d(TAG, "Found a config file: " + f.getPath()); //TODO(b/138222363): Handle duplicate ids across config files. - if (f.getPath().endsWith(CONFIG_FILE_SUFFIX)) { - readConfig(f); - } + readConfig(f); } return this; } @@ -223,7 +221,7 @@ public final class CompatConfig { private void readConfig(File configFile) { try (InputStream in = new BufferedInputStream(new FileInputStream(configFile))) { for (Change change : XmlParser.read(in).getCompatChange()) { - Slog.w(TAG, "Adding: " + change.toString()); + Slog.d(TAG, "Adding: " + change.toString()); addChange(new CompatChange(change)); } } catch (IOException | DatatypeConfigurationException | XmlPullParserException e) { diff --git a/services/core/java/com/android/server/connectivity/DataConnectionStats.java b/services/core/java/com/android/server/connectivity/DataConnectionStats.java index 4990ea136246..27f11ffa60ce 100644 --- a/services/core/java/com/android/server/connectivity/DataConnectionStats.java +++ b/services/core/java/com/android/server/connectivity/DataConnectionStats.java @@ -21,6 +21,8 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.net.ConnectivityManager; +import android.os.Handler; +import android.os.Looper; import android.os.RemoteException; import android.telephony.PhoneStateListener; import android.telephony.ServiceState; @@ -39,15 +41,19 @@ public class DataConnectionStats extends BroadcastReceiver { private final Context mContext; private final IBatteryStats mBatteryStats; + private final Handler mListenerHandler; + private final PhoneStateListener mPhoneStateListener; private IccCardConstants.State mSimState = IccCardConstants.State.READY; private SignalStrength mSignalStrength; private ServiceState mServiceState; private int mDataState = TelephonyManager.DATA_DISCONNECTED; - public DataConnectionStats(Context context) { + public DataConnectionStats(Context context, Handler listenerHandler) { mContext = context; mBatteryStats = BatteryStatsService.getService(); + mListenerHandler = listenerHandler; + mPhoneStateListener = new PhoneStateListenerImpl(listenerHandler.getLooper()); } public void startMonitoring() { @@ -63,7 +69,7 @@ public class DataConnectionStats extends BroadcastReceiver { filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED); filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); filter.addAction(ConnectivityManager.INET_CONDITION_ACTION); - mContext.registerReceiver(this, filter); + mContext.registerReceiver(this, filter, null /* broadcastPermission */, mListenerHandler); } @Override @@ -129,7 +135,11 @@ public class DataConnectionStats extends BroadcastReceiver { && mServiceState.getState() != ServiceState.STATE_POWER_OFF; } - private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() { + private class PhoneStateListenerImpl extends PhoneStateListener { + PhoneStateListenerImpl(Looper looper) { + super(looper); + } + @Override public void onSignalStrengthsChanged(SignalStrength signalStrength) { mSignalStrength = signalStrength; diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java index 86d12124785d..5fd5c4bebb2a 100644 --- a/services/core/java/com/android/server/connectivity/Tethering.java +++ b/services/core/java/com/android/server/connectivity/Tethering.java @@ -455,7 +455,20 @@ public class Tethering extends BaseNetworkObserver { @Override public void onServiceConnected(int profile, BluetoothProfile proxy) { - ((BluetoothPan) proxy).setBluetoothTethering(enable); + // Clear identify is fine because caller already pass tethering permission at + // ConnectivityService#startTethering()(or stopTethering) before the control comes + // here. Bluetooth will check tethering permission again that there is + // Context#getOpPackageName() under BluetoothPan#setBluetoothTethering() to get + // caller's package name for permission check. + // Calling BluetoothPan#setBluetoothTethering() here means the package name always + // be system server. If calling identity is not cleared, that package's uid might + // not match calling uid and end up in permission denied. + final long identityToken = Binder.clearCallingIdentity(); + try { + ((BluetoothPan) proxy).setBluetoothTethering(enable); + } finally { + Binder.restoreCallingIdentity(identityToken); + } // TODO: Enabling bluetooth tethering can fail asynchronously here. // We should figure out a way to bubble up that failure instead of sending success. final int result = (((BluetoothPan) proxy).isTetheringOn() == enable) diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java index 4d5dc6aba937..2b849d69ae1c 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -297,6 +297,11 @@ public class HdmiControlService extends SystemService { mHdmiControlBroadcastReceiver = new HdmiControlBroadcastReceiver(); @Nullable + // Save callback when the device is still under logcial address allocation + // Invoke once new local device is ready. + private IHdmiControlCallback mDisplayStatusCallback = null; + + @Nullable private HdmiCecController mCecController; // HDMI port information. Stored in the unmodifiable list to keep the static information @@ -763,6 +768,11 @@ public class HdmiControlService extends SystemService { // Address allocation completed for all devices. Notify each device. if (allocatingDevices.size() == ++finished[0]) { mAddressAllocated = true; + // Reinvoke the saved display status callback once the local device is ready. + if (mDisplayStatusCallback != null) { + queryDisplayStatus(mDisplayStatusCallback); + mDisplayStatusCallback = null; + } if (initiatedBy != INITIATED_BY_HOTPLUG) { // In case of the hotplug we don't call onInitializeCecComplete() // since we reallocate the logical address only. @@ -2192,6 +2202,13 @@ public class HdmiControlService extends SystemService { @ServiceThreadOnly private void queryDisplayStatus(final IHdmiControlCallback callback) { assertRunOnServiceThread(); + if (!mAddressAllocated) { + mDisplayStatusCallback = callback; + Slog.d(TAG, "Local device is under address allocation. " + + "Queue display callback for later process."); + return; + } + HdmiCecLocalDevicePlayback source = playback(); if (source == null) { Slog.w(TAG, "Local playback device not available"); diff --git a/services/core/java/com/android/server/infra/AbstractMasterSystemService.java b/services/core/java/com/android/server/infra/AbstractMasterSystemService.java index 9782f30d3074..d71ffb770cc3 100644 --- a/services/core/java/com/android/server/infra/AbstractMasterSystemService.java +++ b/services/core/java/com/android/server/infra/AbstractMasterSystemService.java @@ -48,6 +48,7 @@ import com.android.server.SystemService; import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.ArrayList; import java.util.List; /** @@ -79,7 +80,7 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem S extends AbstractPerUserSystemService<S, M>> extends SystemService { /** On a package update, does not refresh the per-user service in the cache. */ - public static final int PACKAGE_UPDATE_POLICY_NO_REFRESH = 0; + public static final int PACKAGE_UPDATE_POLICY_NO_REFRESH = 0x00000001; /** * On a package update, removes any existing per-user services in the cache. @@ -87,20 +88,40 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem * <p>This does not immediately recreate these services. It is assumed they will be recreated * for the next user request. */ - public static final int PACKAGE_UPDATE_POLICY_REFRESH_LAZY = 1; + public static final int PACKAGE_UPDATE_POLICY_REFRESH_LAZY = 0x00000002; /** * On a package update, removes and recreates any existing per-user services in the cache. */ - public static final int PACKAGE_UPDATE_POLICY_REFRESH_EAGER = 2; + public static final int PACKAGE_UPDATE_POLICY_REFRESH_EAGER = 0x00000004; - @IntDef(flag = true, prefix = { "PACKAGE_UPDATE_POLICY_" }, value = { + /** On a package restart, does not refresh the per-user service in the cache. */ + public static final int PACKAGE_RESTART_POLICY_NO_REFRESH = 0x00000010; + + /** + * On a package restart, removes any existing per-user services in the cache. + * + * <p>This does not immediately recreate these services. It is assumed they will be recreated + * for the next user request. + */ + public static final int PACKAGE_RESTART_POLICY_REFRESH_LAZY = 0x00000020; + + /** + * On a package restart, removes and recreates any existing per-user services in the cache. + */ + public static final int PACKAGE_RESTART_POLICY_REFRESH_EAGER = 0x00000040; + + @IntDef(flag = true, prefix = { "PACKAGE_" }, value = { PACKAGE_UPDATE_POLICY_NO_REFRESH, PACKAGE_UPDATE_POLICY_REFRESH_LAZY, - PACKAGE_UPDATE_POLICY_REFRESH_EAGER + PACKAGE_UPDATE_POLICY_REFRESH_EAGER, + PACKAGE_RESTART_POLICY_NO_REFRESH, + PACKAGE_RESTART_POLICY_REFRESH_LAZY, + PACKAGE_RESTART_POLICY_REFRESH_EAGER }) + @Retention(RetentionPolicy.SOURCE) - public @interface PackageUpdatePolicy {} + public @interface ServicePackagePolicyFlags {} /** * Log tag @@ -153,12 +174,10 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem private final SparseArray<S> mServicesCache = new SparseArray<>(); /** - * Whether the per-user service should be removed from the cache when its apk is updated. - * - * <p>One of {@link #PACKAGE_UPDATE_POLICY_NO_REFRESH}, - * {@link #PACKAGE_UPDATE_POLICY_REFRESH_LAZY} or {@link #PACKAGE_UPDATE_POLICY_REFRESH_EAGER}. + * Value that determines whether the per-user service should be removed from the cache when its + * apk is updated or restarted. */ - private final @PackageUpdatePolicy int mPackageUpdatePolicy; + private final @ServicePackagePolicyFlags int mServicePackagePolicyFlags; /** * Name of the service packages whose APK are being updated, keyed by user id. @@ -167,6 +186,12 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem private SparseArray<String> mUpdatingPackageNames; /** + * Lazy-loadable reference to {@link UserManagerInternal}. + */ + @Nullable + private UserManagerInternal mUm; + + /** * Default constructor. * * <p>When using this constructor, the {@link AbstractPerUserSystemService} is removed from @@ -184,11 +209,11 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem @Nullable ServiceNameResolver serviceNameResolver, @Nullable String disallowProperty) { this(context, serviceNameResolver, disallowProperty, - /*packageUpdatePolicy=*/ PACKAGE_UPDATE_POLICY_REFRESH_LAZY); + PACKAGE_UPDATE_POLICY_REFRESH_LAZY | PACKAGE_RESTART_POLICY_REFRESH_LAZY); } /** - * Full constructor. + * Full Constructor. * * @param context system context. * @param serviceNameResolver resolver for @@ -197,19 +222,32 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem * @param disallowProperty when not {@code null}, defines a {@link UserManager} restriction that * disables the service. <b>NOTE: </b> you'll also need to add it to * {@code UserRestrictionsUtils.USER_RESTRICTIONS}. - * @param packageUpdatePolicy when {@link #PACKAGE_UPDATE_POLICY_REFRESH_LAZY}, the - * {@link AbstractPerUserSystemService} is removed from the cache when the service - * package is updated; when {@link #PACKAGE_UPDATE_POLICY_REFRESH_EAGER}, the - * {@link AbstractPerUserSystemService} is removed from the cache and immediately - * re-added when the service package is updated; when - * {@link #PACKAGE_UPDATE_POLICY_NO_REFRESH}, the service is untouched during the update. + * @param servicePackagePolicyFlags a combination of + * {@link #PACKAGE_UPDATE_POLICY_NO_REFRESH}, + * {@link #PACKAGE_UPDATE_POLICY_REFRESH_LAZY}, + * {@link #PACKAGE_UPDATE_POLICY_REFRESH_EAGER}, + * {@link #PACKAGE_RESTART_POLICY_NO_REFRESH}, + * {@link #PACKAGE_RESTART_POLICY_REFRESH_LAZY} or + * {@link #PACKAGE_RESTART_POLICY_REFRESH_EAGER} */ protected AbstractMasterSystemService(@NonNull Context context, - @Nullable ServiceNameResolver serviceNameResolver, - @Nullable String disallowProperty, @PackageUpdatePolicy int packageUpdatePolicy) { + @Nullable ServiceNameResolver serviceNameResolver, @Nullable String disallowProperty, + @ServicePackagePolicyFlags int servicePackagePolicyFlags) { super(context); - mPackageUpdatePolicy = packageUpdatePolicy; + final int updatePolicyMask = PACKAGE_UPDATE_POLICY_NO_REFRESH + | PACKAGE_UPDATE_POLICY_REFRESH_LAZY | PACKAGE_UPDATE_POLICY_REFRESH_EAGER; + if ((servicePackagePolicyFlags & updatePolicyMask) == 0) { + // If the package update policy is not set, add the default flag + servicePackagePolicyFlags |= PACKAGE_UPDATE_POLICY_REFRESH_LAZY; + } + final int restartPolicyMask = PACKAGE_RESTART_POLICY_NO_REFRESH + | PACKAGE_RESTART_POLICY_REFRESH_LAZY | PACKAGE_RESTART_POLICY_REFRESH_EAGER; + if ((servicePackagePolicyFlags & restartPolicyMask) == 0) { + // If the package restart policy is not set, add the default flag + servicePackagePolicyFlags |= PACKAGE_RESTART_POLICY_REFRESH_LAZY; + } + mServicePackagePolicyFlags = servicePackagePolicyFlags; mServiceNameResolver = serviceNameResolver; if (mServiceNameResolver != null) { @@ -222,9 +260,8 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem } else { mDisabledByUserRestriction = new SparseBooleanArray(); // Hookup with UserManager to disable service when necessary. - final UserManager um = context.getSystemService(UserManager.class); - final UserManagerInternal umi = LocalServices.getService(UserManagerInternal.class); - final List<UserInfo> users = um.getUsers(); + final UserManagerInternal umi = getUserManagerInternal(); + final List<UserInfo> users = getSupportedUsers(); for (int i = 0; i < users.size(); i++) { final int userId = users.get(i).id; final boolean disabled = umi.getUserRestriction(userId, disallowProperty); @@ -606,6 +643,20 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem } /** + * Called after the package data that provides the service for the given user is cleared. + */ + protected void onServicePackageDataClearedLocked(@UserIdInt int userId) { + if (verbose) Slog.v(mTag, "onServicePackageDataCleared(" + userId + ")"); + } + + /** + * Called after the package that provides the service for the given user is restarted. + */ + protected void onServicePackageRestartedLocked(@UserIdInt int userId) { + if (verbose) Slog.v(mTag, "onServicePackageRestarted(" + userId + ")"); + } + + /** * Called after the service is removed from the cache. */ @SuppressWarnings("unused") @@ -649,6 +700,36 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem } /** + * Gets a cached reference to {@link UserManagerInternal}. + */ + @NonNull + protected UserManagerInternal getUserManagerInternal() { + if (mUm == null) { + if (verbose) Slog.v(mTag, "lazy-loading UserManagerInternal"); + mUm = LocalServices.getService(UserManagerInternal.class); + } + return mUm; + } + + /** + * Gets a list of all supported users (i.e., those that pass the {@link #isSupported(UserInfo)} + * check). + */ + @NonNull + protected List<UserInfo> getSupportedUsers() { + final UserInfo[] allUsers = getUserManagerInternal().getUserInfos(); + final int size = allUsers.length; + final List<UserInfo> supportedUsers = new ArrayList<>(size); + for (int i = 0; i < size; i++) { + final UserInfo userInfo = allUsers[i]; + if (isSupported(userInfo)) { + supportedUsers.add(userInfo); + } + } + return supportedUsers; + } + + /** * Asserts that the given package name is owned by the UID making this call. * * @throws SecurityException when it's not... @@ -677,15 +758,14 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem final int size = mServicesCache.size(); pw.print(prefix); pw.print("Debug: "); pw.print(realDebug); pw.print(" Verbose: "); pw.println(realVerbose); - pw.print("Refresh on package update: "); pw.println(mPackageUpdatePolicy); + pw.print("Package policy flags: "); pw.println(mServicePackagePolicyFlags); if (mUpdatingPackageNames != null) { pw.print("Packages being updated: "); pw.println(mUpdatingPackageNames); } if (mServiceNameResolver != null) { pw.print(prefix); pw.print("Name resolver: "); mServiceNameResolver.dumpShort(pw); pw.println(); - final UserManager um = getContext().getSystemService(UserManager.class); - final List<UserInfo> users = um.getUsers(); + final List<UserInfo> users = getSupportedUsers(); for (int i = 0; i < users.size(); i++) { final int userId = users.get(i).id; pw.print(prefix2); pw.print(userId); pw.print(": "); @@ -733,7 +813,12 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem } mUpdatingPackageNames.put(userId, packageName); onServicePackageUpdatingLocked(userId); - if (mPackageUpdatePolicy != PACKAGE_UPDATE_POLICY_NO_REFRESH) { + if ((mServicePackagePolicyFlags & PACKAGE_UPDATE_POLICY_NO_REFRESH) != 0) { + if (debug) { + Slog.d(mTag, "Holding service for user " + userId + " while package " + + activePackageName + " is being updated"); + } + } else { if (debug) { Slog.d(mTag, "Removing service for user " + userId + " because package " + activePackageName @@ -741,18 +826,14 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem } removeCachedServiceLocked(userId); - if (mPackageUpdatePolicy == PACKAGE_UPDATE_POLICY_REFRESH_EAGER) { + if ((mServicePackagePolicyFlags & PACKAGE_UPDATE_POLICY_REFRESH_EAGER) + != 0) { if (debug) { Slog.d(mTag, "Eagerly recreating service for user " + userId); } getServiceForUserLocked(userId); } - } else { - if (debug) { - Slog.d(mTag, "Holding service for user " + userId + " while package " - + activePackageName + " is being updated"); - } } } } @@ -804,7 +885,13 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem if (!doit) { return true; } - removeCachedServiceLocked(getChangingUserId()); + final String action = intent.getAction(); + final int userId = getChangingUserId(); + if (Intent.ACTION_PACKAGE_RESTARTED.equals(action)) { + handleActiveServiceRestartedLocked(activePackageName, userId); + } else { + removeCachedServiceLocked(userId); + } } else { handlePackageUpdateLocked(pkg); } @@ -813,6 +900,23 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem return false; } + @Override + public void onPackageDataCleared(String packageName, int uid) { + if (verbose) Slog.v(mTag, "onPackageDataCleared(): " + packageName); + final int userId = getChangingUserId(); + synchronized (mLock) { + final S service = peekServiceForUserLocked(userId); + if (service != null) { + final ComponentName componentName = service.getServiceComponentName(); + if (componentName != null) { + if (packageName.equals(componentName.getPackageName())) { + onServicePackageDataClearedLocked(userId); + } + } + } + } + } + private void handleActiveServiceRemoved(@UserIdInt int userId) { synchronized (mLock) { removeCachedServiceLocked(userId); @@ -824,6 +928,31 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem } } + private void handleActiveServiceRestartedLocked(String activePackageName, + @UserIdInt int userId) { + if ((mServicePackagePolicyFlags & PACKAGE_RESTART_POLICY_NO_REFRESH) != 0) { + if (debug) { + Slog.d(mTag, "Holding service for user " + userId + " while package " + + activePackageName + " is being restarted"); + } + } else { + if (debug) { + Slog.d(mTag, "Removing service for user " + userId + + " because package " + activePackageName + + " is being restarted"); + } + removeCachedServiceLocked(userId); + + if ((mServicePackagePolicyFlags & PACKAGE_RESTART_POLICY_REFRESH_EAGER) != 0) { + if (debug) { + Slog.d(mTag, "Eagerly recreating service for user " + userId); + } + getServiceForUserLocked(userId); + } + } + onServicePackageRestartedLocked(userId); + } + private String getActiveServicePackageNameLocked() { final int userId = getChangingUserId(); final S service = peekServiceForUserLocked(userId); diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java index f38f2f9a0de5..ccc0d4b8334c 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsService.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java @@ -217,6 +217,11 @@ public class LockSettingsService extends ILockSettings.Stub { private final RecoverableKeyStoreManager mRecoverableKeyStoreManager; private boolean mFirstCallToVold; + // Current password metric for all users on the device. Updated when user unlocks + // the device or changes password. Removed when user is stopped. + @GuardedBy("this") + final SparseArray<PasswordMetrics> mUserPasswordMetrics = new SparseArray<>(); + protected IGateKeeperService mGateKeeperService; protected IAuthSecret mAuthSecretService; @@ -424,6 +429,13 @@ public class LockSettingsService extends ILockSettings.Stub { return (UserManager) mContext.getSystemService(Context.USER_SERVICE); } + /** + * Return the {@link DevicePolicyManager} object. + * + * Since LockSettingsService is considered a lower-level component than DevicePolicyManager, + * do NOT hold any lock in this class while calling into DevicePolicyManager to prevent + * the risk of deadlock. + */ public DevicePolicyManager getDevicePolicyManager() { return (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); } @@ -593,6 +605,9 @@ public class LockSettingsService extends ILockSettings.Stub { // the device. int strongAuthRequired = LockPatternUtils.StrongAuthTracker.getDefaultFlags(mContext); requireStrongAuth(strongAuthRequired, userId); + synchronized (this) { + mUserPasswordMetrics.remove(userId); + } } public void onStartUser(final int userId) { @@ -1501,7 +1516,7 @@ public class LockSettingsService extends ILockSettings.Stub { setKeystorePassword(null, userId); fixateNewestUserKeyAuth(userId); synchronizeUnifiedWorkChallengeForProfiles(userId, null); - notifyActivePasswordMetricsAvailable(CREDENTIAL_TYPE_NONE, null, userId); + setUserPasswordMetrics(CREDENTIAL_TYPE_NONE, null, userId); sendCredentialsOnChangeIfRequired( credentialType, credential, userId, isLockTiedToParent); return; @@ -1946,7 +1961,7 @@ public class LockSettingsService extends ILockSettings.Stub { Log.w(TAG, "progressCallback throws exception", e); } } - notifyActivePasswordMetricsAvailable(storedHash.type, credential, userId); + setUserPasswordMetrics(storedHash.type, credential, userId); unlockKeystore(credential, userId); Slog.i(TAG, "Unlocking user " + userId + " with token length " @@ -1988,32 +2003,40 @@ public class LockSettingsService extends ILockSettings.Stub { } /** - * Call this method to notify DPMS regarding the latest password metric. This should be called - * when the user is authenticating or when a new password is being set. + * Keep track of the given user's latest password metric. This should be called + * when the user is authenticating or when a new password is being set. In comparison, + * {@link #notifyPasswordChanged} only needs to be called when the user changes the password. */ - private void notifyActivePasswordMetricsAvailable( - @CredentialType int credentialType, byte[] password, @UserIdInt int userId) { - final PasswordMetrics metrics = - PasswordMetrics.computeForCredential(credentialType, password); + private void setUserPasswordMetrics(@CredentialType int credentialType, byte[] password, + @UserIdInt int userHandle) { + synchronized (this) { + mUserPasswordMetrics.put(userHandle, + PasswordMetrics.computeForCredential(credentialType, password)); + } + } - // Asynchronous to avoid dead lock - mHandler.post(() -> { - final DevicePolicyManager dpm = (DevicePolicyManager) - mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); - dpm.setActivePasswordState(metrics, userId); - }); + @VisibleForTesting + PasswordMetrics getUserPasswordMetrics(int userHandle) { + if (!isUserSecure(userHandle)) { + // for users without password, mUserPasswordMetrics might not be initialized + // since the user never unlock the device manually. In this case, always + // return a default metrics object. This is to distinguish this case from + // the case where during boot user password is unknown yet (returning null here) + return new PasswordMetrics(); + } + synchronized (this) { + return mUserPasswordMetrics.get(userHandle); + } } /** - * Call after {@link #notifyActivePasswordMetricsAvailable} so metrics are updated before + * Call after {@link #setUserPasswordMetrics} so metrics are updated before * reporting the password changed. */ private void notifyPasswordChanged(@UserIdInt int userId) { // Same handler as notifyActivePasswordMetricsAvailable to ensure correct ordering mHandler.post(() -> { - DevicePolicyManager dpm = (DevicePolicyManager) - mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); - dpm.reportPasswordChanged(userId); + mInjector.getDevicePolicyManager().reportPasswordChanged(userId); LocalServices.getService(WindowManagerInternal.class).reportPasswordChanged(userId); }); } @@ -2582,7 +2605,7 @@ public class LockSettingsService extends ILockSettings.Stub { } if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) { - notifyActivePasswordMetricsAvailable(credentialType, userCredential, userId); + setUserPasswordMetrics(credentialType, userCredential, userId); unlockKeystore(authResult.authToken.deriveKeyStorePassword(), userId); // Do resetLockout / revokeChallenge when all profiles are unlocked @@ -2676,7 +2699,7 @@ public class LockSettingsService extends ILockSettings.Stub { setSyntheticPasswordHandleLocked(newHandle, userId); synchronizeUnifiedWorkChallengeForProfiles(userId, profilePasswords); - notifyActivePasswordMetricsAvailable(credentialType, credential, userId); + setUserPasswordMetrics(credentialType, credential, userId); if (profilePasswords != null) { for (Map.Entry<Integer, byte[]> entry : profilePasswords.entrySet()) { @@ -2982,6 +3005,8 @@ public class LockSettingsService extends ILockSettings.Stub { pw.println("hasPassword: " + havePassword(userId)); pw.println("hasPattern: " + havePattern(userId)); // print raw credential type instead? pw.println("SeparateChallenge: " + getSeparateProfileChallengeEnabled(userId)); + pw.println(String.format("metrics: %s", + getUserPasswordMetrics(userId) != null ? "known" : "unknown")); pw.decreaseIndent(); } pw.println(); @@ -3158,5 +3183,23 @@ public class LockSettingsService extends ILockSettings.Stub { public boolean unlockUserWithToken(long tokenHandle, byte[] token, int userId) { return LockSettingsService.this.unlockUserWithToken(tokenHandle, token, userId); } + + @Override + public PasswordMetrics getUserPasswordMetrics(int userHandle) { + long identity = Binder.clearCallingIdentity(); + try { + if (isManagedProfileWithUnifiedLock(userHandle)) { + // A managed profile with unified challenge is supposed to be protected by the + // parent lockscreen, so asking for its password metrics is not really useful, + // as this method would just return the metrics of the random profile password + Slog.w(TAG, "Querying password metrics for unified challenge profile: " + + userHandle); + } + } finally { + Binder.restoreCallingIdentity(identity); + } + return LockSettingsService.this.getUserPasswordMetrics(userHandle); + } + } } diff --git a/services/core/java/com/android/server/net/LockdownVpnTracker.java b/services/core/java/com/android/server/net/LockdownVpnTracker.java index 3f15b381c18b..77fbe41ebb88 100644 --- a/services/core/java/com/android/server/net/LockdownVpnTracker.java +++ b/services/core/java/com/android/server/net/LockdownVpnTracker.java @@ -19,6 +19,8 @@ package com.android.server.net; import static android.Manifest.permission.CONNECTIVITY_INTERNAL; import static android.provider.Settings.ACTION_VPN_SETTINGS; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; @@ -32,7 +34,7 @@ import android.net.LinkProperties; import android.net.NetworkInfo; import android.net.NetworkInfo.DetailedState; import android.net.NetworkInfo.State; -import android.os.INetworkManagementService; +import android.os.Handler; import android.security.Credentials; import android.security.KeyStore; import android.text.TextUtils; @@ -63,22 +65,19 @@ public class LockdownVpnTracker { private static final String ACTION_LOCKDOWN_RESET = "com.android.server.action.LOCKDOWN_RESET"; - private static final int ROOT_UID = 0; + @NonNull private final Context mContext; + @NonNull private final ConnectivityService mConnService; + @NonNull private final Handler mHandler; + @NonNull private final Vpn mVpn; + @NonNull private final VpnProfile mProfile; - private final Context mContext; - private final INetworkManagementService mNetService; - private final ConnectivityService mConnService; - private final Vpn mVpn; - private final VpnProfile mProfile; + @NonNull private final Object mStateLock = new Object(); - private final Object mStateLock = new Object(); - - private final PendingIntent mConfigIntent; - private final PendingIntent mResetIntent; + @NonNull private final PendingIntent mConfigIntent; + @NonNull private final PendingIntent mResetIntent; + @Nullable private String mAcceptedEgressIface; - private String mAcceptedIface; - private List<LinkAddress> mAcceptedSourceAddr; private int mErrorCount; @@ -86,11 +85,14 @@ public class LockdownVpnTracker { return KeyStore.getInstance().contains(Credentials.LOCKDOWN_VPN); } - public LockdownVpnTracker(Context context, INetworkManagementService netService, - ConnectivityService connService, Vpn vpn, VpnProfile profile) { + public LockdownVpnTracker(@NonNull Context context, + @NonNull ConnectivityService connService, + @NonNull Handler handler, + @NonNull Vpn vpn, + @NonNull VpnProfile profile) { mContext = Preconditions.checkNotNull(context); - mNetService = Preconditions.checkNotNull(netService); mConnService = Preconditions.checkNotNull(connService); + mHandler = Preconditions.checkNotNull(handler); mVpn = Preconditions.checkNotNull(vpn); mProfile = Preconditions.checkNotNull(profile); @@ -176,11 +178,6 @@ public class LockdownVpnTracker { final String iface = vpnConfig.interfaze; final List<LinkAddress> sourceAddrs = vpnConfig.addresses; - if (TextUtils.equals(iface, mAcceptedIface) - && sourceAddrs.equals(mAcceptedSourceAddr)) { - return; - } - Slog.d(TAG, "VPN connected using iface=" + iface + ", sourceAddr=" + sourceAddrs.toString()); EventLogTags.writeLockdownVpnConnected(egressType); @@ -205,7 +202,7 @@ public class LockdownVpnTracker { mVpn.setLockdown(true); final IntentFilter resetFilter = new IntentFilter(ACTION_LOCKDOWN_RESET); - mContext.registerReceiver(mResetReceiver, resetFilter, CONNECTIVITY_INTERNAL, null); + mContext.registerReceiver(mResetReceiver, resetFilter, CONNECTIVITY_INTERNAL, mHandler); handleStateChangedLocked(); } diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index b4a80994cc65..976a0c663101 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -217,6 +217,7 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.internal.notification.SystemNotificationChannels; +import com.android.internal.os.SomeArgs; import com.android.internal.telephony.PhoneConstants; import com.android.internal.util.ArrayUtils; import com.android.internal.util.ConcurrentUtils; @@ -3281,7 +3282,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { @Override public void setSubscriptionOverride(int subId, int overrideMask, int overrideValue, - long timeoutMillis, String callingPackage) { + long networkTypeMask, long timeoutMillis, String callingPackage) { enforceSubscriptionPlanAccess(subId, Binder.getCallingUid(), callingPackage); // We can only override when carrier told us about plans @@ -3299,11 +3300,16 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { final boolean overrideEnabled = Settings.Global.getInt(mContext.getContentResolver(), NETPOLICY_OVERRIDE_ENABLED, 1) != 0; if (overrideEnabled || overrideValue == 0) { - mHandler.sendMessage(mHandler.obtainMessage(MSG_SUBSCRIPTION_OVERRIDE, - overrideMask, overrideValue, subId)); + SomeArgs args = SomeArgs.obtain(); + args.arg1 = subId; + args.arg2 = overrideMask; + args.arg3 = overrideValue; + args.arg4 = networkTypeMask; + mHandler.sendMessage(mHandler.obtainMessage(MSG_SUBSCRIPTION_OVERRIDE, args)); if (timeoutMillis > 0) { - mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_SUBSCRIPTION_OVERRIDE, - overrideMask, 0, subId), timeoutMillis); + args.arg3 = 0; + mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_SUBSCRIPTION_OVERRIDE, args), + timeoutMillis); } } } @@ -4439,10 +4445,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } private void dispatchSubscriptionOverride(INetworkPolicyListener listener, int subId, - int overrideMask, int overrideValue) { + int overrideMask, int overrideValue, long networkTypeMask) { if (listener != null) { try { - listener.onSubscriptionOverride(subId, overrideMask, overrideValue); + listener.onSubscriptionOverride(subId, overrideMask, overrideValue, + networkTypeMask); } catch (RemoteException ignored) { } } @@ -4543,13 +4550,16 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { return true; } case MSG_SUBSCRIPTION_OVERRIDE: { - final int overrideMask = msg.arg1; - final int overrideValue = msg.arg2; - final int subId = (int) msg.obj; + final SomeArgs args = (SomeArgs) msg.obj; + final int subId = (int) args.arg1; + final int overrideMask = (int) args.arg2; + final int overrideValue = (int) args.arg3; + final long networkTypeMask = (long) args.arg4; final int length = mListeners.beginBroadcast(); for (int i = 0; i < length; i++) { final INetworkPolicyListener listener = mListeners.getBroadcastItem(i); - dispatchSubscriptionOverride(listener, subId, overrideMask, overrideValue); + dispatchSubscriptionOverride(listener, subId, overrideMask, overrideValue, + networkTypeMask); } mListeners.finishBroadcast(); return true; diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java index 1da5bc6c26ee..dc00cb45596c 100644 --- a/services/core/java/com/android/server/pm/ApexManager.java +++ b/services/core/java/com/android/server/pm/ApexManager.java @@ -261,11 +261,12 @@ abstract class ApexManager { mContext.registerReceiver(new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - populateAllPackagesCacheIfNeeded(); + // Post populateAllPackagesCacheIfNeeded to a background thread, since it's + // expensive to run it in broadcast handler thread. + BackgroundThread.getHandler().post(() -> populateAllPackagesCacheIfNeeded()); mContext.unregisterReceiver(this); } - }, new IntentFilter(Intent.ACTION_BOOT_COMPLETED), /* broadcastPermission */ null, - BackgroundThread.getHandler()); + }, new IntentFilter(Intent.ACTION_BOOT_COMPLETED)); } private void populateAllPackagesCacheIfNeeded() { diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java index c7124314cae0..08e55d3b766b 100644 --- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java +++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java @@ -34,6 +34,8 @@ import android.os.ServiceManager; import android.os.SystemProperties; import android.os.UserHandle; import android.os.storage.StorageManager; +import android.provider.DeviceConfig; +import android.text.TextUtils; import android.util.ArraySet; import android.util.Log; import android.util.StatsLog; @@ -84,6 +86,12 @@ public class BackgroundDexOptService extends JobService { // Used for calculating space threshold for downgrading unused apps. private static final int LOW_THRESHOLD_MULTIPLIER_FOR_DOWNGRADE = 2; + private static final int DEFAULT_INACTIVE_APP_THRESHOLD_DAYS = 10; + + private static final String DOWNGRADE_UNUSED_APPS_ENABLED = "downgrade_unused_apps_enabled"; + private static final String INACTIVE_APP_THRESHOLD_DAYS = "inactive_app_threshold_days"; + private static final String LOW_STORAGE_MULTIPLIER_FOR_DOWNGRADE = + "low_storage_threshold_multiplier_for_downgrade"; /** * Set of failed packages remembered across job runs. @@ -103,8 +111,6 @@ public class BackgroundDexOptService extends JobService { private final AtomicBoolean mExitPostBootUpdate = new AtomicBoolean(false); private final File mDataDir = Environment.getDataDirectory(); - private static final long mDowngradeUnusedAppsThresholdInMillis = - getDowngradeUnusedAppsThresholdInMillis(); public static void schedule(Context context) { if (isBackgroundDexoptDisabled()) { @@ -346,14 +352,14 @@ public class BackgroundDexOptService extends JobService { // Only downgrade apps when space is low on device. // Threshold is selected above the lowStorageThreshold so that we can pro-actively clean // up disk before user hits the actual lowStorageThreshold. - final long lowStorageThresholdForDowngrade = LOW_THRESHOLD_MULTIPLIER_FOR_DOWNGRADE + final long lowStorageThresholdForDowngrade = getLowThresholdMultiplierForDowngrade() * lowStorageThreshold; boolean shouldDowngrade = shouldDowngrade(lowStorageThresholdForDowngrade); Log.d(TAG, "Should Downgrade " + shouldDowngrade); if (shouldDowngrade) { Set<String> unusedPackages = - pm.getUnusedPackages(mDowngradeUnusedAppsThresholdInMillis); - Log.d(TAG, "Unsused Packages " + String.join(",", unusedPackages)); + pm.getUnusedPackages(getDowngradeUnusedAppsThresholdInMillis()); + Log.d(TAG, "Unused Packages " + String.join(",", unusedPackages)); if (!unusedPackages.isEmpty()) { for (String pkg : unusedPackages) { @@ -362,12 +368,9 @@ public class BackgroundDexOptService extends JobService { // Should be aborted by the scheduler. return abortCode; } - if (downgradePackage(pm, pkg, /*isForPrimaryDex*/ true)) { + if (downgradePackage(pm, pkg)) { updatedPackages.add(pkg); } - if (supportSecondaryDex) { - downgradePackage(pm, pkg, /*isForPrimaryDex*/ false); - } } pkgs = new ArraySet<>(pkgs); @@ -415,39 +418,45 @@ public class BackgroundDexOptService extends JobService { * Try to downgrade the package to a smaller compilation filter. * eg. if the package is in speed-profile the package will be downgraded to verify. * @param pm PackageManagerService - * @param pkg The package to be downgraded. - * @param isForPrimaryDex. Apps can have several dex file, primary and secondary. - * @return true if the package was downgraded. + * @param pkg The package to be downgraded + * @return true if the package was downgraded */ - private boolean downgradePackage(PackageManagerService pm, String pkg, - boolean isForPrimaryDex) { + private boolean downgradePackage(PackageManagerService pm, String pkg) { Log.d(TAG, "Downgrading " + pkg); - boolean dex_opt_performed = false; + boolean downgradedPrimary = false; int reason = PackageManagerService.REASON_INACTIVE_PACKAGE_DOWNGRADE; int dexoptFlags = DexoptOptions.DEXOPT_BOOT_COMPLETE | DexoptOptions.DEXOPT_IDLE_BACKGROUND_JOB | DexoptOptions.DEXOPT_DOWNGRADE; + long package_size_before = getPackageSize(pm, pkg); + // An aggressive downgrade deletes the oat files. + boolean aggressive = false; + // This applies for system apps or if packages location is not a directory, i.e. + // monolithic install. + if (!pm.canHaveOatDir(pkg)) { + // For apps that don't have the oat directory, instead of downgrading, + // remove their compiler artifacts from dalvik cache. + pm.deleteOatArtifactsOfPackage(pkg); + aggressive = true; + downgradedPrimary = true; + } else { + downgradedPrimary = performDexOptPrimary(pm, pkg, reason, dexoptFlags); - if (isForPrimaryDex) { - // This applies for system apps or if packages location is not a directory, i.e. - // monolithic install. - if (!pm.canHaveOatDir(pkg)) { - // For apps that don't have the oat directory, instead of downgrading, - // remove their compiler artifacts from dalvik cache. - pm.deleteOatArtifactsOfPackage(pkg); - } else { - dex_opt_performed = performDexOptPrimary(pm, pkg, reason, dexoptFlags); + if (supportSecondaryDex()) { + performDexOptSecondary(pm, pkg, reason, dexoptFlags); } - } else { - dex_opt_performed = performDexOptSecondary(pm, pkg, reason, dexoptFlags); } - if (dex_opt_performed) { + // This metric aims to log the storage savings when downgrading. + // The way disk size is measured using getPackageSize only looks at the primary apks. + // Any logs that are due to secondary dex files will show 0% size reduction and pollute + // the metrics. + if (downgradedPrimary) { StatsLog.write(StatsLog.APP_DOWNGRADED, pkg, package_size_before, - getPackageSize(pm, pkg), /*aggressive=*/ false); + getPackageSize(pm, pkg), aggressive); } - return dex_opt_performed; + return downgradedPrimary; } private boolean supportSecondaryDex() { @@ -471,7 +480,7 @@ public class BackgroundDexOptService extends JobService { * concurrent jobs because PackageDexOptimizer.performDexOpt is synchronized. * @param pm An instance of PackageManagerService * @param pkg The package to be downgraded. - * @param isForPrimaryDex. Apps can have several dex file, primary and secondary. + * @param isForPrimaryDex Apps can have several dex file, primary and secondary. * @return true if the package was downgraded. */ private boolean optimizePackage(PackageManagerService pm, String pkg, @@ -588,12 +597,6 @@ public class BackgroundDexOptService extends JobService { // the checks above. This check is not "live" - the value is determined by a background // restart with a period of ~1 minute. PackageManagerService pm = (PackageManagerService)ServiceManager.getService("package"); - if (pm.isStorageLow()) { - if (DEBUG_DEXOPT) { - Log.i(TAG, "Low storage, skipping this run"); - } - return false; - } final ArraySet<String> pkgs = pm.getOptimizablePackages(); if (pkgs.isEmpty()) { @@ -643,17 +646,77 @@ public class BackgroundDexOptService extends JobService { } private static long getDowngradeUnusedAppsThresholdInMillis() { + long defaultValue = Long.MAX_VALUE; + if (isDowngradeFeatureEnabled()) { + return getInactiveAppsThresholdMillis(); + } final String sysPropKey = "pm.dexopt.downgrade_after_inactive_days"; String sysPropValue = SystemProperties.get(sysPropKey); if (sysPropValue == null || sysPropValue.isEmpty()) { Log.w(TAG, "SysProp " + sysPropKey + " not set"); - return Long.MAX_VALUE; + return defaultValue; + } + try { + return TimeUnit.DAYS.toMillis(Long.parseLong(sysPropValue)); + } catch (NumberFormatException e) { + Log.w(TAG, "Couldn't parse long for pm.dexopt.downgrade_after_inactive_days: " + + sysPropValue + ". Returning default value instead."); + return defaultValue; } - return TimeUnit.DAYS.toMillis(Long.parseLong(sysPropValue)); } private static boolean isBackgroundDexoptDisabled() { return SystemProperties.getBoolean("pm.dexopt.disable_bg_dexopt" /* key */, false /* default */); } + + private static boolean isDowngradeFeatureEnabled() { + // DeviceConfig enables the control of on device features via remotely configurable flags, + // compared to SystemProperties which is only a way of sharing info system-widely, but are + // not configurable on the server-side. + String downgradeUnusedAppsEnabledFlag = + DeviceConfig.getProperty( + DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE, + DOWNGRADE_UNUSED_APPS_ENABLED); + return !TextUtils.isEmpty(downgradeUnusedAppsEnabledFlag) + && Boolean.parseBoolean(downgradeUnusedAppsEnabledFlag); + } + + private static long getInactiveAppsThresholdMillis() { + long defaultValue = TimeUnit.DAYS.toMillis(DEFAULT_INACTIVE_APP_THRESHOLD_DAYS); + String inactiveAppThresholdDaysFlag = + DeviceConfig.getProperty(DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE, + INACTIVE_APP_THRESHOLD_DAYS); + if (!TextUtils.isEmpty(inactiveAppThresholdDaysFlag)) { + try { + return TimeUnit.DAYS.toMillis(Long.parseLong(inactiveAppThresholdDaysFlag)); + } catch (NumberFormatException e) { + Log.w(TAG, "Couldn't parse long for " + INACTIVE_APP_THRESHOLD_DAYS + " flag: " + + inactiveAppThresholdDaysFlag + ". Returning default value instead."); + return defaultValue; + } + } + return defaultValue; + } + + private static int getLowThresholdMultiplierForDowngrade() { + int defaultValue = LOW_THRESHOLD_MULTIPLIER_FOR_DOWNGRADE; + if (isDowngradeFeatureEnabled()) { + String lowStorageThresholdMultiplierFlag = + DeviceConfig.getProperty(DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE, + LOW_STORAGE_MULTIPLIER_FOR_DOWNGRADE); + if (!TextUtils.isEmpty(lowStorageThresholdMultiplierFlag)) { + try { + return Integer.parseInt(lowStorageThresholdMultiplierFlag); + } catch (NumberFormatException e) { + Log.w(TAG, "Couldn't parse long for " + + LOW_STORAGE_MULTIPLIER_FOR_DOWNGRADE + " flag: " + + lowStorageThresholdMultiplierFlag + + ". Returning default value instead."); + return defaultValue; + } + } + } + return defaultValue; + } } diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java index 3aeb2b102afe..b632d18f5cd2 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerService.java +++ b/services/core/java/com/android/server/pm/PackageInstallerService.java @@ -505,6 +505,11 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements params.installFlags &= ~PackageManager.INSTALL_REQUEST_DOWNGRADE; } + if (callingUid != Process.SYSTEM_UID) { + // Only system_server can use INSTALL_DISABLE_VERIFICATION. + params.installFlags &= ~PackageManager.INSTALL_DISABLE_VERIFICATION; + } + boolean isApex = (params.installFlags & PackageManager.INSTALL_APEX) != 0; if (params.isStaged || isApex) { mContext.enforceCallingOrSelfPermission(Manifest.permission.INSTALL_PACKAGES, TAG); diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 2bf5f4d87682..41403fdeeeef 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -2149,6 +2149,14 @@ public class PackageManagerService extends IPackageManager.Stub pkgList.add(packageName); sendResourcesChangedBroadcast(true, true, pkgList, uidArray, null); } + } else if (!ArrayUtils.isEmpty(res.libraryConsumers)) { // if static shared lib + for (int i = 0; i < res.libraryConsumers.size(); i++) { + PackageParser.Package pkg = res.libraryConsumers.get(i); + // send broadcast that all consumers of the static shared library have changed + sendPackageChangedBroadcast(pkg.packageName, false /*killFlag*/, + new ArrayList<>(Collections.singletonList(pkg.packageName)), + pkg.applicationInfo.uid); + } } // Work that needs to happen on first install within each user @@ -11878,6 +11886,9 @@ public class PackageManagerService extends IPackageManager.Stub } } } + if (reconciledPkg.installResult != null) { + reconciledPkg.installResult.libraryConsumers = clientLibPkgs; + } if ((scanFlags & SCAN_BOOTING) != 0) { // No apps can run during boot scan, so they don't need to be frozen @@ -15157,6 +15168,8 @@ public class PackageManagerService extends IPackageManager.Stub String installerPackageName; PackageRemovedInfo removedInfo; ArrayMap<String, PackageInstalledInfo> addedChildPackages; + // The set of packages consuming this shared library or null if no consumers exist. + ArrayList<PackageParser.Package> libraryConsumers; public void setError(int code, String msg) { setReturnCode(code); diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java index 85bc9f3d56d6..af1a095c6871 100644 --- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java +++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java @@ -94,9 +94,11 @@ import android.text.TextUtils; import android.text.format.DateUtils; import android.util.ArraySet; import android.util.PrintWriterPrinter; +import android.util.SparseArray; import com.android.internal.content.PackageHelper; import com.android.internal.util.ArrayUtils; +import com.android.internal.util.IndentingPrintWriter; import com.android.server.LocalServices; import com.android.server.SystemConfig; @@ -347,17 +349,33 @@ class PackageManagerShellCommand extends ShellCommand { } private int getStagedSessions() { - final PrintWriter pw = getOutPrintWriter(); + final IndentingPrintWriter pw = new IndentingPrintWriter( + getOutPrintWriter(), /* singleIndent */ " ", /* wrapLength */ 120); try { - List<SessionInfo> stagedSessionsList = + List<SessionInfo> stagedSessions = mInterface.getPackageInstaller().getStagedSessions().getList(); - for (SessionInfo session: stagedSessionsList) { - pw.println("appPackageName = " + session.getAppPackageName() - + "; sessionId = " + session.getSessionId() - + "; isStaged = " + session.isStaged() - + "; isStagedSessionReady = " + session.isStagedSessionReady() - + "; isStagedSessionApplied = " + session.isStagedSessionApplied() - + "; isStagedSessionFailed = " + session.isStagedSessionFailed() + ";"); + final SparseArray<SessionInfo> sessionById = new SparseArray<>(stagedSessions.size()); + for (SessionInfo session : stagedSessions) { + sessionById.put(session.getSessionId(), session); + } + for (SessionInfo session: stagedSessions) { + if (session.getParentSessionId() != SessionInfo.INVALID_ID) { + continue; + } + printStagedSession(session, pw); + if (session.isMultiPackage()) { + pw.increaseIndent(); + final int[] childIds = session.getChildSessionIds(); + for (int i = 0; i < childIds.length; i++) { + final SessionInfo childSession = sessionById.get(childIds[i]); + if (childSession == null) { + pw.println("sessionId = " + childIds[i] + "; not found"); + } else { + printStagedSession(childSession, pw); + } + } + pw.decreaseIndent(); + } } } catch (RemoteException e) { pw.println("Failure [" @@ -368,6 +386,15 @@ class PackageManagerShellCommand extends ShellCommand { return 1; } + private static void printStagedSession(SessionInfo session, PrintWriter pw) { + pw.println("sessionId = " + session.getSessionId() + + "; appPackageName = " + session.getAppPackageName() + + "; isStaged = " + session.isStaged() + + "; isReady = " + session.isStagedSessionReady() + + "; isApplied = " + session.isStagedSessionApplied() + + "; isFailed = " + session.isStagedSessionFailed() + ";"); + } + private int uninstallSystemUpdates() { final PrintWriter pw = getOutPrintWriter(); List<String> failedUninstalls = new LinkedList<>(); @@ -3097,7 +3124,7 @@ class PackageManagerShellCommand extends ShellCommand { pw.println(" [--user USER_ID] INTENT"); pw.println(" Prints all broadcast receivers that can handle the given INTENT."); pw.println(""); - pw.println(" install [-lrtsfdgw] [-i PACKAGE] [--user USER_ID|all|current]"); + pw.println(" install [-rtsfdgw] [-i PACKAGE] [--user USER_ID|all|current]"); pw.println(" [-p INHERIT_PACKAGE] [--install-location 0/1/2]"); pw.println(" [--install-reason 0/1/2/3/4] [--originating-uri URI]"); pw.println(" [--referrer URI] [--abi ABI_NAME] [--force-sdk]"); @@ -3108,7 +3135,6 @@ class PackageManagerShellCommand extends ShellCommand { pw.println(" [PATH|-]"); pw.println(" Install an application. Must provide the apk data to install, either as a"); pw.println(" file path or '-' to read from stdin. Options are:"); - pw.println(" -l: forward lock application"); pw.println(" -R: disallow replacement of existing application"); pw.println(" -t: allow test packages"); pw.println(" -i: specify package name of installer owning the app"); diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index 1fe551222a06..65fb35d34c01 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -4180,6 +4180,17 @@ public class UserManagerService extends IUserManager.Stub { } return userData == null ? null : userData.info; } + + public @NonNull UserInfo[] getUserInfos() { + synchronized (mUsersLock) { + int userSize = mUsers.size(); + UserInfo[] allInfos = new UserInfo[userSize]; + for (int i = 0; i < userSize; i++) { + allInfos[i] = mUsers.valueAt(i).info; + } + return allInfos; + } + } } /* Remove all the users except of the system one. */ diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java index 5a410d7d820f..22929d835f80 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -650,9 +650,9 @@ public class PermissionManagerService extends IPermissionManager.Stub { private void updatePermissionFlagsInternal(String permName, String packageName, int flagMask, int flagValues, int callingUid, int userId, boolean overridePolicy, PermissionCallback callback) { - if (ApplicationPackageManager.DEBUG_TRACE_GRANTS + if (ApplicationPackageManager.DEBUG_TRACE_PERMISSION_UPDATES && ApplicationPackageManager.shouldTraceGrant(packageName, permName, userId)) { - Log.i(TAG, "System is updating flags for " + Log.i(TAG, "System is updating flags for " + packageName + " " + permName + " for user " + userId + " " + DebugUtils.flagsToString( PackageManager.class, "FLAG_PERMISSION_", flagMask) @@ -1185,7 +1185,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { boolean overridePolicy, int callingUid, final int userId, PermissionCallback callback) { if (ApplicationPackageManager.DEBUG_TRACE_GRANTS && ApplicationPackageManager.shouldTraceGrant(packageName, permName, userId)) { - Log.i(TAG, "System is granting " + Log.i(TAG, "System is granting " + packageName + " " + permName + " for user " + userId + " on behalf of uid " + callingUid + " " + mPackageManagerInt.getNameForUid(callingUid), new RuntimeException()); @@ -1232,7 +1232,8 @@ public class PermissionManagerService extends IPermissionManager.Stub { return; } - final int uid = UserHandle.getUid(userId, pkg.applicationInfo.uid); + final int uid = UserHandle.getUid(userId, + UserHandle.getAppId(pkg.applicationInfo.uid)); final PackageSetting ps = (PackageSetting) pkg.mExtras; final PermissionsState permissionsState = ps.getPermissionsState(); @@ -1344,9 +1345,9 @@ public class PermissionManagerService extends IPermissionManager.Stub { // TODO swap permission name and package name private void revokeRuntimePermissionInternal(String permName, String packageName, boolean overridePolicy, int callingUid, final int userId, PermissionCallback callback) { - if (ApplicationPackageManager.DEBUG_TRACE_GRANTS + if (ApplicationPackageManager.DEBUG_TRACE_PERMISSION_UPDATES && ApplicationPackageManager.shouldTraceGrant(packageName, permName, userId)) { - Log.i(TAG, "System is revoking " + Log.i(TAG, "System is revoking " + packageName + " " + permName + " for user " + userId + " on behalf of uid " + callingUid + " " + mPackageManagerInt.getNameForUid(callingUid), new RuntimeException()); @@ -1432,7 +1433,8 @@ public class PermissionManagerService extends IPermissionManager.Stub { } if (callback != null) { - callback.onPermissionRevoked(pkg.applicationInfo.uid, userId); + callback.onPermissionRevoked(UserHandle.getUid(userId, + UserHandle.getAppId(pkg.applicationInfo.uid)), userId); } if (bp.isRuntime()) { diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java index bfd280c14f6d..ddbd9c9266d0 100644 --- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java +++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java @@ -282,15 +282,6 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { rollbacks.add(rollback.info); } } - - // Also return new rollbacks for which the PackageRollbackInfo is complete. - for (NewRollback newRollback : mNewRollbacks) { - if (newRollback.rollback.info.getPackages().size() - == newRollback.packageSessionIds.length - && !newRollback.isCancelled) { - rollbacks.add(newRollback.rollback.info); - } - } return new ParceledListSlice<>(rollbacks); } } diff --git a/services/core/java/com/android/server/storage/StorageSessionController.java b/services/core/java/com/android/server/storage/StorageSessionController.java new file mode 100644 index 000000000000..2d36a0dd1be4 --- /dev/null +++ b/services/core/java/com/android/server/storage/StorageSessionController.java @@ -0,0 +1,217 @@ +/* + * Copyright (C) 2019 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.storage; + +import android.Manifest; +import android.annotation.Nullable; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ProviderInfo; +import android.content.pm.ResolveInfo; +import android.content.pm.ServiceInfo; +import android.os.ParcelFileDescriptor; +import android.os.storage.VolumeInfo; +import android.provider.MediaStore; +import android.service.storage.ExternalStorageService; +import android.util.Slog; +import android.util.SparseArray; + +import com.android.internal.annotations.GuardedBy; +import com.android.internal.util.Preconditions; + +import java.io.FileDescriptor; +import java.io.IOException; + +/** + * Controls storage sessions for users initiated by the {@link StorageManagerService}. + * Each user on the device will be represented by a {@link StorageUserConnection}. + */ +public final class StorageSessionController { + private static final String TAG = "StorageSessionController"; + + private final Object mLock = new Object(); + private final Context mContext; + private final Callback mCallback; + @GuardedBy("mLock") + private ComponentName mExternalStorageServiceComponent; + @GuardedBy("mLock") + private final SparseArray<StorageUserConnection> mConnections = new SparseArray<>(); + + public StorageSessionController(Context context, Callback callback) { + mContext = Preconditions.checkNotNull(context); + mCallback = Preconditions.checkNotNull(callback); + } + + /** + * Starts a storage session associated with {@code deviceFd} for {@code vol}. + * Does nothing if a session is already started or starting. If the user associated with + * {@code vol} is not yet ready, the session will be retried {@link #onUserStarted}. + * + * A session must be ended with {@link #endSession} when no longer required. + */ + public void onVolumeMounted(int userId, FileDescriptor deviceFd, VolumeInfo vol) { + if (deviceFd == null) { + Slog.w(TAG, "Null device fd. Session not started for " + vol); + return; + } + + // Get realpath for the fd, paths that are not /dev/null need additional + // setup by the ExternalStorageService before they can be ready + String realPath; + try { + realPath = ParcelFileDescriptor.getFile(deviceFd).getPath(); + } catch (IOException e) { + Slog.wtf(TAG, "Could not get real path from fd: " + deviceFd, e); + return; + } + + if ("/dev/null".equals(realPath)) { + Slog.i(TAG, "Volume ready for use: " + vol); + return; + } + + synchronized (mLock) { + StorageUserConnection connection = mConnections.get(userId); + if (connection == null) { + Slog.i(TAG, "Creating new session for vol: " + vol); + connection = new StorageUserConnection(mContext, userId, this); + mConnections.put(userId, connection); + } + try { + Slog.i(TAG, "Starting session for vol: " + vol); + connection.startSession(deviceFd, vol); + } catch (ExternalStorageServiceException e) { + Slog.e(TAG, "Failed to start session for vol: " + vol, e); + } + } + } + + /** + * Ends a storage session for {@code vol}. Does nothing if the session is already + * ended or ending. Ending a session discards all resources associated with that session. + */ + public void onVolumeUnmounted(int userId, VolumeInfo vol) { + synchronized (mLock) { + StorageUserConnection connection = mConnections.get(userId); + if (connection != null) { + Slog.i(TAG, "Ending session for vol: " + vol); + try { + if (connection.endSession(vol)) { + mConnections.remove(userId); + } + } catch (ExternalStorageServiceException e) { + Slog.e(TAG, "Failed to end session for vol: " + vol, e); + } + } else { + Slog.w(TAG, "Session already ended for vol: " + vol); + } + } + } + + /** Restarts all sessions for {@code userId}. */ + public void onUserStarted(int userId) { + synchronized (mLock) { + StorageUserConnection connection = mConnections.get(userId); + if (connection != null) { + try { + Slog.i(TAG, "Restarting all sessions for user: " + userId); + connection.startAllSessions(); + } catch (ExternalStorageServiceException e) { + Slog.e(TAG, "Failed to start all sessions", e); + } + } else { + // TODO(b/135341433): What does this mean in multi-user + } + } + } + + /** Ends all sessions for {@code userId}. */ + public void onUserRemoved(int userId) { + synchronized (mLock) { + StorageUserConnection connection = mConnections.get(userId); + if (connection != null) { + try { + Slog.i(TAG, "Ending all sessions for user: " + userId); + connection.endAllSessions(); + mConnections.remove(userId); + } catch (ExternalStorageServiceException e) { + Slog.e(TAG, "Failed to end all sessions", e); + } + } else { + // TODO(b/135341433): What does this mean in multi-user + } + } + } + + /** Returns the {@link ExternalStorageService} component name. */ + @Nullable + public ComponentName getExternalStorageServiceComponentName() { + synchronized (mLock) { + if (mExternalStorageServiceComponent == null) { + ProviderInfo provider = mContext.getPackageManager().resolveContentProvider( + MediaStore.AUTHORITY, PackageManager.MATCH_DIRECT_BOOT_AWARE + | PackageManager.MATCH_DIRECT_BOOT_UNAWARE + | PackageManager.MATCH_SYSTEM_ONLY); + + if (provider == null) { + Slog.e(TAG, "No valid MediaStore provider found."); + } + String packageName = provider.applicationInfo.packageName; + + Intent intent = new Intent(ExternalStorageService.SERVICE_INTERFACE); + intent.setPackage(packageName); + ResolveInfo resolveInfo = mContext.getPackageManager().resolveService(intent, + PackageManager.GET_SERVICES | PackageManager.GET_META_DATA); + if (resolveInfo == null || resolveInfo.serviceInfo == null) { + Slog.e(TAG, "No valid ExternalStorageService component found."); + return null; + } + + ServiceInfo serviceInfo = resolveInfo.serviceInfo; + ComponentName name = new ComponentName(serviceInfo.packageName, serviceInfo.name); + if (!Manifest.permission.BIND_EXTERNAL_STORAGE_SERVICE + .equals(serviceInfo.permission)) { + Slog.e(TAG, name.flattenToShortString() + " does not require permission " + + Manifest.permission.BIND_EXTERNAL_STORAGE_SERVICE); + return null; + } + mExternalStorageServiceComponent = name; + } + return mExternalStorageServiceComponent; + } + } + + /** Returns the {@link StorageManagerService} callback. */ + public Callback getCallback() { + return mCallback; + } + + /** Callback to listen to session events from the {@link StorageSessionController}. */ + public interface Callback { + /** Called when a {@link StorageUserConnection} is disconnected. */ + void onUserDisconnected(int userId); + } + + /** Exception thrown when communication with the {@link ExternalStorageService}. */ + public static class ExternalStorageServiceException extends Exception { + public ExternalStorageServiceException(Throwable cause) { + super(cause); + } + } +} diff --git a/services/core/java/com/android/server/storage/StorageUserConnection.java b/services/core/java/com/android/server/storage/StorageUserConnection.java new file mode 100644 index 000000000000..ff9c900958ea --- /dev/null +++ b/services/core/java/com/android/server/storage/StorageUserConnection.java @@ -0,0 +1,319 @@ +/* + * Copyright (C) 2019 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.storage; + +import static android.service.storage.ExternalStorageService.EXTRA_ERROR; +import static android.service.storage.ExternalStorageService.FLAG_SESSION_ATTRIBUTE_INDEXABLE; +import static android.service.storage.ExternalStorageService.FLAG_SESSION_TYPE_FUSE; + +import static com.android.server.storage.StorageSessionController.ExternalStorageServiceException; + +import android.annotation.MainThread; +import android.annotation.Nullable; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.Bundle; +import android.os.IBinder; +import android.os.ParcelFileDescriptor; +import android.os.ParcelableException; +import android.os.RemoteCallback; +import android.os.RemoteException; +import android.os.UserHandle; +import android.os.storage.VolumeInfo; +import android.service.storage.ExternalStorageService; +import android.service.storage.IExternalStorageService; +import android.util.Slog; + +import com.android.internal.annotations.GuardedBy; +import com.android.internal.util.Preconditions; + +import java.io.FileDescriptor; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +/** + * Controls the lifecycle of the {@link ActiveConnection} to an {@link ExternalStorageService} + * for a user and manages storage sessions represented by a {@link Session}. + */ +public final class StorageUserConnection { + private static final String TAG = "StorageUserConnection"; + + private final Object mLock = new Object(); + private final Context mContext; + private final int mUserId; + private final StorageSessionController mSessionController; + private final ActiveConnection mActiveConnection = new ActiveConnection(); + @GuardedBy("mLock") private final Map<String, Session> mSessions = new HashMap<>(); + + public StorageUserConnection(Context context, int userId, StorageSessionController controller) { + mContext = Preconditions.checkNotNull(context); + mUserId = Preconditions.checkArgumentNonnegative(userId); + mSessionController = controller; + } + + /** Starts a session for a user */ + public void startSession(FileDescriptor deviceFd, VolumeInfo vol) + throws ExternalStorageServiceException { + String sessionId = vol.getId(); + String upperPath = vol.getPath().getPath(); + String lowerPath = vol.getInternalPath().getPath(); + Slog.i(TAG, "Starting session with id: " + sessionId + " and upperPath: " + upperPath + + " and lowerPath: " + lowerPath); + Session session = new Session(sessionId, deviceFd, upperPath, lowerPath); + synchronized (mLock) { + // TODO(b/135341433): Ensure we don't replace a session without ending the previous + mSessions.put(sessionId, session); + // TODO(b/135341433): If this fails, maybe its at boot, how to handle if not boot? + mActiveConnection.startSessionLocked(session); + } + } + + /** + * Ends a session for a user. + * + * @return {@code true} if there are no more sessions for this user, {@code false} otherwise + **/ + public boolean endSession(VolumeInfo vol) throws ExternalStorageServiceException { + synchronized (mLock) { + Session session = mSessions.remove(vol.getId()); + if (session != null) { + mActiveConnection.endSessionLocked(session); + mSessions.remove(session.sessionId); + } + boolean isAllSessionsEnded = mSessions.isEmpty(); + if (isAllSessionsEnded) { + mActiveConnection.close(); + } + return isAllSessionsEnded; + } + } + + /** Starts all available sessions for a user */ + public void startAllSessions() throws ExternalStorageServiceException { + synchronized (mLock) { + for (Session session : mSessions.values()) { + mActiveConnection.startSessionLocked(session); + } + } + } + + /** Ends all available sessions for a user */ + public void endAllSessions() throws ExternalStorageServiceException { + synchronized (mLock) { + for (Session session : mSessions.values()) { + mActiveConnection.endSessionLocked(session); + mSessions.remove(session.sessionId); + } + mActiveConnection.close(); + } + } + + private final class ActiveConnection implements AutoCloseable { + // Lifecycle connection to the external storage service, needed to unbind. + // We should only try to bind if mServiceConnection is null. + // Non-null indicates we are connected or connecting. + @GuardedBy("mLock") @Nullable private ServiceConnection mServiceConnection; + // Binder object representing the external storage service. + // Non-null indicates we are connected + @GuardedBy("mLock") @Nullable private IExternalStorageService mRemote; + // Exception, if any, thrown from #startSessionLocked or #endSessionLocked + // Local variables cannot be referenced from a lambda expression :( so we + // save the exception received in the callback here. Since we guard access + // (and clear the exception state) with the same lock which we hold during + // the entire transaction, there is no risk of race. + @GuardedBy("mLock") @Nullable private ParcelableException mLastException; + + @Override + public void close() { + synchronized (mLock) { + if (mServiceConnection != null) { + mContext.unbindService(mServiceConnection); + } + mServiceConnection = null; + mRemote = null; + } + } + + public void startSessionLocked(Session session) throws ExternalStorageServiceException { + if (mServiceConnection == null || mRemote == null) { + if (mServiceConnection == null) { + // Not bound + bindLocked(); + } // else we are binding. In any case when we bind we'll re-start all sessions + return; + } + + CountDownLatch latch = new CountDownLatch(1); + try { + mRemote.startSession(session.sessionId, + FLAG_SESSION_TYPE_FUSE | FLAG_SESSION_ATTRIBUTE_INDEXABLE, + new ParcelFileDescriptor(session.deviceFd), session.upperPath, + session.lowerPath, new RemoteCallback(result -> + setResultLocked(latch, result))); + + } catch (RemoteException e) { + throw new ExternalStorageServiceException(e); + } + waitAndReturnResultLocked(latch); + } + + public void endSessionLocked(Session session) throws ExternalStorageServiceException { + if (mRemote == null) { + // TODO(b/135341433): This assumes if there is no connection, there are no + // session resources held. Need to document in the ExternalStorageService + // API that implementors should end all sessions and clean up resources + // when the binding is lost, onDestroy? + return; + } + + CountDownLatch latch = new CountDownLatch(1); + try { + mRemote.endSession(session.sessionId, new RemoteCallback(result -> + setResultLocked(latch, result))); + } catch (RemoteException e) { + throw new ExternalStorageServiceException(e); + } + waitAndReturnResultLocked(latch); + } + + private void setResultLocked(CountDownLatch latch, Bundle result) { + mLastException = result.getParcelable(EXTRA_ERROR); + latch.countDown(); + } + + private void waitAndReturnResultLocked(CountDownLatch latch) + throws ExternalStorageServiceException { + try { + // TODO(b/140025078): Call ActivityManager ANR API? + latch.await(20, TimeUnit.SECONDS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new IllegalStateException( + "Interrupted while waiting for ExternalStorageService result"); + } + if (mLastException != null) { + mLastException = null; + try { + mLastException.maybeRethrow(IOException.class); + } catch (IOException e) { + throw new ExternalStorageServiceException(e); + } + throw new RuntimeException(mLastException); + } + mLastException = null; + } + + private void bindLocked() { + ComponentName name = mSessionController.getExternalStorageServiceComponentName(); + if (name == null) { + Slog.i(TAG, "Not ready to bind to the ExternalStorageService for user " + mUserId); + return; + } + + ServiceConnection connection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + Slog.i(TAG, "Service: [" + name + "] connected. User [" + mUserId + "]"); + handleConnection(service); + } + + @Override + @MainThread + public void onServiceDisconnected(ComponentName name) { + // Service crashed or process was killed, #onServiceConnected will be called + // Don't need to re-bind. + Slog.i(TAG, "Service: [" + name + "] disconnected. User [" + mUserId + "]"); + handleDisconnection(); + } + + @Override + public void onBindingDied(ComponentName name) { + // Application hosting service probably got updated + // Need to re-bind. + Slog.i(TAG, "Service: [" + name + "] died. User [" + mUserId + "]"); + handleDisconnection(); + } + + @Override + public void onNullBinding(ComponentName name) { + // Should never happen. Service returned null from #onBind. + Slog.wtf(TAG, "Service: [" + name + "] is null. User [" + mUserId + "]"); + } + + private void handleConnection(IBinder service) { + synchronized (mLock) { + if (mServiceConnection != null) { + mRemote = IExternalStorageService.Stub.asInterface(service); + } else { + Slog.wtf(TAG, "Service connected without a connection object??"); + } + } + + try { + startAllSessions(); + } catch (ExternalStorageServiceException e) { + Slog.e(TAG, "Failed to start all sessions", e); + } + } + + private void handleDisconnection() { + close(); + // Clear all sessions because we will need a new device fd since + // StorageManagerService will reset the device mount state and #startSession + // will be called for any required mounts. + synchronized (mLock) { + mSessions.clear(); + } + // Notify StorageManagerService so it can restart all necessary sessions + mSessionController.getCallback().onUserDisconnected(mUserId); + } + }; + + Slog.i(TAG, "Binding to the ExternalStorageService for user " + mUserId); + // TODO(b/135341433): Verify required service flags BIND_IMPORTANT? + if (mContext.bindServiceAsUser(new Intent().setComponent(name), connection, + Context.BIND_AUTO_CREATE, UserHandle.of(mUserId))) { + Slog.i(TAG, "Bound to the ExternalStorageService for user " + mUserId); + mServiceConnection = connection; + // Reset the remote, we will set when we connect + mRemote = null; + } else { + Slog.w(TAG, "Failed to bind to the ExternalStorageService for user " + mUserId); + } + } + } + + private static final class Session { + public final String sessionId; + public final FileDescriptor deviceFd; + public final String lowerPath; + public final String upperPath; + + Session(String sessionId, FileDescriptor deviceFd, String upperPath, + String lowerPath) { + this.sessionId = sessionId; + this.upperPath = upperPath; + this.lowerPath = lowerPath; + this.deviceFd = deviceFd; + } + } +} diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index fc36e9984c1b..36e906cf9a62 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -1935,7 +1935,10 @@ final class ActivityRecord extends ConfigurationContainer { * HistoryRecord. * Normally the server-side record will be removed when the client reports back after * destruction. If, however, at this point there is no client process attached, the record will - * removed immediately. + * be removed immediately. + * + * @return {@code true} if activity was immediately removed from history, {@code false} + * otherwise. */ boolean destroyImmediately(boolean removeFromApp, String reason) { if (DEBUG_SWITCH || DEBUG_CLEANUP) { @@ -2918,7 +2921,7 @@ final class ActivityRecord extends ConfigurationContainer { return false; } - boolean handleAlreadyVisible() { + void handleAlreadyVisible() { stopFreezingScreenLocked(false); try { if (returningOptions != null) { @@ -2926,7 +2929,6 @@ final class ActivityRecord extends ConfigurationContainer { } } catch(RemoteException e) { } - return mState == RESUMED; } static void activityResumedLocked(IBinder token) { @@ -3430,8 +3432,8 @@ final class ActivityRecord extends ConfigurationContainer { return false; } final ActivityStack stack = getActivityStack(); - if (stack == null || this == stack.getResumedActivity() || this == stack.mPausingActivity - || !mHaveState || !stopped) { + if (isState(RESUMED) || stack == null || this == stack.mPausingActivity || !mHaveState + || !stopped) { // We're not ready for this kind of thing. return false; } diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java index 8bdedffa581a..5bd557df0616 100644 --- a/services/core/java/com/android/server/wm/ActivityStack.java +++ b/services/core/java/com/android/server/wm/ActivityStack.java @@ -2088,15 +2088,12 @@ class ActivityStack extends ConfigurationContainer { boolean aboveTop = top != null; final boolean stackShouldBeVisible = shouldBeVisible(starting); boolean behindFullscreenActivity = !stackShouldBeVisible; - boolean resumeNextActivity = isFocusable() && isInStackLocked(starting) == null; + final boolean resumeTopActivity = isFocusable() && isInStackLocked(starting) == null; for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { final TaskRecord task = mTaskHistory.get(taskNdx); final ArrayList<ActivityRecord> activities = task.mActivities; for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { final ActivityRecord r = activities.get(activityNdx); - if (r.finishing) { - continue; - } final boolean isTop = r == top; if (aboveTop && !isTop) { continue; @@ -2112,6 +2109,9 @@ class ActivityStack extends ConfigurationContainer { behindFullscreenActivity, r); } if (reallyVisible) { + if (r.finishing) { + continue; + } if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Make visible? " + r + " finishing=" + r.finishing + " state=" + r.getState()); // First: if this is not the current activity being started, make @@ -2122,15 +2122,8 @@ class ActivityStack extends ConfigurationContainer { } if (!r.attachedToProcess()) { - if (makeVisibleAndRestartIfNeeded(starting, configChanges, isTop, - resumeNextActivity, r)) { - if (activityNdx >= activities.size()) { - // Record may be removed if its process needs to restart. - activityNdx = activities.size() - 1; - } else { - resumeNextActivity = false; - } - } + makeVisibleAndRestartIfNeeded(starting, configChanges, isTop, + resumeTopActivity && isTop, r); } else if (r.visible) { // If this activity is already visible, then there is nothing to do here. if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, @@ -2140,10 +2133,7 @@ class ActivityStack extends ConfigurationContainer { r.makeClientVisible(); } - if (r.handleAlreadyVisible()) { - resumeNextActivity = false; - } - + r.handleAlreadyVisible(); if (notifyClients) { r.makeActiveIfNeeded(starting); } diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index 3c5947a51e11..f2ca2ba82dfb 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -82,6 +82,8 @@ import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.PRE import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.SCREEN_COMPAT_PACKAGES; import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.ScreenCompatPackage.MODE; import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.ScreenCompatPackage.PACKAGE; +import static com.android.server.wm.ActivityStack.ActivityState.DESTROYED; +import static com.android.server.wm.ActivityStack.ActivityState.DESTROYING; import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING; import static com.android.server.wm.ActivityStackSupervisor.DEFER_RESUME; import static com.android.server.wm.ActivityStackSupervisor.ON_TOP; @@ -3237,11 +3239,12 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { synchronized (mGlobalLock) { final long origId = Binder.clearCallingIdentity(); try { - ActivityRecord r = ActivityRecord.isInStackLocked(token); - if (r == null) { + final ActivityRecord r = ActivityRecord.isInStackLocked(token); + if (r == null || !r.isDestroyable()) { return false; } - return r.safelyDestroy("app-req"); + r.destroyImmediately(true /* removeFromApp */, "app-req"); + return r.isState(DESTROYING, DESTROYED); } finally { Binder.restoreCallingIdentity(origId); } diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java index d4e95cfb8025..6b2f9da77f62 100644 --- a/services/core/java/com/android/server/wm/AppTransitionController.java +++ b/services/core/java/com/android/server/wm/AppTransitionController.java @@ -462,7 +462,7 @@ public class AppTransitionController { // new rotation animation after the old one finally finishes. It's better to defer the // app transition. if (screenRotationAnimation != null && screenRotationAnimation.isAnimating() && - mService.getDefaultDisplayContentLocked().rotationNeedsUpdate()) { + mDisplayContent.getDisplayRotation().needsUpdate()) { if (DEBUG_APP_TRANSITIONS) { Slog.v(TAG, "Delaying app transition for screen rotation animation to finish"); } diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index e851a06cbb85..71a0126d74f2 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -130,9 +130,7 @@ import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_PLACING_SU import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_REMOVING_FOCUS; import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_ASSIGN_LAYERS; import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES; -import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_ACTIVE; import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_TIMEOUT; -import static com.android.server.wm.WindowManagerService.WINDOW_FREEZE_TIMEOUT_DURATION; import static com.android.server.wm.WindowManagerService.dipToPixel; import static com.android.server.wm.WindowManagerService.logSurface; import static com.android.server.wm.WindowState.EXCLUSION_LEFT; @@ -148,6 +146,7 @@ import android.annotation.CallSuper; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.content.pm.ActivityInfo.ScreenOrientation; import android.content.res.CompatibilityInfo; import android.content.res.Configuration; import android.graphics.Bitmap; @@ -323,7 +322,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo private final Display mDisplay; private final DisplayMetrics mDisplayMetrics = new DisplayMetrics(); private final DisplayPolicy mDisplayPolicy; - private DisplayRotation mDisplayRotation; + private final DisplayRotation mDisplayRotation; DisplayFrames mDisplayFrames; private final RemoteCallbackList<ISystemGestureExclusionListener> @@ -352,22 +351,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo float mCompatibleScreenScale; /** - * Current rotation of the display. - * Constants as per {@link android.view.Surface.Rotation}. - * - * @see #updateRotationUnchecked() - */ - private int mRotation = 0; - - /** - * Last applied orientation of the display. - * Constants as per {@link android.content.pm.ActivityInfo.ScreenOrientation}. - * - * @see #updateOrientationFromAppTokens() - */ - private int mLastOrientation = SCREEN_ORIENTATION_UNSPECIFIED; - - /** * Orientation forced by some window. If there is no visible window that specifies orientation * it is set to {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED}. * @@ -407,7 +390,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo // Accessed directly by all users. private boolean mLayoutNeeded; int pendingLayoutChanges; - int mDeferredRotationPauseCount; /** * Used to gate application window layout until we have sent the complete configuration. @@ -1138,25 +1120,17 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo return mInsetsStateController; } - @VisibleForTesting - void setDisplayRotation(DisplayRotation displayRotation) { - mDisplayRotation = displayRotation; - } - + @Surface.Rotation int getRotation() { - return mRotation; - } - - @VisibleForTesting - void setRotation(int newRotation) { - mRotation = newRotation; - mDisplayRotation.setRotation(newRotation); + return mDisplayRotation.getRotation(); } + @ScreenOrientation int getLastOrientation() { - return mLastOrientation; + return mDisplayRotation.getLastOrientation(); } + @ScreenOrientation int getLastWindowForcedOrientation() { return mLastWindowForcedOrientation; } @@ -1166,48 +1140,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo } /** - * Temporarily pauses rotation changes until resumed. - * - * This can be used to prevent rotation changes from occurring while the user is - * performing certain operations, such as drag and drop. - * - * This call nests and must be matched by an equal number of calls to - * {@link #resumeRotationLocked}. - */ - void pauseRotationLocked() { - mDeferredRotationPauseCount++; - } - - /** - * Resumes normal rotation changes after being paused. - */ - void resumeRotationLocked() { - if (mDeferredRotationPauseCount <= 0) { - return; - } - - mDeferredRotationPauseCount--; - if (mDeferredRotationPauseCount == 0) { - updateRotationAndSendNewConfigIfNeeded(); - } - } - - /** - * If this is true we have updated our desired orientation, but not yet changed the real - * orientation our applied our screen rotation animation. For example, because a previous - * screen rotation was in progress. - * - * @return {@code true} if the there is an ongoing rotation change. - */ - boolean rotationNeedsUpdate() { - final int lastOrientation = getLastOrientation(); - final int oldRotation = getRotation(); - - final int rotation = mDisplayRotation.rotationForOrientation(lastOrientation, oldRotation); - return oldRotation != rotation; - } - - /** * The display content may have configuration set from {@link #DisplayWindowSettings}. This * callback let the owner of container know there is existing configuration to prevent the * values from being replaced by the initializing {@link #ActivityDisplay}. @@ -1225,7 +1157,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo configureDisplayPolicy(); setLayoutNeeded(); - boolean configChanged = updateOrientationFromAppTokens(); + boolean configChanged = updateOrientation(); final Configuration currentDisplayConfig = getConfiguration(); mTmpConfiguration.setTo(currentDisplayConfig); computeScreenConfiguration(mTmpConfiguration); @@ -1263,8 +1195,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo @Override boolean onDescendantOrientationChanged(IBinder freezeDisplayToken, ConfigurationContainer requestingContainer) { - final Configuration config = updateOrientationFromAppTokens( - getRequestedOverrideConfiguration(), freezeDisplayToken, false); + final Configuration config = updateOrientation( + getRequestedOverrideConfiguration(), freezeDisplayToken, false /* forceUpdate */); // If display rotation class tells us that it doesn't consider app requested orientation, // this display won't rotate just because of an app changes its requested orientation. Thus // it indicates that this display chooses not to handle this request. @@ -1298,31 +1230,35 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo /** * Determine the new desired orientation of this display. * - * The orientation is computed from non-application windows first. If none of the - * non-application windows specify orientation, the orientation is computed from application - * tokens. - * - * @return {@code true} if the orientation is changed. + * @see #getOrientation() + * @return {@code true} if the orientation is changed and the caller should call + * {@link #sendNewConfiguration} if the method returns {@code true}. */ - boolean updateOrientationFromAppTokens() { - return updateOrientationFromAppTokens(false /* forceUpdate */); + boolean updateOrientation() { + return mDisplayRotation.updateOrientation(getOrientation(), false /* forceUpdate */); } /** - * Update orientation of the target display, returning a non-null new Configuration if it has + * Update orientation of the display, returning a non-null new Configuration if it has * changed from the current orientation. If a non-null configuration is returned, someone must * call {@link WindowManagerService#setNewDisplayOverrideConfiguration(Configuration, * DisplayContent)} to tell the window manager it can unfreeze the screen. This will typically - * be done by calling {@link WindowManagerService#sendNewConfiguration(int)}. + * be done by calling {@link #sendNewConfiguration}. + * + * @param currentConfig The current requested override configuration (it is usually set from + * the last {@link #sendNewConfiguration}) of the display. It is used to + * check if the configuration container has the latest state. + * @param freezeDisplayToken Freeze the app window token if the orientation is changed. + * @param forceUpdate See {@link DisplayRotation#updateRotationUnchecked(boolean)} */ - Configuration updateOrientationFromAppTokens(Configuration currentConfig, - IBinder freezeDisplayToken, boolean forceUpdate) { + Configuration updateOrientation(Configuration currentConfig, IBinder freezeDisplayToken, + boolean forceUpdate) { if (!mDisplayReady) { return null; } Configuration config = null; - if (updateOrientationFromAppTokens(forceUpdate)) { + if (mDisplayRotation.updateOrientation(getOrientation(), forceUpdate)) { // If we changed the orientation but mOrientationChangeComplete is already true, // we used seamless rotation, and we don't need to freeze the screen. if (freezeDisplayToken != null && !mWmService.mRoot.mOrientationChangeComplete) { @@ -1345,10 +1281,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo if (currentConfig.diff(mTmpConfiguration) != 0) { mWaitingForConfig = true; setLayoutNeeded(); - int[] anim = new int[2]; - getDisplayPolicy().selectRotationAnimationLw(anim); - - mWmService.startFreezingDisplayLocked(anim[0], anim[1], this); + mDisplayRotation.prepareNormalRotationAnimation(); config = new Configuration(mTmpConfiguration); } } @@ -1356,163 +1289,14 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo return config; } - - private boolean updateOrientationFromAppTokens(boolean forceUpdate) { - final int req = getOrientation(); - if (req != mLastOrientation || forceUpdate) { - mLastOrientation = req; - mDisplayRotation.setCurrentOrientation(req); - return updateRotationUnchecked(forceUpdate); - } - return false; - } - - /** - * Update rotation of the display and send configuration if the rotation is changed. - * - * @return {@code true} if the rotation has been changed and the new config is sent. - */ - boolean updateRotationAndSendNewConfigIfNeeded() { - final boolean changed = updateRotationUnchecked(false /* forceUpdate */); - if (changed) { - sendNewConfiguration(); - } - return changed; - } - /** * Update rotation of the display. * * @return {@code true} if the rotation has been changed. In this case YOU MUST CALL - * {@link WindowManagerService#sendNewConfiguration(int)} TO UNFREEZE THE SCREEN. + * {@link #sendNewConfiguration} TO UNFREEZE THE SCREEN. */ boolean updateRotationUnchecked() { - return updateRotationUnchecked(false /* forceUpdate */); - } - - /** - * Update rotation of the DisplayContent with an option to force the update. This updates - * the container's perception of rotation and, depending on the top activities, will freeze - * the screen or start seamless rotation. The display itself gets rotated in - * {@link #applyRotationLocked} during {@link DisplayContent#sendNewConfiguration}. - * - * @param forceUpdate Force the rotation update. Sometimes in WM we might skip updating - * orientation because we're waiting for some rotation to finish or display - * to unfreeze, which results in configuration of the previously visible - * activity being applied to a newly visible one. Forcing the rotation - * update allows to workaround this issue. - * @return {@code true} if the rotation has been changed. In this case YOU MUST CALL - * {@link WindowManagerService#sendNewConfiguration(int)} TO COMPLETE THE ROTATION AND - * UNFREEZE THE SCREEN. - */ - boolean updateRotationUnchecked(boolean forceUpdate) { - ScreenRotationAnimation screenRotationAnimation; - if (!forceUpdate) { - if (mDeferredRotationPauseCount > 0) { - // Rotation updates have been paused temporarily. Defer the update until - // updates have been resumed. - if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, rotation is paused."); - return false; - } - - screenRotationAnimation = - mWmService.mAnimator.getScreenRotationAnimationLocked(mDisplayId); - if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) { - // Rotation updates cannot be performed while the previous rotation change - // animation is still in progress. Skip this update. We will try updating - // again after the animation is finished and the display is unfrozen. - if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, animation in progress."); - return false; - } - if (mWmService.mDisplayFrozen) { - // Even if the screen rotation animation has finished (e.g. isAnimating - // returns false), there is still some time where we haven't yet unfrozen - // the display. We also need to abort rotation here. - if (DEBUG_ORIENTATION) Slog.v(TAG_WM, - "Deferring rotation, still finishing previous rotation"); - return false; - } - } - - if (!mWmService.mDisplayEnabled) { - // No point choosing a rotation if the display is not enabled. - if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, display is not enabled."); - return false; - } - - final int oldRotation = mRotation; - final int lastOrientation = mLastOrientation; - final int rotation = mDisplayRotation.rotationForOrientation(lastOrientation, oldRotation); - if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Computed rotation=" + rotation + " for display id=" - + mDisplayId + " based on lastOrientation=" + lastOrientation - + " and oldRotation=" + oldRotation); - boolean mayRotateSeamlessly = mDisplayPolicy.shouldRotateSeamlessly(mDisplayRotation, - oldRotation, rotation); - - if (mayRotateSeamlessly) { - final WindowState seamlessRotated = getWindow((w) -> w.mSeamlesslyRotated); - if (seamlessRotated != null && !forceUpdate) { - // We can't rotate (seamlessly or not) while waiting for the last seamless rotation - // to complete (that is, waiting for windows to redraw). It's tempting to check - // w.mSeamlessRotationCount but that could be incorrect in the case of - // window-removal. - return false; - } - - // In the presence of the PINNED stack or System Alert - // windows we unfortunately can not seamlessly rotate. - if (hasPinnedStack()) { - mayRotateSeamlessly = false; - } - for (int i = 0; i < mWmService.mSessions.size(); i++) { - if (mWmService.mSessions.valueAt(i).hasAlertWindowSurfaces()) { - mayRotateSeamlessly = false; - break; - } - } - } - final boolean rotateSeamlessly = mayRotateSeamlessly; - - if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Display id=" + mDisplayId - + " selected orientation " + lastOrientation - + ", got rotation " + rotation); - - if (oldRotation == rotation) { - // No change. - return false; - } - - if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Display id=" + mDisplayId - + " rotation changed to " + rotation - + " from " + oldRotation - + ", lastOrientation=" + lastOrientation); - - if (DisplayContent.deltaRotation(rotation, oldRotation) != 2) { - mWaitingForConfig = true; - } - - mRotation = rotation; - - mWmService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_ACTIVE; - mWmService.mH.sendNewMessageDelayed(WindowManagerService.H.WINDOW_FREEZE_TIMEOUT, - this, WINDOW_FREEZE_TIMEOUT_DURATION); - - setLayoutNeeded(); - final int[] anim = new int[2]; - mDisplayPolicy.selectRotationAnimationLw(anim); - - if (!rotateSeamlessly) { - mWmService.startFreezingDisplayLocked(anim[0], anim[1], this); - // startFreezingDisplayLocked can reset the ScreenRotationAnimation. - } else { - // The screen rotation animation uses a screenshot to freeze the screen - // while windows resize underneath. - // When we are rotating seamlessly, we allow the elements to transition - // to their rotated state independently and without a freeze required. - mWmService.startSeamlessRotation(); - } - - return true; + return mDisplayRotation.updateRotationUnchecked(false /* forceUpdate */); } /** @@ -1523,10 +1307,11 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo * @param rotation the rotation to apply. */ void applyRotationLocked(final int oldRotation, final int rotation) { - mDisplayRotation.setRotation(rotation); - final boolean rotateSeamlessly = mWmService.isRotatingSeamlessly(); - ScreenRotationAnimation screenRotationAnimation = rotateSeamlessly + mDisplayRotation.applyCurrentRotation(rotation); + final boolean rotateSeamlessly = mDisplayRotation.isRotatingSeamlessly(); + final ScreenRotationAnimation screenRotationAnimation = rotateSeamlessly ? null : mWmService.mAnimator.getScreenRotationAnimationLocked(mDisplayId); + final Transaction transaction = getPendingTransaction(); // We need to update our screen size information to match the new rotation. If the rotation // has actually changed then this method will return true and, according to the comment at // the top of the method, the caller is obligated to call computeNewConfigurationLocked(). @@ -1537,15 +1322,14 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo // NOTE: We disable the rotation in the emulator because // it doesn't support hardware OpenGL emulation yet. if (screenRotationAnimation != null && screenRotationAnimation.hasScreenshot()) { - screenRotationAnimation.setRotation(getPendingTransaction(), rotation); + screenRotationAnimation.setRotation(transaction, rotation); } forAllWindows(w -> { - w.seamlesslyRotateIfAllowed(getPendingTransaction(), oldRotation, rotation, - rotateSeamlessly); + w.seamlesslyRotateIfAllowed(transaction, oldRotation, rotation, rotateSeamlessly); }, true /* traverseTopToBottom */); - mWmService.mDisplayManagerInternal.performTraversal(getPendingTransaction()); + mWmService.mDisplayManagerInternal.performTraversal(transaction); scheduleAnimation(); forAllWindows(w -> { @@ -1627,19 +1411,20 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo */ private DisplayInfo updateDisplayAndOrientation(int uiMode, Configuration outConfig) { // Use the effective "visual" dimensions based on current rotation - final boolean rotated = (mRotation == ROTATION_90 || mRotation == ROTATION_270); + final int rotation = getRotation(); + final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270); final int dw = rotated ? mBaseDisplayHeight : mBaseDisplayWidth; final int dh = rotated ? mBaseDisplayWidth : mBaseDisplayHeight; // Update application display metrics. - final WmDisplayCutout wmDisplayCutout = calculateDisplayCutoutForRotation(mRotation); + final WmDisplayCutout wmDisplayCutout = calculateDisplayCutoutForRotation(rotation); final DisplayCutout displayCutout = wmDisplayCutout.getDisplayCutout(); - final int appWidth = mDisplayPolicy.getNonDecorDisplayWidth(dw, dh, mRotation, uiMode, + final int appWidth = mDisplayPolicy.getNonDecorDisplayWidth(dw, dh, rotation, uiMode, displayCutout); - final int appHeight = mDisplayPolicy.getNonDecorDisplayHeight(dw, dh, mRotation, uiMode, + final int appHeight = mDisplayPolicy.getNonDecorDisplayHeight(dw, dh, rotation, uiMode, displayCutout); - mDisplayInfo.rotation = mRotation; + mDisplayInfo.rotation = rotation; mDisplayInfo.logicalWidth = dw; mDisplayInfo.logicalHeight = dh; mDisplayInfo.logicalDensityDpi = mBaseDisplayDensity; @@ -2044,7 +1829,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo return mTaskStackContainers.getPinnedStack(); } - private boolean hasPinnedStack() { + boolean hasPinnedStack() { return mTaskStackContainers.getPinnedStack() != null; } @@ -2198,6 +1983,11 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo return mImeWindowsContainers.forAllWindows(callback, traverseTopToBottom); } + /** + * In the general case, the orientation is computed from the above app windows first. If none of + * the above app windows specify orientation, the orientation is computed from the child window + * container, e.g. {@link AppWindowToken#getOrientation(int)}. + */ @Override int getOrientation() { final WindowManagerPolicy policy = mWmService.mPolicy; @@ -2222,8 +2012,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo // things aren't stable while the display is frozen, for example the window could be // momentarily unavailable due to activity relaunch. if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Display id=" + mDisplayId - + " is frozen while keyguard locked, return " + mLastOrientation); - return mLastOrientation; + + " is frozen while keyguard locked, return " + getLastOrientation()); + return getLastOrientation(); } } else { final int orientation = mAboveAppWindowsContainers.getOrientation(); @@ -2835,7 +2625,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo } proto.write(DPI, mBaseDisplayDensity); mDisplayInfo.writeToProto(proto, DISPLAY_INFO); - proto.write(ROTATION, mRotation); + proto.write(ROTATION, getRotation()); final ScreenRotationAnimation screenRotationAnimation = mWmService.mAnimator.getScreenRotationAnimationLocked(mDisplayId); if (screenRotationAnimation != null) { @@ -2892,8 +2682,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo pw.println(); pw.print(prefix); pw.print("mLayoutSeq="); pw.println(mLayoutSeq); - pw.print(prefix); - pw.print("mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount); pw.print(" mCurrentFocus="); pw.println(mCurrentFocus); if (mLastFocus != mCurrentFocus) { @@ -3264,6 +3052,15 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo return mTmpWindow != null; } + boolean hasAlertWindowSurfaces() { + for (int i = mWmService.mSessions.size() - 1; i >= 0; --i) { + if (mWmService.mSessions.valueAt(i).hasAlertWindowSurfaces(this)) { + return true; + } + } + return false; + } + /** * Set input method window for the display. * @param win Set when window added or Null when destroyed. @@ -3747,7 +3544,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_CONFIG) != 0) { if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout"); - if (updateOrientationFromAppTokens()) { + if (updateOrientation()) { setLayoutNeeded(); sendNewConfiguration(); } @@ -3887,7 +3684,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo calculateDisplayCutoutForRotation(mDisplayInfo.rotation)); // TODO: Not sure if we really need to set the rotation here since we are updating from // the display info above... - mDisplayFrames.mRotation = mRotation; + mDisplayFrames.mRotation = getRotation(); mDisplayPolicy.beginLayoutLw(mDisplayFrames, getConfiguration().uiMode); int seq = mLayoutSeq + 1; @@ -4002,25 +3799,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo } } - void onSeamlessRotationTimeout() { - // Used to indicate the layout is needed. - mTmpWindow = null; - - forAllWindows(w -> { - if (!w.mSeamlesslyRotated) { - return; - } - mTmpWindow = w; - w.setDisplayLayoutNeeded(); - w.finishSeamlessRotation(true /* timeout */); - mWmService.markForSeamlessRotation(w, false); - }, true /* traverseTopToBottom */); - - if (mTmpWindow != null) { - mWmService.mWindowPlacerLocked.performSurfacePlacement(); - } - } - void setExitingTokensHasVisible(boolean hasVisible) { for (int i = mExitingTokens.size() - 1; i >= 0; i--) { mExitingTokens.get(i).hasVisible = hasVisible; @@ -4502,11 +4280,11 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo } if (DEBUG_ORIENTATION) Slog.v(TAG_WM, - "No app is requesting an orientation, return " + mLastOrientation + "No app is requesting an orientation, return " + getLastOrientation() + " for display id=" + mDisplayId); // The next app has not been requested to be visible, so we keep the current orientation // to prevent freezing/unfreezing the display too early. - return mLastOrientation; + return getLastOrientation(); } @Override diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index e5962ae19413..8328770b6cb2 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -57,10 +57,6 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_INHERIT_TRANS import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION; -import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE; -import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_JUMPCUT; -import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_ROTATE; -import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS; import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING; import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST; @@ -257,7 +253,6 @@ public class DisplayPolicy { private volatile boolean mNavigationBarCanMove; private volatile boolean mNavigationBarLetsThroughTaps; private volatile boolean mNavigationBarAlwaysShowOnSideGesture; - private volatile boolean mAllowSeamlessRotationDespiteNavBarMoving; // Written by vr manager thread, only read in this class. private volatile boolean mPersistentVrModeEnabled; @@ -1151,81 +1146,6 @@ public class DisplayPolicy { } /** - * Determine the animation to run for a rotation transition based on the - * top fullscreen windows {@link WindowManager.LayoutParams#rotationAnimation} - * and whether it is currently fullscreen and frontmost. - * - * @param anim The exiting animation resource id is stored in anim[0], the - * entering animation resource id is stored in anim[1]. - */ - public void selectRotationAnimationLw(int anim[]) { - // If the screen is off or non-interactive, force a jumpcut. - final boolean forceJumpcut = !mScreenOnFully || !mService.mPolicy.okToAnimate(); - if (DEBUG_ANIM) Slog.i(TAG, "selectRotationAnimation mTopFullscreen=" - + mTopFullscreenOpaqueWindowState + " rotationAnimation=" - + (mTopFullscreenOpaqueWindowState == null - ? "0" : mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation) - + " forceJumpcut=" + forceJumpcut); - if (forceJumpcut) { - anim[0] = R.anim.rotation_animation_jump_exit; - anim[1] = R.anim.rotation_animation_enter; - return; - } - if (mTopFullscreenOpaqueWindowState != null) { - int animationHint = mTopFullscreenOpaqueWindowState.getRotationAnimationHint(); - if (animationHint < 0 && mTopIsFullscreen) { - animationHint = mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation; - } - switch (animationHint) { - case ROTATION_ANIMATION_CROSSFADE: - case ROTATION_ANIMATION_SEAMLESS: // Crossfade is fallback for seamless. - anim[0] = R.anim.rotation_animation_xfade_exit; - anim[1] = R.anim.rotation_animation_enter; - break; - case ROTATION_ANIMATION_JUMPCUT: - anim[0] = R.anim.rotation_animation_jump_exit; - anim[1] = R.anim.rotation_animation_enter; - break; - case ROTATION_ANIMATION_ROTATE: - default: - anim[0] = anim[1] = 0; - break; - } - } else { - anim[0] = anim[1] = 0; - } - } - - /** - * Validate whether the current top fullscreen has specified the same - * {@link WindowManager.LayoutParams#rotationAnimation} value as that - * being passed in from the previous top fullscreen window. - * - * @param exitAnimId exiting resource id from the previous window. - * @param enterAnimId entering resource id from the previous window. - * @param forceDefault For rotation animations only, if true ignore the - * animation values and just return false. - * @return true if the previous values are still valid, false if they - * should be replaced with the default. - */ - public boolean validateRotationAnimationLw(int exitAnimId, int enterAnimId, - boolean forceDefault) { - switch (exitAnimId) { - case R.anim.rotation_animation_xfade_exit: - case R.anim.rotation_animation_jump_exit: - // These are the only cases that matter. - if (forceDefault) { - return false; - } - int anim[] = new int[2]; - selectRotationAnimationLw(anim); - return (exitAnimId == anim[0] && enterAnimId == anim[1]); - default: - return true; - } - } - - /** * Called when a new system UI visibility is being reported, allowing * the policy to adjust what is actually reported. * @param visibility The raw visibility reported by the status bar. @@ -2388,6 +2308,14 @@ public class DisplayPolicy { displayFrames.mVoiceContent.bottom = Math.min(displayFrames.mVoiceContent.bottom, top); } + WindowState getTopFullscreenOpaqueWindow() { + return mTopFullscreenOpaqueWindowState; + } + + boolean isTopLayoutFullscreen() { + return mTopIsFullscreen; + } + /** * Called following layout of all windows before each window has policy applied. */ @@ -2773,8 +2701,7 @@ public class DisplayPolicy { mNavigationBarCanMove = mDisplayContent.mBaseDisplayWidth != mDisplayContent.mBaseDisplayHeight && res.getBoolean(R.bool.config_navBarCanMove); - mAllowSeamlessRotationDespiteNavBarMoving = - res.getBoolean(R.bool.config_allowSeamlessRotationDespiteNavBarMoving); + mDisplayContent.getDisplayRotation().updateUserDependentConfiguration(res); } /** @@ -3562,45 +3489,6 @@ public class DisplayPolicy { return (systemUiFlags & disableNavigationBar) == disableNavigationBar; } - boolean shouldRotateSeamlessly(DisplayRotation displayRotation, int oldRotation, - int newRotation) { - // For the upside down rotation we don't rotate seamlessly as the navigation - // bar moves position. - // Note most apps (using orientation:sensor or user as opposed to fullSensor) - // will not enter the reverse portrait orientation, so actually the - // orientation won't change at all. - if (oldRotation == displayRotation.getUpsideDownRotation() - || newRotation == displayRotation.getUpsideDownRotation()) { - return false; - } - // If the navigation bar can't change sides, then it will - // jump when we change orientations and we don't rotate - // seamlessly - unless that is allowed, eg. with gesture - // navigation where the navbar is low-profile enough that this isn't very noticeable. - if (!navigationBarCanMove() && !mAllowSeamlessRotationDespiteNavBarMoving) { - return false; - } - - final WindowState w = mTopFullscreenOpaqueWindowState; - if (w == null || w != mFocusedWindow) { - return false; - } - // If the bounds of activity window is different from its parent, then reject to be seamless - // because the window position may change after rotation that will look like a sudden jump. - if (w.mAppToken != null && !w.mAppToken.matchParentBounds()) { - return false; - } - - // We only enable seamless rotation if the top window has requested - // it and is in the fullscreen opaque state. Seamless rotation - // requires freezing various Surface states and won't work well - // with animations, so we disable it in the animation case for now. - if (!w.isAnimatingLw() && w.getAttrs().rotationAnimation == ROTATION_ANIMATION_SEAMLESS) { - return true; - } - return false; - } - private final Runnable mHiddenNavPanic = new Runnable() { @Override public void run() { @@ -3665,7 +3553,7 @@ public class DisplayPolicy { } void dump(String prefix, PrintWriter pw) { - pw.print(prefix); pw.print("DisplayPolicy"); + pw.print(prefix); pw.println("DisplayPolicy"); prefix += " "; pw.print(prefix); pw.print("mCarDockEnablesAccelerometer="); pw.print(mCarDockEnablesAccelerometer); @@ -3724,12 +3612,12 @@ public class DisplayPolicy { pw.print(prefix); pw.print("mForcingShowNavBarLayer="); pw.println(mForcingShowNavBarLayer); } - pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen); + pw.print(prefix); pw.print("mTopIsFullscreen="); pw.println(mTopIsFullscreen); pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar); pw.print(" mForceStatusBarFromKeyguard="); pw.println(mForceStatusBarFromKeyguard); - pw.print(" mForceShowSystemBarsFromExternal="); - pw.println(mForceShowSystemBarsFromExternal); - pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.println(mAllowLockscreenWhenOn); + pw.print(prefix); pw.print("mForceShowSystemBarsFromExternal="); + pw.print(mForceShowSystemBarsFromExternal); + pw.print(" mAllowLockscreenWhenOn="); pw.println(mAllowLockscreenWhenOn); mStatusBarController.dump(pw, prefix); mNavigationBarController.dump(pw, prefix); diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java index 410cc94869d8..4d188f4f1e19 100644 --- a/services/core/java/com/android/server/wm/DisplayRotation.java +++ b/services/core/java/com/android/server/wm/DisplayRotation.java @@ -16,11 +16,21 @@ package com.android.server.wm; +import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; +import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE; +import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_JUMPCUT; +import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_ROTATE; +import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS; + import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.LID_OPEN; +import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; +import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_ACTIVE; +import static com.android.server.wm.WindowManagerService.WINDOW_FREEZE_TIMEOUT_DURATION; +import android.annotation.AnimRes; import android.annotation.IntDef; import android.annotation.UserIdInt; import android.app.ActivityManager; @@ -28,6 +38,7 @@ import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; +import android.content.pm.ActivityInfo.ScreenOrientation; import android.content.pm.PackageManager; import android.content.res.Resources; import android.database.ContentObserver; @@ -41,6 +52,7 @@ import android.util.Slog; import android.util.SparseArray; import android.view.Surface; +import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.server.LocalServices; import com.android.server.UiThread; @@ -59,6 +71,13 @@ import java.lang.annotation.RetentionPolicy; public class DisplayRotation { private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplayRotation" : TAG_WM; + private static class RotationAnimationPair { + @AnimRes + int mEnter; + @AnimRes + int mExit; + } + private final WindowManagerService mService; private final DisplayContent mDisplayContent; private final DisplayPolicy mDisplayPolicy; @@ -72,12 +91,30 @@ public class DisplayRotation { private final int mCarDockRotation; private final int mDeskDockRotation; private final int mUndockedHdmiRotation; + private final RotationAnimationPair mTmpRotationAnim = new RotationAnimationPair(); private OrientationListener mOrientationListener; private StatusBarManagerInternal mStatusBarManagerInternal; private SettingsObserver mSettingsObserver; - private int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; + @ScreenOrientation + private int mCurrentAppOrientation = SCREEN_ORIENTATION_UNSPECIFIED; + + /** + * Last applied orientation of the display. + * + * @see #updateOrientationFromApp + */ + @ScreenOrientation + private int mLastOrientation = SCREEN_ORIENTATION_UNSPECIFIED; + + /** + * Current rotation of the display. + * + * @see #updateRotationUnchecked + */ + @Surface.Rotation + private int mRotation; @VisibleForTesting int mLandscapeRotation; // default landscape @@ -88,11 +125,52 @@ public class DisplayRotation { @VisibleForTesting int mUpsideDownRotation; // "other" portrait - // Behavior of rotation suggestions. (See Settings.Secure.SHOW_ROTATION_SUGGESTION) + private boolean mAllowSeamlessRotationDespiteNavBarMoving; + + private int mDeferredRotationPauseCount; + + /** + * A count of the windows which are 'seamlessly rotated', e.g. a surface at an old orientation + * is being transformed. We freeze orientation updates while any windows are seamlessly rotated, + * so we need to track when this hits zero so we can apply deferred orientation updates. + */ + private int mSeamlessRotationCount; + + /** + * True in the interval from starting seamless rotation until the last rotated window draws in + * the new orientation. + */ + private boolean mRotatingSeamlessly; + + /** + * Behavior of rotation suggestions. + * + * @see Settings.Secure#SHOW_ROTATION_SUGGESTIONS + */ private int mShowRotationSuggestions; - private int mAllowAllRotations = -1; + private static final int ALLOW_ALL_ROTATIONS_UNDEFINED = -1; + private static final int ALLOW_ALL_ROTATIONS_DISABLED = 0; + private static final int ALLOW_ALL_ROTATIONS_ENABLED = 1; + + @IntDef({ ALLOW_ALL_ROTATIONS_UNDEFINED, ALLOW_ALL_ROTATIONS_DISABLED, + ALLOW_ALL_ROTATIONS_ENABLED }) + @Retention(RetentionPolicy.SOURCE) + private @interface AllowAllRotations {} + + /** + * Whether to allow the screen to rotate to all rotations (including 180 degree) according to + * the sensor even when the current orientation is not + * {@link ActivityInfo#SCREEN_ORIENTATION_FULL_SENSOR} or + * {@link ActivityInfo#SCREEN_ORIENTATION_FULL_USER}. + */ + @AllowAllRotations + private int mAllowAllRotations = ALLOW_ALL_ROTATIONS_UNDEFINED; + + @WindowManagerPolicy.UserRotationMode private int mUserRotationMode = WindowManagerPolicy.USER_ROTATION_FREE; + + @Surface.Rotation private int mUserRotation = Surface.ROTATION_0; /** @@ -125,6 +203,7 @@ public class DisplayRotation { * regardless of all other states (including app requrested orientation). {@code true} the * display rotation should be fixed to user specified rotation, {@code false} otherwise. */ + @FixedToUserRotation private int mFixedToUserRotation = FIXED_TO_USER_ROTATION_DEFAULT; private int mDemoHdmiRotation; @@ -149,21 +228,17 @@ public class DisplayRotation { mLock = lock; isDefaultDisplay = displayContent.isDefaultDisplay; - mSupportAutoRotation = mContext.getResources().getBoolean( - com.android.internal.R.bool.config_supportAutoRotation); - mLidOpenRotation = readRotation( - com.android.internal.R.integer.config_lidOpenRotation); - mCarDockRotation = readRotation( - com.android.internal.R.integer.config_carDockRotation); - mDeskDockRotation = readRotation( - com.android.internal.R.integer.config_deskDockRotation); - mUndockedHdmiRotation = readRotation( - com.android.internal.R.integer.config_undockedHdmiRotation); + mSupportAutoRotation = + mContext.getResources().getBoolean(R.bool.config_supportAutoRotation); + mLidOpenRotation = readRotation(R.integer.config_lidOpenRotation); + mCarDockRotation = readRotation(R.integer.config_carDockRotation); + mDeskDockRotation = readRotation(R.integer.config_deskDockRotation); + mUndockedHdmiRotation = readRotation(R.integer.config_undockedHdmiRotation); if (isDefaultDisplay) { final Handler uiHandler = UiThread.getHandler(); mOrientationListener = new OrientationListener(mContext, uiHandler); - mOrientationListener.setCurrentRotation(displayContent.getRotation()); + mOrientationListener.setCurrentRotation(mRotation); mSettingsObserver = new SettingsObserver(uiHandler); mSettingsObserver.observe(); } @@ -188,12 +263,21 @@ public class DisplayRotation { return -1; } + /** + * Updates the configuration which may have different values depending on current user, e.g. + * runtime resource overlay. + */ + void updateUserDependentConfiguration(Resources currentUserRes) { + mAllowSeamlessRotationDespiteNavBarMoving = + currentUserRes.getBoolean(R.bool.config_allowSeamlessRotationDespiteNavBarMoving); + } + void configure(int width, int height, int shortSizeDp, int longSizeDp) { final Resources res = mContext.getResources(); if (width > height) { mLandscapeRotation = Surface.ROTATION_0; mSeascapeRotation = Surface.ROTATION_180; - if (res.getBoolean(com.android.internal.R.bool.config_reverseDefaultRotation)) { + if (res.getBoolean(R.bool.config_reverseDefaultRotation)) { mPortraitRotation = Surface.ROTATION_90; mUpsideDownRotation = Surface.ROTATION_270; } else { @@ -203,7 +287,7 @@ public class DisplayRotation { } else { mPortraitRotation = Surface.ROTATION_0; mUpsideDownRotation = Surface.ROTATION_180; - if (res.getBoolean(com.android.internal.R.bool.config_reverseDefaultRotation)) { + if (res.getBoolean(R.bool.config_reverseDefaultRotation)) { mLandscapeRotation = Surface.ROTATION_270; mSeascapeRotation = Surface.ROTATION_90; } else { @@ -246,19 +330,325 @@ public class DisplayRotation { && !"true".equals(SystemProperties.get("config.override_forced_orient")); } - void setRotation(int rotation) { + void applyCurrentRotation(@Surface.Rotation int rotation) { if (mOrientationListener != null) { mOrientationListener.setCurrentRotation(rotation); } } - void setCurrentOrientation(int newOrientation) { + @VisibleForTesting + void setRotation(@Surface.Rotation int rotation) { + mRotation = rotation; + } + + @Surface.Rotation + int getRotation() { + return mRotation; + } + + @ScreenOrientation + int getLastOrientation() { + return mLastOrientation; + } + + boolean updateOrientation(@ScreenOrientation int newOrientation, boolean forceUpdate) { + if (newOrientation == mLastOrientation && !forceUpdate) { + return false; + } + mLastOrientation = newOrientation; if (newOrientation != mCurrentAppOrientation) { mCurrentAppOrientation = newOrientation; if (isDefaultDisplay) { updateOrientationListenerLw(); } } + return updateRotationUnchecked(forceUpdate); + } + + /** + * Update rotation of the display and send configuration if the rotation is changed. + * + * @return {@code true} if the rotation has been changed and the new config is sent. + */ + boolean updateRotationAndSendNewConfigIfChanged() { + final boolean changed = updateRotationUnchecked(false /* forceUpdate */); + if (changed) { + mDisplayContent.sendNewConfiguration(); + } + return changed; + } + + /** + * Update rotation with an option to force the update. This updates the container's perception + * of rotation and, depending on the top activities, will freeze the screen or start seamless + * rotation. The display itself gets rotated in {@link DisplayContent#applyRotationLocked} + * during {@link DisplayContent#sendNewConfiguration}. + * + * @param forceUpdate Force the rotation update. Sometimes in WM we might skip updating + * orientation because we're waiting for some rotation to finish or display + * to unfreeze, which results in configuration of the previously visible + * activity being applied to a newly visible one. Forcing the rotation + * update allows to workaround this issue. + * @return {@code true} if the rotation has been changed. In this case YOU MUST CALL + * {@link DisplayContent#sendNewConfiguration} TO COMPLETE THE ROTATION AND UNFREEZE + * THE SCREEN. + */ + boolean updateRotationUnchecked(boolean forceUpdate) { + final int displayId = mDisplayContent.getDisplayId(); + if (!forceUpdate) { + if (mDeferredRotationPauseCount > 0) { + // Rotation updates have been paused temporarily. Defer the update until updates + // have been resumed. + if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, rotation is paused."); + return false; + } + + final ScreenRotationAnimation screenRotationAnimation = + mService.mAnimator.getScreenRotationAnimationLocked(displayId); + if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) { + // Rotation updates cannot be performed while the previous rotation change animation + // is still in progress. Skip this update. We will try updating again after the + // animation is finished and the display is unfrozen. + if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, animation in progress."); + return false; + } + if (mService.mDisplayFrozen) { + // Even if the screen rotation animation has finished (e.g. isAnimating returns + // false), there is still some time where we haven't yet unfrozen the display. We + // also need to abort rotation here. + if (DEBUG_ORIENTATION) Slog.v(TAG_WM, + "Deferring rotation, still finishing previous rotation"); + return false; + } + } + + if (!mService.mDisplayEnabled) { + // No point choosing a rotation if the display is not enabled. + if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, display is not enabled."); + return false; + } + + final int oldRotation = mRotation; + final int lastOrientation = mLastOrientation; + final int rotation = rotationForOrientation(lastOrientation, oldRotation); + if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Computed rotation=" + rotation + " for display id=" + + displayId + " based on lastOrientation=" + lastOrientation + + " and oldRotation=" + oldRotation); + + if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Display id=" + displayId + + " selected orientation " + lastOrientation + + ", got rotation " + rotation); + + if (oldRotation == rotation) { + // No change. + return false; + } + + if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Display id=" + displayId + + " rotation changed to " + rotation + + " from " + oldRotation + + ", lastOrientation=" + lastOrientation); + + if (DisplayContent.deltaRotation(rotation, oldRotation) != 2) { + mDisplayContent.mWaitingForConfig = true; + } + + mRotation = rotation; + + mService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_ACTIVE; + mService.mH.sendNewMessageDelayed(WindowManagerService.H.WINDOW_FREEZE_TIMEOUT, + mDisplayContent, WINDOW_FREEZE_TIMEOUT_DURATION); + + mDisplayContent.setLayoutNeeded(); + + if (shouldRotateSeamlessly(oldRotation, rotation, forceUpdate)) { + // The screen rotation animation uses a screenshot to freeze the screen while windows + // resize underneath. When we are rotating seamlessly, we allow the elements to + // transition to their rotated state independently and without a freeze required. + prepareSeamlessRotation(); + } else { + prepareNormalRotationAnimation(); + } + + return true; + } + + void prepareNormalRotationAnimation() { + final RotationAnimationPair anim = selectRotationAnimation(); + mService.startFreezingDisplayLocked(anim.mExit, anim.mEnter, mDisplayContent); + } + + private void prepareSeamlessRotation() { + // We are careful to reset this in case a window was removed before it finished + // seamless rotation. + mSeamlessRotationCount = 0; + mRotatingSeamlessly = true; + } + + boolean isRotatingSeamlessly() { + return mRotatingSeamlessly; + } + + @VisibleForTesting + boolean shouldRotateSeamlessly(int oldRotation, int newRotation, boolean forceUpdate) { + final WindowState w = mDisplayPolicy.getTopFullscreenOpaqueWindow(); + if (w == null || w != mDisplayContent.mCurrentFocus) { + return false; + } + // We only enable seamless rotation if the top window has requested it and is in the + // fullscreen opaque state. Seamless rotation requires freezing various Surface states and + // won't work well with animations, so we disable it in the animation case for now. + if (w.getAttrs().rotationAnimation != ROTATION_ANIMATION_SEAMLESS || w.isAnimatingLw()) { + return false; + } + + // For the upside down rotation we don't rotate seamlessly as the navigation bar moves + // position. Note most apps (using orientation:sensor or user as opposed to fullSensor) + // will not enter the reverse portrait orientation, so actually the orientation won't change + // at all. + if (oldRotation == mUpsideDownRotation || newRotation == mUpsideDownRotation) { + return false; + } + + // If the navigation bar can't change sides, then it will jump when we change orientations + // and we don't rotate seamlessly - unless that is allowed, eg. with gesture navigation + // where the navbar is low-profile enough that this isn't very noticeable. + if (!mAllowSeamlessRotationDespiteNavBarMoving && !mDisplayPolicy.navigationBarCanMove()) { + return false; + } + + // If the bounds of activity window is different from its parent, then reject to be seamless + // because the window position may change after rotation that will look like a sudden jump. + if (w.mAppToken != null && !w.mAppToken.matchParentBounds()) { + return false; + } + + // In the presence of the PINNED stack or System Alert windows we unfortunately can not + // seamlessly rotate. + if (mDisplayContent.hasPinnedStack() || mDisplayContent.hasAlertWindowSurfaces()) { + return false; + } + + // We can't rotate (seamlessly or not) while waiting for the last seamless rotation to + // complete (that is, waiting for windows to redraw). It's tempting to check + // mSeamlessRotationCount but that could be incorrect in the case of window-removal. + if (!forceUpdate && mDisplayContent.getWindow(win -> win.mSeamlesslyRotated) != null) { + return false; + } + + return true; + } + + void markForSeamlessRotation(WindowState w, boolean seamlesslyRotated) { + if (seamlesslyRotated == w.mSeamlesslyRotated || w.mForceSeamlesslyRotate) { + return; + } + + w.mSeamlesslyRotated = seamlesslyRotated; + if (seamlesslyRotated) { + mSeamlessRotationCount++; + } else { + mSeamlessRotationCount--; + } + if (mSeamlessRotationCount == 0) { + if (DEBUG_ORIENTATION) { + Slog.i(TAG, "Performing post-rotate rotation after seamless rotation"); + } + // Finish seamless rotation. + mRotatingSeamlessly = false; + + updateRotationAndSendNewConfigIfChanged(); + } + } + + void onSeamlessRotationTimeout() { + final boolean[] isLayoutNeeded = { false }; + + mDisplayContent.forAllWindows(w -> { + if (!w.mSeamlesslyRotated) { + return; + } + isLayoutNeeded[0] = true; + w.setDisplayLayoutNeeded(); + w.finishSeamlessRotation(true /* timeout */); + markForSeamlessRotation(w, false /* seamlesslyRotated */); + }, true /* traverseTopToBottom */); + + if (isLayoutNeeded[0]) { + mService.mWindowPlacerLocked.performSurfacePlacement(); + } + } + + /** + * Returns the animation to run for a rotation transition based on the top fullscreen windows + * {@link android.view.WindowManager.LayoutParams#rotationAnimation} and whether it is currently + * fullscreen and frontmost. + */ + private RotationAnimationPair selectRotationAnimation() { + // If the screen is off or non-interactive, force a jumpcut. + final boolean forceJumpcut = !mDisplayPolicy.isScreenOnFully() + || !mService.mPolicy.okToAnimate(); + final WindowState topFullscreen = mDisplayPolicy.getTopFullscreenOpaqueWindow(); + if (DEBUG_ANIM) Slog.i(TAG, "selectRotationAnimation topFullscreen=" + + topFullscreen + " rotationAnimation=" + + (topFullscreen == null ? 0 : topFullscreen.getAttrs().rotationAnimation) + + " forceJumpcut=" + forceJumpcut); + if (forceJumpcut) { + mTmpRotationAnim.mExit = R.anim.rotation_animation_jump_exit; + mTmpRotationAnim.mEnter = R.anim.rotation_animation_enter; + return mTmpRotationAnim; + } + if (topFullscreen != null) { + int animationHint = topFullscreen.getRotationAnimationHint(); + if (animationHint < 0 && mDisplayPolicy.isTopLayoutFullscreen()) { + animationHint = topFullscreen.getAttrs().rotationAnimation; + } + switch (animationHint) { + case ROTATION_ANIMATION_CROSSFADE: + case ROTATION_ANIMATION_SEAMLESS: // Crossfade is fallback for seamless. + mTmpRotationAnim.mExit = R.anim.rotation_animation_xfade_exit; + mTmpRotationAnim.mEnter = R.anim.rotation_animation_enter; + break; + case ROTATION_ANIMATION_JUMPCUT: + mTmpRotationAnim.mExit = R.anim.rotation_animation_jump_exit; + mTmpRotationAnim.mEnter = R.anim.rotation_animation_enter; + break; + case ROTATION_ANIMATION_ROTATE: + default: + mTmpRotationAnim.mExit = mTmpRotationAnim.mEnter = 0; + break; + } + } else { + mTmpRotationAnim.mExit = mTmpRotationAnim.mEnter = 0; + } + return mTmpRotationAnim; + } + + /** + * Validate whether the current top fullscreen has specified the same + * {@link android.view.WindowManager.LayoutParams#rotationAnimation} value as that being passed + * in from the previous top fullscreen window. + * + * @param exitAnimId exiting resource id from the previous window. + * @param enterAnimId entering resource id from the previous window. + * @param forceDefault For rotation animations only, if true ignore the animation values and + * just return false. + * @return {@code true} if the previous values are still valid, false if they should be replaced + * with the default. + */ + boolean validateRotationAnimation(int exitAnimId, int enterAnimId, boolean forceDefault) { + switch (exitAnimId) { + case R.anim.rotation_animation_xfade_exit: + case R.anim.rotation_animation_jump_exit: + // These are the only cases that matter. + if (forceDefault) { + return false; + } + final RotationAnimationPair anim = selectRotationAnimation(); + return exitAnimId == anim.mExit && enterAnimId == anim.mEnter; + default: + return true; + } } void restoreSettings(int userRotationMode, int userRotation, @@ -327,7 +717,7 @@ public class DisplayRotation { } void freezeRotation(int rotation) { - rotation = (rotation == -1) ? mDisplayContent.getRotation() : rotation; + rotation = (rotation == -1) ? mRotation : rotation; setUserRotation(WindowManagerPolicy.USER_ROTATION_LOCKED, rotation); } @@ -407,6 +797,30 @@ public class DisplayRotation { } /** + * Temporarily pauses rotation changes until resumed. + * <p> + * This can be used to prevent rotation changes from occurring while the user is performing + * certain operations, such as drag and drop. + * <p> + * This call nests and must be matched by an equal number of calls to {@link #resume}. + */ + void pause() { + mDeferredRotationPauseCount++; + } + + /** Resumes normal rotation changes after being paused. */ + void resume() { + if (mDeferredRotationPauseCount <= 0) { + return; + } + + mDeferredRotationPauseCount--; + if (mDeferredRotationPauseCount == 0) { + updateRotationAndSendNewConfigIfChanged(); + } + } + + /** * Various use cases for invoking this function: * <li>Screen turning off, should always disable listeners if already enabled.</li> * <li>Screen turned on and current app has sensor based orientation, enable listeners @@ -515,14 +929,28 @@ public class DisplayRotation { } /** - * Given an orientation constant, returns the appropriate surface rotation, - * taking into account sensors, docking mode, rotation lock, and other factors. + * If this is true we have updated our desired orientation, but not yet changed the real + * orientation our applied our screen rotation animation. For example, because a previous + * screen rotation was in progress. + * + * @return {@code true} if the there is an ongoing rotation change. + */ + boolean needsUpdate() { + final int oldRotation = mRotation; + final int rotation = rotationForOrientation(mLastOrientation, oldRotation); + return oldRotation != rotation; + } + + /** + * Given an orientation constant, returns the appropriate surface rotation, taking into account + * sensors, docking mode, rotation lock, and other factors. * * @param orientation An orientation constant, such as - * {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_LANDSCAPE}. + * {@link ActivityInfo#SCREEN_ORIENTATION_LANDSCAPE}. * @param lastRotation The most recently used rotation. * @return The surface rotation to use. */ + @VisibleForTesting int rotationForOrientation(int orientation, int lastRotation) { if (DEBUG_ORIENTATION) { Slog.v(TAG, "rotationForOrientation(orient=" @@ -614,15 +1042,16 @@ public class DisplayRotation { || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) { // Otherwise, use sensor only if requested by the application or enabled // by default for USER or UNSPECIFIED modes. Does not apply to NOSENSOR. - if (mAllowAllRotations < 0) { - // Can't read this during init() because the context doesn't - // have display metrics at that time so we cannot determine - // tablet vs. phone then. + if (mAllowAllRotations == ALLOW_ALL_ROTATIONS_UNDEFINED) { + // Can't read this during init() because the context doesn't have display metrics at + // that time so we cannot determine tablet vs. phone then. mAllowAllRotations = mContext.getResources().getBoolean( - com.android.internal.R.bool.config_allowAllRotations) ? 1 : 0; + R.bool.config_allowAllRotations) + ? ALLOW_ALL_ROTATIONS_ENABLED + : ALLOW_ALL_ROTATIONS_DISABLED; } if (sensorRotation != Surface.ROTATION_180 - || mAllowAllRotations == 1 + || mAllowAllRotations == ALLOW_ALL_ROTATIONS_ENABLED || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER) { preferredRotation = sensorRotation; @@ -883,6 +1312,10 @@ public class DisplayRotation { pw.println(prefix + "DisplayRotation"); pw.println(prefix + " mCurrentAppOrientation=" + ActivityInfo.screenOrientationToString(mCurrentAppOrientation)); + pw.println(prefix + " mLastOrientation=" + mLastOrientation); + pw.print(prefix + " mRotation=" + mRotation); + pw.println(" mDeferredRotationPauseCount=" + mDeferredRotationPauseCount); + pw.print(prefix + " mLandscapeRotation=" + Surface.rotationToString(mLandscapeRotation)); pw.println(" mSeascapeRotation=" + Surface.rotationToString(mSeascapeRotation)); pw.print(prefix + " mPortraitRotation=" + Surface.rotationToString(mPortraitRotation)); diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java index c8f7af5b10c8..c48f07c213fe 100644 --- a/services/core/java/com/android/server/wm/DragState.java +++ b/services/core/java/com/android/server/wm/DragState.java @@ -305,7 +305,7 @@ class DragState { if (DEBUG_ORIENTATION) { Slog.d(TAG_WM, "Pausing rotation during drag"); } - mDisplayContent.pauseRotationLocked(); + mDisplayContent.getDisplayRotation().pause(); } void tearDown() { @@ -324,7 +324,7 @@ class DragState { if (DEBUG_ORIENTATION) { Slog.d(TAG_WM, "Resuming rotation after drag"); } - mDisplayContent.resumeRotationLocked(); + mDisplayContent.getDisplayRotation().resume(); } } diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java index 402ec5976840..b7835aa1c04e 100644 --- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java +++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java @@ -106,6 +106,11 @@ class InsetsSourceProvider { @Nullable TriConsumer<DisplayFrames, WindowState, Rect> frameProvider) { if (mWin != null) { mWin.setInsetProvider(null); + // The window may be animating such that we can hand out the leash to the control + // target. Revoke the leash by cancelling the animation to correct the state. + // TODO: Ideally, we should wait for the animation to finish so previous window can + // animate-out as new one animates-in. + mWin.cancelAnimation(); } mWin = win; mFrameProvider = frameProvider; diff --git a/services/core/java/com/android/server/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java index 3401de629268..eb5d096aa781 100644 --- a/services/core/java/com/android/server/wm/RootActivityContainer.java +++ b/services/core/java/com/android/server/wm/RootActivityContainer.java @@ -636,7 +636,7 @@ class RootActivityContainer extends ConfigurationContainer final DisplayContent displayContent = mRootWindowContainer.getDisplayContent(displayId); Configuration config = null; if (displayContent != null) { - config = displayContent.updateOrientationFromAppTokens( + config = displayContent.updateOrientation( getDisplayOverrideConfiguration(displayId), starting != null && starting.mayFreezeScreenLocked(starting.app) ? starting.appToken : null, diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index a00bee0859ad..968d02baff7b 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -925,8 +925,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> boolean updateRotationUnchecked() { boolean changed = false; for (int i = mChildren.size() - 1; i >= 0; i--) { - final DisplayContent displayContent = mChildren.get(i); - if (displayContent.updateRotationAndSendNewConfigIfNeeded()) { + if (mChildren.get(i).getDisplayRotation().updateRotationAndSendNewConfigIfChanged()) { changed = true; } } diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java index 9f8f2651389a..4a76042a2c66 100644 --- a/services/core/java/com/android/server/wm/Session.java +++ b/services/core/java/com/android/server/wm/Session.java @@ -40,6 +40,7 @@ import android.os.Process; import android.os.RemoteException; import android.os.Trace; import android.os.UserHandle; +import android.util.ArraySet; import android.util.MergedConfiguration; import android.util.Slog; import android.view.DisplayCutout; @@ -57,9 +58,7 @@ import com.android.internal.os.logging.MetricsLoggerWrapper; import com.android.server.wm.WindowManagerService.H; import java.io.PrintWriter; -import java.util.HashSet; import java.util.List; -import java.util.Set; import java.util.function.BiConsumer; /** @@ -75,9 +74,9 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient { SurfaceSession mSurfaceSession; private int mNumWindow = 0; // Set of visible application overlay window surfaces connected to this session. - private final Set<WindowSurfaceController> mAppOverlaySurfaces = new HashSet<>(); + private final ArraySet<WindowSurfaceController> mAppOverlaySurfaces = new ArraySet<>(); // Set of visible alert window surfaces connected to this session. - private final Set<WindowSurfaceController> mAlertWindowSurfaces = new HashSet<>(); + private final ArraySet<WindowSurfaceController> mAlertWindowSurfaces = new ArraySet<>(); private final DragDropController mDragDropController; final boolean mCanAddInternalSystemWindow; final boolean mCanHideNonSystemOverlayWindows; @@ -609,8 +608,15 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient { return mStringName; } - boolean hasAlertWindowSurfaces() { - return !mAlertWindowSurfaces.isEmpty(); + /** @return {@code true} if there is an alert window surface on the given display. */ + boolean hasAlertWindowSurfaces(DisplayContent displayContent) { + for (int i = mAlertWindowSurfaces.size() - 1; i >= 0; i--) { + final WindowSurfaceController surfaceController = mAlertWindowSurfaces.valueAt(i); + if (surfaceController.mAnimator.mWin.getDisplayContent() == displayContent) { + return true; + } + } + return false; } public void blessInputSurface(int displayId, SurfaceControl surface, diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java index 2fc64eaf8c97..8b0b6ce8ce32 100644 --- a/services/core/java/com/android/server/wm/TaskPositioner.java +++ b/services/core/java/com/android/server/wm/TaskPositioner.java @@ -304,7 +304,7 @@ class TaskPositioner implements IBinder.DeathRecipient { if (DEBUG_ORIENTATION) { Slog.d(TAG, "Pausing rotation during re-position"); } - mDisplayContent.pauseRotationLocked(); + mDisplayContent.getDisplayRotation().pause(); // Notify InputMonitor to take mDragWindowHandle. mDisplayContent.getInputMonitor().updateInputWindowsLw(true /*force*/); @@ -347,7 +347,7 @@ class TaskPositioner implements IBinder.DeathRecipient { if (DEBUG_ORIENTATION) { Slog.d(TAG, "Resuming rotation after re-position"); } - mDisplayContent.resumeRotationLocked(); + mDisplayContent.getDisplayRotation().resume(); mDisplayContent = null; mClientCallback.unlinkToDeath(this, 0 /* flags */); } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index b25677a70929..d49d24545666 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -141,7 +141,6 @@ import android.database.ContentObserver; import android.graphics.Bitmap; import android.graphics.Insets; import android.graphics.Matrix; -import android.graphics.PixelFormat; import android.graphics.Point; import android.graphics.Rect; import android.graphics.RectF; @@ -667,19 +666,6 @@ public class WindowManagerService extends IWindowManager.Stub WindowManagerInternal.OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener; SettingsObserver mSettingsObserver; - /** - * A count of the windows which are 'seamlessly rotated', e.g. a surface - * at an old orientation is being transformed. We freeze orientation updates - * while any windows are seamlessly rotated, so we need to track when this - * hits zero so we can apply deferred orientation updates. - */ - private int mSeamlessRotationCount = 0; - /** - * True in the interval from starting seamless rotation until the last rotated - * window draws in the new orientation. - */ - private boolean mRotatingSeamlessly = false; - private final class SettingsObserver extends ContentObserver { private final Uri mDisplayInversionEnabledUri = Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED); @@ -1247,7 +1233,6 @@ public class WindowManagerService extends IWindowManager.Stub return res; } - boolean reportNewConfig = false; WindowState parentWindow = null; long origId; final int callingUid = Binder.getCallingUid(); @@ -1623,11 +1608,7 @@ public class WindowManagerService extends IWindowManager.Stub if (localLOGV || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "addWindow: New client " + client.asBinder() + ": window=" + win + " Callers=" + Debug.getCallers(5)); - if (win.isVisibleOrAdding() && displayContent.updateOrientationFromAppTokens()) { - reportNewConfig = true; - } - - if (reportNewConfig) { + if (win.isVisibleOrAdding() && displayContent.updateOrientation()) { displayContent.sendNewConfiguration(); } } @@ -1791,11 +1772,11 @@ public class WindowManagerService extends IWindowManager.Stub if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "postWindowRemoveCleanupLocked: " + win); mWindowMap.remove(win.mClient.asBinder()); - markForSeamlessRotation(win, false); + final DisplayContent dc = win.getDisplayContent(); + dc.getDisplayRotation().markForSeamlessRotation(win, false /* seamlesslyRotated */); win.resetAppOpsState(); - final DisplayContent dc = win.getDisplayContent(); if (dc.mCurrentFocus == null) { dc.mWinRemovedSinceNullFocus.add(win); } @@ -2241,9 +2222,8 @@ public class WindowManagerService extends IWindowManager.Stub displayContent.mUnknownAppVisibilityController.notifyRelayouted(win.mAppToken); } - Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, - "relayoutWindow: updateOrientationFromAppTokens"); - configChanged = displayContent.updateOrientationFromAppTokens(); + Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: updateOrientation"); + configChanged = displayContent.updateOrientation(); Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); if (toBeDisplayed && win.mIsWallpaper) { @@ -4859,7 +4839,7 @@ public class WindowManagerService extends IWindowManager.Stub case SEAMLESS_ROTATION_TIMEOUT: { final DisplayContent displayContent = (DisplayContent) msg.obj; synchronized (mGlobalLock) { - displayContent.onSeamlessRotationTimeout(); + displayContent.getDisplayRotation().onSeamlessRotationTimeout(); } break; } @@ -5321,7 +5301,7 @@ public class WindowManagerService extends IWindowManager.Stub void startFreezingDisplayLocked(int exitAnim, int enterAnim, DisplayContent displayContent) { - if (mDisplayFrozen || mRotatingSeamlessly) { + if (mDisplayFrozen || displayContent.getDisplayRotation().isRotatingSeamlessly()) { return; } @@ -5430,8 +5410,8 @@ public class WindowManagerService extends IWindowManager.Stub if (DEBUG_ORIENTATION) Slog.i(TAG_WM, "**** Dismissing screen rotation animation"); DisplayInfo displayInfo = displayContent.getDisplayInfo(); // Get rotation animation again, with new top window - if (!displayContent.getDisplayPolicy() - .validateRotationAnimationLw(mExitAnimId, mEnterAnimId, false)) { + if (!displayContent.getDisplayRotation().validateRotationAnimation( + mExitAnimId, mEnterAnimId, false /* forceDefault */)) { mExitAnimId = mEnterAnimId = 0; } if (screenRotationAnimation.dismiss(mTransaction, MAX_ANIMATION_DURATION, @@ -5458,7 +5438,7 @@ public class WindowManagerService extends IWindowManager.Stub // to avoid inconsistent states. However, something interesting // could have actually changed during that time so re-evaluate it // now to catch that. - configChanged = displayContent != null && displayContent.updateOrientationFromAppTokens(); + configChanged = displayContent != null && displayContent.updateOrientation(); // A little kludge: a lot could have happened while the // display was frozen, so now that we are coming back we @@ -6984,26 +6964,6 @@ public class WindowManagerService extends IWindowManager.Stub mPolicy.requestUserActivityNotification(); } - void markForSeamlessRotation(WindowState w, boolean seamlesslyRotated) { - if (seamlesslyRotated == w.mSeamlesslyRotated || w.mForceSeamlesslyRotate) { - return; - } - w.mSeamlesslyRotated = seamlesslyRotated; - if (seamlesslyRotated) { - mSeamlessRotationCount++; - } else { - mSeamlessRotationCount--; - } - if (mSeamlessRotationCount == 0) { - if (DEBUG_ORIENTATION) { - Slog.i(TAG, "Performing post-rotate rotation after seamless rotation"); - } - finishSeamlessRotation(); - - w.getDisplayContent().updateRotationAndSendNewConfigIfNeeded(); - } - } - private final class LocalService extends WindowManagerInternal { @Override public void requestTraversalFromDisplayManager() { @@ -7531,22 +7491,6 @@ public class WindowManagerService extends IWindowManager.Stub return mSurfaceBuilderFactory.make(s); } - void startSeamlessRotation() { - // We are careful to reset this in case a window was removed before it finished - // seamless rotation. - mSeamlessRotationCount = 0; - - mRotatingSeamlessly = true; - } - - boolean isRotatingSeamlessly() { - return mRotatingSeamlessly; - } - - void finishSeamlessRotation() { - mRotatingSeamlessly = false; - } - /** * Called when the state of lock task mode changes. This should be used to disable immersive * mode confirmation. diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index d87a0ed966dc..4900869f209d 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -652,7 +652,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP if (mForceSeamlesslyRotate || requested) { mPendingSeamlessRotate = new SeamlessRotator(oldRotation, rotation, getDisplayInfo()); mPendingSeamlessRotate.unrotate(transaction, this); - mWmService.markForSeamlessRotation(this, true); + getDisplayContent().getDisplayRotation().markForSeamlessRotation(this, + true /* seamlesslyRotated */); } } @@ -661,7 +662,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP mPendingSeamlessRotate.finish(this, timeout); mFinishSeamlessRotateFrameNumber = getFrameNumber(); mPendingSeamlessRotate = null; - mWmService.markForSeamlessRotation(this, false); + getDisplayContent().getDisplayRotation().markForSeamlessRotation(this, + false /* seamlesslyRotated */); } } @@ -2086,7 +2088,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP // So just update orientation if needed. if (wasVisible) { final DisplayContent displayContent = getDisplayContent(); - if (displayContent.updateOrientationFromAppTokens()) { + if (displayContent.updateOrientation()) { displayContent.sendNewConfiguration(); } } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index f933b09b0c15..478bc88fe815 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -248,6 +248,7 @@ import com.android.internal.util.Preconditions; import com.android.internal.util.StatLogger; import com.android.internal.util.XmlUtils; import com.android.internal.widget.LockPatternUtils; +import com.android.internal.widget.LockSettingsInternal; import com.android.server.LocalServices; import com.android.server.LockGuard; import com.android.server.SystemServerInitThreadPool; @@ -500,6 +501,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { final UsageStatsManagerInternal mUsageStatsManagerInternal; final TelephonyManager mTelephonyManager; private final LockPatternUtils mLockPatternUtils; + private final LockSettingsInternal mLockSettingsInternal; private final DeviceAdminServiceController mDeviceAdminServiceController; private final OverlayPackagesProvider mOverlayPackagesProvider; @@ -739,7 +741,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { final SparseArray<DevicePolicyData> mUserData = new SparseArray<>(); @GuardedBy("getLockObject()") - final SparseArray<PasswordMetrics> mUserPasswordMetrics = new SparseArray<>(); final Handler mHandler; final Handler mBackgroundHandler; @@ -1994,6 +1995,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return IAudioService.Stub.asInterface(ServiceManager.getService(Context.AUDIO_SERVICE)); } + LockSettingsInternal getLockSettingsInternal() { + return LocalServices.getService(LockSettingsInternal.class); + } + boolean isBuildDebuggable() { return Build.IS_DEBUGGABLE; } @@ -2233,7 +2238,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { mLocalService = new LocalService(); mLockPatternUtils = injector.newLockPatternUtils(); - + mLockSettingsInternal = injector.getLockSettingsInternal(); // TODO: why does SecurityLogMonitor need to be created even when mHasFeature == false? mSecurityLogMonitor = new SecurityLogMonitor(this); @@ -2309,17 +2314,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } /** - * Provides PasswordMetrics object corresponding to the given user. - * @param userHandle the user for whom to provide metrics. - * @return the user password metrics, or {@code null} if none have been associated with - * the user yet (for example, if the device has booted but not been unlocked). - */ - @GuardedBy("getLockObject()") - PasswordMetrics getUserPasswordMetricsLocked(int userHandle) { - return mUserPasswordMetrics.get(userHandle); - } - - /** * Creates and loads the policy data from xml for data that is shared between * various profiles of a user. In contrast to {@link #getUserData(int)} * it allows access to data of users other than the calling user. @@ -2353,9 +2347,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (policy != null) { mUserData.remove(userHandle); } - if (mUserPasswordMetrics.get(userHandle) != null) { - mUserPasswordMetrics.remove(userHandle); - } File policyFile = new File(mInjector.environmentGetUserSystemDirectory(userHandle), DEVICE_POLICIES_XML); @@ -4183,15 +4174,16 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { private void updatePasswordValidityCheckpointLocked(int userHandle, boolean parent) { final int credentialOwner = getCredentialOwner(userHandle, parent); DevicePolicyData policy = getUserData(credentialOwner); - PasswordMetrics metrics = getUserPasswordMetricsLocked(credentialOwner); - if (metrics == null) { - metrics = new PasswordMetrics(); + PasswordMetrics metrics = mLockSettingsInternal.getUserPasswordMetrics(credentialOwner); + // Update the checkpoint only if the user's password metrics is known + if (metrics != null) { + final boolean newCheckpoint = isPasswordSufficientForUserWithoutCheckpointLocked( + metrics, userHandle, parent); + if (newCheckpoint != policy.mPasswordValidAtLastCheckpoint) { + policy.mPasswordValidAtLastCheckpoint = newCheckpoint; + saveSettingsLocked(credentialOwner); + } } - policy.mPasswordValidAtLastCheckpoint = - isPasswordSufficientForUserWithoutCheckpointLocked( - metrics, userHandle, parent); - - saveSettingsLocked(credentialOwner); } /** @@ -4766,7 +4758,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { getActiveAdminForCallerLocked(null, DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, parent); int credentialOwner = getCredentialOwner(userHandle, parent); DevicePolicyData policy = getUserDataUnchecked(credentialOwner); - PasswordMetrics metrics = getUserPasswordMetricsLocked(credentialOwner); + PasswordMetrics metrics = mLockSettingsInternal.getUserPasswordMetrics(credentialOwner); return isActivePasswordSufficientForUserLocked( policy.mPasswordValidAtLastCheckpoint, metrics, userHandle, parent); } @@ -4796,15 +4788,15 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { enforceUserUnlocked(targetUser, false); int credentialOwner = getCredentialOwner(userHandle, false); DevicePolicyData policy = getUserDataUnchecked(credentialOwner); - PasswordMetrics metrics = getUserPasswordMetricsLocked(credentialOwner); + PasswordMetrics metrics = mLockSettingsInternal.getUserPasswordMetrics(credentialOwner); return isActivePasswordSufficientForUserLocked( policy.mPasswordValidAtLastCheckpoint, metrics, targetUser, false); } } private boolean isActivePasswordSufficientForUserLocked( - boolean passwordValidAtLastCheckpoint, PasswordMetrics metrics, int userHandle, - boolean parent) { + boolean passwordValidAtLastCheckpoint, @Nullable PasswordMetrics metrics, + int userHandle, boolean parent) { if (!mInjector.storageManagerIsFileBasedEncryptionEnabled() && (metrics == null)) { // Before user enters their password for the first time after a reboot, return the // value of this flag, which tells us whether the password was valid the last time @@ -4815,9 +4807,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } if (metrics == null) { - // This could happen if the user never had a password set, for example, so - // setActivePasswordState has never been called for it. - metrics = new PasswordMetrics(); + // Called on a FBE device when the user password exists but its metrics is unknown. + // This shouldn't happen since we enforce the user to be unlocked (which would result + // in the metrics known to the framework on a FBE device) at all call sites. + throw new IllegalStateException("isActivePasswordSufficient called on FBE-locked user"); } return isPasswordSufficientForUserWithoutCheckpointLocked(metrics, userHandle, parent); @@ -4829,7 +4822,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { * {@code userId} (or its parent, if {@code parent} is set to {@code true}). */ private boolean isPasswordSufficientForUserWithoutCheckpointLocked( - PasswordMetrics metrics, @UserIdInt int userId, boolean parent) { + @NonNull PasswordMetrics metrics, @UserIdInt int userId, boolean parent) { final int requiredQuality = getPasswordQuality(null, userId, parent); if (requiredQuality >= PASSWORD_QUALITY_NUMERIC @@ -4867,7 +4860,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { synchronized (getLockObject()) { int targetUserId = getCredentialOwner(callingUserId, /* parent= */ false); - PasswordMetrics metrics = getUserPasswordMetricsLocked(targetUserId); + PasswordMetrics metrics = mLockSettingsInternal.getUserPasswordMetrics(targetUserId); return metrics == null ? PASSWORD_COMPLEXITY_NONE : metrics.determineComplexity(); } } @@ -6707,31 +6700,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } - /** - * Notify DPMS regarding the metric of the current password. This happens when the user changes - * the password, but also when the user just unlocks the keyguard. In comparison, - * reportPasswordChanged() is only called when the user changes the password. - */ - @Override - public void setActivePasswordState(PasswordMetrics metrics, int userHandle) { - if (!mLockPatternUtils.hasSecureLockScreen()) { - return; - } - enforceFullCrossUsersPermission(userHandle); - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.BIND_DEVICE_ADMIN, null); - - // If the managed profile doesn't have a separate password, set the metrics to default - if (isManagedProfile(userHandle) && !isSeparateProfileChallengeEnabled(userHandle)) { - metrics = new PasswordMetrics(); - } - - validateQualityConstant(metrics.quality); - synchronized (getLockObject()) { - mUserPasswordMetrics.put(userHandle, metrics); - } - } - @Override public void reportPasswordChanged(@UserIdInt int userId) { if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) { diff --git a/services/net/Android.bp b/services/net/Android.bp index fb548f9975c5..8f8f9f9bbf55 100644 --- a/services/net/Android.bp +++ b/services/net/Android.bp @@ -67,7 +67,7 @@ java_library_static { static_libs: [ "dnsresolver_aidl_interface-V2-java", "ipmemorystore-client", - "netd_aidl_interface-V2-java", + "netd_aidl_interface-java", "networkstack-aidl-interfaces-V3-java", ], } diff --git a/services/tests/servicestests/src/com/android/server/accessibility/gestures/TouchExplorerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/gestures/TouchExplorerTest.java index 274ca368baa1..104aacb5ef79 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/gestures/TouchExplorerTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/gestures/TouchExplorerTest.java @@ -16,15 +16,18 @@ package com.android.server.accessibility.gestures; +import static com.android.server.accessibility.gestures.TouchState.STATE_CLEAR; +import static com.android.server.accessibility.gestures.TouchState.STATE_DELEGATING; +import static com.android.server.accessibility.gestures.TouchState.STATE_DRAGGING; +import static com.android.server.accessibility.gestures.TouchState.STATE_TOUCH_EXPLORING; + import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import android.content.Context; import android.graphics.PointF; import android.os.SystemClock; import android.testing.DexmakerShareClassLoaderRule; -import android.util.DebugUtils; import android.view.InputDevice; import android.view.MotionEvent; @@ -46,10 +49,6 @@ import java.util.List; @RunWith(AndroidJUnit4.class) public class TouchExplorerTest { - public static final int STATE_TOUCH_EXPLORING = 0x00000001; - public static final int STATE_DRAGGING = 0x00000002; - public static final int STATE_DELEGATING = 0x00000004; - private static final int FLAG_1FINGER = 0x8000; private static final int FLAG_2FINGERS = 0x0100; private static final int FLAG_3FINGERS = 0x0200; @@ -112,7 +111,7 @@ public class TouchExplorerTest { @Test public void testTwoFingersMove_shouldDelegatingAndInjectActionDownPointerDown() { - goFromStateIdleTo(STATE_MOVING_2FINGERS); + goFromStateClearTo(STATE_MOVING_2FINGERS); assertState(STATE_DELEGATING); assertCapturedEvents( @@ -123,7 +122,7 @@ public class TouchExplorerTest { @Test public void testTwoFingersDrag_shouldDraggingAndActionDown() { - goFromStateIdleTo(STATE_DRAGGING_2FINGERS); + goFromStateClearTo(STATE_DRAGGING_2FINGERS); assertState(STATE_DRAGGING); assertCapturedEvents(MotionEvent.ACTION_DOWN); @@ -133,7 +132,7 @@ public class TouchExplorerTest { @Test public void testTwoFingersNotDrag_shouldDelegatingAndActionUpDownPointerDown() { // only from dragging state, and withMoveHistory no dragging - goFromStateIdleTo(STATE_PINCH_2FINGERS); + goFromStateClearTo(STATE_PINCH_2FINGERS); assertState(STATE_DELEGATING); assertCapturedEvents( @@ -146,7 +145,7 @@ public class TouchExplorerTest { @Test public void testThreeFingersMove_shouldDelegatingAnd3ActionPointerDown() { - goFromStateIdleTo(STATE_MOVING_3FINGERS); + goFromStateClearTo(STATE_MOVING_3FINGERS); assertState(STATE_DELEGATING); assertCapturedEvents( @@ -165,52 +164,47 @@ public class TouchExplorerTest { return new PointF(x, y); } - private static String stateToString(int state) { - return DebugUtils.valueToString(TouchExplorerTest.class, "STATE_", state); - } - - private void goFromStateIdleTo(int state) { + private void goFromStateClearTo(int state) { try { switch (state) { - case STATE_TOUCH_EXPLORING: { + case STATE_CLEAR: { mTouchExplorer.onDestroy(); } break; case STATE_TOUCH_EXPLORING_1FINGER: { - goFromStateIdleTo(STATE_TOUCH_EXPLORING); send(downEvent()); } break; case STATE_TOUCH_EXPLORING_2FINGER: { - goFromStateIdleTo(STATE_TOUCH_EXPLORING_1FINGER); + goFromStateClearTo(STATE_TOUCH_EXPLORING_1FINGER); send(pointerDownEvent()); } break; case STATE_TOUCH_EXPLORING_3FINGER: { - goFromStateIdleTo(STATE_TOUCH_EXPLORING_2FINGER); + goFromStateClearTo(STATE_TOUCH_EXPLORING_2FINGER); send(thirdPointerDownEvent()); } break; case STATE_MOVING_2FINGERS: { - goFromStateIdleTo(STATE_TOUCH_EXPLORING_2FINGER); + goFromStateClearTo(STATE_TOUCH_EXPLORING_2FINGER); moveEachPointers(mLastEvent, p(10, 0), p(5, 10)); send(mLastEvent); } break; case STATE_DRAGGING_2FINGERS: { - goFromStateIdleTo(STATE_TOUCH_EXPLORING_2FINGER); + goFromStateClearTo(STATE_TOUCH_EXPLORING_2FINGER); moveEachPointers(mLastEvent, p(10, 0), p(10, 0)); send(mLastEvent); } break; case STATE_PINCH_2FINGERS: { - goFromStateIdleTo(STATE_DRAGGING_2FINGERS); + goFromStateClearTo(STATE_DRAGGING_2FINGERS); moveEachPointers(mLastEvent, p(10, 0), p(-10, 1)); send(mLastEvent); } break; case STATE_MOVING_3FINGERS: { - goFromStateIdleTo(STATE_TOUCH_EXPLORING_3FINGER); + goFromStateClearTo(STATE_TOUCH_EXPLORING_3FINGER); moveEachPointers(mLastEvent, p(1, 0), p(1, 0), p(1, 0)); send(mLastEvent); } @@ -219,7 +213,8 @@ public class TouchExplorerTest { throw new IllegalArgumentException("Illegal state: " + state); } } catch (Throwable t) { - throw new RuntimeException("Failed to go to state " + stateToString(state), t); + throw new RuntimeException("Failed to go to state " + + TouchState.getStateSymbolicName(state), t); } } @@ -234,9 +229,9 @@ public class TouchExplorerTest { } private void assertState(int expect) { - final String expectState = "STATE_" + stateToString(expect); - assertTrue(String.format("Expect state: %s, but: %s", expectState, mTouchExplorer), - mTouchExplorer.toString().contains(expectState)); + assertEquals( + TouchState.getStateSymbolicName(expect), + TouchState.getStateSymbolicName(mTouchExplorer.getState().getState())); } private void assertCapturedEvents(int... actionsInOrder) { diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java index ce83df702b2a..64ea59d2fa2d 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java @@ -48,6 +48,7 @@ import androidx.annotation.NonNull; import com.android.internal.util.FunctionalUtils.ThrowingRunnable; import com.android.internal.widget.LockPatternUtils; +import com.android.internal.widget.LockSettingsInternal; import com.android.server.net.NetworkPolicyManagerInternal; import java.io.File; @@ -210,6 +211,11 @@ public class DevicePolicyManagerServiceTestable extends DevicePolicyManagerServi } @Override + LockSettingsInternal getLockSettingsInternal() { + return services.lockSettingsInternal; + } + + @Override IAudioService getIAudioService() { return services.iaudioService; } diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java index 9ae9824da3e2..d6cb9826d514 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java @@ -40,6 +40,7 @@ import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Matchers.isNull; import static org.mockito.Mockito.atLeast; +import static org.mockito.Mockito.atMost; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.never; @@ -764,7 +765,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { } /** - * Test for: @{link DevicePolicyManager#setActivePasswordState} + * Test for: @{link DevicePolicyManager#reportPasswordChanged} * * Validates that when the password for a user changes, the notification broadcast intent * {@link DeviceAdminReceiver#ACTION_PASSWORD_CHANGED} is sent to managed profile owners, in @@ -806,7 +807,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { } /** - * Test for: @{link DevicePolicyManager#setActivePasswordState} + * Test for: @{link DevicePolicyManager#reportPasswordChanged} * * Validates that when the password for a managed profile changes, the notification broadcast * intent {@link DeviceAdminReceiver#ACTION_PASSWORD_CHANGED} is only sent to the profile, not @@ -4258,6 +4259,10 @@ public class DevicePolicyManagerTest extends DpmTestBase { mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID; mContext.packageName = admin1.getPackageName(); setupDeviceOwner(); + final int userHandle = UserHandle.getUserId(mContext.binder.callingUid); + // When there is no lockscreen, user password metrics is always empty. + when(getServices().lockSettingsInternal.getUserPasswordMetrics(userHandle)) + .thenReturn(new PasswordMetrics()); // If no password requirements are set, isActivePasswordSufficient should succeed. assertTrue(dpm.isActivePasswordSufficient()); @@ -4266,14 +4271,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { dpm.setPasswordQuality(admin1, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING); reset(mContext.spiedContext); - final int userHandle = UserHandle.getUserId(mContext.binder.callingUid); - PasswordMetrics passwordMetricsNoSymbols = new PasswordMetrics( - DevicePolicyManager.PASSWORD_QUALITY_COMPLEX, 9, - 8, 2, - 6, 1, - 0, 1); // This should be ignored, as there is no lock screen. - dpm.setActivePasswordState(passwordMetricsNoSymbols, userHandle); dpm.reportPasswordChanged(userHandle); // No broadcast should be sent. @@ -4290,19 +4288,24 @@ public class DevicePolicyManagerTest extends DpmTestBase { final int userHandle = UserHandle.getUserId(mContext.binder.callingUid); final long ident = mContext.binder.clearCallingIdentity(); - dpm.setActivePasswordState(passwordMetrics, userHandle); + when(getServices().lockSettingsInternal.getUserPasswordMetrics(userHandle)) + .thenReturn(passwordMetrics); dpm.reportPasswordChanged(userHandle); // Drain ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED broadcasts as part of // reportPasswordChanged() - // This broadcast should be sent 4 times: + // This broadcast should be sent 2-4 times: // * Twice from calls to DevicePolicyManagerService.updatePasswordExpirationsLocked, // once for each affected user, in DevicePolicyManagerService.reportPasswordChanged. - // * Twice from calls to DevicePolicyManagerService.saveSettingsLocked + // * Optionally, at most twice from calls to DevicePolicyManagerService.saveSettingsLocked // in DevicePolicyManagerService.reportPasswordChanged, once with the userId // the password change is relevant to and another with the credential owner of said - // userId. - verify(mContext.spiedContext, times(4)).sendBroadcastAsUser( + // userId, if the password checkpoint value changes. + verify(mContext.spiedContext, atMost(4)).sendBroadcastAsUser( + MockUtils.checkIntentAction( + DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED), + MockUtils.checkUserHandle(userHandle)); + verify(mContext.spiedContext, atLeast(2)).sendBroadcastAsUser( MockUtils.checkIntentAction( DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED), MockUtils.checkUserHandle(userHandle)); @@ -5224,9 +5227,9 @@ public class DevicePolicyManagerTest extends DpmTestBase { mServiceContext.permissions.add(permission.REQUEST_PASSWORD_COMPLEXITY); when(getServices().userManager.getCredentialOwnerProfile(DpmMockContext.CALLER_USER_HANDLE)) .thenReturn(DpmMockContext.CALLER_USER_HANDLE); - dpms.mUserPasswordMetrics.put( - DpmMockContext.CALLER_USER_HANDLE, - PasswordMetrics.computeForPassword("asdf".getBytes())); + when(getServices().lockSettingsInternal + .getUserPasswordMetrics(DpmMockContext.CALLER_USER_HANDLE)) + .thenReturn(PasswordMetrics.computeForPassword("asdf".getBytes())); assertEquals(PASSWORD_COMPLEXITY_MEDIUM, dpm.getPasswordComplexity()); } @@ -5241,12 +5244,12 @@ public class DevicePolicyManagerTest extends DpmTestBase { when(getServices().userManager.getCredentialOwnerProfile(DpmMockContext.CALLER_USER_HANDLE)) .thenReturn(parentUser.id); - dpms.mUserPasswordMetrics.put( - DpmMockContext.CALLER_USER_HANDLE, - PasswordMetrics.computeForPassword("asdf".getBytes())); - dpms.mUserPasswordMetrics.put( - parentUser.id, - PasswordMetrics.computeForPassword("parentUser".getBytes())); + when(getServices().lockSettingsInternal + .getUserPasswordMetrics(DpmMockContext.CALLER_USER_HANDLE)) + .thenReturn(PasswordMetrics.computeForPassword("asdf".getBytes())); + when(getServices().lockSettingsInternal + .getUserPasswordMetrics(parentUser.id)) + .thenReturn(PasswordMetrics.computeForPassword("parentUser".getBytes())); assertEquals(PASSWORD_COMPLEXITY_HIGH, dpm.getPasswordComplexity()); } diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java b/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java index f6f365ec1494..b0d0303a82d9 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java @@ -64,6 +64,7 @@ import android.view.IWindowManager; import com.android.internal.util.test.FakeSettingsProvider; import com.android.internal.widget.LockPatternUtils; +import com.android.internal.widget.LockSettingsInternal; import com.android.server.net.NetworkPolicyManagerInternal; import com.android.server.wm.ActivityTaskManagerInternal; @@ -102,6 +103,7 @@ public class MockSystemServices { public final IBackupManager ibackupManager; public final IAudioService iaudioService; public final LockPatternUtils lockPatternUtils; + public final LockSettingsInternal lockSettingsInternal; public final StorageManagerForMock storageManager; public final WifiManager wifiManager; public final SettingsForMock settings; @@ -143,6 +145,7 @@ public class MockSystemServices { ibackupManager = mock(IBackupManager.class); iaudioService = mock(IAudioService.class); lockPatternUtils = mock(LockPatternUtils.class); + lockSettingsInternal = mock(LockSettingsInternal.class); storageManager = mock(StorageManagerForMock.class); wifiManager = mock(WifiManager.class); settings = mock(SettingsForMock.class); diff --git a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java index 1cd590c39f49..341b8f036263 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java @@ -341,6 +341,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { final byte[] pattern = "123654".getBytes(); final byte[] token = "some-high-entropy-secure-token".getBytes(); initializeCredentialUnderSP(password, PRIMARY_USER_ID); + reset(mDevicePolicyManager); final byte[] storageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID); assertFalse(mService.hasPendingEscrowToken(PRIMARY_USER_ID)); @@ -360,7 +361,8 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { flushHandlerTasks(); final PasswordMetrics metric = PasswordMetrics.computeForCredential( LockPatternUtils.CREDENTIAL_TYPE_PATTERN, pattern); - verify(mDevicePolicyManager).setActivePasswordState(metric, PRIMARY_USER_ID); + assertEquals(metric, mService.getUserPasswordMetrics(PRIMARY_USER_ID)); + verify(mDevicePolicyManager).reportPasswordChanged(PRIMARY_USER_ID); assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential( pattern, LockPatternUtils.CREDENTIAL_TYPE_PATTERN, 0, PRIMARY_USER_ID) diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java index 13748cbf8c9c..31babd04f31d 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java @@ -30,6 +30,7 @@ import static android.view.WindowManager.TRANSIT_TASK_CLOSE; import static com.android.dx.mockito.inline.extended.ExtendedMockito.any; import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.atLeast; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; @@ -866,7 +867,7 @@ public class ActivityRecordTests extends ActivityTestsBase { mActivity.setState(PAUSED, "test"); mActivity.finishIfPossible("test", false /* oomAdj */); - verify(mActivity).setVisibility(eq(false)); + verify(mActivity, atLeast(1)).setVisibility(eq(false)); verify(mActivity.getDisplay().mDisplayContent) .prepareAppTransition(eq(TRANSIT_TASK_CLOSE), eq(false) /* alwaysKeepCurrent */); verify(mActivity.getDisplay().mDisplayContent).executeAppTransition(); diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java index 60c5f0bd7188..c83e5cb71feb 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java @@ -26,6 +26,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMAR import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; @@ -1122,6 +1123,22 @@ public class ActivityStackTests extends ActivityTestsBase { assertThat(result).isEqualTo(taskTop); } + @Test + public void testNonTopVisibleActivityNotResume() { + final ActivityRecord nonTopVisibleActivity = + new ActivityBuilder(mService).setTask(mTask).build(); + new ActivityBuilder(mService).setTask(mTask).build(); + doReturn(false).when(nonTopVisibleActivity).attachedToProcess(); + doReturn(true).when(nonTopVisibleActivity).shouldBeVisibleIgnoringKeyguard(anyBoolean()); + doNothing().when(mSupervisor).startSpecificActivityLocked(any(), anyBoolean(), + anyBoolean()); + + mStack.ensureActivitiesVisibleLocked(null /* starting */, 0 /* configChanges */, + false /* preserveWindows */); + verify(mSupervisor).startSpecificActivityLocked(any(), eq(false) /* andResume */, + anyBoolean()); + } + private void verifyShouldSleepActivities(boolean focusedStack, boolean keyguardGoingAway, boolean displaySleeping, boolean expected) { final ActivityDisplay display = mock(ActivityDisplay.class); diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java index e387e186182b..1f634b11d173 100644 --- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java @@ -36,7 +36,6 @@ import static android.view.WindowManager.TRANSIT_UNSET; import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; -import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM; import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM; import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_NONE; @@ -160,7 +159,7 @@ public class AppWindowTokenTests extends WindowTestsBase { // Set initial orientation and update. mToken.setOrientation(SCREEN_ORIENTATION_LANDSCAPE); - mDisplayContent.updateOrientationFromAppTokens( + mDisplayContent.updateOrientation( mDisplayContent.getRequestedOverrideConfiguration(), null /* freezeThisOneIfNeeded */, false /* forceUpdate */); assertEquals(SCREEN_ORIENTATION_LANDSCAPE, mDisplayContent.getLastOrientation()); @@ -168,7 +167,7 @@ public class AppWindowTokenTests extends WindowTestsBase { // Update the orientation to perform 180 degree rotation and check that resize was reported. mToken.setOrientation(SCREEN_ORIENTATION_REVERSE_LANDSCAPE); - mDisplayContent.updateOrientationFromAppTokens( + mDisplayContent.updateOrientation( mDisplayContent.getRequestedOverrideConfiguration(), null /* freezeThisOneIfNeeded */, false /* forceUpdate */); // In this test, DC will not get config update. Set the waiting flag to false. @@ -181,8 +180,8 @@ public class AppWindowTokenTests extends WindowTestsBase { @Test public void testLandscapeSeascapeRotationByPolicy() { + // This instance has been spied in {@link TestActivityDisplay}. final DisplayRotation displayRotation = mDisplayContent.getDisplayRotation(); - spyOn(displayRotation); final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams( TYPE_BASE_APPLICATION); diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java index 62897687b8ad..44f3ee4130e0 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -445,7 +445,7 @@ public class DisplayContentTests extends WindowTestsBase { .computeSafeInsets(200, 400).getDisplayCutout(); dc.mInitialDisplayCutout = cutout; - dc.setRotation(Surface.ROTATION_0); + dc.getDisplayRotation().setRotation(Surface.ROTATION_0); dc.computeScreenConfiguration(new Configuration()); // recomputes dc.mDisplayInfo. assertEquals(cutout, dc.getDisplayInfo().displayCutout); @@ -476,7 +476,7 @@ public class DisplayContentTests extends WindowTestsBase { .computeSafeInsets(displayWidth, displayHeight).getDisplayCutout(); dc.mInitialDisplayCutout = cutout; - dc.setRotation(Surface.ROTATION_90); + dc.getDisplayRotation().setRotation(Surface.ROTATION_90); dc.computeScreenConfiguration(new Configuration()); // recomputes dc.mDisplayInfo. // ----o---------- ------------- @@ -608,18 +608,18 @@ public class DisplayContentTests extends WindowTestsBase { portraitDisplay.mInitialDisplayHeight = 2000; portraitDisplay.mInitialDisplayWidth = 1000; - portraitDisplay.setRotation(Surface.ROTATION_0); + portraitDisplay.getDisplayRotation().setRotation(Surface.ROTATION_0); assertFalse(isOptionsPanelAtRight(portraitDisplay.getDisplayId())); - portraitDisplay.setRotation(Surface.ROTATION_90); + portraitDisplay.getDisplayRotation().setRotation(Surface.ROTATION_90); assertTrue(isOptionsPanelAtRight(portraitDisplay.getDisplayId())); final DisplayContent landscapeDisplay = createNewDisplay(); landscapeDisplay.mInitialDisplayHeight = 1000; landscapeDisplay.mInitialDisplayWidth = 2000; - landscapeDisplay.setRotation(Surface.ROTATION_0); + landscapeDisplay.getDisplayRotation().setRotation(Surface.ROTATION_0); assertTrue(isOptionsPanelAtRight(landscapeDisplay.getDisplayId())); - landscapeDisplay.setRotation(Surface.ROTATION_90); + landscapeDisplay.getDisplayRotation().setRotation(Surface.ROTATION_90); assertFalse(isOptionsPanelAtRight(landscapeDisplay.getDisplayId())); } diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java index 6a3c81ab73bc..3ead97795954 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java @@ -28,16 +28,12 @@ import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED; -import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; import static android.view.WindowManager.LayoutParams.TYPE_TOAST; -import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; -import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; -import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_BOTTOM; import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_RIGHT; @@ -52,7 +48,6 @@ import static org.mockito.Mockito.when; import android.graphics.PixelFormat; import android.graphics.Rect; import android.platform.test.annotations.Presubmit; -import android.view.Surface; import android.view.WindowManager; import androidx.test.filters.FlakyTest; @@ -213,32 +208,15 @@ public class DisplayPolicyTests extends WindowTestsBase { } @Test - public void testShouldRotateSeamlessly() { - final DisplayPolicy policy = mDisplayContent.getDisplayPolicy(); + public void testComputeTopFullscreenOpaqueWindow() { final WindowManager.LayoutParams attrs = mAppWindow.mAttrs; attrs.x = attrs.y = 0; attrs.height = attrs.width = WindowManager.LayoutParams.MATCH_PARENT; - attrs.rotationAnimation = ROTATION_ANIMATION_SEAMLESS; - final DisplayRotation displayRotation = mock(DisplayRotation.class); - doReturn(Surface.ROTATION_180).when(displayRotation).getUpsideDownRotation(); + final DisplayPolicy policy = mDisplayContent.getDisplayPolicy(); + policy.applyPostLayoutPolicyLw( + mAppWindow, attrs, null /* attached */, null /* imeTarget */); - synchronized (mWm.mGlobalLock) { - policy.focusChangedLw(null /* lastFocus */, mAppWindow); - policy.applyPostLayoutPolicyLw( - mAppWindow, attrs, null /* attached */, null /* imeTarget */); - spyOn(policy); - doReturn(true).when(policy).navigationBarCanMove(); - // The focused fullscreen opaque window without override bounds should be able to be - // rotated seamlessly. - assertTrue(policy.shouldRotateSeamlessly( - displayRotation, Surface.ROTATION_0, Surface.ROTATION_90)); - - spyOn(mAppWindow.mAppToken); - doReturn(false).when(mAppWindow.mAppToken).matchParentBounds(); - // No seamless rotation if the window may be positioned with offset after rotation. - assertFalse(policy.shouldRotateSeamlessly( - displayRotation, Surface.ROTATION_0, Surface.ROTATION_90)); - } + assertEquals(mAppWindow, policy.getTopFullscreenOpaqueWindow()); } @Test diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java index 49d38c062049..059ff3d70660 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java @@ -24,6 +24,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.any; import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean; import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt; import static com.android.dx.mockito.inline.extended.ExtendedMockito.atMost; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset; @@ -55,6 +56,7 @@ import android.os.SystemClock; import android.platform.test.annotations.Presubmit; import android.provider.Settings; import android.view.Surface; +import android.view.WindowManager; import androidx.test.filters.SmallTest; @@ -584,6 +586,33 @@ public class DisplayRotationTests { SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0)); } + @Test + public void testShouldRotateSeamlessly() throws Exception { + mBuilder.build(); + + final WindowState win = mock(WindowState.class); + win.mAppToken = mock(AppWindowToken.class); + final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(); + attrs.rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS; + + doReturn(attrs).when(win).getAttrs(); + doReturn(true).when(mMockDisplayPolicy).navigationBarCanMove(); + doReturn(win).when(mMockDisplayPolicy).getTopFullscreenOpaqueWindow(); + mMockDisplayContent.mCurrentFocus = win; + mTarget.mUpsideDownRotation = Surface.ROTATION_180; + + doReturn(true).when(win.mAppToken).matchParentBounds(); + // The focused fullscreen opaque window without override bounds should be able to be + // rotated seamlessly. + assertTrue(mTarget.shouldRotateSeamlessly( + Surface.ROTATION_0, Surface.ROTATION_90, false /* forceUpdate */)); + + doReturn(false).when(win.mAppToken).matchParentBounds(); + // No seamless rotation if the window may be positioned with offset after rotation. + assertFalse(mTarget.shouldRotateSeamlessly( + Surface.ROTATION_0, Surface.ROTATION_90, false /* forceUpdate */)); + } + // ======================== // Non-rotation API Tests // ======================== diff --git a/services/tests/wmtests/src/com/android/server/wm/TestActivityDisplay.java b/services/tests/wmtests/src/com/android/server/wm/TestActivityDisplay.java index c14396933143..778f0ca3c782 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TestActivityDisplay.java +++ b/services/tests/wmtests/src/com/android/server/wm/TestActivityDisplay.java @@ -69,20 +69,22 @@ class TestActivityDisplay extends ActivityDisplay { mSupervisor = supervisor; spyOn(this); spyOn(mDisplayContent); + + final DisplayRotation displayRotation = mDisplayContent.getDisplayRotation(); + spyOn(displayRotation); doAnswer(invocation -> { // Bypass all the rotation animation and display freezing stuff for testing and just // set the rotation we want for the display - final DisplayContent dc = mDisplayContent; - final int oldRotation = dc.getRotation(); - final int rotation = dc.getDisplayRotation().rotationForOrientation( - dc.getLastOrientation(), oldRotation); + final int oldRotation = displayRotation.getRotation(); + final int rotation = displayRotation.rotationForOrientation( + displayRotation.getLastOrientation(), oldRotation); if (oldRotation == rotation) { return false; } - dc.setLayoutNeeded(); - dc.setRotation(rotation); + mDisplayContent.setLayoutNeeded(); + displayRotation.setRotation(rotation); return true; - }).when(mDisplayContent).updateRotationUnchecked(anyBoolean()); + }).when(displayRotation).updateRotationUnchecked(anyBoolean()); } @SuppressWarnings("TypeParameterUnusedInFormals") diff --git a/telecomm/java/android/telecom/AudioState.java b/telecomm/java/android/telecom/AudioState.java index 6b9b83ddb887..8b8c86be7b0a 100644 --- a/telecomm/java/android/telecom/AudioState.java +++ b/telecomm/java/android/telecom/AudioState.java @@ -16,6 +16,8 @@ package android.telecom; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.UnsupportedAppUsage; import android.os.Build; @@ -81,7 +83,7 @@ public class AudioState implements Parcelable { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (obj == null) { return false; } @@ -93,6 +95,7 @@ public class AudioState implements Parcelable { getSupportedRouteMask() == state.getSupportedRouteMask(); } + @NonNull @Override public String toString() { return String.format(Locale.US, diff --git a/telephony/java/android/telephony/CallAttributes.java b/telephony/java/android/telephony/CallAttributes.java index 3a340053ace3..1c03d8089df7 100644 --- a/telephony/java/android/telephony/CallAttributes.java +++ b/telephony/java/android/telephony/CallAttributes.java @@ -17,6 +17,7 @@ package android.telephony; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; @@ -44,6 +45,7 @@ public final class CallAttributes implements Parcelable { this.mCallQuality = callQuality; } + @NonNull @Override public String toString() { return "mPreciseCallState=" + mPreciseCallState + " mNetworkType=" + mNetworkType @@ -109,7 +111,7 @@ public final class CallAttributes implements Parcelable { } @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (o == null || !(o instanceof CallAttributes) || hashCode() != o.hashCode()) { return false; } diff --git a/telephony/java/android/telephony/CallQuality.java b/telephony/java/android/telephony/CallQuality.java index 10a04a9db260..028280c332e2 100644 --- a/telephony/java/android/telephony/CallQuality.java +++ b/telephony/java/android/telephony/CallQuality.java @@ -17,6 +17,8 @@ package android.telephony; import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; @@ -252,6 +254,7 @@ public final class CallQuality implements Parcelable { } // Parcelable things + @NonNull @Override public String toString() { return "CallQuality: {downlinkCallQualityLevel=" + mDownlinkCallQualityLevel @@ -285,7 +288,7 @@ public final class CallQuality implements Parcelable { } @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (o == null || !(o instanceof CallQuality) || hashCode() != o.hashCode()) { return false; } diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index 654b54d988cf..2aca206a8cc5 100755 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -2791,6 +2791,13 @@ public class CarrierConfigManager { "opportunistic_network_data_switch_exit_hysteresis_time_long"; /** + * Controls time in milli seconds until DcTracker reevaluates 5G connection state. + * @hide + */ + public static final String KEY_5G_WATCHDOG_TIME_MS_LONG = + "5g_watchdog_time_long"; + + /** * Indicates zero or more emergency number prefix(es), because some carrier requires * if users dial an emergency number address with a specific prefix, the combination of the * prefix and the address is also a valid emergency number to dial. For example, an emergency @@ -3565,6 +3572,8 @@ public class CarrierConfigManager { sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_DATA_SWITCH_HYSTERESIS_TIME_LONG, 10000); /* Default value is 3 seconds. */ sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_DATA_SWITCH_EXIT_HYSTERESIS_TIME_LONG, 3000); + /* Default value is 1 hour. */ + sDefaults.putLong(KEY_5G_WATCHDOG_TIME_MS_LONG, 3600000); sDefaults.putAll(Gps.getDefaults()); sDefaults.putAll(Wifi.getDefaults()); sDefaults.putIntArray(KEY_CDMA_ENHANCED_ROAMING_INDICATOR_FOR_HOME_NETWORK_INT_ARRAY, @@ -3799,7 +3808,7 @@ public class CarrierConfigManager { * @see #getConfigForSubId */ @Nullable - public PersistableBundle getConfigByComponentForSubId(String prefix, int subId) { + public PersistableBundle getConfigByComponentForSubId(@NonNull String prefix, int subId) { PersistableBundle configs = getConfigForSubId(subId); if (configs == null) { diff --git a/telephony/java/android/telephony/CarrierRestrictionRules.java b/telephony/java/android/telephony/CarrierRestrictionRules.java index 950ae6cf5ed8..c13801887572 100644 --- a/telephony/java/android/telephony/CarrierRestrictionRules.java +++ b/telephony/java/android/telephony/CarrierRestrictionRules.java @@ -323,6 +323,7 @@ public final class CarrierRestrictionRules implements Parcelable { } }; + @NonNull @Override public String toString() { return "CarrierRestrictionRules(allowed:" + mAllowedCarriers + ", excluded:" diff --git a/telephony/java/android/telephony/DataSpecificRegistrationInfo.java b/telephony/java/android/telephony/DataSpecificRegistrationInfo.java index 3dd931898c18..407ced71a0e7 100644 --- a/telephony/java/android/telephony/DataSpecificRegistrationInfo.java +++ b/telephony/java/android/telephony/DataSpecificRegistrationInfo.java @@ -17,6 +17,7 @@ package android.telephony; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.TestApi; import android.os.Parcel; @@ -134,6 +135,7 @@ public final class DataSpecificRegistrationInfo implements Parcelable { return 0; } + @NonNull @Override public String toString() { return new StringBuilder().append(this.getClass().getName()) @@ -155,7 +157,7 @@ public final class DataSpecificRegistrationInfo implements Parcelable { } @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (this == o) return true; if (!(o instanceof DataSpecificRegistrationInfo)) return false; diff --git a/telephony/java/android/telephony/LteVopsSupportInfo.java b/telephony/java/android/telephony/LteVopsSupportInfo.java index ec9f078367b8..7994c1b05977 100644 --- a/telephony/java/android/telephony/LteVopsSupportInfo.java +++ b/telephony/java/android/telephony/LteVopsSupportInfo.java @@ -17,6 +17,8 @@ package android.telephony; import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.TestApi; import android.os.Parcel; @@ -94,7 +96,7 @@ public final class LteVopsSupportInfo implements Parcelable { } @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (o == null || !(o instanceof LteVopsSupportInfo)) { return false; } @@ -112,6 +114,7 @@ public final class LteVopsSupportInfo implements Parcelable { /** * @return string representation. */ + @NonNull @Override public String toString() { return ("LteVopsSupportInfo : " diff --git a/telephony/java/android/telephony/NetworkRegistrationInfo.java b/telephony/java/android/telephony/NetworkRegistrationInfo.java index 2fae949cacb3..a76b8da09064 100644 --- a/telephony/java/android/telephony/NetworkRegistrationInfo.java +++ b/telephony/java/android/telephony/NetworkRegistrationInfo.java @@ -501,6 +501,7 @@ public final class NetworkRegistrationInfo implements Parcelable { } } + @NonNull @Override public String toString() { return new StringBuilder("NetworkRegistrationInfo{") @@ -531,7 +532,7 @@ public final class NetworkRegistrationInfo implements Parcelable { } @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (this == o) return true; if (!(o instanceof NetworkRegistrationInfo)) { diff --git a/telephony/java/android/telephony/PhoneNumberRange.java b/telephony/java/android/telephony/PhoneNumberRange.java index c35a485d613f..e6f107e28c98 100644 --- a/telephony/java/android/telephony/PhoneNumberRange.java +++ b/telephony/java/android/telephony/PhoneNumberRange.java @@ -17,6 +17,7 @@ package android.telephony; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; @@ -104,7 +105,7 @@ public final class PhoneNumberRange implements Parcelable { } @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; PhoneNumberRange that = (PhoneNumberRange) o; @@ -119,6 +120,7 @@ public final class PhoneNumberRange implements Parcelable { return Objects.hash(mCountryCode, mPrefix, mLowerBound, mUpperBound); } + @NonNull @Override public String toString() { return "PhoneNumberRange{" diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java index f03a9dc0f963..af3ba5e44158 100644 --- a/telephony/java/android/telephony/PhoneNumberUtils.java +++ b/telephony/java/android/telephony/PhoneNumberUtils.java @@ -217,6 +217,9 @@ public class PhoneNumberUtils { } String scheme = uri.getScheme(); + if (scheme == null) { + return null; + } if (scheme.equals("tel") || scheme.equals("sip")) { return uri.getSchemeSpecificPart(); diff --git a/telephony/java/android/telephony/PreciseCallState.java b/telephony/java/android/telephony/PreciseCallState.java index 5fb9bacb55b8..701a375a3039 100644 --- a/telephony/java/android/telephony/PreciseCallState.java +++ b/telephony/java/android/telephony/PreciseCallState.java @@ -17,6 +17,8 @@ package android.telephony; import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.UnsupportedAppUsage; import android.os.Parcel; @@ -276,7 +278,7 @@ public final class PreciseCallState implements Parcelable { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (this == obj) { return true; } @@ -294,6 +296,7 @@ public final class PreciseCallState implements Parcelable { && mPreciseDisconnectCause == other.mPreciseDisconnectCause); } + @NonNull @Override public String toString() { StringBuffer sb = new StringBuffer(); diff --git a/telephony/java/android/telephony/PreciseDataConnectionState.java b/telephony/java/android/telephony/PreciseDataConnectionState.java index cd4fbacd180e..90d443a6d8ee 100644 --- a/telephony/java/android/telephony/PreciseDataConnectionState.java +++ b/telephony/java/android/telephony/PreciseDataConnectionState.java @@ -177,7 +177,7 @@ public final class PreciseDataConnectionState implements Parcelable { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (!(obj instanceof PreciseDataConnectionState)) { return false; @@ -191,6 +191,7 @@ public final class PreciseDataConnectionState implements Parcelable { && mState == other.mState; } + @NonNull @Override public String toString() { StringBuilder sb = new StringBuilder(); diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java index b44e4f179392..cd0f57efe880 100644 --- a/telephony/java/android/telephony/SmsManager.java +++ b/telephony/java/android/telephony/SmsManager.java @@ -53,7 +53,6 @@ import com.android.internal.telephony.SmsRawData; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.concurrent.Executor; @@ -1555,15 +1554,13 @@ public final class SmsManager { public boolean deleteMessageFromIcc(int messageIndex) { boolean success = false; - byte[] pdu = new byte[SMS_RECORD_LENGTH-1]; - Arrays.fill(pdu, (byte)0xff); try { ISms iSms = getISmsService(); if (iSms != null) { success = iSms.updateMessageOnIccEfForSubscriber(getSubscriptionId(), ActivityThread.currentPackageName(), - messageIndex, STATUS_ON_ICC_FREE, pdu); + messageIndex, STATUS_ON_ICC_FREE, null /* pdu */); } } catch (RemoteException ex) { // ignore it diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java index 5e47e498ee10..d93d1d6a418e 100644 --- a/telephony/java/android/telephony/SubscriptionManager.java +++ b/telephony/java/android/telephony/SubscriptionManager.java @@ -53,6 +53,7 @@ import android.os.ParcelUuid; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; +import android.telephony.TelephonyManager.NetworkType; import android.telephony.euicc.EuiccManager; import android.telephony.ims.ImsMmTelManager; import android.util.DisplayMetrics; @@ -2454,10 +2455,51 @@ public class SubscriptionManager { */ public void setSubscriptionOverrideUnmetered(int subId, boolean overrideUnmetered, @DurationMillisLong long timeoutMillis) { + setSubscriptionOverrideUnmetered(subId, null, overrideUnmetered, timeoutMillis); + } + + /** + * Temporarily override the billing relationship between a carrier and + * a specific subscriber to be considered unmetered for the given network + * types. This will be reflected to apps via + * {@link NetworkCapabilities#NET_CAPABILITY_NOT_METERED}. + * This method is only accessible to the following narrow set of apps: + * <ul> + * <li>The carrier app for this subscriberId, as determined by + * {@link TelephonyManager#hasCarrierPrivileges()}. + * <li>The carrier app explicitly delegated access through + * {@link CarrierConfigManager#KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING}. + * </ul> + * + * @param subId the subscriber this override applies to. + * @param networkTypes all network types to set an override for. A null + * network type means to apply the override to all network types. + * Any unspecified network types will default to metered. + * @param overrideUnmetered set if the billing relationship should be + * considered unmetered. + * @param timeoutMillis the timeout after which the requested override will + * be automatically cleared, or {@code 0} to leave in the + * requested state until explicitly cleared, or the next reboot, + * whichever happens first. + * @throws SecurityException if the caller doesn't meet the requirements + * outlined above. + * {@hide} + */ + public void setSubscriptionOverrideUnmetered(int subId, + @Nullable @NetworkType int[] networkTypes, boolean overrideUnmetered, + @DurationMillisLong long timeoutMillis) { try { + long networkTypeMask = 0; + if (networkTypes != null) { + for (int networkType : networkTypes) { + networkTypeMask |= TelephonyManager.getBitMaskForNetworkType(networkType); + } + } else { + networkTypeMask = ~0; + } final int overrideValue = overrideUnmetered ? OVERRIDE_UNMETERED : 0; getNetworkPolicy().setSubscriptionOverride(subId, OVERRIDE_UNMETERED, overrideValue, - timeoutMillis, mContext.getOpPackageName()); + networkTypeMask, timeoutMillis, mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2489,10 +2531,52 @@ public class SubscriptionManager { */ public void setSubscriptionOverrideCongested(int subId, boolean overrideCongested, @DurationMillisLong long timeoutMillis) { + setSubscriptionOverrideCongested(subId, null, overrideCongested, timeoutMillis); + } + + /** + * Temporarily override the billing relationship plan between a carrier and + * a specific subscriber to be considered congested. This will cause the + * device to delay certain network requests when possible, such as developer + * jobs that are willing to run in a flexible time window. + * <p> + * This method is only accessible to the following narrow set of apps: + * <ul> + * <li>The carrier app for this subscriberId, as determined by + * {@link TelephonyManager#hasCarrierPrivileges()}. + * <li>The carrier app explicitly delegated access through + * {@link CarrierConfigManager#KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING}. + * </ul> + * + * @param subId the subscriber this override applies to. + * @param networkTypes all network types to set an override for. A null + * network type means to apply the override to all network types. + * Any unspecified network types will default to not congested. + * @param overrideCongested set if the subscription should be considered + * congested. + * @param timeoutMillis the timeout after which the requested override will + * be automatically cleared, or {@code 0} to leave in the + * requested state until explicitly cleared, or the next reboot, + * whichever happens first. + * @throws SecurityException if the caller doesn't meet the requirements + * outlined above. + * @hide + */ + public void setSubscriptionOverrideCongested(int subId, + @Nullable @NetworkType int[] networkTypes, boolean overrideCongested, + @DurationMillisLong long timeoutMillis) { try { + long networkTypeMask = 0; + if (networkTypes != null) { + for (int networkType : networkTypes) { + networkTypeMask |= TelephonyManager.getBitMaskForNetworkType(networkType); + } + } else { + networkTypeMask = ~0; + } final int overrideValue = overrideCongested ? OVERRIDE_CONGESTED : 0; getNetworkPolicy().setSubscriptionOverride(subId, OVERRIDE_CONGESTED, overrideValue, - timeoutMillis, mContext.getOpPackageName()); + networkTypeMask, timeoutMillis, mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/telephony/java/android/telephony/SubscriptionPlan.java b/telephony/java/android/telephony/SubscriptionPlan.java index e0838b375fdb..ec2050fb1a44 100644 --- a/telephony/java/android/telephony/SubscriptionPlan.java +++ b/telephony/java/android/telephony/SubscriptionPlan.java @@ -131,7 +131,7 @@ public final class SubscriptionPlan implements Parcelable { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (obj instanceof SubscriptionPlan) { final SubscriptionPlan other = (SubscriptionPlan) obj; return Objects.equals(cycleRule, other.cycleRule) diff --git a/telephony/java/android/telephony/TelephonyHistogram.java b/telephony/java/android/telephony/TelephonyHistogram.java index 63bdac514477..b94cb60ffa00 100644 --- a/telephony/java/android/telephony/TelephonyHistogram.java +++ b/telephony/java/android/telephony/TelephonyHistogram.java @@ -15,13 +15,12 @@ */ package android.telephony; +import android.annotation.NonNull; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; -import java.util.ArrayList; import java.util.Arrays; -import java.util.List; /** * Parcelable class to store Telephony histogram. @@ -238,6 +237,8 @@ public final class TelephonyHistogram implements Parcelable { } } + @NonNull + @Override public String toString() { String basic = " Histogram id = " + mId + " Time(ms): min = " + mMinTimeMs + " max = " + mMaxTimeMs + " avg = " + mAverageTimeMs + " Count = " + mSampleCount; diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 553bff26f78f..475563d37197 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -2829,6 +2829,55 @@ public class TelephonyManager { } } + /** + * Returns the bitmask for a given technology (network type) + * @param networkType for which bitmask is returned + * @return the network type bitmask + * {@hide} + */ + public static @NetworkTypeBitMask long getBitMaskForNetworkType(@NetworkType int networkType) { + switch(networkType) { + case NETWORK_TYPE_GSM: + return NETWORK_TYPE_BITMASK_GSM; + case NETWORK_TYPE_GPRS: + return NETWORK_TYPE_BITMASK_GPRS; + case NETWORK_TYPE_EDGE: + return NETWORK_TYPE_BITMASK_EDGE; + case NETWORK_TYPE_CDMA: + return NETWORK_TYPE_BITMASK_CDMA; + case NETWORK_TYPE_1xRTT: + return NETWORK_TYPE_BITMASK_1xRTT; + case NETWORK_TYPE_EVDO_0: + return NETWORK_TYPE_BITMASK_EVDO_0; + case NETWORK_TYPE_EVDO_A: + return NETWORK_TYPE_BITMASK_EVDO_A; + case NETWORK_TYPE_EVDO_B: + return NETWORK_TYPE_BITMASK_EVDO_B; + case NETWORK_TYPE_EHRPD: + return NETWORK_TYPE_BITMASK_EHRPD; + case NETWORK_TYPE_HSUPA: + return NETWORK_TYPE_BITMASK_HSUPA; + case NETWORK_TYPE_HSDPA: + return NETWORK_TYPE_BITMASK_HSDPA; + case NETWORK_TYPE_HSPA: + return NETWORK_TYPE_BITMASK_HSPA; + case NETWORK_TYPE_HSPAP: + return NETWORK_TYPE_BITMASK_HSPAP; + case NETWORK_TYPE_UMTS: + return NETWORK_TYPE_BITMASK_UMTS; + case NETWORK_TYPE_TD_SCDMA: + return NETWORK_TYPE_BITMASK_TD_SCDMA; + case NETWORK_TYPE_LTE: + return NETWORK_TYPE_BITMASK_LTE; + case NETWORK_TYPE_LTE_CA: + return NETWORK_TYPE_BITMASK_LTE_CA; + case NETWORK_TYPE_NR: + return NETWORK_TYPE_BITMASK_NR; + default: + return NETWORK_TYPE_BITMASK_UNKNOWN; + } + } + // // // SIM Card diff --git a/telephony/java/android/telephony/UiccAccessRule.java b/telephony/java/android/telephony/UiccAccessRule.java index 37a4491141a0..811722f0bbff 100644 --- a/telephony/java/android/telephony/UiccAccessRule.java +++ b/telephony/java/android/telephony/UiccAccessRule.java @@ -15,6 +15,7 @@ */ package android.telephony; +import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.content.pm.PackageInfo; @@ -213,7 +214,7 @@ public final class UiccAccessRule implements Parcelable { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (this == obj) { return true; } @@ -236,6 +237,7 @@ public final class UiccAccessRule implements Parcelable { return result; } + @NonNull @Override public String toString() { return "cert: " + IccUtils.bytesToHexString(mCertificateHash) + " pkg: " + diff --git a/telephony/java/android/telephony/UiccSlotInfo.java b/telephony/java/android/telephony/UiccSlotInfo.java index fb1da7b12556..a0e949aa7fc5 100644 --- a/telephony/java/android/telephony/UiccSlotInfo.java +++ b/telephony/java/android/telephony/UiccSlotInfo.java @@ -16,6 +16,8 @@ package android.telephony; import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; @@ -179,7 +181,7 @@ public class UiccSlotInfo implements Parcelable { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (this == obj) { return true; } @@ -210,6 +212,7 @@ public class UiccSlotInfo implements Parcelable { return result; } + @NonNull @Override public String toString() { return "UiccSlotInfo (mIsActive=" diff --git a/telephony/java/android/telephony/data/DataCallResponse.java b/telephony/java/android/telephony/data/DataCallResponse.java index 17699d70cb18..9170e88ce832 100644 --- a/telephony/java/android/telephony/data/DataCallResponse.java +++ b/telephony/java/android/telephony/data/DataCallResponse.java @@ -213,6 +213,7 @@ public final class DataCallResponse implements Parcelable { */ public int getMtu() { return mMtu; } + @NonNull @Override public String toString() { StringBuffer sb = new StringBuffer(); @@ -233,7 +234,7 @@ public final class DataCallResponse implements Parcelable { } @Override - public boolean equals (Object o) { + public boolean equals(@Nullable Object o) { if (this == o) return true; if (!(o instanceof DataCallResponse)) { diff --git a/telephony/java/android/telephony/data/DataProfile.java b/telephony/java/android/telephony/data/DataProfile.java index c53ade16cae4..0d79ec98fcbb 100644 --- a/telephony/java/android/telephony/data/DataProfile.java +++ b/telephony/java/android/telephony/data/DataProfile.java @@ -257,6 +257,7 @@ public final class DataProfile implements Parcelable { return 0; } + @NonNull @Override public String toString() { return "DataProfile=" + mProfileId + "/" + mProtocolType + "/" + mAuthType @@ -303,7 +304,7 @@ public final class DataProfile implements Parcelable { }; @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; DataProfile that = (DataProfile) o; diff --git a/telephony/java/android/telephony/euicc/EuiccNotification.java b/telephony/java/android/telephony/euicc/EuiccNotification.java index b27f7756151d..c348cff25052 100644 --- a/telephony/java/android/telephony/euicc/EuiccNotification.java +++ b/telephony/java/android/telephony/euicc/EuiccNotification.java @@ -16,6 +16,7 @@ package android.telephony.euicc; import android.annotation.IntDef; +import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.os.Parcel; @@ -107,7 +108,7 @@ public final class EuiccNotification implements Parcelable { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (this == obj) { return true; } @@ -132,6 +133,7 @@ public final class EuiccNotification implements Parcelable { return result; } + @NonNull @Override public String toString() { return "EuiccNotification (seq=" diff --git a/telephony/java/android/telephony/euicc/EuiccRulesAuthTable.java b/telephony/java/android/telephony/euicc/EuiccRulesAuthTable.java index 89842aefc66e..d5a05ae2dbb8 100644 --- a/telephony/java/android/telephony/euicc/EuiccRulesAuthTable.java +++ b/telephony/java/android/telephony/euicc/EuiccRulesAuthTable.java @@ -16,6 +16,7 @@ package android.telephony.euicc; import android.annotation.IntDef; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; @@ -28,7 +29,6 @@ import com.android.internal.annotations.VisibleForTesting; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Arrays; -import java.util.ArrayList; import java.util.List; /** @@ -204,7 +204,7 @@ public final class EuiccRulesAuthTable implements Parcelable { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (this == obj) { return true; } diff --git a/telephony/java/android/telephony/ims/ImsCallForwardInfo.java b/telephony/java/android/telephony/ims/ImsCallForwardInfo.java index 9b72d58aa89f..79cdfef96300 100644 --- a/telephony/java/android/telephony/ims/ImsCallForwardInfo.java +++ b/telephony/java/android/telephony/ims/ImsCallForwardInfo.java @@ -185,6 +185,7 @@ public final class ImsCallForwardInfo implements Parcelable { out.writeInt(mServiceClass); } + @NonNull @Override public String toString() { return super.toString() + ", Condition: " + mCondition diff --git a/telephony/java/android/telephony/ims/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java index 20879141bdb5..77ee20512d11 100644 --- a/telephony/java/android/telephony/ims/ImsCallProfile.java +++ b/telephony/java/android/telephony/ims/ImsCallProfile.java @@ -539,7 +539,7 @@ public final class ImsCallProfile implements Parcelable { mMediaProfile = profile.mMediaProfile; } - + @NonNull @Override public String toString() { return "{ serviceType=" + mServiceType diff --git a/telephony/java/android/telephony/ims/ImsConferenceState.java b/telephony/java/android/telephony/ims/ImsConferenceState.java index 44595b5bc1fd..6f062f4185f2 100644 --- a/telephony/java/android/telephony/ims/ImsConferenceState.java +++ b/telephony/java/android/telephony/ims/ImsConferenceState.java @@ -16,6 +16,7 @@ package android.telephony.ims; +import android.annotation.NonNull; import android.annotation.SystemApi; import android.os.Bundle; import android.os.Parcel; @@ -176,6 +177,7 @@ public final class ImsConferenceState implements Parcelable { return Call.STATE_ACTIVE; } + @NonNull @Override public String toString() { StringBuilder sb = new StringBuilder(); diff --git a/telephony/java/android/telephony/ims/ImsExternalCallState.java b/telephony/java/android/telephony/ims/ImsExternalCallState.java index 37b11eda6916..eb2ebcad2c1d 100644 --- a/telephony/java/android/telephony/ims/ImsExternalCallState.java +++ b/telephony/java/android/telephony/ims/ImsExternalCallState.java @@ -213,6 +213,7 @@ public final class ImsExternalCallState implements Parcelable { return mIsHeld; } + @NonNull @Override public String toString() { return "ImsExternalCallState { mCallId = " + mCallId + diff --git a/telephony/java/android/telephony/ims/ImsReasonInfo.java b/telephony/java/android/telephony/ims/ImsReasonInfo.java index 20aba4d97849..1e0d9a786acc 100644 --- a/telephony/java/android/telephony/ims/ImsReasonInfo.java +++ b/telephony/java/android/telephony/ims/ImsReasonInfo.java @@ -17,6 +17,7 @@ package android.telephony.ims; import android.annotation.IntDef; +import android.annotation.NonNull; import android.annotation.SystemApi; import android.annotation.UnsupportedAppUsage; import android.os.Parcel; @@ -1183,6 +1184,8 @@ public final class ImsReasonInfo implements Parcelable { /** * @return the string format of {@link ImsReasonInfo} */ + @NonNull + @Override public String toString() { return "ImsReasonInfo :: {" + mCode + ", " + mExtraCode + ", " + mExtraMessage + "}"; } diff --git a/telephony/java/android/telephony/ims/ImsSsData.java b/telephony/java/android/telephony/ims/ImsSsData.java index 32b4382829df..ec2ff6c58a40 100644 --- a/telephony/java/android/telephony/ims/ImsSsData.java +++ b/telephony/java/android/telephony/ims/ImsSsData.java @@ -570,6 +570,8 @@ public final class ImsSsData implements Parcelable { return mCfInfo; } + @NonNull + @Override public String toString() { return "[ImsSsData] " + "ServiceType: " + getServiceType() + " RequestType: " + getRequestType() diff --git a/telephony/java/android/telephony/ims/ImsSsInfo.java b/telephony/java/android/telephony/ims/ImsSsInfo.java index 9912eced0543..be34f9db3e54 100644 --- a/telephony/java/android/telephony/ims/ImsSsInfo.java +++ b/telephony/java/android/telephony/ims/ImsSsInfo.java @@ -254,6 +254,7 @@ public final class ImsSsInfo implements Parcelable { out.writeInt(mClirOutgoingState); } + @NonNull @Override public String toString() { return super.toString() + ", Status: " + ((mStatus == 0) ? "disabled" : "enabled") diff --git a/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java b/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java index fd75a6b192d2..c1f059e1cc89 100644 --- a/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java +++ b/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java @@ -16,6 +16,7 @@ package android.telephony.ims; +import android.annotation.NonNull; import android.annotation.SystemApi; import android.annotation.UnsupportedAppUsage; import android.os.Parcel; @@ -194,6 +195,7 @@ public final class ImsStreamMediaProfile implements Parcelable { mRttMode = profile.mRttMode; } + @NonNull @Override public String toString() { return "{ audioQuality=" + mAudioQuality + diff --git a/telephony/java/android/telephony/ims/ImsSuppServiceNotification.java b/telephony/java/android/telephony/ims/ImsSuppServiceNotification.java index 2e4288d0cf0a..16303685d0a3 100644 --- a/telephony/java/android/telephony/ims/ImsSuppServiceNotification.java +++ b/telephony/java/android/telephony/ims/ImsSuppServiceNotification.java @@ -17,6 +17,7 @@ package android.telephony.ims; +import android.annotation.NonNull; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; @@ -67,6 +68,7 @@ public final class ImsSuppServiceNotification implements Parcelable { history = in.createStringArray(); } + @NonNull @Override public String toString() { return "{ notificationType=" + notificationType + diff --git a/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java b/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java index 80fc09e2b0cc..87a5094a95f3 100644 --- a/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java +++ b/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java @@ -16,6 +16,7 @@ package android.telephony.ims.feature; +import android.annotation.NonNull; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; @@ -98,6 +99,7 @@ public final class CapabilityChangeRequest implements Parcelable { return radioTech; } + @NonNull @Override public String toString() { return "CapabilityPair{" @@ -219,6 +221,7 @@ public final class CapabilityChangeRequest implements Parcelable { } } + @NonNull @Override public String toString() { return "CapabilityChangeRequest{" diff --git a/telephony/java/android/telephony/ims/feature/MmTelFeature.java b/telephony/java/android/telephony/ims/feature/MmTelFeature.java index 056a0abe7a29..20c191da0550 100644 --- a/telephony/java/android/telephony/ims/feature/MmTelFeature.java +++ b/telephony/java/android/telephony/ims/feature/MmTelFeature.java @@ -291,6 +291,7 @@ public class MmTelFeature extends ImsFeature { return super.isCapable(capabilities); } + @NonNull @Override public String toString() { StringBuilder builder = new StringBuilder("MmTel Capabilities - ["); diff --git a/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java b/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java index 3b298bb82f8b..cd9ebbf38e35 100644 --- a/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java +++ b/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java @@ -16,6 +16,8 @@ package android.telephony.ims.stub; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; @@ -60,7 +62,7 @@ public final class ImsFeatureConfiguration implements Parcelable { } @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; @@ -77,6 +79,7 @@ public final class ImsFeatureConfiguration implements Parcelable { return result; } + @NonNull @Override public String toString() { return "{s=" + slotId + ", f=" + ImsFeature.FEATURE_LOG_MAP.get(featureType) + "}"; diff --git a/telephony/java/android/telephony/mbms/DownloadRequest.java b/telephony/java/android/telephony/mbms/DownloadRequest.java index 52b51d243bd1..ac258cd40d65 100644 --- a/telephony/java/android/telephony/mbms/DownloadRequest.java +++ b/telephony/java/android/telephony/mbms/DownloadRequest.java @@ -17,6 +17,7 @@ package android.telephony.mbms; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.TestApi; import android.content.Intent; @@ -381,7 +382,7 @@ public final class DownloadRequest implements Parcelable { } @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (this == o) return true; if (o == null) { return false; diff --git a/telephony/java/com/android/internal/telephony/DctConstants.java b/telephony/java/com/android/internal/telephony/DctConstants.java index e1113eba006f..668a6af08145 100644 --- a/telephony/java/com/android/internal/telephony/DctConstants.java +++ b/telephony/java/com/android/internal/telephony/DctConstants.java @@ -111,6 +111,9 @@ public class DctConstants { public static final int EVENT_DATA_SERVICE_BINDING_CHANGED = BASE + 49; public static final int EVENT_DEVICE_PROVISIONED_CHANGE = BASE + 50; public static final int EVENT_DATA_ENABLED_OVERRIDE_RULES_CHANGED = BASE + 51; + public static final int EVENT_5G_NETWORK_CHANGED = BASE + 52; + public static final int EVENT_5G_TIMER_HYSTERESIS = BASE + 53; + public static final int EVENT_5G_TIMER_WATCHDOG = BASE + 54; /***** Constants *****/ diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java index 6b3126dd8f1c..d892e559c899 100644 --- a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java +++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java @@ -696,6 +696,89 @@ public class SmsMessage extends SmsMessageBase { } /** + * Pre-processes an SMS WAP for Teleservice Id 0xFDEA(65002). + * + * It requires an additional header parsing to extract new Message Identifier and new User Data + * from WDP SMS User Data. + * + * - WDP SMS User Data Subparameter = + * |User Data SUBPARAMETER_ID ~ NUM_FIELDS| + |CHARi| + |RESERVED| + * + * - WDP SMS User Data Subparameter CHARi = + * |New Message Identifier Subparameter(HEADER_IND = 0)| + + * |New User Data Subparameter(MSG_ENCODING = ENCODING_OCTET)| + * + * @return true if preprocessing is successful, false otherwise. + */ + public boolean preprocessCdmaFdeaWap() { + try { + BitwiseInputStream inStream = new BitwiseInputStream(mUserData); + + // Message Identifier SUBPARAMETER_ID(0x00) + if (inStream.read(8) != 0x00) { + Rlog.e(LOG_TAG, "Invalid FDEA WDP Header Message Identifier SUBPARAMETER_ID"); + return false; + } + + // Message Identifier SUBPARAM_LEN(0x03) + if (inStream.read(8) != 0x03) { + Rlog.e(LOG_TAG, "Invalid FDEA WDP Header Message Identifier SUBPARAM_LEN"); + return false; + } + + // Message Identifier MESSAGE_TYPE + mBearerData.messageType = inStream.read(4); + + // Message Identifier MESSAGE_ID + int msgId = inStream.read(8) << 8; + msgId |= inStream.read(8); + mBearerData.messageId = msgId; + mMessageRef = msgId; + + // Message Identifier HEADER_IND + mBearerData.hasUserDataHeader = (inStream.read(1) == 1); + if (mBearerData.hasUserDataHeader) { + Rlog.e(LOG_TAG, "Invalid FDEA WDP Header Message Identifier HEADER_IND"); + return false; + } + + // Message Identifier RESERVED + inStream.skip(3); + + // User Data SUBPARAMETER_ID(0x01) + if (inStream.read(8) != 0x01) { + Rlog.e(LOG_TAG, "Invalid FDEA WDP Header User Data SUBPARAMETER_ID"); + return false; + } + + // User Data SUBPARAM_LEN + int userDataLen = inStream.read(8) * 8; + + // User Data MSG_ENCODING + mBearerData.userData.msgEncoding = inStream.read(5); + int consumedBits = 5; + if (mBearerData.userData.msgEncoding != UserData.ENCODING_OCTET) { + Rlog.e(LOG_TAG, "Invalid FDEA WDP Header User Data MSG_ENCODING"); + return false; + } + + // User Data NUM_FIELDS + mBearerData.userData.numFields = inStream.read(8); + consumedBits += 8; + + int remainingBits = userDataLen - consumedBits; + int dataBits = mBearerData.userData.numFields * 8; + dataBits = dataBits < remainingBits ? dataBits : remainingBits; + mBearerData.userData.payload = inStream.readByteArray(dataBits); + mUserData = mBearerData.userData.payload; + return true; + } catch (BitwiseInputStream.AccessException ex) { + Rlog.e(LOG_TAG, "Fail to preprocess FDEA WAP: " + ex); + } + return false; + } + + /** * Parses a SMS message from its BearerData stream. */ @UnsupportedAppUsage diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java b/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java index 2181bc425a78..d9be54845efe 100644 --- a/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java +++ b/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java @@ -781,13 +781,13 @@ public final class BearerData { " > " + SmsConstants.MAX_USER_DATA_BYTES + " bytes)"); } - /* - * TODO(cleanup): figure out what the right answer is WRT paddingBits field - * - * userData.paddingBits = (userData.payload.length * 8) - (userData.numFields * 7); - * userData.paddingBits = 0; // XXX this seems better, but why? - * - */ + if (bData.userData.msgEncoding == UserData.ENCODING_7BIT_ASCII) { + bData.userData.paddingBits = + (bData.userData.payload.length * 8) - (bData.userData.numFields * 7); + } else { + bData.userData.paddingBits = 0; + } + int dataBits = (bData.userData.payload.length * 8) - bData.userData.paddingBits; int paramBits = dataBits + 13; if ((bData.userData.msgEncoding == UserData.ENCODING_IS91_EXTENDED_PROTOCOL) || diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/SmsEnvelope.java b/telephony/java/com/android/internal/telephony/cdma/sms/SmsEnvelope.java index 6af174c851cc..3440c651c8ea 100644 --- a/telephony/java/com/android/internal/telephony/cdma/sms/SmsEnvelope.java +++ b/telephony/java/com/android/internal/telephony/cdma/sms/SmsEnvelope.java @@ -39,6 +39,9 @@ public final class SmsEnvelope { static public final int TELESERVICE_WEMT = 0x1005; static public final int TELESERVICE_SCPT = 0x1006; + /** Carriers specific Teleservice IDs. */ + public static final int TELESERVICE_FDEA_WAP = 0xFDEA; // 65002 + /** * The following are defined as extensions to the standard teleservices */ diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java index 5bb818bd3286..da32c8c45a73 100644 --- a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java +++ b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java @@ -1247,6 +1247,7 @@ public class SmsMessage extends SmsMessageBase { int encodingType = ENCODING_UNKNOWN; + Resources r = Resources.getSystem(); // Look up the data encoding scheme if ((mDataCodingScheme & 0x80) == 0) { userDataCompressed = (0 != (mDataCodingScheme & 0x20)); @@ -1268,7 +1269,6 @@ public class SmsMessage extends SmsMessageBase { case 1: // 8 bit data //Support decoding the user data payload as pack GSM 8-bit (a GSM alphabet string //that's stored in 8-bit unpacked format) characters. - Resources r = Resources.getSystem(); if (r.getBoolean(com.android.internal. R.bool.config_sms_decode_gsm_8bit_data)) { encodingType = ENCODING_8BIT; @@ -1278,7 +1278,8 @@ public class SmsMessage extends SmsMessageBase { case 3: // reserved Rlog.w(LOG_TAG, "1 - Unsupported SMS data coding scheme " + (mDataCodingScheme & 0xff)); - encodingType = ENCODING_8BIT; + encodingType = r.getInteger( + com.android.internal.R.integer.default_reserved_data_coding_scheme); break; } } @@ -1432,7 +1433,6 @@ public class SmsMessage extends SmsMessageBase { case ENCODING_8BIT: //Support decoding the user data payload as pack GSM 8-bit (a GSM alphabet string //that's stored in 8-bit unpacked format) characters. - Resources r = Resources.getSystem(); if (r.getBoolean(com.android.internal. R.bool.config_sms_decode_gsm_8bit_data)) { mMessageBody = p.getUserDataGSM8bit(count); diff --git a/test-mock/Android.bp b/test-mock/Android.bp index 9a653cf7204c..34ac3dcc824f 100644 --- a/test-mock/Android.bp +++ b/test-mock/Android.bp @@ -19,14 +19,14 @@ java_sdk_library { name: "android.test.mock", - srcs: ["src/**/*.java"], + srcs: [ + "src/**/*.java", + ":framework-srcs", + ], api_packages: [ "android.test.mock", ], - - srcs_lib: "framework-minus-apex", - srcs_lib_whitelist_pkgs: ["android"], compile_dex: true, } diff --git a/tests/BackgroundDexOptServiceIntegrationTests/AndroidManifest.xml b/tests/BackgroundDexOptServiceIntegrationTests/AndroidManifest.xml index aec9f77cf922..7291dc729541 100644 --- a/tests/BackgroundDexOptServiceIntegrationTests/AndroidManifest.xml +++ b/tests/BackgroundDexOptServiceIntegrationTests/AndroidManifest.xml @@ -28,6 +28,8 @@ <uses-permission android:name="android.permission.SET_TIME" /> <uses-permission android:name="android.permission.UPDATE_DEVICE_STATS" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> + <uses-permission android:name="android.permission.WRITE_DEVICE_CONFIG" /> + <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" /> <application> <uses-library android:name="android.test.runner" /> diff --git a/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java b/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java index 7d826f7172da..4cd56c3c42be 100644 --- a/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java +++ b/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java @@ -22,6 +22,7 @@ import android.os.Environment; import android.os.ParcelFileDescriptor; import android.os.SystemProperties; import android.os.storage.StorageManager; +import android.provider.DeviceConfig; import android.util.Log; import androidx.test.InstrumentationRegistry; @@ -30,7 +31,9 @@ import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -52,6 +55,13 @@ import java.util.concurrent.TimeUnit; * 3. Under low storage conditions and package is recently used, check * that dexopt upgrades test app to $(getprop pm.dexopt.bg-dexopt). * + * When downgrade feature is on (downgrade_unused_apps_enabled flag is set to true): + * 4 On low storage, check that the inactive packages are downgraded. + * 5. On low storage, check that used packages are upgraded. + * 6. On storage completely full, dexopt fails. + * 7. Not on low storage, unused packages are upgraded. + * 8. Low storage, unused app is downgraded. When app is used again, app is upgraded. + * * Each test case runs "cmd package bg-dexopt-job com.android.frameworks.bgdexopttest". * * The setup for these tests make sure this package has been configured to have been recently used @@ -59,6 +69,10 @@ import java.util.concurrent.TimeUnit; * recently used, it sets the time forward more than * `getprop pm.dexopt.downgrade_after_inactive_days` days. * + * For some of the tests, the DeviceConfig flags inactive_app_threshold_days and + * downgrade_unused_apps_enabled are set. These turn on/off the downgrade unused apps feature for + * all devices and set the time threshold for unused apps. + * * For tests that require low storage, the phone is filled up. * * Run with "atest BackgroundDexOptServiceIntegrationTests". @@ -80,10 +94,14 @@ public final class BackgroundDexOptServiceIntegrationTests { "pm.dexopt.downgrade_after_inactive_days", 0); // Needs to be between 1.0 and 2.0. private static final double LOW_STORAGE_MULTIPLIER = 1.5; + private static final int DOWNGRADE_FEATURE_PKG_INACTIVE_AFTER_DAYS = 15; // The file used to fill up storage. private File mBigFile; + @Rule + public ExpectedException mExpectedException = ExpectedException.none(); + // Remember start time. @BeforeClass public static void setUpAll() { @@ -196,11 +214,27 @@ public final class BackgroundDexOptServiceIntegrationTests { logSpaceRemaining(); } + private void fillUpStorageCompletely() throws IOException { + fillUpStorage((getStorageLowBytes())); + } + // Fill up storage so that device is in low storage condition. private void fillUpToLowStorage() throws IOException { fillUpStorage((long) (getStorageLowBytes() * LOW_STORAGE_MULTIPLIER)); } + private void setInactivePackageThreshold(int threshold) { + DeviceConfig.setProperty( + DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE, + "inactive_app_threshold_days", Integer.toString(threshold), false); + } + + private void enableDowngradeFeature(boolean enabled) { + DeviceConfig.setProperty( + DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE, + "downgrade_unused_apps_enabled", Boolean.toString(enabled), false); + } + // TODO(aeubanks): figure out how to get scheduled bg-dexopt to run private static void runBackgroundDexOpt() throws IOException { String result = runShellCommand("cmd package bg-dexopt-job " + PACKAGE_NAME); @@ -244,7 +278,7 @@ public final class BackgroundDexOptServiceIntegrationTests { // Test that background dexopt under normal conditions succeeds. @Test - public void testBackgroundDexOpt() throws IOException { + public void testBackgroundDexOpt_normalConditions_dexOptSucceeds() throws IOException { // Set filter to quicken. compilePackageWithFilter(PACKAGE_NAME, "verify"); Assert.assertEquals("verify", getCompilerFilter(PACKAGE_NAME)); @@ -257,17 +291,16 @@ public final class BackgroundDexOptServiceIntegrationTests { // Test that background dexopt under low storage conditions upgrades used packages. @Test - public void testBackgroundDexOptDowngradeSkipRecentlyUsedPackage() throws IOException { + public void testBackgroundDexOpt_lowStorage_usedPkgsUpgraded() throws IOException { // Should be less than DOWNGRADE_AFTER_DAYS. long deltaDays = DOWNGRADE_AFTER_DAYS - 1; try { + enableDowngradeFeature(false); // Set time to future. setTimeFutureDays(deltaDays); - // Set filter to quicken. compilePackageWithFilter(PACKAGE_NAME, "quicken"); Assert.assertEquals("quicken", getCompilerFilter(PACKAGE_NAME)); - // Fill up storage to trigger low storage threshold. fillUpToLowStorage(); @@ -282,18 +315,48 @@ public final class BackgroundDexOptServiceIntegrationTests { } // Test that background dexopt under low storage conditions downgrades unused packages. + // This happens if the system property pm.dexopt.downgrade_after_inactive_days is set + // (e.g. on Android Go devices). @Test - public void testBackgroundDexOptDowngradeSuccessful() throws IOException { + public void testBackgroundDexOpt_lowStorage_unusedPkgsDowngraded() + throws IOException { // Should be more than DOWNGRADE_AFTER_DAYS. long deltaDays = DOWNGRADE_AFTER_DAYS + 1; try { + enableDowngradeFeature(false); // Set time to future. setTimeFutureDays(deltaDays); - // Set filter to quicken. compilePackageWithFilter(PACKAGE_NAME, "quicken"); Assert.assertEquals("quicken", getCompilerFilter(PACKAGE_NAME)); + // Fill up storage to trigger low storage threshold. + fillUpToLowStorage(); + + runBackgroundDexOpt(); + + // Verify that downgrade is successful. + Assert.assertEquals(DOWNGRADE_COMPILER_FILTER, getCompilerFilter(PACKAGE_NAME)); + } finally { + // Reset time. + setTimeFutureDays(-deltaDays); + } + } + // Test that the background dexopt downgrades inactive packages when the downgrade feature is + // enabled. + @Test + public void testBackgroundDexOpt_downgradeFeatureEnabled_lowStorage_inactivePkgsDowngraded() + throws IOException { + // Should be more than DOWNGRADE_FEATURE_PKG_INACTIVE_AFTER_DAYS. + long deltaDays = DOWNGRADE_FEATURE_PKG_INACTIVE_AFTER_DAYS + 1; + try { + enableDowngradeFeature(true); + setInactivePackageThreshold(DOWNGRADE_FEATURE_PKG_INACTIVE_AFTER_DAYS); + // Set time to future. + setTimeFutureDays(deltaDays); + // Set filter to quicken. + compilePackageWithFilter(PACKAGE_NAME, "quicken"); + Assert.assertEquals("quicken", getCompilerFilter(PACKAGE_NAME)); // Fill up storage to trigger low storage threshold. fillUpToLowStorage(); @@ -307,4 +370,106 @@ public final class BackgroundDexOptServiceIntegrationTests { } } + // Test that the background dexopt upgrades used packages when the downgrade feature is enabled. + // This test doesn't fill the device storage completely, but to a multiplier of the low storage + // threshold and this is why apps can still be optimized. + @Test + public void testBackgroundDexOpt_downgradeFeatureEnabled_lowStorage_usedPkgsUpgraded() + throws IOException { + enableDowngradeFeature(true); + // Set filter to quicken. + compilePackageWithFilter(PACKAGE_NAME, "quicken"); + Assert.assertEquals("quicken", getCompilerFilter(PACKAGE_NAME)); + // Fill up storage to trigger low storage threshold. + fillUpToLowStorage(); + + runBackgroundDexOpt(); + + /// Verify that bg-dexopt is successful in upgrading the used packages. + Assert.assertEquals(BG_DEXOPT_COMPILER_FILTER, getCompilerFilter(PACKAGE_NAME)); + } + + // Test that the background dexopt fails and doesn't change the compilation filter of used + // packages when the downgrade feature is enabled and the storage is filled up completely. + // The bg-dexopt shouldn't optimise nor downgrade these packages. + @Test + public void testBackgroundDexOpt_downgradeFeatureEnabled_fillUpStorageCompletely_dexOptFails() + throws IOException { + enableDowngradeFeature(true); + String previousCompilerFilter = getCompilerFilter(PACKAGE_NAME); + + // Fill up storage completely, without using a multiplier for the low storage threshold. + fillUpStorageCompletely(); + + // When the bg dexopt runs with the storage filled up completely, it will fail. + mExpectedException.expect(IllegalStateException.class); + runBackgroundDexOpt(); + + /// Verify that bg-dexopt doesn't change the compilation filter of used apps. + Assert.assertEquals(previousCompilerFilter, getCompilerFilter(PACKAGE_NAME)); + } + + // Test that the background dexopt upgrades the unused packages when the downgrade feature is + // on if the device is not low on storage. + @Test + public void testBackgroundDexOpt_downgradeFeatureEnabled_notLowStorage_unusedPkgsUpgraded() + throws IOException { + // Should be more than DOWNGRADE_FEATURE_PKG_INACTIVE_AFTER_DAYS. + long deltaDays = DOWNGRADE_FEATURE_PKG_INACTIVE_AFTER_DAYS + 1; + try { + enableDowngradeFeature(true); + setInactivePackageThreshold(DOWNGRADE_FEATURE_PKG_INACTIVE_AFTER_DAYS); + // Set time to future. + setTimeFutureDays(deltaDays); + // Set filter to quicken. + compilePackageWithFilter(PACKAGE_NAME, "quicken"); + Assert.assertEquals("quicken", getCompilerFilter(PACKAGE_NAME)); + + runBackgroundDexOpt(); + + // Verify that bg-dexopt is successful in upgrading the unused packages when the device + // is not low on storage. + Assert.assertEquals(BG_DEXOPT_COMPILER_FILTER, getCompilerFilter(PACKAGE_NAME)); + } finally { + // Reset time. + setTimeFutureDays(-deltaDays); + } + } + + // Test that when an unused package (which was downgraded) is used again, it's re-optimized when + // bg-dexopt runs again. + @Test + public void testBackgroundDexOpt_downgradeFeatureEnabled_downgradedPkgsUpgradedAfterUse() + throws IOException { + // Should be more than DOWNGRADE_FEATURE_PKG_INACTIVE_AFTER_DAYS. + long deltaDays = DOWNGRADE_FEATURE_PKG_INACTIVE_AFTER_DAYS + 1; + try { + enableDowngradeFeature(true); + setInactivePackageThreshold(DOWNGRADE_FEATURE_PKG_INACTIVE_AFTER_DAYS); + // Set time to future. + setTimeFutureDays(deltaDays); + // Fill up storage to trigger low storage threshold. + fillUpToLowStorage(); + // Set filter to quicken. + compilePackageWithFilter(PACKAGE_NAME, "quicken"); + Assert.assertEquals("quicken", getCompilerFilter(PACKAGE_NAME)); + + runBackgroundDexOpt(); + + // Verify that downgrade is successful. + Assert.assertEquals(DOWNGRADE_COMPILER_FILTER, getCompilerFilter(PACKAGE_NAME)); + + // Reset time. + setTimeFutureDays(-deltaDays); + deltaDays = 0; + runBackgroundDexOpt(); + + // Verify that bg-dexopt is successful in upgrading the unused packages that were used + // again. + Assert.assertEquals(BG_DEXOPT_COMPILER_FILTER, getCompilerFilter(PACKAGE_NAME)); + } finally { + // Reset time. + setTimeFutureDays(-deltaDays); + } + } } diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java index 720c1af906ff..ed8f272874e1 100644 --- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java +++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java @@ -19,6 +19,8 @@ package com.android.tests.rollback; import static com.android.cts.install.lib.InstallUtils.processUserData; import static com.android.cts.rollback.lib.RollbackInfoSubject.assertThat; import static com.android.cts.rollback.lib.RollbackUtils.getUniqueRollbackInfoForPackage; +import static com.android.cts.rollback.lib.RollbackUtils.waitForAvailableRollback; +import static com.android.cts.rollback.lib.RollbackUtils.waitForUnavailableRollback; import static com.google.common.truth.Truth.assertThat; @@ -118,8 +120,7 @@ public class RollbackTest { } // The app should not be available for rollback. - assertThat( - getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TestApp.A)).isNull(); + waitForUnavailableRollback(TestApp.A); // There should be no recently committed rollbacks for this package. assertThat(getUniqueRollbackInfoForPackage( @@ -134,9 +135,7 @@ public class RollbackTest { assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); // The app should now be available for rollback. - RollbackInfo available = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TestApp.A); - assertThat(available).isNotNull(); + RollbackInfo available = waitForAvailableRollback(TestApp.A); assertThat(available).isNotStaged(); assertThat(available).packagesContainsExactly( Rollback.from(TestApp.A2).to(TestApp.A1)); @@ -197,14 +196,12 @@ public class RollbackTest { assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2); // Both test apps should now be available for rollback. - RollbackInfo rollbackA = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TestApp.A); + RollbackInfo rollbackA = waitForAvailableRollback(TestApp.A); assertThat(rollbackA).isNotNull(); assertThat(rollbackA).packagesContainsExactly( Rollback.from(TestApp.A2).to(TestApp.A1)); - RollbackInfo rollbackB = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TestApp.B); + RollbackInfo rollbackB = waitForAvailableRollback(TestApp.B); assertThat(rollbackB).isNotNull(); assertThat(rollbackB).packagesContainsExactly( Rollback.from(TestApp.B2).to(TestApp.B1)); @@ -213,14 +210,12 @@ public class RollbackTest { rm.reloadPersistedData(); // The apps should still be available for rollback. - rollbackA = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TestApp.A); + rollbackA = waitForAvailableRollback(TestApp.A); assertThat(rollbackA).isNotNull(); assertThat(rollbackA).packagesContainsExactly( Rollback.from(TestApp.A2).to(TestApp.A1)); - rollbackB = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TestApp.B); + rollbackB = waitForAvailableRollback(TestApp.B); assertThat(rollbackB).isNotNull(); assertThat(rollbackB).packagesContainsExactly( Rollback.from(TestApp.B2).to(TestApp.B1)); @@ -255,15 +250,13 @@ public class RollbackTest { assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2); // The app should now be available for rollback. - RollbackInfo availableA = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TestApp.A); + RollbackInfo availableA = waitForAvailableRollback(TestApp.A); assertThat(availableA).isNotNull(); assertThat(availableA).packagesContainsExactly( Rollback.from(TestApp.A2).to(TestApp.A1), Rollback.from(TestApp.B2).to(TestApp.B1)); - RollbackInfo availableB = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TestApp.B); + RollbackInfo availableB = waitForAvailableRollback(TestApp.B); assertThat(availableB).isNotNull(); assertThat(availableB).packagesContainsExactly( Rollback.from(TestApp.A2).to(TestApp.A1), @@ -276,13 +269,13 @@ public class RollbackTest { rm.reloadPersistedData(); // The apps should still be available for rollback. - availableA = getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TestApp.A); + availableA = waitForAvailableRollback(TestApp.A); assertThat(availableA).isNotNull(); assertThat(availableA).packagesContainsExactly( Rollback.from(TestApp.A2).to(TestApp.A1), Rollback.from(TestApp.B2).to(TestApp.B1)); - availableB = getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TestApp.B); + availableB = waitForAvailableRollback(TestApp.B); assertThat(availableB).isNotNull(); assertThat(availableB).packagesContainsExactly( Rollback.from(TestApp.A2).to(TestApp.A1), @@ -334,8 +327,7 @@ public class RollbackTest { assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); // The app should now be available for rollback. - RollbackInfo available = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TestApp.A); + RollbackInfo available = waitForAvailableRollback(TestApp.A); assertThat(available).isNotNull(); // Roll back the app. @@ -405,13 +397,11 @@ public class RollbackTest { // Check that the rollback data has not expired Thread.sleep(1000); - RollbackInfo rollback = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TestApp.A); - assertThat(rollback).isNotNull(); + RollbackInfo rollback = waitForAvailableRollback(TestApp.A); assertThat(rollback).packagesContainsExactly( Rollback.from(TestApp.A2).to(TestApp.A1)); - // Give it a little more time, but still not the long enough to expire + // Give it a little more time, but still not long enough to expire Thread.sleep(expirationTime / 2); rollback = getUniqueRollbackInfoForPackage( rm.getAvailableRollbacks(), TestApp.A); @@ -536,9 +526,7 @@ public class RollbackTest { assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); // The app should now be available for rollback. - RollbackInfo rollback = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TestApp.A); - assertThat(rollback).isNotNull(); + RollbackInfo rollback = waitForAvailableRollback(TestApp.A); assertThat(rollback).packagesContainsExactly( Rollback.from(TestApp.A2).to(TestApp.A1)); @@ -570,9 +558,7 @@ public class RollbackTest { Install.single(TestApp.A2).setEnableRollback().commit(); processUserData(TestApp.A); - RollbackManager rm = RollbackUtils.getRollbackManager(); - RollbackInfo rollback = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TestApp.A); + RollbackInfo rollback = waitForAvailableRollback(TestApp.A); RollbackUtils.rollback(rollback.getRollbackId()); processUserData(TestApp.A); } finally { @@ -598,10 +584,7 @@ public class RollbackTest { Install.single(TestApp.ASplit2).setEnableRollback().commit(); processUserData(TestApp.A); - RollbackManager rm = RollbackUtils.getRollbackManager(); - RollbackInfo rollback = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TestApp.A); - assertThat(rollback).isNotNull(); + RollbackInfo rollback = waitForAvailableRollback(TestApp.A); RollbackUtils.rollback(rollback.getRollbackId()); processUserData(TestApp.A); } finally { @@ -644,7 +627,6 @@ public class RollbackTest { Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES, Manifest.permission.TEST_MANAGE_ROLLBACKS); - RollbackManager rm = RollbackUtils.getRollbackManager(); // Prep installation of the test apps. Uninstall.packages(TestApp.A); @@ -659,15 +641,11 @@ public class RollbackTest { // Both test apps should now be available for rollback, and the // RollbackInfo returned for the rollbacks should be correct. - RollbackInfo rollbackA = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TestApp.A); - assertThat(rollbackA).isNotNull(); + RollbackInfo rollbackA = waitForAvailableRollback(TestApp.A); assertThat(rollbackA).packagesContainsExactly( Rollback.from(TestApp.A2).to(TestApp.A1)); - RollbackInfo rollbackB = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TestApp.B); - assertThat(rollbackB).isNotNull(); + RollbackInfo rollbackB = waitForAvailableRollback(TestApp.B); assertThat(rollbackB).packagesContainsExactly( Rollback.from(TestApp.B2).to(TestApp.B1)); @@ -822,8 +800,7 @@ public class RollbackTest { assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2); // TestApp.A should now be available for rollback. - RollbackInfo rollback = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TestApp.A); + RollbackInfo rollback = waitForAvailableRollback(TestApp.A); assertThat(rollback).isNotNull(); assertThat(rollback).packagesContainsExactly( Rollback.from(TestApp.A2).to(TestApp.A1), @@ -938,7 +915,6 @@ public class RollbackTest { Manifest.permission.TEST_MANAGE_ROLLBACKS, Manifest.permission.FORCE_STOP_PACKAGES, Manifest.permission.RESTART_PACKAGES); - RollbackManager rm = RollbackUtils.getRollbackManager(); // Prep installation of the test apps. Uninstall.packages(TestApp.A, TestApp.B); @@ -952,13 +928,11 @@ public class RollbackTest { // Both test apps should now be available for rollback, and the // targetPackage returned for rollback should be correct. - RollbackInfo rollbackA = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TestApp.A); + RollbackInfo rollbackA = waitForAvailableRollback(TestApp.A); assertThat(rollbackA).packagesContainsExactly( Rollback.from(TestApp.A2).to(TestApp.A1)); - RollbackInfo rollbackB = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TestApp.B); + RollbackInfo rollbackB = waitForAvailableRollback(TestApp.B); assertThat(rollbackB).packagesContainsExactly( Rollback.from(TestApp.B2).to(TestApp.B1)); @@ -1002,8 +976,7 @@ public class RollbackTest { Install.single(TestApp.A2).setEnableRollback().commit(); assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); - RollbackInfo rollback = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TestApp.A); + RollbackInfo rollback = waitForAvailableRollback(TestApp.A); assertThat(rollback).packagesContainsExactly( Rollback.from(TestApp.A2).to(TestApp.A1)); @@ -1047,6 +1020,7 @@ public class RollbackTest { Uninstall.packages(TestApp.A); Install.single(TestApp.A1).commit(); + waitForUnavailableRollback(TestApp.A); // Block the RollbackManager to make extra sure it will not be // able to enable the rollback in time. @@ -1055,6 +1029,10 @@ public class RollbackTest { assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); + // Give plenty of time for RollbackManager to unblock and attempt + // to make the rollback available before asserting that the + // rollback was not made available. + Thread.sleep(TimeUnit.SECONDS.toMillis(2)); assertThat( getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TestApp.A)).isNull(); } finally { diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index f3c735cd8880..6ae639a6ee52 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -5692,7 +5692,6 @@ public class ConnectivityServiceTest { String[] values = tcpBufferSizes.split(","); String rmemValues = String.join(" ", values[0], values[1], values[2]); String wmemValues = String.join(" ", values[3], values[4], values[5]); - waitForIdle(); verify(mMockNetd, atLeastOnce()).setTcpRWmemorySize(rmemValues, wmemValues); reset(mMockNetd); } @@ -5700,18 +5699,32 @@ public class ConnectivityServiceTest { @Test public void testTcpBufferReset() throws Exception { final String testTcpBufferSizes = "1,2,3,4,5,6"; + final NetworkRequest networkRequest = new NetworkRequest.Builder() + .addTransportType(TRANSPORT_CELLULAR) + .addCapability(NET_CAPABILITY_INTERNET) + .build(); + final TestNetworkCallback networkCallback = new TestNetworkCallback(); + mCm.registerNetworkCallback(networkRequest, networkCallback); mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); reset(mMockNetd); // Switching default network updates TCP buffer sizes. mCellNetworkAgent.connect(false); + networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES); // Change link Properties should have updated tcp buffer size. LinkProperties lp = new LinkProperties(); lp.setTcpBufferSizes(testTcpBufferSizes); mCellNetworkAgent.sendLinkProperties(lp); + networkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED, mCellNetworkAgent); verifyTcpBufferSizeChange(testTcpBufferSizes); + + // Clean up. + mCellNetworkAgent.disconnect(); + networkCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent); + networkCallback.assertNoCallback(); + mCm.unregisterNetworkCallback(networkCallback); } @Test diff --git a/wifi/java/android/net/wifi/RttManager.java b/wifi/java/android/net/wifi/RttManager.java index 6ce21216f753..6a03c73bc3f9 100644 --- a/wifi/java/android/net/wifi/RttManager.java +++ b/wifi/java/android/net/wifi/RttManager.java @@ -211,6 +211,7 @@ public class RttManager { /** Draft 11mc version supported, including major and minor version. e.g, draft 4.3 is 43 */ public int mcVersion; + @NonNull @Override public String toString() { StringBuffer sb = new StringBuffer(); @@ -1130,6 +1131,7 @@ public class RttManager { */ public int preamble; + @NonNull @Override public String toString() { StringBuilder builder = new StringBuilder(); diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java index f2ae44730973..eb5a717d2b07 100644 --- a/wifi/java/android/net/wifi/WifiConfiguration.java +++ b/wifi/java/android/net/wifi/WifiConfiguration.java @@ -18,6 +18,7 @@ package android.net.wifi; import android.annotation.IntDef; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.UnsupportedAppUsage; import android.content.pm.PackageManager; @@ -510,6 +511,12 @@ public class WifiConfiguration implements Parcelable { public String preSharedKey; /** + * Optional SAE Password Id for use with WPA3-SAE. It is an ASCII string. + * @hide + */ + public @Nullable String saePasswordId; + + /** * Four WEP keys. For each of the four values, provide either an ASCII * string enclosed in double quotation marks (e.g., {@code "abcdef"}), * a string of hex digits (e.g., {@code 0102030405}), or an empty string @@ -2004,6 +2011,9 @@ public class WifiConfiguration implements Parcelable { sbuf.append('*'); } + sbuf.append('\n').append(" SAE Password Id: "); + sbuf.append(this.saePasswordId); + sbuf.append("\nEnterprise config:\n"); sbuf.append(enterpriseConfig); @@ -2372,6 +2382,7 @@ public class WifiConfiguration implements Parcelable { providerFriendlyName = source.providerFriendlyName; isHomeProviderNetwork = source.isHomeProviderNetwork; preSharedKey = source.preSharedKey; + saePasswordId = source.saePasswordId; mNetworkSelectionStatus.copy(source.getNetworkSelectionStatus()); apBand = source.apBand; @@ -2462,6 +2473,7 @@ public class WifiConfiguration implements Parcelable { dest.writeLong(roamingConsortiumId); } dest.writeString(preSharedKey); + dest.writeString(saePasswordId); for (String wepKey : wepKeys) { dest.writeString(wepKey); } @@ -2537,6 +2549,7 @@ public class WifiConfiguration implements Parcelable { config.roamingConsortiumIds[i] = in.readLong(); } config.preSharedKey = in.readString(); + config.saePasswordId = in.readString(); for (int i = 0; i < config.wepKeys.length; i++) { config.wepKeys[i] = in.readString(); } @@ -2608,6 +2621,7 @@ public class WifiConfiguration implements Parcelable { out.writeInt(apBand); out.writeInt(apChannel); BackupUtils.writeString(out, preSharedKey); + BackupUtils.writeString(out, saePasswordId); out.writeInt(getAuthType()); out.writeBoolean(hiddenSSID); return baos.toByteArray(); @@ -2631,6 +2645,7 @@ public class WifiConfiguration implements Parcelable { config.apBand = in.readInt(); config.apChannel = in.readInt(); config.preSharedKey = BackupUtils.readString(in); + config.saePasswordId = BackupUtils.readString(in); config.allowedKeyManagement.set(in.readInt()); if (version >= 3) { config.hiddenSSID = in.readBoolean(); diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index e9c24cd6e3e0..6bf7bfb9b4a1 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -634,10 +634,19 @@ public class WifiManager { */ public static final int SAP_START_FAILURE_NO_CHANNEL = 1; + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = {"IFACE_IP_MODE_"}, value = { + IFACE_IP_MODE_UNSPECIFIED, + IFACE_IP_MODE_CONFIGURATION_ERROR, + IFACE_IP_MODE_TETHERED, + IFACE_IP_MODE_LOCAL_ONLY}) + public @interface IfaceIpMode {} + /** * Interface IP mode unspecified. * - * @see updateInterfaceIpState(String, int) + * @see #updateInterfaceIpState(String, int) * * @hide */ @@ -646,7 +655,7 @@ public class WifiManager { /** * Interface IP mode for configuration error. * - * @see updateInterfaceIpState(String, int) + * @see #updateInterfaceIpState(String, int) * * @hide */ @@ -655,7 +664,7 @@ public class WifiManager { /** * Interface IP mode for tethering. * - * @see updateInterfaceIpState(String, int) + * @see #updateInterfaceIpState(String, int) * * @hide */ @@ -664,7 +673,7 @@ public class WifiManager { /** * Interface IP mode for Local Only Hotspot. * - * @see updateInterfaceIpState(String, int) + * @see #updateInterfaceIpState(String, int) * * @hide */ @@ -2670,9 +2679,9 @@ public class WifiManager { /** * Call allowing ConnectivityService to update WifiService with interface mode changes. * - * The possible modes include: {@link IFACE_IP_MODE_TETHERED}, - * {@link IFACE_IP_MODE_LOCAL_ONLY}, - * {@link IFACE_IP_MODE_CONFIGURATION_ERROR} + * The possible modes include: {@link #IFACE_IP_MODE_TETHERED}, + * {@link #IFACE_IP_MODE_LOCAL_ONLY}, + * {@link #IFACE_IP_MODE_CONFIGURATION_ERROR} * * @param ifaceName String name of the updated interface * @param mode int representing the new mode @@ -3397,6 +3406,7 @@ public class WifiManager { private final CloseGuard mCloseGuard = CloseGuard.get(); private final WifiConfiguration mConfig; + private boolean mClosed = false; /** @hide */ @VisibleForTesting @@ -3412,8 +3422,13 @@ public class WifiManager { @Override public void close() { try { - stopLocalOnlyHotspot(); - mCloseGuard.close(); + synchronized (mLock) { + if (!mClosed) { + mClosed = true; + stopLocalOnlyHotspot(); + mCloseGuard.close(); + } + } } catch (Exception e) { Log.e(TAG, "Failed to stop Local Only Hotspot."); } diff --git a/wifi/java/android/net/wifi/WifiNetworkConnectionStatistics.java b/wifi/java/android/net/wifi/WifiNetworkConnectionStatistics.java index 8262a7a36c56..95b2e77c5c1e 100644 --- a/wifi/java/android/net/wifi/WifiNetworkConnectionStatistics.java +++ b/wifi/java/android/net/wifi/WifiNetworkConnectionStatistics.java @@ -16,8 +16,8 @@ package android.net.wifi; +import android.annotation.NonNull; import android.annotation.SystemApi; - import android.os.Parcel; import android.os.Parcelable; @@ -39,7 +39,7 @@ public class WifiNetworkConnectionStatistics implements Parcelable { public WifiNetworkConnectionStatistics() { } - + @NonNull @Override public String toString() { StringBuilder sbuf = new StringBuilder(); diff --git a/wifi/java/android/net/wifi/hotspot2/OsuProvider.java b/wifi/java/android/net/wifi/hotspot2/OsuProvider.java index 57dff9d761cb..a32bd547e1e2 100644 --- a/wifi/java/android/net/wifi/hotspot2/OsuProvider.java +++ b/wifi/java/android/net/wifi/hotspot2/OsuProvider.java @@ -16,6 +16,7 @@ package android.net.wifi.hotspot2; +import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.graphics.drawable.Icon; @@ -219,7 +220,7 @@ public final class OsuProvider implements Parcelable { } @Override - public boolean equals(Object thatObject) { + public boolean equals(@Nullable Object thatObject) { if (this == thatObject) { return true; } @@ -246,6 +247,7 @@ public final class OsuProvider implements Parcelable { mServerUri, mNetworkAccessIdentifier, mMethodList); } + @NonNull @Override public String toString() { return "OsuProvider{mOsuSsid=" + mOsuSsid diff --git a/wifi/java/android/net/wifi/rtt/RangingRequest.java b/wifi/java/android/net/wifi/rtt/RangingRequest.java index 70af03e56262..318efa61a110 100644 --- a/wifi/java/android/net/wifi/rtt/RangingRequest.java +++ b/wifi/java/android/net/wifi/rtt/RangingRequest.java @@ -17,6 +17,7 @@ package android.net.wifi.rtt; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.net.MacAddress; import android.net.wifi.ScanResult; @@ -245,7 +246,7 @@ public final class RangingRequest implements Parcelable { } @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (this == o) { return true; } diff --git a/wifi/java/android/net/wifi/rtt/ResponderConfig.java b/wifi/java/android/net/wifi/rtt/ResponderConfig.java index e6ae48344afc..64dfc3499aaf 100644 --- a/wifi/java/android/net/wifi/rtt/ResponderConfig.java +++ b/wifi/java/android/net/wifi/rtt/ResponderConfig.java @@ -21,6 +21,7 @@ import static android.net.wifi.ScanResult.InformationElement.EID_VHT_CAPABILITIE import android.annotation.IntDef; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.net.MacAddress; import android.net.wifi.ScanResult; @@ -443,7 +444,7 @@ public final class ResponderConfig implements Parcelable { }; @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (this == o) { return true; } |