summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp19
-rw-r--r--TEST_MAPPING16
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java2
-rw-r--r--apex/sdkext/TEST_MAPPING7
-rw-r--r--apex/sdkext/framework/tests/Android.bp1
-rw-r--r--apex/sdkext/framework/tests/src/android/os/ext/SdkExtensionsTest.java5
-rw-r--r--apex/statsd/aidl/Android.bp35
-rw-r--r--apex/statsd/aidl/android/os/IPullAtomCallback.aidl (renamed from core/java/android/os/IPullAtomCallback.aidl)0
-rw-r--r--apex/statsd/aidl/android/os/IPullAtomResultReceiver.aidl (renamed from core/java/android/os/IPullAtomResultReceiver.aidl)4
-rw-r--r--apex/statsd/aidl/android/os/IStatsCompanionService.aidl (renamed from core/java/android/os/IStatsCompanionService.aidl)0
-rw-r--r--apex/statsd/aidl/android/os/IStatsManager.aidl (renamed from core/java/android/os/IStatsManager.aidl)2
-rw-r--r--apex/statsd/aidl/android/os/IStatsPullerCallback.aidl (renamed from core/java/android/os/IStatsPullerCallback.aidl)0
-rw-r--r--apex/statsd/aidl/android/util/StatsEventParcel.aidl8
-rw-r--r--apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java62
-rw-r--r--api/current.txt9
-rw-r--r--api/system-current.txt72
-rw-r--r--api/test-current.txt2
-rw-r--r--cmds/statsd/src/StatsService.cpp8
-rw-r--r--cmds/statsd/src/StatsService.h4
-rw-r--r--cmds/statsd/src/atoms.proto38
-rw-r--r--cmds/statsd/src/external/PullResultReceiver.cpp7
-rw-r--r--cmds/statsd/src/external/PullResultReceiver.h7
-rw-r--r--cmds/statsd/src/external/StatsCallbackPuller.cpp12
-rw-r--r--cmds/statsd/src/external/StatsPullerManager.cpp3
-rw-r--r--cmds/statsd/src/metrics/ValueMetricProducer.cpp20
-rw-r--r--cmds/statsd/src/metrics/ValueMetricProducer.h7
-rw-r--r--cmds/statsd/src/state/StateTracker.cpp7
-rw-r--r--core/java/android/app/ActivityThread.java1
-rw-r--r--core/java/android/app/INotificationManager.aidl2
-rw-r--r--core/java/android/app/StatsManager.java9
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java84
-rw-r--r--core/java/android/app/admin/DevicePolicyManagerInternal.java9
-rw-r--r--core/java/android/app/admin/IDevicePolicyManager.aidl4
-rw-r--r--core/java/android/bluetooth/BluetoothA2dp.java101
-rwxr-xr-xcore/java/android/bluetooth/BluetoothA2dpSink.java2
-rw-r--r--core/java/android/bluetooth/BluetoothAdapter.java13
-rw-r--r--core/java/android/bluetooth/BluetoothCodecConfig.java179
-rw-r--r--core/java/android/bluetooth/BluetoothCodecStatus.java42
-rw-r--r--core/java/android/bluetooth/BluetoothDevice.java35
-rw-r--r--core/java/android/content/pm/PackageInstaller.java14
-rw-r--r--core/java/android/ddm/DdmHandleAppName.java64
-rw-r--r--core/java/android/ddm/DdmHandleHello.java14
-rw-r--r--core/java/android/hardware/biometrics/BiometricConstants.java10
-rw-r--r--core/java/android/hardware/display/DisplayViewport.java7
-rw-r--r--core/java/android/os/Binder.java31
-rw-r--r--core/java/android/os/UserManager.java94
-rw-r--r--core/java/android/os/connectivity/WifiActivityEnergyInfo.java32
-rw-r--r--core/java/android/provider/MediaStore.java73
-rw-r--r--core/java/android/provider/Telephony.java19
-rwxr-xr-xcore/java/android/telephony/SubscriptionPlan.aidl (renamed from telephony/java/android/telephony/SubscriptionPlan.aidl)0
-rw-r--r--core/java/android/telephony/SubscriptionPlan.java (renamed from telephony/java/android/telephony/SubscriptionPlan.java)0
-rw-r--r--core/java/android/util/StatsEvent.java37
-rw-r--r--core/java/android/util/StatsLog.java6
-rw-r--r--core/java/android/view/DisplayAddress.java34
-rw-r--r--core/java/android/view/ViewRootImpl.java2
-rw-r--r--core/java/android/widget/RemoteViews.java23
-rw-r--r--core/java/com/android/internal/os/RuntimeInit.java5
-rw-r--r--core/java/com/android/internal/widget/ILockSettings.aidl2
-rw-r--r--core/java/com/android/internal/widget/LockPatternUtils.java30
-rw-r--r--core/java/com/android/server/BootReceiver.java40
-rw-r--r--core/jni/AndroidRuntime.cpp9
-rw-r--r--core/jni/android_content_res_ApkAssets.cpp17
-rw-r--r--core/proto/android/service/notification.proto11
-rw-r--r--core/res/res/values/config.xml3
-rw-r--r--core/res/res/values/symbols.xml1
-rw-r--r--core/res/res/values/themes_device_defaults.xml1
-rw-r--r--data/etc/privapp-permissions-platform.xml5
-rw-r--r--data/sounds/AudioPackageGo.mk4
-rw-r--r--drm/java/android/drm/DrmManagerClient.java14
-rw-r--r--location/java/android/location/LocationManager.java35
-rw-r--r--location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java9
-rw-r--r--media/java/android/media/MediaScannerConnection.java2
-rw-r--r--media/java/android/media/tv/tuner/FilterSettings.java383
-rw-r--r--media/java/android/media/tv/tuner/Tuner.java15
-rw-r--r--media/java/android/media/tv/tuner/TunerConstants.java11
-rw-r--r--media/jni/Android.bp2
-rw-r--r--media/jni/android_media_MediaMetricsJNI.cpp259
-rw-r--r--media/jni/android_media_MediaMetricsJNI.h1
-rw-r--r--media/jni/android_media_tv_Tuner.cpp159
-rw-r--r--media/jni/android_media_tv_Tuner.h18
-rw-r--r--media/jni/soundpool/StreamManager.cpp3
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java14
-rw-r--r--packages/SystemUI/TEST_MAPPING6
-rw-r--r--packages/SystemUI/docs/executors.md321
-rw-r--r--packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/StatusBarStateController.java3
-rw-r--r--packages/SystemUI/res/layout/bubble_menu_view.xml43
-rw-r--r--packages/SystemUI/res/values-television/config.xml39
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java106
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleExperimentConfig.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleMenuView.java81
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java64
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleTouchHandler.java27
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClicker.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeController.java49
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java46
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowViewController.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/concurrency/DelayableExecutor.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/concurrency/ExecutorImpl.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java12
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowViewTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/util/concurrency/FakeExecutor.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/util/concurrency/FakeExecutorTest.java30
-rw-r--r--packages/Tethering/apex/manifest.json2
-rw-r--r--services/core/java/com/android/server/BluetoothManagerService.java37
-rw-r--r--services/core/java/com/android/server/LocationManagerService.java145
-rw-r--r--services/core/java/com/android/server/NetworkManagementService.java13
-rw-r--r--services/core/java/com/android/server/PackageWatchdog.java31
-rw-r--r--services/core/java/com/android/server/TelephonyRegistry.java25
-rw-r--r--services/core/java/com/android/server/UiModeManagerService.java5
-rw-r--r--services/core/java/com/android/server/ZramWriteback.java7
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java18
-rw-r--r--services/core/java/com/android/server/am/AppErrors.java6
-rw-r--r--services/core/java/com/android/server/am/BatteryExternalStatsWorker.java2
-rw-r--r--services/core/java/com/android/server/am/CarUserSwitchingDialog.java4
-rw-r--r--services/core/java/com/android/server/am/OWNERS2
-rw-r--r--services/core/java/com/android/server/am/ProcessList.java88
-rw-r--r--services/core/java/com/android/server/am/UserSwitchingDialog.java13
-rw-r--r--services/core/java/com/android/server/audio/AudioDeviceInventory.java16
-rw-r--r--services/core/java/com/android/server/display/LocalDisplayAdapter.java2
-rw-r--r--services/core/java/com/android/server/integrity/model/BitInputStream.java55
-rw-r--r--services/core/java/com/android/server/integrity/parser/RuleBinaryParser.java16
-rw-r--r--services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java6
-rw-r--r--services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java6
-rw-r--r--services/core/java/com/android/server/locksettings/LockSettingsService.java155
-rw-r--r--services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java9
-rwxr-xr-xservices/core/java/com/android/server/notification/NotificationManagerService.java67
-rw-r--r--services/core/java/com/android/server/notification/NotificationUsageStats.java54
-rw-r--r--services/core/java/com/android/server/notification/PulledStats.java129
-rw-r--r--services/core/java/com/android/server/om/OverlayManagerService.java151
-rw-r--r--services/core/java/com/android/server/pm/ApexManager.java46
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java4
-rw-r--r--services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java57
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java25
-rw-r--r--services/core/java/com/android/server/wm/AppTransitionController.java1
-rw-r--r--services/core/java/com/android/server/wm/DisplayWindowSettings.java3
-rw-r--r--services/core/java/com/android/server/wm/WindowStateAnimator.java4
-rw-r--r--services/core/java/com/android/server/wm/WindowToken.java5
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java277
-rw-r--r--services/java/com/android/server/SystemServer.java23
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java79
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java14
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java71
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java21
-rw-r--r--services/tests/servicestests/src/com/android/server/locksettings/CachedSyntheticPasswordTests.java151
-rw-r--r--services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java49
-rw-r--r--services/tests/servicestests/src/com/android/server/locksettings/LockscreenFrpTest.java20
-rw-r--r--services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java39
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java2
-rw-r--r--services/tests/uiservicestests/Android.bp1
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/PulledStatsTest.java113
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java13
-rw-r--r--services/usage/java/com/android/server/usage/UsageStatsDatabase.java36
-rw-r--r--services/usage/java/com/android/server/usage/UsageStatsService.java18
-rwxr-xr-xtelephony/java/android/telephony/CarrierConfigManager.java43
-rw-r--r--telephony/java/android/telephony/CellSignalStrengthNr.java167
-rw-r--r--telephony/java/android/telephony/SignalThresholdInfo.java256
-rw-r--r--telephony/java/android/telephony/SubscriptionInfo.java6
-rw-r--r--telephony/java/android/telephony/SubscriptionManager.java34
-rw-r--r--telephony/java/android/telephony/ims/ImsMmTelManager.java10
-rw-r--r--telephony/java/android/telephony/ims/ImsRcsManager.java10
-rw-r--r--telephony/java/android/telephony/ims/ProvisioningManager.java21
-rw-r--r--telephony/java/android/telephony/ims/RcsUceAdapter.java19
-rw-r--r--telephony/java/android/telephony/ims/RegistrationManager.java45
-rw-r--r--telephony/java/android/telephony/ims/feature/RcsFeature.java12
-rw-r--r--telephony/java/com/android/internal/telephony/util/TelephonyUtils.java37
-rw-r--r--tests/FlickerTests/AndroidTest.xml2
-rw-r--r--tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java132
-rw-r--r--tools/aapt2/java/JavaClassGenerator.cpp8
-rw-r--r--tools/stats_log_api_gen/java_writer.cpp13
-rw-r--r--wifi/java/android/net/wifi/IWifiManager.aidl3
-rw-r--r--wifi/java/android/net/wifi/WifiInfo.java4
-rw-r--r--wifi/java/android/net/wifi/WifiManager.java19
-rw-r--r--wifi/java/android/net/wifi/WifiNetworkSuggestion.java49
-rw-r--r--wifi/java/android/net/wifi/aware/PublishConfig.java3
-rw-r--r--wifi/java/android/net/wifi/aware/SubscribeConfig.java3
-rw-r--r--wifi/java/android/net/wifi/aware/WifiAwareAgentNetworkSpecifier.java3
-rw-r--r--wifi/java/android/net/wifi/aware/WifiAwareManager.java15
-rw-r--r--wifi/java/android/net/wifi/util/HexEncoding.java183
-rw-r--r--wifi/java/com/android/server/wifi/BaseWifiService.java5
-rw-r--r--wifi/tests/src/android/net/wifi/WifiManagerTest.java14
-rw-r--r--wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java67
-rw-r--r--wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java3
-rw-r--r--wifi/tests/src/android/net/wifi/util/HexEncodingTest.java130
200 files changed, 4803 insertions, 1994 deletions
diff --git a/Android.bp b/Android.bp
index 661b1ccf988e..7b6d145e14e5 100644
--- a/Android.bp
+++ b/Android.bp
@@ -253,6 +253,8 @@ filegroup {
":libcamera_client_aidl",
":libcamera_client_framework_aidl",
":libupdate_engine_aidl",
+ // TODO: this needs to be removed when statsd-framework.jar is separated out
+ ":statsd_aidl",
":storaged_aidl",
":vold_aidl",
@@ -413,18 +415,6 @@ filegroup {
}
filegroup {
- name: "statsd_aidl",
- srcs: [
- "core/java/android/os/IPullAtomCallback.aidl",
- "core/java/android/os/IPullAtomResultReceiver.aidl",
- "core/java/android/os/IStatsCompanionService.aidl",
- "core/java/android/os/IStatsManager.aidl",
- "core/java/android/os/IStatsPullerCallback.aidl",
- ],
- path: "core/java",
-}
-
-filegroup {
name: "libvibrator_aidl",
srcs: [
"core/java/android/os/IExternalVibrationController.aidl",
@@ -1690,16 +1680,13 @@ filegroup {
}
filegroup {
- name: "framework-wifistack-shared-srcs",
+ name: "framework-wifi-service-shared-srcs",
srcs: [
":framework-annotations",
"core/java/android/os/HandlerExecutor.java",
"core/java/android/util/BackupUtils.java",
- "core/java/android/util/KeyValueListParser.java",
"core/java/android/util/LocalLog.java",
"core/java/android/util/Rational.java",
- "core/java/android/util/proto/ProtoStream.java",
- "core/java/android/util/proto/ProtoOutputStream.java",
"core/java/com/android/internal/util/FastXmlSerializer.java",
"core/java/com/android/internal/util/HexDump.java",
"core/java/com/android/internal/util/IState.java",
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 55fa5ed13d79..b1c4cad72dc9 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -7,6 +7,22 @@
"exclude-annotation": "androidx.test.filters.FlakyTest"
}
]
+ },
+ {
+ "name": "ExtServicesUnitTests",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
+ },
+ {
+ "name": "TestablesTests",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
}
],
"postsubmit-managedprofile-stress": [
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
index 3204013042c6..1ec96ecc561b 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -2689,7 +2689,7 @@ public class JobSchedulerService extends com.android.server.SystemService
}
@Override
- protected int handleShellCommand(@NonNull ParcelFileDescriptor in,
+ public int handleShellCommand(@NonNull ParcelFileDescriptor in,
@NonNull ParcelFileDescriptor out, @NonNull ParcelFileDescriptor err,
@NonNull String[] args) {
return (new JobSchedulerShellCommand(JobSchedulerService.this)).exec(
diff --git a/apex/sdkext/TEST_MAPPING b/apex/sdkext/TEST_MAPPING
new file mode 100644
index 000000000000..8dc732d36c79
--- /dev/null
+++ b/apex/sdkext/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "framework-sdkext-tests"
+ }
+ ]
+}
diff --git a/apex/sdkext/framework/tests/Android.bp b/apex/sdkext/framework/tests/Android.bp
index 3d5dbb3d8a2d..ab6327582efd 100644
--- a/apex/sdkext/framework/tests/Android.bp
+++ b/apex/sdkext/framework/tests/Android.bp
@@ -6,5 +6,6 @@ android_test {
"android.test.runner",
],
static_libs: [ "framework-sdkext" ],
+ test_suites: [ "general-tests" ],
platform_apis: true,
}
diff --git a/apex/sdkext/framework/tests/src/android/os/ext/SdkExtensionsTest.java b/apex/sdkext/framework/tests/src/android/os/ext/SdkExtensionsTest.java
index 688511096a43..d7dca90e0b8f 100644
--- a/apex/sdkext/framework/tests/src/android/os/ext/SdkExtensionsTest.java
+++ b/apex/sdkext/framework/tests/src/android/os/ext/SdkExtensionsTest.java
@@ -29,11 +29,6 @@ public class SdkExtensionsTest extends TestCase {
SdkExtensions.getExtensionVersion(Build.VERSION_CODES.Q);
fail("expected IllegalArgumentException");
} catch (IllegalArgumentException expected) { }
-
- try {
- SdkExtensions.getExtensionVersion(999999);
- fail("expected IllegalArgumentException");
- } catch (IllegalArgumentException expected) { }
}
@SmallTest
diff --git a/apex/statsd/aidl/Android.bp b/apex/statsd/aidl/Android.bp
new file mode 100644
index 000000000000..e6ca544c04be
--- /dev/null
+++ b/apex/statsd/aidl/Android.bp
@@ -0,0 +1,35 @@
+//
+// 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.
+//
+
+// TODO(b/145815909): move StatsDimensionsValue.aidl and StatsLogEventWrapper.aidl here
+filegroup {
+ name: "statsd_aidl",
+ srcs: ["**/*.aidl"],
+}
+
+// This library is currently unused
+aidl_interface {
+ name: "stats-event-parcel-aidl",
+ srcs: ["android/util/StatsEventParcel.aidl"],
+ backend: {
+ java: {
+ sdk_version: "28",
+ },
+ cpp: {
+ enabled: false,
+ }
+ }
+}
diff --git a/core/java/android/os/IPullAtomCallback.aidl b/apex/statsd/aidl/android/os/IPullAtomCallback.aidl
index 88d3c3e46ff5..88d3c3e46ff5 100644
--- a/core/java/android/os/IPullAtomCallback.aidl
+++ b/apex/statsd/aidl/android/os/IPullAtomCallback.aidl
diff --git a/core/java/android/os/IPullAtomResultReceiver.aidl b/apex/statsd/aidl/android/os/IPullAtomResultReceiver.aidl
index bfb35ff0c9d1..00d026e25df3 100644
--- a/core/java/android/os/IPullAtomResultReceiver.aidl
+++ b/apex/statsd/aidl/android/os/IPullAtomResultReceiver.aidl
@@ -16,7 +16,7 @@
package android.os;
-import android.util.StatsEvent;
+import android.util.StatsEventParcel;
/**
* Binder interface to pull atoms for the stats service.
@@ -27,6 +27,6 @@ interface IPullAtomResultReceiver {
/**
* Indicate that a pull request for an atom is complete.
*/
- oneway void pullFinished(int atomTag, boolean success, in StatsEvent[] output);
+ oneway void pullFinished(int atomTag, boolean success, in StatsEventParcel[] output);
}
diff --git a/core/java/android/os/IStatsCompanionService.aidl b/apex/statsd/aidl/android/os/IStatsCompanionService.aidl
index 22a25374e064..22a25374e064 100644
--- a/core/java/android/os/IStatsCompanionService.aidl
+++ b/apex/statsd/aidl/android/os/IStatsCompanionService.aidl
diff --git a/core/java/android/os/IStatsManager.aidl b/apex/statsd/aidl/android/os/IStatsManager.aidl
index 5ebb9f2e4e90..cc62f07a3750 100644
--- a/core/java/android/os/IStatsManager.aidl
+++ b/apex/statsd/aidl/android/os/IStatsManager.aidl
@@ -240,7 +240,7 @@ interface IStatsManager {
* Logs an event for watchdog rollbacks.
*/
oneway void sendWatchdogRollbackOccurredAtom(in int rollbackType, in String packageName,
- in long packageVersionCode);
+ in long packageVersionCode, in int rollbackReason, in String failingPackageName);
/**
* Returns the most recently registered experiment IDs.
diff --git a/core/java/android/os/IStatsPullerCallback.aidl b/apex/statsd/aidl/android/os/IStatsPullerCallback.aidl
index c3e1e55dde06..c3e1e55dde06 100644
--- a/core/java/android/os/IStatsPullerCallback.aidl
+++ b/apex/statsd/aidl/android/os/IStatsPullerCallback.aidl
diff --git a/apex/statsd/aidl/android/util/StatsEventParcel.aidl b/apex/statsd/aidl/android/util/StatsEventParcel.aidl
new file mode 100644
index 000000000000..add8bfb47b1a
--- /dev/null
+++ b/apex/statsd/aidl/android/util/StatsEventParcel.aidl
@@ -0,0 +1,8 @@
+package android.util;
+
+/**
+ * @hide
+ */
+parcelable StatsEventParcel {
+ byte[] buffer;
+}
diff --git a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
index c9139b15f223..6fb3bc47859d 100644
--- a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
+++ b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
@@ -41,6 +41,7 @@ import android.app.AppOpsManager.HistoricalOps;
import android.app.AppOpsManager.HistoricalOpsRequest;
import android.app.AppOpsManager.HistoricalPackageOps;
import android.app.AppOpsManager.HistoricalUidOps;
+import android.app.INotificationManager;
import android.app.ProcessMemoryState;
import android.app.StatsManager;
import android.bluetooth.BluetoothActivityEnergyInfo;
@@ -139,6 +140,7 @@ import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.SystemServiceManager;
import com.android.server.am.MemoryStatUtil.MemoryStat;
+import com.android.server.notification.NotificationManagerService;
import com.android.server.role.RoleManagerInternal;
import com.android.server.stats.IonMemoryUtil.IonAllocations;
import com.android.server.stats.ProcfsMemoryUtil.MemorySnapshot;
@@ -1750,14 +1752,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
if (statsFiles.size() != 1) {
return;
}
- InputStream stream = new ParcelFileDescriptor.AutoCloseInputStream(
- statsFiles.get(0));
- int[] len = new int[1];
- byte[] stats = readFully(stream, len);
- StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos,
- wallClockNanos);
- e.writeStorage(Arrays.copyOf(stats, len[0]));
- pulledData.add(e);
+ unpackStreamedData(tagId, elapsedNanos, wallClockNanos, pulledData, statsFiles);
new File(mBaseDir.getAbsolutePath() + "/" + section + "_"
+ lastHighWaterMark).delete();
new File(
@@ -1773,6 +1768,52 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
}
}
+ private INotificationManager mNotificationManager =
+ INotificationManager.Stub.asInterface(
+ ServiceManager.getService(Context.NOTIFICATION_SERVICE));
+
+ private void pullNotificationStats(int reportId, int tagId, long elapsedNanos,
+ long wallClockNanos,
+ List<StatsLogEventWrapper> pulledData) {
+ final long callingToken = Binder.clearCallingIdentity();
+ try {
+ // determine last pull tine. Copy file trick from pullProcessStats?
+ long lastNotificationStatsNs = wallClockNanos -
+ TimeUnit.NANOSECONDS.convert(1, TimeUnit.DAYS);
+
+ List<ParcelFileDescriptor> statsFiles = new ArrayList<>();
+ long notificationStatsNs = mNotificationManager.pullStats(
+ lastNotificationStatsNs, reportId, true, statsFiles);
+ if (statsFiles.size() != 1) {
+ return;
+ }
+ unpackStreamedData(tagId, elapsedNanos, wallClockNanos, pulledData, statsFiles);
+ } catch (IOException e) {
+ Log.e(TAG, "Getting notistats failed: ", e);
+
+ } catch (RemoteException e) {
+ Log.e(TAG, "Getting notistats failed: ", e);
+ } catch (SecurityException e) {
+ Log.e(TAG, "Getting notistats failed: ", e);
+ } finally {
+ Binder.restoreCallingIdentity(callingToken);
+ }
+
+ }
+
+ static void unpackStreamedData(int tagId, long elapsedNanos, long wallClockNanos,
+ List<StatsLogEventWrapper> pulledData, List<ParcelFileDescriptor> statsFiles)
+ throws IOException {
+ InputStream stream = new ParcelFileDescriptor.AutoCloseInputStream(
+ statsFiles.get(0));
+ int[] len = new int[1];
+ byte[] stats = readFully(stream, len);
+ StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos,
+ wallClockNanos);
+ e.writeStorage(Arrays.copyOf(stats, len[0]));
+ pulledData.add(e);
+ }
+
static byte[] readFully(InputStream stream, int[] outLen) throws IOException {
int pos = 0;
final int initialAvail = stream.available();
@@ -2621,6 +2662,11 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
pullAppOps(elapsedNanos, wallClockNanos, ret);
break;
}
+ case StatsLog.NOTIFICATION_REMOTE_VIEWS: {
+ pullNotificationStats(NotificationManagerService.REPORT_REMOTE_VIEWS,
+ tagId, elapsedNanos, wallClockNanos, ret);
+ break;
+ }
default:
Slog.w(TAG, "No such tagId data as " + tagId);
return null;
diff --git a/api/current.txt b/api/current.txt
index 3cf158dbf142..542267c416f6 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -6834,7 +6834,7 @@ package android.app.admin {
method public boolean removeOverrideApn(@NonNull android.content.ComponentName, int);
method public boolean removeUser(@NonNull android.content.ComponentName, @NonNull android.os.UserHandle);
method public boolean requestBugreport(@NonNull android.content.ComponentName);
- method public boolean resetPassword(String, int);
+ method @Deprecated public boolean resetPassword(String, int);
method public boolean resetPasswordWithToken(@NonNull android.content.ComponentName, String, byte[], int);
method @Nullable public java.util.List<android.app.admin.NetworkEvent> retrieveNetworkLogs(@Nullable android.content.ComponentName, long);
method @Nullable public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrievePreRebootSecurityLogs(@NonNull android.content.ComponentName);
@@ -13453,6 +13453,7 @@ package android.drm {
method public android.drm.DrmConvertedStatus closeConvertSession(int);
method public android.drm.DrmConvertedStatus convertData(int, byte[]);
method public String[] getAvailableDrmEngines();
+ method @NonNull public java.util.Collection<android.drm.DrmSupportInfo> getAvailableDrmSupportInfo();
method public android.content.ContentValues getConstraints(String, int);
method public android.content.ContentValues getConstraints(android.net.Uri, int);
method public int getDrmObjectType(String, String);
@@ -23277,6 +23278,8 @@ package android.location {
method public void unregisterGnssMeasurementsCallback(@NonNull android.location.GnssMeasurementsEvent.Callback);
method public void unregisterGnssNavigationMessageCallback(@NonNull android.location.GnssNavigationMessage.Callback);
method public void unregisterGnssStatusCallback(@NonNull android.location.GnssStatus.Callback);
+ field public static final String EXTRA_LOCATION_ENABLED = "android.location.extra.LOCATION_ENABLED";
+ field public static final String EXTRA_PROVIDER_ENABLED = "android.location.extra.PROVIDER_ENABLED";
field public static final String EXTRA_PROVIDER_NAME = "android.location.extra.PROVIDER_NAME";
field public static final String GPS_PROVIDER = "gps";
field public static final String KEY_LOCATION_CHANGED = "location";
@@ -38905,6 +38908,7 @@ package android.provider {
field public static final int MEDIA_TYPE_IMAGE = 1; // 0x1
field public static final int MEDIA_TYPE_NONE = 0; // 0x0
field public static final int MEDIA_TYPE_PLAYLIST = 4; // 0x4
+ field public static final int MEDIA_TYPE_SUBTITLE = 5; // 0x5
field public static final int MEDIA_TYPE_VIDEO = 3; // 0x3
field public static final String MIME_TYPE = "mime_type";
field public static final String PARENT = "parent";
@@ -42824,6 +42828,7 @@ package android.system {
method public static String[] listxattr(String) throws android.system.ErrnoException;
method public static long lseek(java.io.FileDescriptor, long, int) throws android.system.ErrnoException;
method public static android.system.StructStat lstat(String) throws android.system.ErrnoException;
+ method @NonNull public static java.io.FileDescriptor memfd_create(@NonNull String, int) throws android.system.ErrnoException;
method public static void mincore(long, long, byte[]) throws android.system.ErrnoException;
method public static void mkdir(String, int) throws android.system.ErrnoException;
method public static void mkfifo(String, int) throws android.system.ErrnoException;
@@ -43132,6 +43137,7 @@ package android.system {
field public static final int MCAST_UNBLOCK_SOURCE;
field public static final int MCL_CURRENT;
field public static final int MCL_FUTURE;
+ field public static final int MFD_CLOEXEC;
field public static final int MSG_CTRUNC;
field public static final int MSG_DONTROUTE;
field public static final int MSG_EOR;
@@ -44703,7 +44709,6 @@ package android.telephony {
field public static final String KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_RSSNR_INT = "opportunistic_network_entry_threshold_rssnr_int";
field public static final String KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_RSRP_INT = "opportunistic_network_exit_threshold_rsrp_int";
field public static final String KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_RSSNR_INT = "opportunistic_network_exit_threshold_rssnr_int";
- field public static final String KEY_PARAMETERS_USE_FOR_5G_NR_SIGNAL_BAR_INT = "parameters_use_for_5g_nr_signal_bar_int";
field public static final String KEY_PREFER_2G_BOOL = "prefer_2g_bool";
field public static final String KEY_PREVENT_CLIR_ACTIVATION_AND_DEACTIVATION_CODE_BOOL = "prevent_clir_activation_and_deactivation_code_bool";
field public static final String KEY_RADIO_RESTART_FAILURE_CAUSES_INT_ARRAY = "radio_restart_failure_causes_int_array";
diff --git a/api/system-current.txt b/api/system-current.txt
index c7bde93c61fd..217943c519af 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -1331,8 +1331,22 @@ package android.app.usage {
package android.bluetooth {
public final class BluetoothA2dp implements android.bluetooth.BluetoothProfile {
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public void disableOptionalCodecs(@Nullable android.bluetooth.BluetoothDevice);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public void enableOptionalCodecs(@Nullable android.bluetooth.BluetoothDevice);
+ method @Nullable @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothDevice getActiveDevice();
+ method @Nullable @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothCodecStatus getCodecStatus(@Nullable android.bluetooth.BluetoothDevice);
method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public int getOptionalCodecsEnabled(@Nullable android.bluetooth.BluetoothDevice);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public void setCodecConfigPreference(@Nullable android.bluetooth.BluetoothDevice, @Nullable android.bluetooth.BluetoothCodecConfig);
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public void setOptionalCodecsEnabled(@Nullable android.bluetooth.BluetoothDevice, int);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public int supportsOptionalCodecs(@Nullable android.bluetooth.BluetoothDevice);
+ field public static final int OPTIONAL_CODECS_NOT_SUPPORTED = 0; // 0x0
+ field public static final int OPTIONAL_CODECS_PREF_DISABLED = 0; // 0x0
+ field public static final int OPTIONAL_CODECS_PREF_ENABLED = 1; // 0x1
+ field public static final int OPTIONAL_CODECS_PREF_UNKNOWN = -1; // 0xffffffff
+ field public static final int OPTIONAL_CODECS_SUPPORTED = 1; // 0x1
+ field public static final int OPTIONAL_CODECS_SUPPORT_UNKNOWN = -1; // 0xffffffff
}
public final class BluetoothAdapter {
@@ -1361,6 +1375,52 @@ package android.bluetooth {
method public void onMetadataChanged(@NonNull android.bluetooth.BluetoothDevice, int, @Nullable byte[]);
}
+ public final class BluetoothCodecConfig implements android.os.Parcelable {
+ ctor public BluetoothCodecConfig(int, int, int, int, int, long, long, long, long);
+ ctor public BluetoothCodecConfig(int);
+ method public int getBitsPerSample();
+ method @NonNull public String getCodecName();
+ method public int getCodecPriority();
+ method public long getCodecSpecific1();
+ method public int getCodecType();
+ method public int getSampleRate();
+ method public boolean isMandatoryCodec();
+ field public static final int BITS_PER_SAMPLE_16 = 1; // 0x1
+ field public static final int BITS_PER_SAMPLE_24 = 2; // 0x2
+ field public static final int BITS_PER_SAMPLE_32 = 4; // 0x4
+ field public static final int BITS_PER_SAMPLE_NONE = 0; // 0x0
+ field public static final int CHANNEL_MODE_MONO = 1; // 0x1
+ field public static final int CHANNEL_MODE_NONE = 0; // 0x0
+ field public static final int CHANNEL_MODE_STEREO = 2; // 0x2
+ field public static final int CODEC_PRIORITY_DEFAULT = 0; // 0x0
+ field public static final int CODEC_PRIORITY_DISABLED = -1; // 0xffffffff
+ field public static final int CODEC_PRIORITY_HIGHEST = 1000000; // 0xf4240
+ field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothCodecConfig> CREATOR;
+ field public static final int SAMPLE_RATE_176400 = 16; // 0x10
+ field public static final int SAMPLE_RATE_192000 = 32; // 0x20
+ field public static final int SAMPLE_RATE_44100 = 1; // 0x1
+ field public static final int SAMPLE_RATE_48000 = 2; // 0x2
+ field public static final int SAMPLE_RATE_88200 = 4; // 0x4
+ field public static final int SAMPLE_RATE_96000 = 8; // 0x8
+ field public static final int SAMPLE_RATE_NONE = 0; // 0x0
+ field public static final int SOURCE_CODEC_TYPE_AAC = 1; // 0x1
+ field public static final int SOURCE_CODEC_TYPE_APTX = 2; // 0x2
+ field public static final int SOURCE_CODEC_TYPE_APTX_HD = 3; // 0x3
+ field public static final int SOURCE_CODEC_TYPE_INVALID = 1000000; // 0xf4240
+ field public static final int SOURCE_CODEC_TYPE_LDAC = 4; // 0x4
+ field public static final int SOURCE_CODEC_TYPE_MAX = 5; // 0x5
+ field public static final int SOURCE_CODEC_TYPE_SBC = 0; // 0x0
+ }
+
+ public final class BluetoothCodecStatus implements android.os.Parcelable {
+ ctor public BluetoothCodecStatus(@Nullable android.bluetooth.BluetoothCodecConfig, @Nullable android.bluetooth.BluetoothCodecConfig[], @Nullable android.bluetooth.BluetoothCodecConfig[]);
+ method @Nullable public android.bluetooth.BluetoothCodecConfig getCodecConfig();
+ method @Nullable public android.bluetooth.BluetoothCodecConfig[] getCodecsLocalCapabilities();
+ method @Nullable public android.bluetooth.BluetoothCodecConfig[] getCodecsSelectableCapabilities();
+ field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothCodecStatus> CREATOR;
+ field public static final String EXTRA_CODEC_STATUS = "android.bluetooth.extra.CODEC_STATUS";
+ }
+
public final class BluetoothDevice implements android.os.Parcelable {
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean cancelBondProcess();
method @Nullable @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public byte[] getMetadata(int);
@@ -6075,6 +6135,7 @@ package android.os {
}
public class Binder implements android.os.IBinder {
+ method public int handleShellCommand(@NonNull android.os.ParcelFileDescriptor, @NonNull android.os.ParcelFileDescriptor, @NonNull android.os.ParcelFileDescriptor, @NonNull String[]);
method public static void setProxyTransactListener(@Nullable android.os.Binder.ProxyTransactListener);
}
@@ -6623,7 +6684,7 @@ package android.os.connectivity {
}
public final class WifiActivityEnergyInfo implements android.os.Parcelable {
- ctor public WifiActivityEnergyInfo(long, int, long, long, long, long, long);
+ ctor public WifiActivityEnergyInfo(long, int, long, long, long, long);
method public int describeContents();
method public long getControllerEnergyUsedMicroJoules();
method public long getControllerIdleDurationMillis();
@@ -6980,6 +7041,11 @@ package android.provider {
field public static final int FLAG_REMOVABLE_USB = 524288; // 0x80000
}
+ public final class MediaStore {
+ method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_MEDIA_STORAGE) public static java.util.Set<java.lang.String> getRecentExternalVolumeNames(@NonNull android.content.Context);
+ method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_MEDIA_STORAGE) public static java.util.Collection<java.io.File> getVolumeScanPaths(@NonNull String) throws java.io.FileNotFoundException;
+ }
+
public abstract class SearchIndexableData {
ctor public SearchIndexableData();
ctor public SearchIndexableData(android.content.Context);
@@ -7237,6 +7303,10 @@ package android.provider {
field public static final String SUB_ID = "sub_id";
}
+ public static final class Telephony.SimInfo {
+ field @NonNull public static final android.net.Uri CONTENT_URI;
+ }
+
public static final class Telephony.Sms.Intents {
field public static final String ACTION_SMS_EMERGENCY_CB_RECEIVED = "android.provider.action.SMS_EMERGENCY_CB_RECEIVED";
}
diff --git a/api/test-current.txt b/api/test-current.txt
index 3ce8c5ead4cb..3e144697ee28 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -2455,7 +2455,7 @@ package android.provider {
method @RequiresPermission(android.Manifest.permission.CLEAR_APP_USER_DATA) public static void deleteContributedMedia(android.content.Context, String, android.os.UserHandle) throws java.io.IOException;
method @RequiresPermission(android.Manifest.permission.CLEAR_APP_USER_DATA) public static long getContributedMediaSize(android.content.Context, String, android.os.UserHandle) throws java.io.IOException;
method @NonNull public static java.io.File getVolumePath(@NonNull String) throws java.io.FileNotFoundException;
- method @NonNull public static java.util.Collection<java.io.File> getVolumeScanPaths(@NonNull String) throws java.io.FileNotFoundException;
+ method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_MEDIA_STORAGE) public static java.util.Collection<java.io.File> getVolumeScanPaths(@NonNull String) throws java.io.FileNotFoundException;
method public static android.net.Uri scanFile(android.content.Context, java.io.File);
method public static android.net.Uri scanFileFromShell(android.content.Context, java.io.File);
method public static void scanVolume(android.content.Context, java.io.File);
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index d10a661c6d83..3c5ad4231133 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -1417,7 +1417,10 @@ Status StatsService::sendBinaryPushStateChangedAtom(const android::String16& tra
Status StatsService::sendWatchdogRollbackOccurredAtom(const int32_t rollbackTypeIn,
const android::String16& packageNameIn,
- const int64_t packageVersionCodeIn) {
+ const int64_t packageVersionCodeIn,
+ const int32_t rollbackReasonIn,
+ const android::String16&
+ failingPackageNameIn) {
// Note: We skip the usage stats op check here since we do not have a package name.
// This is ok since we are overloading the usage_stats permission.
// This method only sends data, it does not receive it.
@@ -1439,7 +1442,8 @@ Status StatsService::sendWatchdogRollbackOccurredAtom(const int32_t rollbackType
}
android::util::stats_write(android::util::WATCHDOG_ROLLBACK_OCCURRED,
- rollbackTypeIn, String8(packageNameIn).string(), packageVersionCodeIn);
+ rollbackTypeIn, String8(packageNameIn).string(), packageVersionCodeIn,
+ rollbackReasonIn, String8(failingPackageNameIn).string());
// Fast return to save disk read.
if (rollbackTypeIn != android::util::WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_SUCCESS
diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h
index 8c98e7b96936..50b1014f4e8a 100644
--- a/cmds/statsd/src/StatsService.h
+++ b/cmds/statsd/src/StatsService.h
@@ -214,7 +214,9 @@ public:
virtual Status sendWatchdogRollbackOccurredAtom(
const int32_t rollbackTypeIn,
const android::String16& packageNameIn,
- const int64_t packageVersionCodeIn) override;
+ const int64_t packageVersionCodeIn,
+ const int32_t rollbackReasonIn,
+ const android::String16& failingPackageNameIn) override;
/**
* Binder call to get registered experiment IDs.
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 2efb78943812..f1ea4c9e0c68 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -112,7 +112,7 @@ message Atom {
TouchEventReported touch_event_reported = 34;
WakeupAlarmOccurred wakeup_alarm_occurred = 35;
KernelWakeupReported kernel_wakeup_reported = 36;
- WifiLockStateChanged wifi_lock_state_changed = 37;
+ WifiLockStateChanged wifi_lock_state_changed = 37 [(log_from_module) = "wifi"];
WifiSignalStrengthChanged wifi_signal_strength_changed = 38;
WifiScanStateChanged wifi_scan_state_changed = 39;
PhoneSignalStrengthChanged phone_signal_strength_changed = 40;
@@ -356,7 +356,7 @@ message Atom {
}
// Pulled events will start at field 10000.
- // Next: 10065
+ // Next: 10067
oneof pulled {
WifiBytesTransfer wifi_bytes_transfer = 10000;
WifiBytesTransferByFgBg wifi_bytes_transfer_by_fg_bg = 10001;
@@ -423,6 +423,7 @@ message Atom {
SurfaceflingerStatsLayerInfo surfaceflinger_stats_layer_info = 10063;
ProcessMemorySnapshot process_memory_snapshot = 10064;
VmsClientStats vms_client_stats = 10065;
+ NotificationRemoteViews notification_remote_views = 10066;
}
// DO NOT USE field numbers above 100,000 in AOSP.
@@ -1742,6 +1743,19 @@ message WatchdogRollbackOccurred {
optional string package_name = 2;
optional int32 package_version_code = 3;
+
+ enum RollbackReasonType {
+ REASON_UNKNOWN = 0;
+ REASON_NATIVE_CRASH = 1;
+ REASON_EXPLICIT_HEALTH_CHECK = 2;
+ REASON_APP_CRASH = 3;
+ REASON_APP_NOT_RESPONDING = 4;
+ }
+ optional RollbackReasonType rollback_reason = 4;
+
+ // Set by RollbackPackageHealthObserver to be the package that is failing when a rollback
+ // is initiated. Empty if the package is unknown.
+ optional string failing_package_name = 5;
}
/**
@@ -4947,6 +4961,24 @@ message ProcStatsPkgProc {
optional ProcessStatsSectionProto proc_stats_section = 1;
}
+// Next Tag: 2
+message PackageRemoteViewInfoProto {
+ optional string package_name = 1;
+ // add per-package additional info here (like channels)
+}
+
+// Next Tag: 2
+message NotificationRemoteViewsProto {
+ repeated PackageRemoteViewInfoProto package_remote_view_info = 1;
+}
+
+/**
+ * Pulled from NotificationManagerService.java
+ */
+message NotificationRemoteViews {
+ optional NotificationRemoteViewsProto notification_remote_views = 1;
+}
+
message PowerProfileProto {
optional double cpu_suspend = 1;
@@ -5960,6 +5992,8 @@ message PermissionGrantRequestResultReported {
IGNORED_RESTRICTED_PERMISSION = 9;
// one time permission was granted by user action
USER_GRANTED_ONE_TIME = 10;
+ // user ignored request by leaving the request screen without choosing any option
+ USER_IGNORED = 11;
}
// The result of the permission grant
optional Result result = 6;
diff --git a/cmds/statsd/src/external/PullResultReceiver.cpp b/cmds/statsd/src/external/PullResultReceiver.cpp
index 6bd05452f3b0..6b6fe7d9617f 100644
--- a/cmds/statsd/src/external/PullResultReceiver.cpp
+++ b/cmds/statsd/src/external/PullResultReceiver.cpp
@@ -25,12 +25,13 @@ namespace os {
namespace statsd {
PullResultReceiver::PullResultReceiver(
- std::function<void(int32_t, bool, const vector<android::util::StatsEvent>&)> pullFinishCb)
+ std::function<void(int32_t, bool, const vector<android::util::StatsEventParcel>&)>
+ pullFinishCb)
: pullFinishCallback(std::move(pullFinishCb)) {
}
Status PullResultReceiver::pullFinished(int32_t atomTag, bool success,
- const vector<StatsEvent>& output) {
+ const vector<StatsEventParcel>& output) {
pullFinishCallback(atomTag, success, output);
return Status::ok();
}
@@ -40,4 +41,4 @@ PullResultReceiver::~PullResultReceiver() {
} // namespace statsd
} // namespace os
-} // namespace android \ No newline at end of file
+} // namespace android
diff --git a/cmds/statsd/src/external/PullResultReceiver.h b/cmds/statsd/src/external/PullResultReceiver.h
index f731f778a337..17d06e4ff4db 100644
--- a/cmds/statsd/src/external/PullResultReceiver.h
+++ b/cmds/statsd/src/external/PullResultReceiver.h
@@ -24,7 +24,7 @@ namespace statsd {
class PullResultReceiver : public BnPullAtomResultReceiver {
public:
- PullResultReceiver(function<void(int32_t, bool, const vector<android::util::StatsEvent>&)>
+ PullResultReceiver(function<void(int32_t, bool, const vector<android::util::StatsEventParcel>&)>
pullFinishCallback);
~PullResultReceiver();
@@ -32,10 +32,11 @@ public:
* Binder call for finishing a pull.
*/
binder::Status pullFinished(int32_t atomTag, bool success,
- const vector<android::util::StatsEvent>& output) override;
+ const vector<android::util::StatsEventParcel>& output) override;
private:
- function<void(int32_t, bool, const vector<android::util::StatsEvent>&)> pullFinishCallback;
+ function<void(int32_t, bool, const vector<android::util::StatsEventParcel>&)>
+ pullFinishCallback;
};
} // namespace statsd
diff --git a/cmds/statsd/src/external/StatsCallbackPuller.cpp b/cmds/statsd/src/external/StatsCallbackPuller.cpp
index 92db68477dbd..f5b1e7f78736 100644
--- a/cmds/statsd/src/external/StatsCallbackPuller.cpp
+++ b/cmds/statsd/src/external/StatsCallbackPuller.cpp
@@ -20,7 +20,7 @@
#include "StatsCallbackPuller.h"
#include <android/os/IPullAtomCallback.h>
-#include <android/util/StatsEvent.h>
+#include <android/util/StatsEventParcel.h>
#include "PullResultReceiver.h"
#include "StatsPullerManager.h"
@@ -57,13 +57,19 @@ bool StatsCallbackPuller::PullInternal(vector<shared_ptr<LogEvent>>* data) {
sp<PullResultReceiver> resultReceiver = new PullResultReceiver(
[cv_mutex, cv, pullFinish, pullSuccess, sharedData](
- int32_t atomTag, bool success, const vector<StatsEvent>& output) {
+ int32_t atomTag, bool success, const vector<StatsEventParcel>& output) {
// This is the result of the pull, executing in a statsd binder thread.
// The pull could have taken a long time, and we should only modify
// data (the output param) if the pointer is in scope and the pull did not time out.
{
lock_guard<mutex> lk(*cv_mutex);
- // TODO: fill the shared vector of LogEvents once StatsEvent is complete.
+ for (const StatsEventParcel& parcel: output) {
+ shared_ptr<LogEvent> event =
+ make_shared<LogEvent>(const_cast<uint8_t*>(parcel.buffer.data()),
+ parcel.buffer.size(),
+ /*uid=*/ -1);
+ sharedData->push_back(event);
+ }
*pullSuccess = success;
*pullFinish = true;
}
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index b5bad0530503..615af89e3186 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -281,6 +281,9 @@ std::map<PullerKey, PullAtomInfo> StatsPullerManager::kAllPullAtomInfo = {
{{.atomTag = android::util::VMS_CLIENT_STATS},
{.additiveFields = {5, 6, 7, 8, 9, 10},
.puller = new CarStatsPuller(android::util::VMS_CLIENT_STATS)}},
+ // NotiifcationRemoteViews.
+ {{.atomTag = android::util::NOTIFICATION_REMOTE_VIEWS},
+ {.puller = new StatsCompanionServicePuller(android::util::NOTIFICATION_REMOTE_VIEWS)}},
};
StatsPullerManager::StatsPullerManager() : mNextPullTimeNs(NO_ALARM_UPDATE) {
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index eb78ebc521e1..b7d169de89c8 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -159,7 +159,7 @@ ValueMetricProducer::ValueMetricProducer(
// Kicks off the puller immediately if condition is true and diff based.
if (mIsActive && mIsPulled && mCondition == ConditionState::kTrue && mUseDiff) {
- pullAndMatchEventsLocked(mCurrentBucketStartTimeNs, mCondition);
+ pullAndMatchEventsLocked(mCurrentBucketStartTimeNs);
}
// Now that activations are processed, start the condition timer if needed.
mConditionTimer.onConditionChanged(mIsActive && mCondition == ConditionState::kTrue,
@@ -216,7 +216,7 @@ void ValueMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
invalidateCurrentBucket();
break;
case NO_TIME_CONSTRAINTS:
- pullAndMatchEventsLocked(dumpTimeNs, mCondition);
+ pullAndMatchEventsLocked(dumpTimeNs);
break;
}
}
@@ -366,7 +366,7 @@ void ValueMetricProducer::onActiveStateChangedLocked(const int64_t& eventTimeNs)
// Pull on active state changes.
if (!isEventTooLate) {
if (mIsPulled) {
- pullAndMatchEventsLocked(eventTimeNs, mCondition);
+ pullAndMatchEventsLocked(eventTimeNs);
}
// When active state changes from true to false, clear diff base but don't
// reset other counters as we may accumulate more value in the bucket.
@@ -425,7 +425,7 @@ void ValueMetricProducer::onConditionChangedLocked(const bool condition,
// called before #onDataPulled.
if (mIsPulled &&
(newCondition == ConditionState::kTrue || mCondition == ConditionState::kTrue)) {
- pullAndMatchEventsLocked(eventTimeNs, newCondition);
+ pullAndMatchEventsLocked(eventTimeNs);
}
// For metrics that use diff, when condition changes from true to false,
@@ -443,8 +443,7 @@ void ValueMetricProducer::onConditionChangedLocked(const bool condition,
mConditionTimer.onConditionChanged(mCondition, eventTimeNs);
}
-void ValueMetricProducer::pullAndMatchEventsLocked(const int64_t timestampNs,
- ConditionState condition) {
+void ValueMetricProducer::pullAndMatchEventsLocked(const int64_t timestampNs) {
vector<std::shared_ptr<LogEvent>> allData;
if (!mPullerManager->Pull(mPullTagId, &allData)) {
ALOGE("Stats puller failed for tag: %d at %lld", mPullTagId, (long long)timestampNs);
@@ -452,7 +451,7 @@ void ValueMetricProducer::pullAndMatchEventsLocked(const int64_t timestampNs,
return;
}
- accumulateEvents(allData, timestampNs, timestampNs, condition);
+ accumulateEvents(allData, timestampNs, timestampNs);
}
int64_t ValueMetricProducer::calcPreviousBucketEndTime(const int64_t currentTimeNs) {
@@ -474,7 +473,7 @@ void ValueMetricProducer::onDataPulled(const std::vector<std::shared_ptr<LogEven
if (isEventLate) {
// If the event is late, we are in the middle of a bucket. Just
// process the data without trying to snap the data to the nearest bucket.
- accumulateEvents(allData, originalPullTimeNs, originalPullTimeNs, mCondition);
+ accumulateEvents(allData, originalPullTimeNs, originalPullTimeNs);
} else {
// For scheduled pulled data, the effective event time is snap to the nearest
// bucket end. In the case of waking up from a deep sleep state, we will
@@ -488,7 +487,7 @@ void ValueMetricProducer::onDataPulled(const std::vector<std::shared_ptr<LogEven
int64_t bucketEndTime = calcPreviousBucketEndTime(originalPullTimeNs) - 1;
StatsdStats::getInstance().noteBucketBoundaryDelayNs(
mMetricId, originalPullTimeNs - bucketEndTime);
- accumulateEvents(allData, originalPullTimeNs, bucketEndTime, mCondition);
+ accumulateEvents(allData, originalPullTimeNs, bucketEndTime);
}
}
}
@@ -499,8 +498,7 @@ void ValueMetricProducer::onDataPulled(const std::vector<std::shared_ptr<LogEven
}
void ValueMetricProducer::accumulateEvents(const std::vector<std::shared_ptr<LogEvent>>& allData,
- int64_t originalPullTimeNs, int64_t eventElapsedTimeNs,
- ConditionState condition) {
+ int64_t originalPullTimeNs, int64_t eventElapsedTimeNs) {
bool isEventLate = eventElapsedTimeNs < mCurrentBucketStartTimeNs;
if (isEventLate) {
VLOG("Skip bucket end pull due to late arrival: %lld vs %lld",
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h
index 206e602dd1c7..2033a2a0cd02 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.h
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.h
@@ -78,7 +78,7 @@ public:
return;
}
if (mIsPulled && mCondition) {
- pullAndMatchEventsLocked(eventTimeNs, mCondition);
+ pullAndMatchEventsLocked(eventTimeNs);
}
flushCurrentBucketLocked(eventTimeNs, eventTimeNs);
};
@@ -188,11 +188,10 @@ private:
bool hitFullBucketGuardRailLocked(const MetricDimensionKey& newKey);
- void pullAndMatchEventsLocked(const int64_t timestampNs, ConditionState condition);
+ void pullAndMatchEventsLocked(const int64_t timestampNs);
void accumulateEvents(const std::vector<std::shared_ptr<LogEvent>>& allData,
- int64_t originalPullTimeNs, int64_t eventElapsedTimeNs,
- ConditionState condition);
+ int64_t originalPullTimeNs, int64_t eventElapsedTimeNs);
ValueBucket buildPartialBucket(int64_t bucketEndTime,
const std::vector<Interval>& intervals);
diff --git a/cmds/statsd/src/state/StateTracker.cpp b/cmds/statsd/src/state/StateTracker.cpp
index 90ce1e90142e..ef59c9242cb2 100644
--- a/cmds/statsd/src/state/StateTracker.cpp
+++ b/cmds/statsd/src/state/StateTracker.cpp
@@ -139,6 +139,13 @@ void StateTracker::handlePartialReset(const int64_t eventTimeNs,
const HashableDimensionKey& primaryKey) {
VLOG("StateTracker handle partial reset");
if (mStateMap.find(primaryKey) != mStateMap.end()) {
+ for (auto l : mListeners) {
+ auto sl = l.promote();
+ if (sl != nullptr) {
+ sl->onStateChanged(eventTimeNs, mAtomId, primaryKey,
+ mStateMap.find(primaryKey)->second.state, mDefaultState);
+ }
+ }
mStateMap.erase(primaryKey);
}
}
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 35a48a82cd5e..49a8e2f3f816 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -6254,6 +6254,7 @@ public final class ActivityThread extends ClientTransactionHandler {
// send up app name; do this *before* waiting for debugger
Process.setArgV0(data.processName);
android.ddm.DdmHandleAppName.setAppName(data.processName,
+ data.appInfo.packageName,
UserHandle.myUserId());
VMRuntime.setProcessPackageName(data.appInfo.packageName);
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 0957dba4eac1..86f52af1a13b 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -207,4 +207,6 @@ interface INotificationManager
void setPrivateNotificationsAllowed(boolean allow);
boolean getPrivateNotificationsAllowed();
+
+ long pullStats(long startNs, int report, boolean doAgg, out List<ParcelFileDescriptor> stats);
}
diff --git a/core/java/android/app/StatsManager.java b/core/java/android/app/StatsManager.java
index 2ef05105825a..90cd51f8649f 100644
--- a/core/java/android/app/StatsManager.java
+++ b/core/java/android/app/StatsManager.java
@@ -34,6 +34,7 @@ import android.os.ServiceManager;
import android.util.AndroidException;
import android.util.Slog;
import android.util.StatsEvent;
+import android.util.StatsEventParcel;
import com.android.internal.annotations.GuardedBy;
@@ -540,10 +541,12 @@ public final class StatsManager {
mExecutor.execute(() -> {
List<StatsEvent> data = new ArrayList<>();
boolean success = mCallback.onPullAtom(atomTag, data);
- StatsEvent[] arr = new StatsEvent[data.size()];
- arr = data.toArray(arr);
+ StatsEventParcel[] parcels = new StatsEventParcel[data.size()];
+ for (int i = 0; i < data.size(); i++) {
+ parcels[i].buffer = data.get(i).getBytes();
+ }
try {
- resultReceiver.pullFinished(atomTag, success, arr);
+ resultReceiver.pullFinished(atomTag, success, parcels);
} catch (RemoteException e) {
Slog.w(TAG, "StatsPullResultReceiver failed for tag " + mAtomId);
}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 34ceb08f39bf..915e4572c035 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -3742,17 +3742,35 @@ public class DevicePolicyManager {
/**
* Force a new password for device unlock (the password needed to access the entire device) or
* the work profile challenge on the current user. This takes effect immediately.
- * <p>
- * <em>For device owner and profile owners targeting SDK level
- * {@link android.os.Build.VERSION_CODES#O} or above, this API is no longer available and will
- * throw {@link SecurityException}. Please use the new API {@link #resetPasswordWithToken}
- * instead. </em>
- * <p>
- * <em>Note: This API has been limited as of {@link android.os.Build.VERSION_CODES#N} for
- * device admins that are not device owner and not profile owner.
- * The password can now only be changed if there is currently no password set. Device owner
- * and profile owner can still do this when user is unlocked and does not have a managed
- * profile.</em>
+ *
+ * <p> Before {@link android.os.Build.VERSION_CODES#N}, this API is available to device admin,
+ * profile owner and device owner. Starting from {@link android.os.Build.VERSION_CODES#N},
+ * legacy device admin (who is not also profile owner or device owner) can only call this
+ * API to set a new password if there is currently no password set. Profile owner and device
+ * owner can continue to force change an existing password as long as the target user is
+ * unlocked, although device owner will not be able to call this API at all if there is also a
+ * managed profile on the device.
+ *
+ * <p> Between {@link android.os.Build.VERSION_CODES#O},
+ * {@link android.os.Build.VERSION_CODES#P} and {@link android.os.Build.VERSION_CODES#Q},
+ * profile owner and devices owner targeting SDK level {@link android.os.Build.VERSION_CODES#O}
+ * or above who attempt to call this API will receive {@link SecurityException}; they are
+ * encouraged to migrate to the new {@link #resetPasswordWithToken} API instead.
+ * Profile owner and device owner targeting older SDK levels are not affected: they continue
+ * to experience the existing behaviour described in the previous paragraph.
+ *
+ * <p><em>Starting from {@link android.os.Build.VERSION_CODES#R}, this API is no longer
+ * supported in most cases.</em> Device owner and profile owner calling
+ * this API will receive {@link SecurityException} if they target SDK level
+ * {@link android.os.Build.VERSION_CODES#O} or above, or they will receive a silent failure
+ * (API returning {@code false}) if they target lower SDK level.
+ * For legacy device admins, this API throws {@link SecurityException} if they target SDK level
+ * {@link android.os.Build.VERSION_CODES#N} or above, and returns {@code false} otherwise. Only
+ * privileged apps holding RESET_PASSWORD permission which are part of
+ * the system factory image can still call this API to set a new password if there is currently
+ * no password set. In this case, if the device already has a password, this API will throw
+ * {@link SecurityException}.
+ *
* <p>
* The given password must be sufficient for the current password quality and length constraints
* as returned by {@link #getPasswordQuality(ComponentName)} and
@@ -3760,12 +3778,7 @@ public class DevicePolicyManager {
* it will be rejected and false returned. Note that the password may be a stronger quality
* (containing alphanumeric characters when the requested quality is only numeric), in which
* case the currently active quality will be increased to match.
- * <p>
- * Calling with a null or empty password will clear any existing PIN, pattern or password if the
- * current password constraints allow it. <em>Note: This will not work in
- * {@link android.os.Build.VERSION_CODES#N} and later for managed profiles, or for device admins
- * that are not device owner or profile owner. Once set, the password cannot be changed to null
- * or empty except by these admins.</em>
+ *
* <p>On devices not supporting {@link PackageManager#FEATURE_SECURE_LOCK_SCREEN} feature, this
* methods does nothing.
* <p>
@@ -3777,11 +3790,13 @@ public class DevicePolicyManager {
* @param flags May be 0 or combination of {@link #RESET_PASSWORD_REQUIRE_ENTRY} and
* {@link #RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT}.
* @return Returns true if the password was applied, or false if it is not acceptable for the
- * current constraints or if the user has not been decrypted yet.
+ * current constraints.
* @throws SecurityException if the calling application does not own an active administrator
* that uses {@link DeviceAdminInfo#USES_POLICY_RESET_PASSWORD}
* @throws IllegalStateException if the calling user is locked or has a managed profile.
+ * @deprecated Please use {@link #resetPasswordWithToken} instead.
*/
+ @Deprecated
@RequiresFeature(PackageManager.FEATURE_SECURE_LOCK_SCREEN)
public boolean resetPassword(String password, int flags) {
throwIfParentInstance("resetPassword");
@@ -5555,7 +5570,12 @@ public class DevicePolicyManager {
* device, for this user. After setting this, no applications running as this user will be able
* to access any cameras on the device.
* <p>
- * If the caller is device owner, then the restriction will be applied to all users.
+ * This method can be called on the {@link DevicePolicyManager} instance,
+ * returned by {@link #getParentProfileInstance(ComponentName)}, where the caller must be
+ * the profile owner of an organization-owned managed profile.
+ * <p>
+ * If the caller is device owner or called on the parent instance, then the
+ * restriction will be applied to all users.
* <p>
* The calling device admin must have requested
* {@link DeviceAdminInfo#USES_POLICY_DISABLE_CAMERA} to be able to call this method; if it has
@@ -5567,10 +5587,9 @@ public class DevicePolicyManager {
* {@link DeviceAdminInfo#USES_POLICY_DISABLE_CAMERA}.
*/
public void setCameraDisabled(@NonNull ComponentName admin, boolean disabled) {
- throwIfParentInstance("setCameraDisabled");
if (mService != null) {
try {
- mService.setCameraDisabled(admin, disabled);
+ mService.setCameraDisabled(admin, disabled, mParentInstance);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -5580,11 +5599,15 @@ public class DevicePolicyManager {
/**
* Determine whether or not the device's cameras have been disabled for this user,
* either by the calling admin, if specified, or all admins.
+ * <p>
+ * This method can be called on the {@link DevicePolicyManager} instance,
+ * returned by {@link #getParentProfileInstance(ComponentName)}, where the caller must be
+ * the profile owner of an organization-owned managed profile.
+ *
* @param admin The name of the admin component to check, or {@code null} to check whether any admins
* have disabled the camera
*/
public boolean getCameraDisabled(@Nullable ComponentName admin) {
- throwIfParentInstance("getCameraDisabled");
return getCameraDisabled(admin, myUserId());
}
@@ -5593,7 +5616,7 @@ public class DevicePolicyManager {
public boolean getCameraDisabled(@Nullable ComponentName admin, int userHandle) {
if (mService != null) {
try {
- return mService.getCameraDisabled(admin, userHandle);
+ return mService.getCameraDisabled(admin, userHandle, mParentInstance);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -7893,7 +7916,8 @@ public class DevicePolicyManager {
* for the list of keys.
* @throws SecurityException if {@code admin} is not a device or profile owner.
*/
- public void addUserRestriction(@NonNull ComponentName admin, String key) {
+ public void addUserRestriction(@NonNull ComponentName admin,
+ @UserManager.UserRestrictionKey String key) {
throwIfParentInstance("addUserRestriction");
if (mService != null) {
try {
@@ -7915,7 +7939,8 @@ public class DevicePolicyManager {
* for the list of keys.
* @throws SecurityException if {@code admin} is not a device or profile owner.
*/
- public void clearUserRestriction(@NonNull ComponentName admin, String key) {
+ public void clearUserRestriction(@NonNull ComponentName admin,
+ @UserManager.UserRestrictionKey String key) {
throwIfParentInstance("clearUserRestriction");
if (mService != null) {
try {
@@ -9344,7 +9369,6 @@ public class DevicePolicyManager {
* <li>{@link #setPasswordExpirationTimeout}</li>
* <li>{@link #getPasswordExpiration}</li>
* <li>{@link #getPasswordMaximumLength}</li>
- * <li>{@link #getPasswordComplexity}</li>
* <li>{@link #isActivePasswordSufficient}</li>
* <li>{@link #getCurrentFailedPasswordAttempts}</li>
* <li>{@link #getMaximumFailedPasswordsForWipe}</li>
@@ -9359,6 +9383,14 @@ public class DevicePolicyManager {
* <li>{@link #getRequiredStrongAuthTimeout}</li>
* <li>{@link #setRequiredStrongAuthTimeout}</li>
* </ul>
+ * <p>
+ * The following methods are supported for the parent instance but can only be called by the
+ * profile owner of a managed profile that was created during the device provisioning flow:
+ * <ul>
+ * <li>{@link #getPasswordComplexity}</li>
+ * <li>{@link #setCameraDisabled}</li>
+ * <li>{@link #getCameraDisabled}</li>
+ * </ul>
*
* <p>The following methods can be called by the profile owner of a managed profile
* on an organization-owned device:
diff --git a/core/java/android/app/admin/DevicePolicyManagerInternal.java b/core/java/android/app/admin/DevicePolicyManagerInternal.java
index 713126ee9341..f299d456a18f 100644
--- a/core/java/android/app/admin/DevicePolicyManagerInternal.java
+++ b/core/java/android/app/admin/DevicePolicyManagerInternal.java
@@ -145,15 +145,6 @@ public abstract class DevicePolicyManagerInternal {
public abstract void reportSeparateProfileChallengeChanged(@UserIdInt int userId);
/**
- * Check whether the user could have their password reset in an untrusted manor due to there
- * being an admin which can call {@link #resetPassword} to reset the password without knowledge
- * of the previous password.
- *
- * @param userId The user in question
- */
- public abstract boolean canUserHaveUntrustedCredentialReset(@UserIdInt int userId);
-
- /**
* Return text of error message if printing is disabled.
* Called by Print Service when printing is disabled by PO or DO when printing is attempted.
*
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index f55026c76906..34246fa808bd 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -114,8 +114,8 @@ interface IDevicePolicyManager {
boolean requestBugreport(in ComponentName who);
- void setCameraDisabled(in ComponentName who, boolean disabled);
- boolean getCameraDisabled(in ComponentName who, int userHandle);
+ void setCameraDisabled(in ComponentName who, boolean disabled, boolean parent);
+ boolean getCameraDisabled(in ComponentName who, int userHandle, boolean parent);
void setScreenCaptureDisabled(in ComponentName who, boolean disabled);
boolean getScreenCaptureDisabled(in ComponentName who, int userHandle);
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index 8ed61b6c87e3..64df0e84f6dc 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -17,6 +17,7 @@
package android.bluetooth;
import android.Manifest;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -32,6 +33,8 @@ import android.os.ParcelUuid;
import android.os.RemoteException;
import android.util.Log;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
@@ -154,13 +157,22 @@ public final class BluetoothA2dp implements BluetoothProfile {
*/
public static final int STATE_NOT_PLAYING = 11;
+ /** @hide */
+ @IntDef(prefix = "OPTIONAL_CODECS_", value = {
+ OPTIONAL_CODECS_SUPPORT_UNKNOWN,
+ OPTIONAL_CODECS_NOT_SUPPORTED,
+ OPTIONAL_CODECS_SUPPORTED
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface OptionalCodecsSupportStatus {}
+
/**
* We don't have a stored preference for whether or not the given A2DP sink device supports
* optional codecs.
*
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public static final int OPTIONAL_CODECS_SUPPORT_UNKNOWN = -1;
/**
@@ -168,7 +180,7 @@ public final class BluetoothA2dp implements BluetoothProfile {
*
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public static final int OPTIONAL_CODECS_NOT_SUPPORTED = 0;
/**
@@ -176,16 +188,25 @@ public final class BluetoothA2dp implements BluetoothProfile {
*
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public static final int OPTIONAL_CODECS_SUPPORTED = 1;
+ /** @hide */
+ @IntDef(prefix = "OPTIONAL_CODECS_PREF_", value = {
+ OPTIONAL_CODECS_PREF_UNKNOWN,
+ OPTIONAL_CODECS_PREF_DISABLED,
+ OPTIONAL_CODECS_PREF_ENABLED
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface OptionalCodecsPreferenceStatus {}
+
/**
- * We don't have a stored preference for whether optional codecs should be enabled or disabled
- * for the given A2DP device.
+ * We don't have a stored preference for whether optional codecs should be enabled or
+ * disabled for the given A2DP device.
*
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public static final int OPTIONAL_CODECS_PREF_UNKNOWN = -1;
/**
@@ -193,7 +214,7 @@ public final class BluetoothA2dp implements BluetoothProfile {
*
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public static final int OPTIONAL_CODECS_PREF_DISABLED = 0;
/**
@@ -201,7 +222,7 @@ public final class BluetoothA2dp implements BluetoothProfile {
*
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public static final int OPTIONAL_CODECS_PREF_ENABLED = 1;
private BluetoothAdapter mAdapter;
@@ -248,13 +269,12 @@ public final class BluetoothA2dp implements BluetoothProfile {
* the state. Users can get the connection state of the profile
* from this intent.
*
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
- * permission.
*
* @param device Remote Bluetooth Device
* @return false on immediate error, true otherwise
* @hide
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
@UnsupportedAppUsage
public boolean connect(BluetoothDevice device) {
if (DBG) log("connect(" + device + ")");
@@ -289,13 +309,12 @@ public final class BluetoothA2dp implements BluetoothProfile {
* {@link #STATE_DISCONNECTING} can be used to distinguish between the
* two scenarios.
*
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
- * permission.
*
* @param device Remote Bluetooth Device
* @return false on immediate error, true otherwise
* @hide
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
@UnsupportedAppUsage
public boolean disconnect(BluetoothDevice device) {
if (DBG) log("disconnect(" + device + ")");
@@ -384,14 +403,12 @@ public final class BluetoothA2dp implements BluetoothProfile {
* {@link #ACTION_ACTIVE_DEVICE_CHANGED} intent will be broadcasted
* with the active device.
*
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
- * permission.
- *
* @param device the remote Bluetooth device. Could be null to clear
* the active device and stop streaming audio to a Bluetooth device.
* @return false on immediate error, true otherwise
* @hide
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
@UnsupportedAppUsage
public boolean setActiveDevice(@Nullable BluetoothDevice device) {
if (DBG) log("setActiveDevice(" + device + ")");
@@ -412,16 +429,13 @@ public final class BluetoothA2dp implements BluetoothProfile {
/**
* Get the connected device that is active.
*
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
- * permission.
- *
* @return the connected device that is active or null if no device
* is active
* @hide
*/
- @RequiresPermission(Manifest.permission.BLUETOOTH)
+ @SystemApi
@Nullable
- @UnsupportedAppUsage
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
public BluetoothDevice getActiveDevice() {
if (VDBG) log("getActiveDevice()");
try {
@@ -441,7 +455,7 @@ public final class BluetoothA2dp implements BluetoothProfile {
* Set priority of the profile
*
* <p> The device should already be paired.
- * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF},
+ * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF}
*
* @param device Paired bluetooth device
* @param priority
@@ -626,8 +640,10 @@ public final class BluetoothA2dp implements BluetoothProfile {
* @return the current codec status
* @hide
*/
- @UnsupportedAppUsage
- public @Nullable BluetoothCodecStatus getCodecStatus(BluetoothDevice device) {
+ @SystemApi
+ @Nullable
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
+ public BluetoothCodecStatus getCodecStatus(@Nullable BluetoothDevice device) {
if (DBG) Log.d(TAG, "getCodecStatus(" + device + ")");
try {
final IBluetoothA2dp service = getService();
@@ -652,9 +668,10 @@ public final class BluetoothA2dp implements BluetoothProfile {
* @param codecConfig the codec configuration preference
* @hide
*/
- @UnsupportedAppUsage
- public void setCodecConfigPreference(BluetoothDevice device,
- BluetoothCodecConfig codecConfig) {
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+ public void setCodecConfigPreference(@Nullable BluetoothDevice device,
+ @Nullable BluetoothCodecConfig codecConfig) {
if (DBG) Log.d(TAG, "setCodecConfigPreference(" + device + ")");
try {
final IBluetoothA2dp service = getService();
@@ -676,8 +693,9 @@ public final class BluetoothA2dp implements BluetoothProfile {
* active A2DP Bluetooth device.
* @hide
*/
- @UnsupportedAppUsage
- public void enableOptionalCodecs(BluetoothDevice device) {
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+ public void enableOptionalCodecs(@Nullable BluetoothDevice device) {
if (DBG) Log.d(TAG, "enableOptionalCodecs(" + device + ")");
enableDisableOptionalCodecs(device, true);
}
@@ -689,8 +707,9 @@ public final class BluetoothA2dp implements BluetoothProfile {
* active A2DP Bluetooth device.
* @hide
*/
- @UnsupportedAppUsage
- public void disableOptionalCodecs(BluetoothDevice device) {
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+ public void disableOptionalCodecs(@Nullable BluetoothDevice device) {
if (DBG) Log.d(TAG, "disableOptionalCodecs(" + device + ")");
enableDisableOptionalCodecs(device, false);
}
@@ -728,8 +747,10 @@ public final class BluetoothA2dp implements BluetoothProfile {
* OPTIONAL_CODECS_SUPPORTED.
* @hide
*/
- @UnsupportedAppUsage
- public int supportsOptionalCodecs(BluetoothDevice device) {
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+ @OptionalCodecsSupportStatus
+ public int supportsOptionalCodecs(@Nullable BluetoothDevice device) {
try {
final IBluetoothA2dp service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
@@ -738,7 +759,7 @@ public final class BluetoothA2dp implements BluetoothProfile {
if (service == null) Log.w(TAG, "Proxy not attached to service");
return OPTIONAL_CODECS_SUPPORT_UNKNOWN;
} catch (RemoteException e) {
- Log.e(TAG, "Error talking to BT service in getSupportsOptionalCodecs()", e);
+ Log.e(TAG, "Error talking to BT service in supportsOptionalCodecs()", e);
return OPTIONAL_CODECS_SUPPORT_UNKNOWN;
}
}
@@ -751,8 +772,10 @@ public final class BluetoothA2dp implements BluetoothProfile {
* OPTIONAL_CODECS_PREF_DISABLED.
* @hide
*/
- @UnsupportedAppUsage
- public int getOptionalCodecsEnabled(BluetoothDevice device) {
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+ @OptionalCodecsPreferenceStatus
+ public int getOptionalCodecsEnabled(@Nullable BluetoothDevice device) {
try {
final IBluetoothA2dp service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
@@ -761,7 +784,7 @@ public final class BluetoothA2dp implements BluetoothProfile {
if (service == null) Log.w(TAG, "Proxy not attached to service");
return OPTIONAL_CODECS_PREF_UNKNOWN;
} catch (RemoteException e) {
- Log.e(TAG, "Error talking to BT service in getSupportsOptionalCodecs()", e);
+ Log.e(TAG, "Error talking to BT service in getOptionalCodecsEnabled()", e);
return OPTIONAL_CODECS_PREF_UNKNOWN;
}
}
@@ -775,8 +798,10 @@ public final class BluetoothA2dp implements BluetoothProfile {
* OPTIONAL_CODECS_PREF_DISABLED.
* @hide
*/
- @UnsupportedAppUsage
- public void setOptionalCodecsEnabled(BluetoothDevice device, int value) {
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+ public void setOptionalCodecsEnabled(@Nullable BluetoothDevice device,
+ @OptionalCodecsPreferenceStatus int value) {
try {
if (value != BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN
&& value != BluetoothA2dp.OPTIONAL_CODECS_PREF_DISABLED
diff --git a/core/java/android/bluetooth/BluetoothA2dpSink.java b/core/java/android/bluetooth/BluetoothA2dpSink.java
index c17834aa8e52..cf3367602aa9 100755
--- a/core/java/android/bluetooth/BluetoothA2dpSink.java
+++ b/core/java/android/bluetooth/BluetoothA2dpSink.java
@@ -320,7 +320,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile {
* Set priority of the profile
*
* <p> The device should already be paired.
- * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF},
+ * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF}
*
* @param device Paired bluetooth device
* @param priority
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 9b5280d48f45..3f8cb627e382 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -862,18 +862,7 @@ public final class BluetoothAdapter {
*/
@RequiresPermission(Manifest.permission.BLUETOOTH)
public boolean isEnabled() {
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- return mService.isEnabled();
- }
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- } finally {
- mServiceLock.readLock().unlock();
- }
-
- return false;
+ return getState() == BluetoothAdapter.STATE_ON;
}
/**
diff --git a/core/java/android/bluetooth/BluetoothCodecConfig.java b/core/java/android/bluetooth/BluetoothCodecConfig.java
index 36f3a1eeba79..08d0797997b5 100644
--- a/core/java/android/bluetooth/BluetoothCodecConfig.java
+++ b/core/java/android/bluetooth/BluetoothCodecConfig.java
@@ -16,10 +16,15 @@
package android.bluetooth;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.Objects;
/**
@@ -29,78 +34,131 @@ import java.util.Objects;
*
* {@hide}
*/
+@SystemApi
public final class BluetoothCodecConfig implements Parcelable {
// Add an entry for each source codec here.
// NOTE: The values should be same as those listed in the following file:
// hardware/libhardware/include/hardware/bt_av.h
- @UnsupportedAppUsage
+
+ /** @hide */
+ @IntDef(prefix = "SOURCE_CODEC_TYPE_", value = {
+ SOURCE_CODEC_TYPE_SBC,
+ SOURCE_CODEC_TYPE_AAC,
+ SOURCE_CODEC_TYPE_APTX,
+ SOURCE_CODEC_TYPE_APTX_HD,
+ SOURCE_CODEC_TYPE_LDAC,
+ SOURCE_CODEC_TYPE_MAX,
+ SOURCE_CODEC_TYPE_INVALID
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SourceCodecType {}
+
public static final int SOURCE_CODEC_TYPE_SBC = 0;
- @UnsupportedAppUsage
+
public static final int SOURCE_CODEC_TYPE_AAC = 1;
- @UnsupportedAppUsage
+
public static final int SOURCE_CODEC_TYPE_APTX = 2;
- @UnsupportedAppUsage
+
public static final int SOURCE_CODEC_TYPE_APTX_HD = 3;
- @UnsupportedAppUsage
+
public static final int SOURCE_CODEC_TYPE_LDAC = 4;
- @UnsupportedAppUsage
+
public static final int SOURCE_CODEC_TYPE_MAX = 5;
- @UnsupportedAppUsage
+
public static final int SOURCE_CODEC_TYPE_INVALID = 1000 * 1000;
- @UnsupportedAppUsage
+ /** @hide */
+ @IntDef(prefix = "CODEC_PRIORITY_", value = {
+ CODEC_PRIORITY_DISABLED,
+ CODEC_PRIORITY_DEFAULT,
+ CODEC_PRIORITY_HIGHEST
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface CodecPriority {}
+
public static final int CODEC_PRIORITY_DISABLED = -1;
- @UnsupportedAppUsage
+
public static final int CODEC_PRIORITY_DEFAULT = 0;
- @UnsupportedAppUsage
+
public static final int CODEC_PRIORITY_HIGHEST = 1000 * 1000;
- @UnsupportedAppUsage
+
+ /** @hide */
+ @IntDef(prefix = "SAMPLE_RATE_", value = {
+ SAMPLE_RATE_NONE,
+ SAMPLE_RATE_44100,
+ SAMPLE_RATE_48000,
+ SAMPLE_RATE_88200,
+ SAMPLE_RATE_96000,
+ SAMPLE_RATE_176400,
+ SAMPLE_RATE_192000
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SampleRate {}
+
public static final int SAMPLE_RATE_NONE = 0;
- @UnsupportedAppUsage
+
public static final int SAMPLE_RATE_44100 = 0x1 << 0;
- @UnsupportedAppUsage
+
public static final int SAMPLE_RATE_48000 = 0x1 << 1;
- @UnsupportedAppUsage
+
public static final int SAMPLE_RATE_88200 = 0x1 << 2;
- @UnsupportedAppUsage
+
public static final int SAMPLE_RATE_96000 = 0x1 << 3;
- @UnsupportedAppUsage
+
public static final int SAMPLE_RATE_176400 = 0x1 << 4;
- @UnsupportedAppUsage
+
public static final int SAMPLE_RATE_192000 = 0x1 << 5;
- @UnsupportedAppUsage
+
+ /** @hide */
+ @IntDef(prefix = "BITS_PER_SAMPLE_", value = {
+ BITS_PER_SAMPLE_NONE,
+ BITS_PER_SAMPLE_16,
+ BITS_PER_SAMPLE_24,
+ BITS_PER_SAMPLE_32
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface BitsPerSample {}
+
public static final int BITS_PER_SAMPLE_NONE = 0;
- @UnsupportedAppUsage
+
public static final int BITS_PER_SAMPLE_16 = 0x1 << 0;
- @UnsupportedAppUsage
+
public static final int BITS_PER_SAMPLE_24 = 0x1 << 1;
- @UnsupportedAppUsage
+
public static final int BITS_PER_SAMPLE_32 = 0x1 << 2;
- @UnsupportedAppUsage
+
+ /** @hide */
+ @IntDef(prefix = "CHANNEL_MODE_", value = {
+ CHANNEL_MODE_NONE,
+ CHANNEL_MODE_MONO,
+ CHANNEL_MODE_STEREO
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ChannelMode {}
+
public static final int CHANNEL_MODE_NONE = 0;
- @UnsupportedAppUsage
+
public static final int CHANNEL_MODE_MONO = 0x1 << 0;
- @UnsupportedAppUsage
+
public static final int CHANNEL_MODE_STEREO = 0x1 << 1;
- private final int mCodecType;
- private int mCodecPriority;
- private final int mSampleRate;
- private final int mBitsPerSample;
- private final int mChannelMode;
+ private final @SourceCodecType int mCodecType;
+ private @CodecPriority int mCodecPriority;
+ private final @SampleRate int mSampleRate;
+ private final @BitsPerSample int mBitsPerSample;
+ private final @ChannelMode int mChannelMode;
private final long mCodecSpecific1;
private final long mCodecSpecific2;
private final long mCodecSpecific3;
private final long mCodecSpecific4;
- @UnsupportedAppUsage
- public BluetoothCodecConfig(int codecType, int codecPriority,
- int sampleRate, int bitsPerSample,
- int channelMode, long codecSpecific1,
+ public BluetoothCodecConfig(@SourceCodecType int codecType, @CodecPriority int codecPriority,
+ @SampleRate int sampleRate, @BitsPerSample int bitsPerSample,
+ @ChannelMode int channelMode, long codecSpecific1,
long codecSpecific2, long codecSpecific3,
long codecSpecific4) {
mCodecType = codecType;
@@ -114,8 +172,7 @@ public final class BluetoothCodecConfig implements Parcelable {
mCodecSpecific4 = codecSpecific4;
}
- @UnsupportedAppUsage
- public BluetoothCodecConfig(int codecType) {
+ public BluetoothCodecConfig(@SourceCodecType int codecType) {
mCodecType = codecType;
mCodecPriority = BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT;
mSampleRate = BluetoothCodecConfig.SAMPLE_RATE_NONE;
@@ -144,6 +201,12 @@ public final class BluetoothCodecConfig implements Parcelable {
return false;
}
+ /**
+ * Returns a hash based on the config values
+ *
+ * @return a hash based on the config values
+ * @hide
+ */
@Override
public int hashCode() {
return Objects.hash(mCodecType, mCodecPriority, mSampleRate,
@@ -155,6 +218,7 @@ public final class BluetoothCodecConfig implements Parcelable {
* Checks whether the object contains valid codec configuration.
*
* @return true if the object contains valid codec configuration, otherwise false.
+ * @hide
*/
public boolean isValid() {
return (mSampleRate != SAMPLE_RATE_NONE)
@@ -242,6 +306,12 @@ public final class BluetoothCodecConfig implements Parcelable {
+ ",mCodecSpecific4:" + mCodecSpecific4 + "}";
}
+ /**
+ * Always returns 0
+ *
+ * @return 0
+ * @hide
+ */
@Override
public int describeContents() {
return 0;
@@ -271,6 +341,14 @@ public final class BluetoothCodecConfig implements Parcelable {
}
};
+ /**
+ * Flattens the object to a parcel
+ *
+ * @param out The Parcel in which the object should be written.
+ * @param flags Additional flags about how the object should be written.
+ *
+ * @hide
+ */
@Override
public void writeToParcel(Parcel out, int flags) {
out.writeInt(mCodecType);
@@ -289,7 +367,7 @@ public final class BluetoothCodecConfig implements Parcelable {
*
* @return the codec name
*/
- public String getCodecName() {
+ public @NonNull String getCodecName() {
switch (mCodecType) {
case SOURCE_CODEC_TYPE_SBC:
return "SBC";
@@ -315,8 +393,7 @@ public final class BluetoothCodecConfig implements Parcelable {
*
* @return the codec type
*/
- @UnsupportedAppUsage
- public int getCodecType() {
+ public @SourceCodecType int getCodecType() {
return mCodecType;
}
@@ -336,8 +413,7 @@ public final class BluetoothCodecConfig implements Parcelable {
*
* @return the codec priority
*/
- @UnsupportedAppUsage
- public int getCodecPriority() {
+ public @CodecPriority int getCodecPriority() {
return mCodecPriority;
}
@@ -347,9 +423,10 @@ public final class BluetoothCodecConfig implements Parcelable {
* means higher priority. If 0, reset to default.
*
* @param codecPriority the codec priority
+ * @hide
*/
@UnsupportedAppUsage
- public void setCodecPriority(int codecPriority) {
+ public void setCodecPriority(@CodecPriority int codecPriority) {
mCodecPriority = codecPriority;
}
@@ -366,8 +443,7 @@ public final class BluetoothCodecConfig implements Parcelable {
*
* @return the codec sample rate
*/
- @UnsupportedAppUsage
- public int getSampleRate() {
+ public @SampleRate int getSampleRate() {
return mSampleRate;
}
@@ -381,8 +457,7 @@ public final class BluetoothCodecConfig implements Parcelable {
*
* @return the codec bits per sample
*/
- @UnsupportedAppUsage
- public int getBitsPerSample() {
+ public @BitsPerSample int getBitsPerSample() {
return mBitsPerSample;
}
@@ -394,9 +469,10 @@ public final class BluetoothCodecConfig implements Parcelable {
* {@link android.bluetooth.BluetoothCodecConfig#CHANNEL_MODE_STEREO}
*
* @return the codec channel mode
+ * @hide
*/
@UnsupportedAppUsage
- public int getChannelMode() {
+ public @ChannelMode int getChannelMode() {
return mChannelMode;
}
@@ -405,7 +481,6 @@ public final class BluetoothCodecConfig implements Parcelable {
*
* @return a codec specific value1.
*/
- @UnsupportedAppUsage
public long getCodecSpecific1() {
return mCodecSpecific1;
}
@@ -414,6 +489,7 @@ public final class BluetoothCodecConfig implements Parcelable {
* Gets a codec specific value2.
*
* @return a codec specific value2
+ * @hide
*/
@UnsupportedAppUsage
public long getCodecSpecific2() {
@@ -424,6 +500,7 @@ public final class BluetoothCodecConfig implements Parcelable {
* Gets a codec specific value3.
*
* @return a codec specific value3
+ * @hide
*/
@UnsupportedAppUsage
public long getCodecSpecific3() {
@@ -434,6 +511,7 @@ public final class BluetoothCodecConfig implements Parcelable {
* Gets a codec specific value4.
*
* @return a codec specific value4
+ * @hide
*/
@UnsupportedAppUsage
public long getCodecSpecific4() {
@@ -445,6 +523,7 @@ public final class BluetoothCodecConfig implements Parcelable {
*
* @param valueSet the value set presented by a bitmask
* @return true if the valueSet contains zero or single bit, otherwise false.
+ * @hide
*/
private static boolean hasSingleBit(int valueSet) {
return (valueSet == 0 || (valueSet & (valueSet - 1)) == 0);
@@ -454,6 +533,7 @@ public final class BluetoothCodecConfig implements Parcelable {
* Checks whether the object contains none or single sample rate.
*
* @return true if the object contains none or single sample rate, otherwise false.
+ * @hide
*/
public boolean hasSingleSampleRate() {
return hasSingleBit(mSampleRate);
@@ -463,6 +543,7 @@ public final class BluetoothCodecConfig implements Parcelable {
* Checks whether the object contains none or single bits per sample.
*
* @return true if the object contains none or single bits per sample, otherwise false.
+ * @hide
*/
public boolean hasSingleBitsPerSample() {
return hasSingleBit(mBitsPerSample);
@@ -472,6 +553,7 @@ public final class BluetoothCodecConfig implements Parcelable {
* Checks whether the object contains none or single channel mode.
*
* @return true if the object contains none or single channel mode, otherwise false.
+ * @hide
*/
public boolean hasSingleChannelMode() {
return hasSingleBit(mChannelMode);
@@ -482,6 +564,7 @@ public final class BluetoothCodecConfig implements Parcelable {
*
* @param other the codec config to compare against
* @return true if the audio feeding parameters are same, otherwise false
+ * @hide
*/
public boolean sameAudioFeedingParameters(BluetoothCodecConfig other) {
return (other != null && other.mSampleRate == mSampleRate
@@ -495,6 +578,7 @@ public final class BluetoothCodecConfig implements Parcelable {
*
* @param other the codec config to compare against
* @return true if the audio feeding parameters are similar, otherwise false.
+ * @hide
*/
public boolean similarCodecFeedingParameters(BluetoothCodecConfig other) {
if (other == null || mCodecType != other.mCodecType) {
@@ -526,6 +610,7 @@ public final class BluetoothCodecConfig implements Parcelable {
*
* @param other the codec config to compare against
* @return true if the codec specific parameters are the same, otherwise false.
+ * @hide
*/
public boolean sameCodecSpecificParameters(BluetoothCodecConfig other) {
if (other == null && mCodecType != other.mCodecType) {
diff --git a/core/java/android/bluetooth/BluetoothCodecStatus.java b/core/java/android/bluetooth/BluetoothCodecStatus.java
index 58a764a85bed..b6e77391da5d 100644
--- a/core/java/android/bluetooth/BluetoothCodecStatus.java
+++ b/core/java/android/bluetooth/BluetoothCodecStatus.java
@@ -17,7 +17,7 @@
package android.bluetooth;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -32,6 +32,7 @@ import java.util.Objects;
*
* {@hide}
*/
+@SystemApi
public final class BluetoothCodecStatus implements Parcelable {
/**
* Extra for the codec configuration intents of the individual profiles.
@@ -39,17 +40,16 @@ public final class BluetoothCodecStatus implements Parcelable {
* This extra represents the current codec status of the A2DP
* profile.
*/
- @UnsupportedAppUsage
public static final String EXTRA_CODEC_STATUS =
- "android.bluetooth.codec.extra.CODEC_STATUS";
+ "android.bluetooth.extra.CODEC_STATUS";
private final @Nullable BluetoothCodecConfig mCodecConfig;
private final BluetoothCodecConfig[] mCodecsLocalCapabilities;
private final BluetoothCodecConfig[] mCodecsSelectableCapabilities;
- public BluetoothCodecStatus(BluetoothCodecConfig codecConfig,
- BluetoothCodecConfig[] codecsLocalCapabilities,
- BluetoothCodecConfig[] codecsSelectableCapabilities) {
+ public BluetoothCodecStatus(@Nullable BluetoothCodecConfig codecConfig,
+ @Nullable BluetoothCodecConfig[] codecsLocalCapabilities,
+ @Nullable BluetoothCodecConfig[] codecsSelectableCapabilities) {
mCodecConfig = codecConfig;
mCodecsLocalCapabilities = codecsLocalCapabilities;
mCodecsSelectableCapabilities = codecsSelectableCapabilities;
@@ -74,6 +74,7 @@ public final class BluetoothCodecStatus implements Parcelable {
* @param c1 the first array of capabilities to compare
* @param c2 the second array of capabilities to compare
* @return true if both arrays contain same capabilities
+ * @hide
*/
public static boolean sameCapabilities(BluetoothCodecConfig[] c1,
BluetoothCodecConfig[] c2) {
@@ -95,6 +96,7 @@ public final class BluetoothCodecStatus implements Parcelable {
*
* @param codecConfig the codec config to compare against
* @return true if the codec config matches, otherwise false
+ * @hide
*/
public boolean isCodecConfigSelectable(BluetoothCodecConfig codecConfig) {
if (codecConfig == null || !codecConfig.hasSingleSampleRate()
@@ -125,7 +127,12 @@ public final class BluetoothCodecStatus implements Parcelable {
return false;
}
-
+ /**
+ * Returns a hash based on the codec config and local capabilities
+ *
+ * @return a hash based on the config values
+ * @hide
+ */
@Override
public int hashCode() {
return Objects.hash(mCodecConfig, mCodecsLocalCapabilities,
@@ -140,6 +147,12 @@ public final class BluetoothCodecStatus implements Parcelable {
+ "}";
}
+ /**
+ * Always returns 0
+ *
+ * @return 0
+ * @hide
+ */
@Override
public int describeContents() {
return 0;
@@ -165,6 +178,14 @@ public final class BluetoothCodecStatus implements Parcelable {
}
};
+ /**
+ * Flattens the object to a parcel
+ *
+ * @param out The Parcel in which the object should be written.
+ * @param flags Additional flags about how the object should be written.
+ *
+ * @hide
+ */
@Override
public void writeToParcel(Parcel out, int flags) {
out.writeTypedObject(mCodecConfig, 0);
@@ -177,7 +198,6 @@ public final class BluetoothCodecStatus implements Parcelable {
*
* @return the current codec configuration
*/
- @UnsupportedAppUsage
public @Nullable BluetoothCodecConfig getCodecConfig() {
return mCodecConfig;
}
@@ -187,8 +207,7 @@ public final class BluetoothCodecStatus implements Parcelable {
*
* @return an array with the codecs local capabilities
*/
- @UnsupportedAppUsage
- public BluetoothCodecConfig[] getCodecsLocalCapabilities() {
+ public @Nullable BluetoothCodecConfig[] getCodecsLocalCapabilities() {
return mCodecsLocalCapabilities;
}
@@ -197,8 +216,7 @@ public final class BluetoothCodecStatus implements Parcelable {
*
* @return an array with the codecs selectable capabilities
*/
- @UnsupportedAppUsage
- public BluetoothCodecConfig[] getCodecsSelectableCapabilities() {
+ public @Nullable BluetoothCodecConfig[] getCodecsSelectableCapabilities() {
return mCodecsSelectableCapabilities;
}
}
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index 0be3eca8239e..49187dcde342 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -1131,20 +1131,7 @@ public final class BluetoothDevice implements Parcelable {
*/
@RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public boolean createBond() {
- final IBluetooth service = sService;
- if (service == null) {
- Log.e(TAG, "BT not enabled. Cannot create bond to Remote Device");
- return false;
- }
- try {
- Log.i(TAG, "createBond() for device " + getAddress()
- + " called by pid: " + Process.myPid()
- + " tid: " + Process.myTid());
- return service.createBond(this, TRANSPORT_AUTO);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- return false;
+ return createBond(TRANSPORT_AUTO);
}
/**
@@ -1165,23 +1152,7 @@ public final class BluetoothDevice implements Parcelable {
*/
@UnsupportedAppUsage
public boolean createBond(int transport) {
- final IBluetooth service = sService;
- if (service == null) {
- Log.e(TAG, "BT not enabled. Cannot create bond to Remote Device");
- return false;
- }
- if (TRANSPORT_AUTO > transport || transport > TRANSPORT_LE) {
- throw new IllegalArgumentException(transport + " is not a valid Bluetooth transport");
- }
- try {
- Log.i(TAG, "createBond() for device " + getAddress()
- + " called by pid: " + Process.myPid()
- + " tid: " + Process.myTid());
- return service.createBond(this, transport);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- return false;
+ return createBondOutOfBand(transport, null);
}
/**
@@ -1209,7 +1180,7 @@ public final class BluetoothDevice implements Parcelable {
return false;
}
try {
- return service.createBondOutOfBand(this, transport, oobData);
+ return service.createBond(this, transport, oobData);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index e9fc8f6acfc6..f017aad25c0c 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -185,7 +185,8 @@ public class PackageInstaller {
* {@link #STATUS_FAILURE}, {@link #STATUS_FAILURE_ABORTED},
* {@link #STATUS_FAILURE_BLOCKED}, {@link #STATUS_FAILURE_CONFLICT},
* {@link #STATUS_FAILURE_INCOMPATIBLE}, {@link #STATUS_FAILURE_INVALID},
- * {@link #STATUS_FAILURE_STORAGE}.
+ * {@link #STATUS_FAILURE_STORAGE}, {@link #STATUS_FAILURE_NAME_NOT_FOUND},
+ * {@link #STATUS_FAILURE_ILLEGAL_STATE} or {@link #STATUS_FAILURE_SECURITY}.
* <p>
* More information about a status may be available through additional
* extras; see the individual status documentation for details.
@@ -1130,9 +1131,14 @@ public class PackageInstaller {
*
* @param packageName The package of the new owner. Needs to hold the INSTALL_PACKAGES
* permission.
- * @param statusReceiver Called when the state of the session changes. Intents sent to this
- * receiver contain {@link #EXTRA_STATUS}. Refer to the individual
- * transfer status codes on how to handle them.
+ * @param statusReceiver Called when the state of the session changes. Intents sent to
+ * this receiver contain {@link #EXTRA_STATUS}. Possible statuses:
+ * {@link #STATUS_FAILURE_NAME_NOT_FOUND},
+ * {@link #STATUS_FAILURE_ILLEGAL_STATE},
+ * {@link #STATUS_FAILURE_SECURITY},
+ * {@link #STATUS_FAILURE}.
+ * Refer to the individual transfer status codes on how to handle
+ * them.
*
* @throws PackageManager.NameNotFoundException if the new owner could not be found.
* @throws SecurityException if called after the session has been committed or abandoned.
diff --git a/core/java/android/ddm/DdmHandleAppName.java b/core/java/android/ddm/DdmHandleAppName.java
index 956078772ca8..de7acbaf6e55 100644
--- a/core/java/android/ddm/DdmHandleAppName.java
+++ b/core/java/android/ddm/DdmHandleAppName.java
@@ -17,10 +17,12 @@
package android.ddm;
import android.annotation.UnsupportedAppUsage;
+import android.util.Log;
+
import org.apache.harmony.dalvik.ddmc.Chunk;
import org.apache.harmony.dalvik.ddmc.ChunkHandler;
import org.apache.harmony.dalvik.ddmc.DdmServer;
-import android.util.Log;
+
import java.nio.ByteBuffer;
@@ -31,7 +33,7 @@ public class DdmHandleAppName extends ChunkHandler {
public static final int CHUNK_APNM = type("APNM");
- private volatile static String mAppName = "";
+ private static volatile Names sNames = new Names("", "");
private static DdmHandleAppName mInstance = new DdmHandleAppName();
@@ -66,45 +68,81 @@ public class DdmHandleAppName extends ChunkHandler {
/**
+ * Sets all names to the same name.
+ */
+ @UnsupportedAppUsage
+ public static void setAppName(String name, int userId) {
+ setAppName(name, name, userId);
+ }
+
+ /**
* Set the application name. Called when we get named, which may be
* before or after DDMS connects. For the latter we need to send up
* an APNM message.
*/
@UnsupportedAppUsage
- public static void setAppName(String name, int userId) {
- if (name == null || name.length() == 0)
- return;
+ public static void setAppName(String appName, String pkgName, int userId) {
+ if (appName == null || appName.isEmpty() || pkgName == null || pkgName.isEmpty()) return;
- mAppName = name;
+ sNames = new Names(appName, pkgName);
// if DDMS is already connected, send the app name up
- sendAPNM(name, userId);
+ sendAPNM(appName, pkgName, userId);
}
@UnsupportedAppUsage
- public static String getAppName() {
- return mAppName;
+ public static Names getNames() {
+ return sNames;
}
- /*
+ /**
* Send an APNM (APplication NaMe) chunk.
*/
- private static void sendAPNM(String appName, int userId) {
+ private static void sendAPNM(String appName, String pkgName, int userId) {
if (false)
Log.v("ddm", "Sending app name");
ByteBuffer out = ByteBuffer.allocate(
4 /* appName's length */
- + appName.length()*2 /* appName */
- + 4 /* userId */);
+ + appName.length() * 2 /* appName */
+ + 4 /* userId */
+ + 4 /* pkgName's length */
+ + pkgName.length() * 2 /* pkgName */);
out.order(ChunkHandler.CHUNK_ORDER);
out.putInt(appName.length());
putString(out, appName);
out.putInt(userId);
+ out.putInt(pkgName.length());
+ putString(out, pkgName);
Chunk chunk = new Chunk(CHUNK_APNM, out);
DdmServer.sendChunk(chunk);
}
+ /**
+ * A class that encapsulates the app and package names into a single
+ * instance, effectively synchronizing the two names.
+ */
+ static final class Names {
+
+ private final String mAppName;
+
+ private final String mPkgName;
+
+ private Names(String appName, String pkgName) {
+ mAppName = appName;
+ mPkgName = pkgName;
+ }
+
+ public String getAppName() {
+ return mAppName;
+ }
+
+ public String getPkgName() {
+ return mPkgName;
+ }
+
+ }
+
}
diff --git a/core/java/android/ddm/DdmHandleHello.java b/core/java/android/ddm/DdmHandleHello.java
index 87568e857d6d..60dfc8d7ee7b 100644
--- a/core/java/android/ddm/DdmHandleHello.java
+++ b/core/java/android/ddm/DdmHandleHello.java
@@ -126,10 +126,9 @@ public class DdmHandleHello extends ChunkHandler {
String vmVersion = System.getProperty("java.vm.version", "?");
String vmIdent = vmName + " v" + vmVersion;
- //String appName = android.app.ActivityThread.currentPackageName();
- //if (appName == null)
- // appName = "unknown";
- String appName = DdmHandleAppName.getAppName();
+ DdmHandleAppName.Names names = DdmHandleAppName.getNames();
+ String appName = names.getAppName();
+ String pkgName = names.getPkgName();
VMRuntime vmRuntime = VMRuntime.getRuntime();
String instructionSetDescription =
@@ -142,12 +141,13 @@ public class DdmHandleHello extends ChunkHandler {
+ (vmRuntime.isCheckJniEnabled() ? "true" : "false");
boolean isNativeDebuggable = vmRuntime.isNativeDebuggable();
- ByteBuffer out = ByteBuffer.allocate(28
+ ByteBuffer out = ByteBuffer.allocate(32
+ vmIdent.length() * 2
+ appName.length() * 2
+ instructionSetDescription.length() * 2
+ vmFlags.length() * 2
- + 1);
+ + 1
+ + pkgName.length() * 2);
out.order(ChunkHandler.CHUNK_ORDER);
out.putInt(CLIENT_PROTOCOL_VERSION);
out.putInt(android.os.Process.myPid());
@@ -161,6 +161,8 @@ public class DdmHandleHello extends ChunkHandler {
out.putInt(vmFlags.length());
putString(out, vmFlags);
out.put((byte)(isNativeDebuggable ? 1 : 0));
+ out.putInt(pkgName.length());
+ putString(out, pkgName);
Chunk reply = new Chunk(CHUNK_HELO, out);
diff --git a/core/java/android/hardware/biometrics/BiometricConstants.java b/core/java/android/hardware/biometrics/BiometricConstants.java
index c8bf570e1bc8..191516b5b992 100644
--- a/core/java/android/hardware/biometrics/BiometricConstants.java
+++ b/core/java/android/hardware/biometrics/BiometricConstants.java
@@ -86,12 +86,10 @@ public interface BiometricConstants {
int BIOMETRIC_ERROR_LOCKOUT = 7;
/**
- * Hardware vendors may extend this list if there are conditions that do not fall under one of
- * the above categories. Vendors are responsible for providing error strings for these errors.
- * These messages are typically reserved for internal operations such as enrollment, but may be
- * used to express vendor errors not otherwise covered. Applications are expected to show the
- * error message string if they happen, but are advised not to rely on the message id since they
- * will be device and vendor-specific
+ * OEMs should use this constant if there are conditions that do not fit under any of the other
+ * publicly defined constants, and must provide appropriate strings for these
+ * errors to the {@link BiometricPrompt.AuthenticationCallback#onAuthenticationError(int,
+ * CharSequence)} callback. OEMs should expect that the error message will be shown to users.
*/
int BIOMETRIC_ERROR_VENDOR = 8;
diff --git a/core/java/android/hardware/display/DisplayViewport.java b/core/java/android/hardware/display/DisplayViewport.java
index f2c50b5cc464..5adf948de348 100644
--- a/core/java/android/hardware/display/DisplayViewport.java
+++ b/core/java/android/hardware/display/DisplayViewport.java
@@ -134,7 +134,9 @@ public final class DisplayViewport {
result += prime * result + deviceWidth;
result += prime * result + deviceHeight;
result += prime * result + uniqueId.hashCode();
- result += prime * result + physicalPort;
+ if (physicalPort != null) {
+ result += prime * result + physicalPort.hashCode();
+ }
result += prime * result + type;
return result;
}
@@ -142,11 +144,12 @@ public final class DisplayViewport {
// For debugging purposes.
@Override
public String toString() {
+ final Integer port = physicalPort == null ? null : Byte.toUnsignedInt(physicalPort);
return "DisplayViewport{type=" + typeToString(type)
+ ", valid=" + valid
+ ", displayId=" + displayId
+ ", uniqueId='" + uniqueId + "'"
- + ", physicalPort=" + physicalPort
+ + ", physicalPort=" + port
+ ", orientation=" + orientation
+ ", logicalFrame=" + logicalFrame
+ ", physicalFrame=" + physicalFrame
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index 15ff69e7fd2a..a9c5a9118a31 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -909,8 +909,11 @@ public class Binder implements IBinder {
}
/**
- * Handle a call to {@link #shellCommand}. The default implementation simply prints
- * an error message. Override and replace with your own.
+ * Handle a call to {@link #shellCommand}.
+ *
+ * <p>The default implementation performs a caller check to make sure the caller UID is of
+ * SHELL or ROOT, and then call {@link #handleShellCommand}.
+ *
* <p class="caution">Note: no permission checking is done before calling this method; you must
* apply any security checks as appropriate for the command being executed.
* Consider using {@link ShellCommand} to help in the implementation.</p>
@@ -921,6 +924,12 @@ public class Binder implements IBinder {
@NonNull String[] args, @Nullable ShellCallback callback,
@NonNull ResultReceiver resultReceiver) throws RemoteException {
+ final int callingUid = Binder.getCallingUid();
+ if (callingUid != Process.ROOT_UID && callingUid != Process.SHELL_UID) {
+ resultReceiver.send(-1, null);
+ throw new SecurityException("Shell commands are only callable by ADB");
+ }
+
// First, convert in, out and err to @NonNull, by redirecting any that's null to /dev/null.
try {
if (in == null) {
@@ -961,19 +970,23 @@ public class Binder implements IBinder {
/**
* System services can implement this method to implement ADB shell commands.
*
- * TODO More Javadoc.
- * TODO Add a generic way to define subcommands and their permissions.
+ * <p>A system binder service can implement it to handle shell commands on ADB. For example,
+ * the Job Scheduler service implements it to handle <code>adb shell cmd jobscheduler</code>.
*
- * @param in standard input.
- * @param out standard output.
- * @param err standard error.
+ * <p>Commands are only executable by ADB shell; i.e. only {@link Process#SHELL_UID} and
+ * {@link Process#ROOT_UID} can call them.
+ *
+ * @param in standard input
+ * @param out standard output
+ * @param err standard error
* @param args arguments passed to the command. Can be empty. The first argument is typically
* a subcommand, such as {@code run} for {@code adb shell cmd jobscheduler run}.
+ * @return the status code returned from the <code>cmd</code> command.
*
* @hide
*/
- // @SystemApi TODO Make it a system API.
- protected int handleShellCommand(@NonNull ParcelFileDescriptor in,
+ @SystemApi
+ public int handleShellCommand(@NonNull ParcelFileDescriptor in,
@NonNull ParcelFileDescriptor out, @NonNull ParcelFileDescriptor err,
@NonNull String[] args) {
FileOutputStream ferr = new FileOutputStream(err.getFileDescriptor());
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 9e9cd9218a0f..137f53782124 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -24,6 +24,7 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
+import android.annotation.StringDef;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
@@ -1112,6 +1113,82 @@ public class UserManager {
*/
public static final String KEY_RESTRICTIONS_PENDING = "restrictions_pending";
+ /**
+ * List of key values that can be passed into the various user restriction related methods
+ * in {@link UserManager} & {@link DevicePolicyManager}.
+ * Note: This is slightly different from the real set of user restrictions listed in {@link
+ * com.android.server.pm.UserRestrictionsUtils#USER_RESTRICTIONS}. For example
+ * {@link #KEY_RESTRICTIONS_PENDING} is not a real user restriction, but is a a legitimate
+ * value that can be passed into {@link #hasUserRestriction(String)}.
+ * @hide
+ */
+ @StringDef(value = {
+ DISALLOW_MODIFY_ACCOUNTS,
+ DISALLOW_CONFIG_WIFI,
+ DISALLOW_CONFIG_LOCALE,
+ DISALLOW_INSTALL_APPS,
+ DISALLOW_UNINSTALL_APPS,
+ DISALLOW_SHARE_LOCATION,
+ DISALLOW_AIRPLANE_MODE,
+ DISALLOW_CONFIG_BRIGHTNESS,
+ DISALLOW_AMBIENT_DISPLAY,
+ DISALLOW_CONFIG_SCREEN_TIMEOUT,
+ DISALLOW_INSTALL_UNKNOWN_SOURCES,
+ DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY,
+ DISALLOW_CONFIG_BLUETOOTH,
+ DISALLOW_BLUETOOTH,
+ DISALLOW_BLUETOOTH_SHARING,
+ DISALLOW_USB_FILE_TRANSFER,
+ DISALLOW_CONFIG_CREDENTIALS,
+ DISALLOW_REMOVE_USER,
+ DISALLOW_REMOVE_MANAGED_PROFILE,
+ DISALLOW_DEBUGGING_FEATURES,
+ DISALLOW_CONFIG_VPN,
+ DISALLOW_CONFIG_LOCATION,
+ DISALLOW_CONFIG_DATE_TIME,
+ DISALLOW_CONFIG_TETHERING,
+ DISALLOW_NETWORK_RESET,
+ DISALLOW_FACTORY_RESET,
+ DISALLOW_ADD_USER,
+ DISALLOW_ADD_MANAGED_PROFILE,
+ ENSURE_VERIFY_APPS,
+ DISALLOW_CONFIG_CELL_BROADCASTS,
+ DISALLOW_CONFIG_MOBILE_NETWORKS,
+ DISALLOW_APPS_CONTROL,
+ DISALLOW_MOUNT_PHYSICAL_MEDIA,
+ DISALLOW_UNMUTE_MICROPHONE,
+ DISALLOW_ADJUST_VOLUME,
+ DISALLOW_OUTGOING_CALLS,
+ DISALLOW_SMS,
+ DISALLOW_FUN,
+ DISALLOW_CREATE_WINDOWS,
+ DISALLOW_SYSTEM_ERROR_DIALOGS,
+ DISALLOW_CROSS_PROFILE_COPY_PASTE,
+ DISALLOW_OUTGOING_BEAM,
+ DISALLOW_WALLPAPER,
+ DISALLOW_SET_WALLPAPER,
+ DISALLOW_SAFE_BOOT,
+ DISALLOW_RECORD_AUDIO,
+ DISALLOW_RUN_IN_BACKGROUND,
+ DISALLOW_CAMERA,
+ DISALLOW_UNMUTE_DEVICE,
+ DISALLOW_DATA_ROAMING,
+ DISALLOW_SET_USER_ICON,
+ DISALLOW_OEM_UNLOCK,
+ DISALLOW_UNIFIED_PASSWORD,
+ ALLOW_PARENT_PROFILE_APP_LINKING,
+ DISALLOW_AUTOFILL,
+ DISALLOW_CONTENT_CAPTURE,
+ DISALLOW_CONTENT_SUGGESTIONS,
+ DISALLOW_USER_SWITCH,
+ DISALLOW_SHARE_INTO_MANAGED_PROFILE,
+ DISALLOW_PRINTING,
+ DISALLOW_CONFIG_PRIVATE_DNS,
+ KEY_RESTRICTIONS_PENDING,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface UserRestrictionKey {}
+
private static final String ACTION_CREATE_USER = "android.os.action.CREATE_USER";
/**
@@ -2026,7 +2103,8 @@ public class UserManager {
@SystemApi
@UserRestrictionSource
@RequiresPermission(android.Manifest.permission.MANAGE_USERS)
- public int getUserRestrictionSource(String restrictionKey, UserHandle userHandle) {
+ public int getUserRestrictionSource(@UserRestrictionKey String restrictionKey,
+ UserHandle userHandle) {
try {
return mService.getUserRestrictionSource(restrictionKey, userHandle.getIdentifier());
} catch (RemoteException re) {
@@ -2045,7 +2123,7 @@ public class UserManager {
@SystemApi
@RequiresPermission(android.Manifest.permission.MANAGE_USERS)
public List<EnforcingUser> getUserRestrictionSources(
- String restrictionKey, UserHandle userHandle) {
+ @UserRestrictionKey String restrictionKey, UserHandle userHandle) {
try {
return mService.getUserRestrictionSources(restrictionKey, userHandle.getIdentifier());
} catch (RemoteException re) {
@@ -2091,7 +2169,8 @@ public class UserManager {
* @param userHandle the UserHandle of the user for whom to retrieve the restrictions.
*/
@UnsupportedAppUsage
- public boolean hasBaseUserRestriction(String restrictionKey, UserHandle userHandle) {
+ public boolean hasBaseUserRestriction(@UserRestrictionKey String restrictionKey,
+ UserHandle userHandle) {
try {
return mService.hasBaseUserRestriction(restrictionKey, userHandle.getIdentifier());
} catch (RemoteException re) {
@@ -2162,7 +2241,7 @@ public class UserManager {
* @param restrictionKey The string key representing the restriction.
* @return {@code true} if the current user has the given restriction, {@code false} otherwise.
*/
- public boolean hasUserRestriction(String restrictionKey) {
+ public boolean hasUserRestriction(@UserRestrictionKey String restrictionKey) {
return hasUserRestrictionForUser(restrictionKey, Process.myUserHandle());
}
@@ -2174,7 +2253,8 @@ public class UserManager {
* @param userHandle the UserHandle of the user for whom to retrieve the restrictions.
*/
@UnsupportedAppUsage
- public boolean hasUserRestriction(String restrictionKey, UserHandle userHandle) {
+ public boolean hasUserRestriction(@UserRestrictionKey String restrictionKey,
+ UserHandle userHandle) {
return hasUserRestrictionForUser(restrictionKey, userHandle);
}
@@ -2194,7 +2274,7 @@ public class UserManager {
@RequiresPermission(anyOf = {
android.Manifest.permission.MANAGE_USERS,
android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional = true)
- public boolean hasUserRestrictionForUser(@NonNull String restrictionKey,
+ public boolean hasUserRestrictionForUser(@NonNull @UserRestrictionKey String restrictionKey,
@NonNull UserHandle userHandle) {
try {
return mService.hasUserRestriction(restrictionKey, userHandle.getIdentifier());
@@ -2207,7 +2287,7 @@ public class UserManager {
* @hide
* Returns whether any user on the device has the given user restriction set.
*/
- public boolean hasUserRestrictionOnAnyUser(String restrictionKey) {
+ public boolean hasUserRestrictionOnAnyUser(@UserRestrictionKey String restrictionKey) {
try {
return mService.hasUserRestrictionOnAnyUser(restrictionKey);
} catch (RemoteException re) {
diff --git a/core/java/android/os/connectivity/WifiActivityEnergyInfo.java b/core/java/android/os/connectivity/WifiActivityEnergyInfo.java
index 7db003d9853c..664b6c87d339 100644
--- a/core/java/android/os/connectivity/WifiActivityEnergyInfo.java
+++ b/core/java/android/os/connectivity/WifiActivityEnergyInfo.java
@@ -19,9 +19,13 @@ package android.os.connectivity;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
+import android.app.ActivityThread;
+import android.content.Context;
import android.os.Parcel;
import android.os.Parcelable;
+import com.android.internal.os.PowerProfile;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -72,7 +76,6 @@ public final class WifiActivityEnergyInfo implements Parcelable {
* @param scanDurationMillis Cumulative milliseconds when radio is awake due to scan.
* @param idleDurationMillis Cumulative milliseconds when radio is awake but not transmitting or
* receiving.
- * @param energyUsedMicroJoules Cumulative energy consumed by Wifi, in microjoules.
*/
public WifiActivityEnergyInfo(
long timeSinceBootMillis,
@@ -80,14 +83,33 @@ public final class WifiActivityEnergyInfo implements Parcelable {
long txDurationMillis,
long rxDurationMillis,
long scanDurationMillis,
- long idleDurationMillis,
- long energyUsedMicroJoules) {
+ long idleDurationMillis) {
mTimeSinceBootMillis = timeSinceBootMillis;
mStackState = stackState;
mControllerTxDurationMillis = txDurationMillis;
mControllerRxDurationMillis = rxDurationMillis;
mControllerScanDurationMillis = scanDurationMillis;
mControllerIdleDurationMillis = idleDurationMillis;
+
+ final Context context = ActivityThread.currentActivityThread().getSystemContext();
+ if (context == null) {
+ mControllerEnergyUsedMicroJoules = 0L;
+ return;
+ }
+ // Calculate energy used using PowerProfile.
+ PowerProfile powerProfile = new PowerProfile(context);
+ final double rxIdleCurrent = powerProfile.getAveragePower(
+ PowerProfile.POWER_WIFI_CONTROLLER_IDLE);
+ final double rxCurrent = powerProfile.getAveragePower(
+ PowerProfile.POWER_WIFI_CONTROLLER_RX);
+ final double txCurrent = powerProfile.getAveragePower(
+ PowerProfile.POWER_WIFI_CONTROLLER_TX);
+ final double voltage = powerProfile.getAveragePower(
+ PowerProfile.POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
+ final long energyUsedMicroJoules = (long) ((mControllerTxDurationMillis * txCurrent
+ + mControllerRxDurationMillis * rxCurrent
+ + mControllerIdleDurationMillis * rxIdleCurrent)
+ * voltage);
mControllerEnergyUsedMicroJoules = energyUsedMicroJoules;
}
@@ -113,9 +135,8 @@ public final class WifiActivityEnergyInfo implements Parcelable {
long rxTime = in.readLong();
long scanTime = in.readLong();
long idleTime = in.readLong();
- long energyUsed = in.readLong();
return new WifiActivityEnergyInfo(timestamp, stackState,
- txTime, rxTime, scanTime, idleTime, energyUsed);
+ txTime, rxTime, scanTime, idleTime);
}
public WifiActivityEnergyInfo[] newArray(int size) {
return new WifiActivityEnergyInfo[size];
@@ -130,7 +151,6 @@ public final class WifiActivityEnergyInfo implements Parcelable {
out.writeLong(mControllerRxDurationMillis);
out.writeLong(mControllerScanDurationMillis);
out.writeLong(mControllerIdleDurationMillis);
- out.writeLong(mControllerEnergyUsedMicroJoules);
}
@Override
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 2c53025da350..2fa3386bccb8 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -27,6 +27,7 @@ import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.app.Activity;
@@ -62,6 +63,7 @@ import android.os.UserManager;
import android.os.storage.StorageManager;
import android.os.storage.StorageVolume;
import android.os.storage.VolumeInfo;
+import android.os.storage.VolumeRecord;
import android.service.media.CameraPrewarmService;
import android.text.TextUtils;
import android.text.format.DateUtils;
@@ -157,6 +159,8 @@ public final class MediaStore {
public static final String SCAN_FILE_CALL = "scan_file";
/** {@hide} */
public static final String SCAN_VOLUME_CALL = "scan_volume";
+ /** {@hide} */
+ public static final String SUICIDE_CALL = "suicide";
/**
* Extra used with {@link #SCAN_FILE_CALL} or {@link #SCAN_VOLUME_CALL} to indicate that
@@ -1590,31 +1594,41 @@ public final class MediaStore {
/**
* Constant for the {@link #MEDIA_TYPE} column indicating that file
- * is not an audio, image, video or playlist file.
+ * is not an audio, image, video, playlist, or subtitles file.
*/
public static final int MEDIA_TYPE_NONE = 0;
/**
- * Constant for the {@link #MEDIA_TYPE} column indicating that file is an image file.
+ * Constant for the {@link #MEDIA_TYPE} column indicating that file
+ * is an image file.
*/
public static final int MEDIA_TYPE_IMAGE = 1;
/**
- * Constant for the {@link #MEDIA_TYPE} column indicating that file is an audio file.
+ * Constant for the {@link #MEDIA_TYPE} column indicating that file
+ * is an audio file.
*/
public static final int MEDIA_TYPE_AUDIO = 2;
/**
- * Constant for the {@link #MEDIA_TYPE} column indicating that file is a video file.
+ * Constant for the {@link #MEDIA_TYPE} column indicating that file
+ * is a video file.
*/
public static final int MEDIA_TYPE_VIDEO = 3;
/**
- * Constant for the {@link #MEDIA_TYPE} column indicating that file is a playlist file.
+ * Constant for the {@link #MEDIA_TYPE} column indicating that file
+ * is a playlist file.
*/
public static final int MEDIA_TYPE_PLAYLIST = 4;
/**
+ * Constant for the {@link #MEDIA_TYPE} column indicating that file
+ * is a subtitles or lyrics file.
+ */
+ public static final int MEDIA_TYPE_SUBTITLE = 5;
+
+ /**
* Column indicating if the file is part of Downloads collection.
* @hide
*/
@@ -3603,6 +3617,43 @@ public final class MediaStore {
}
/**
+ * Return list of all specific volume names that have recently been part of
+ * {@link #VOLUME_EXTERNAL}.
+ * <p>
+ * This includes both currently mounted volumes <em>and</em> recently
+ * mounted (but currently unmounted) volumes. Any indexed metadata for these
+ * volumes is preserved to optimize the speed of remounting at a later time.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.WRITE_MEDIA_STORAGE)
+ public static @NonNull Set<String> getRecentExternalVolumeNames(@NonNull Context context) {
+ final StorageManager sm = context.getSystemService(StorageManager.class);
+
+ // We always have primary storage
+ final Set<String> volumeNames = new ArraySet<>();
+ volumeNames.add(VOLUME_EXTERNAL_PRIMARY);
+
+ final long lastWeek = System.currentTimeMillis() - DateUtils.WEEK_IN_MILLIS;
+ for (VolumeRecord rec : sm.getVolumeRecords()) {
+ // Skip volumes without valid UUIDs
+ if (TextUtils.isEmpty(rec.fsUuid)) continue;
+
+ final VolumeInfo vi = sm.findVolumeByUuid(rec.fsUuid);
+ if (vi != null && vi.isVisibleForUser(UserHandle.myUserId())
+ && vi.isMountedReadable()) {
+ // We're mounted right now
+ volumeNames.add(rec.getNormalizedFsUuid());
+ } else if (rec.lastSeenMillis > 0 && rec.lastSeenMillis < lastWeek) {
+ // We're not mounted right now, but we've been seen recently
+ volumeNames.add(rec.getNormalizedFsUuid());
+ }
+ }
+ return volumeNames;
+ }
+
+ /**
* Return the volume name that the given {@link Uri} references.
*/
public static @NonNull String getVolumeName(@NonNull Uri uri) {
@@ -3701,6 +3752,8 @@ public final class MediaStore {
* @hide
*/
@TestApi
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.WRITE_MEDIA_STORAGE)
public static @NonNull Collection<File> getVolumeScanPaths(@NonNull String volumeName)
throws FileNotFoundException {
if (TextUtils.isEmpty(volumeName)) {
@@ -3929,6 +3982,16 @@ public final class MediaStore {
}
/** @hide */
+ public static void suicide(Context context) {
+ final ContentResolver resolver = context.getContentResolver();
+ try (ContentProviderClient client = resolver
+ .acquireUnstableContentProviderClient(AUTHORITY)) {
+ client.call(SUICIDE_CALL, null, null);
+ } catch (Exception ignored) {
+ }
+ }
+
+ /** @hide */
@TestApi
public static Uri scanFile(Context context, File file) {
return scan(context, SCAN_FILE_CALL, file, false);
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index 22f90f62b114..70c8e5d311bd 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -4837,4 +4837,23 @@ public final class Telephony {
public static final Uri CONTENT_URI = Uri.parse("content://carrier_id/all");
}
}
+
+ /**
+ * Contains SIM Information
+ * @hide
+ */
+ @SystemApi
+ public static final class SimInfo {
+ /**
+ * Not instantiable.
+ * @hide
+ */
+ private SimInfo() {}
+
+ /**
+ * The {@code content://} style URI for this provider.
+ */
+ @NonNull
+ public static final Uri CONTENT_URI = Uri.parse("content://telephony/siminfo");
+ }
}
diff --git a/telephony/java/android/telephony/SubscriptionPlan.aidl b/core/java/android/telephony/SubscriptionPlan.aidl
index 655df3a71b3d..655df3a71b3d 100755
--- a/telephony/java/android/telephony/SubscriptionPlan.aidl
+++ b/core/java/android/telephony/SubscriptionPlan.aidl
diff --git a/telephony/java/android/telephony/SubscriptionPlan.java b/core/java/android/telephony/SubscriptionPlan.java
index 28a5c2086ede..28a5c2086ede 100644
--- a/telephony/java/android/telephony/SubscriptionPlan.java
+++ b/core/java/android/telephony/SubscriptionPlan.java
diff --git a/core/java/android/util/StatsEvent.java b/core/java/android/util/StatsEvent.java
index 0a4069d15706..7e7164042781 100644
--- a/core/java/android/util/StatsEvent.java
+++ b/core/java/android/util/StatsEvent.java
@@ -20,8 +20,6 @@ import static java.nio.charset.StandardCharsets.UTF_8;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
import android.os.SystemClock;
import com.android.internal.annotations.GuardedBy;
@@ -44,7 +42,7 @@ import com.android.internal.annotations.VisibleForTesting;
* </pre>
* @hide
**/
-public final class StatsEvent implements Parcelable {
+public final class StatsEvent {
// Type Ids.
/**
* @hide
@@ -265,39 +263,6 @@ public final class StatsEvent implements Parcelable {
}
/**
- * Boilerplate for Parcel.
- */
- public static final @NonNull Parcelable.Creator<StatsEvent> CREATOR =
- new Parcelable.Creator<StatsEvent>() {
- public StatsEvent createFromParcel(Parcel in) {
- // Purposefully leaving this method not implemented.
- throw new RuntimeException("Not implemented");
- }
-
- public StatsEvent[] newArray(int size) {
- // Purposefully leaving this method not implemented.
- throw new RuntimeException("Not implemented");
- }
- };
-
- /**
- * Boilerplate for Parcel.
- */
- public void writeToParcel(Parcel out, int flags) {
- out.writeInt(mAtomId);
- out.writeInt(getNumBytes());
- out.writeByteArray(getBytes());
- }
-
- /**
- * Boilerplate for Parcel.
- */
- public int describeContents() {
- return 0;
- }
-
-
- /**
* Builder for constructing a StatsEvent object.
*
* <p>This class defines and encapsulates the socket encoding for the buffer.
diff --git a/core/java/android/util/StatsLog.java b/core/java/android/util/StatsLog.java
index 64e15cfb7948..8cb5b05df685 100644
--- a/core/java/android/util/StatsLog.java
+++ b/core/java/android/util/StatsLog.java
@@ -179,6 +179,8 @@ public final class StatsLog extends StatsLogInternal {
* @param rollbackType state of the rollback.
* @param packageName package name being rolled back.
* @param packageVersionCode version of the package being rolled back.
+ * @param rollbackReason reason the package is being rolled back.
+ * @param failingPackageName the package name causing the failure.
*
* @return True if the log request was sent to statsd.
*
@@ -186,7 +188,7 @@ public final class StatsLog extends StatsLogInternal {
*/
@RequiresPermission(allOf = {DUMP, PACKAGE_USAGE_STATS})
public static boolean logWatchdogRollbackOccurred(int rollbackType, String packageName,
- long packageVersionCode) {
+ long packageVersionCode, int rollbackReason, String failingPackageName) {
synchronized (sLogLock) {
try {
IStatsManager service = getIStatsManagerLocked();
@@ -198,7 +200,7 @@ public final class StatsLog extends StatsLogInternal {
}
service.sendWatchdogRollbackOccurredAtom(rollbackType, packageName,
- packageVersionCode);
+ packageVersionCode, rollbackReason, failingPackageName);
return true;
} catch (RemoteException e) {
sService = null;
diff --git a/core/java/android/view/DisplayAddress.java b/core/java/android/view/DisplayAddress.java
index c8b7e25e59fb..e0d9a4dd1df0 100644
--- a/core/java/android/view/DisplayAddress.java
+++ b/core/java/android/view/DisplayAddress.java
@@ -41,6 +41,18 @@ public abstract class DisplayAddress implements Parcelable {
}
/**
+ * Creates an address for a physical display given its port and model.
+ *
+ * @param port A port in the range [0, 255] interpreted as signed.
+ * @param model A positive integer, or {@code null} if the model cannot be identified.
+ * @return The {@link Physical} address.
+ */
+ @NonNull
+ public static Physical fromPortAndModel(byte port, Long model) {
+ return new Physical(port, model);
+ }
+
+ /**
* Creates an address for a network display given its MAC address.
*
* @param macAddress A MAC address in colon notation.
@@ -64,12 +76,23 @@ public abstract class DisplayAddress implements Parcelable {
public static final class Physical extends DisplayAddress {
private static final long UNKNOWN_MODEL = 0;
private static final int MODEL_SHIFT = 8;
- private static final int PORT_MASK = 0xFF;
private final long mPhysicalDisplayId;
/**
+ * Stable display ID combining port and model.
+ *
+ * @return An ID in the range [0, 2^64) interpreted as signed.
+ * @see SurfaceControl#getPhysicalDisplayIds
+ */
+ public long getPhysicalDisplayId() {
+ return mPhysicalDisplayId;
+ }
+
+ /**
* Physical port to which the display is connected.
+ *
+ * @return A port in the range [0, 255] interpreted as signed.
*/
public byte getPort() {
return (byte) mPhysicalDisplayId;
@@ -78,7 +101,7 @@ public abstract class DisplayAddress implements Parcelable {
/**
* Model identifier unique across manufacturers.
*
- * @return The model ID, or {@code null} if the model cannot be identified.
+ * @return A positive integer, or {@code null} if the model cannot be identified.
*/
@Nullable
public Long getModel() {
@@ -95,7 +118,7 @@ public abstract class DisplayAddress implements Parcelable {
@Override
public String toString() {
final StringBuilder builder = new StringBuilder("{")
- .append("port=").append(getPort() & PORT_MASK);
+ .append("port=").append(Byte.toUnsignedInt(getPort()));
final Long model = getModel();
if (model != null) {
@@ -119,6 +142,11 @@ public abstract class DisplayAddress implements Parcelable {
mPhysicalDisplayId = physicalDisplayId;
}
+ private Physical(byte port, Long model) {
+ mPhysicalDisplayId = Byte.toUnsignedLong(port)
+ | (model == null ? UNKNOWN_MODEL : (model << MODEL_SHIFT));
+ }
+
public static final @NonNull Parcelable.Creator<Physical> CREATOR =
new Parcelable.Creator<Physical>() {
@Override
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index afa661e26d4c..3171306fc568 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1646,7 +1646,7 @@ public final class ViewRootImpl implements ViewParent,
mBlastSurfaceControl, width, height);
}
- mBlastBufferQueue.update(mSurfaceControl, width, height);
+ mBlastBufferQueue.update(mBlastSurfaceControl, width, height);
mTransaction.show(mBlastSurfaceControl)
.reparent(mBlastSurfaceControl, mSurfaceControl)
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index c571737cec8f..7cec440dd80b 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -3473,18 +3473,10 @@ public class RemoteViews implements Parcelable, Filter {
return applyAsync(context, parent, executor, listener, null);
}
- private CancellationSignal startTaskOnExecutor(AsyncApplyTask task, Executor executor) {
- CancellationSignal cancelSignal = new CancellationSignal();
- cancelSignal.setOnCancelListener(task);
-
- task.executeOnExecutor(executor == null ? AsyncTask.THREAD_POOL_EXECUTOR : executor);
- return cancelSignal;
- }
-
/** @hide */
public CancellationSignal applyAsync(Context context, ViewGroup parent,
Executor executor, OnViewAppliedListener listener, OnClickHandler handler) {
- return startTaskOnExecutor(getAsyncApplyTask(context, parent, listener, handler), executor);
+ return getAsyncApplyTask(context, parent, listener, handler).startTaskOnExecutor(executor);
}
private AsyncApplyTask getAsyncApplyTask(Context context, ViewGroup parent,
@@ -3495,6 +3487,7 @@ public class RemoteViews implements Parcelable, Filter {
private class AsyncApplyTask extends AsyncTask<Void, Void, ViewTree>
implements CancellationSignal.OnCancelListener {
+ final CancellationSignal mCancelSignal = new CancellationSignal();
final RemoteViews mRV;
final ViewGroup mParent;
final Context mContext;
@@ -3545,6 +3538,7 @@ public class RemoteViews implements Parcelable, Filter {
@Override
protected void onPostExecute(ViewTree viewTree) {
+ mCancelSignal.setOnCancelListener(null);
if (mError == null) {
if (mListener != null) {
mListener.onViewInflated(viewTree.mRoot);
@@ -3581,6 +3575,13 @@ public class RemoteViews implements Parcelable, Filter {
@Override
public void onCancel() {
cancel(true);
+ mCancelSignal.setOnCancelListener(null);
+ }
+
+ private CancellationSignal startTaskOnExecutor(Executor executor) {
+ mCancelSignal.setOnCancelListener(this);
+ executeOnExecutor(executor == null ? AsyncTask.THREAD_POOL_EXECUTOR : executor);
+ return mCancelSignal;
}
}
@@ -3646,8 +3647,8 @@ public class RemoteViews implements Parcelable, Filter {
}
}
- return startTaskOnExecutor(new AsyncApplyTask(rvToApply, (ViewGroup) v.getParent(),
- context, listener, handler, v), executor);
+ return new AsyncApplyTask(rvToApply, (ViewGroup) v.getParent(),
+ context, listener, handler, v).startTaskOnExecutor(executor);
}
private void performApply(View v, ViewGroup parent, OnClickHandler handler) {
diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java
index fd3cd42b07a1..a21187165c65 100644
--- a/core/java/com/android/internal/os/RuntimeInit.java
+++ b/core/java/com/android/internal/os/RuntimeInit.java
@@ -30,8 +30,10 @@ import android.os.SystemProperties;
import android.os.Trace;
import android.util.Log;
import android.util.Slog;
+
import com.android.internal.logging.AndroidConfig;
import com.android.server.NetworkManagementSocketTagger;
+
import dalvik.system.RuntimeHooks;
import dalvik.system.VMRuntime;
@@ -374,9 +376,6 @@ public class RuntimeInit {
// leftover running threads to crash before the process actually exits.
nativeSetExitWithoutCleanup(true);
- // We want to be fairly aggressive about heap utilization, to avoid
- // holding on to a lot of memory that isn't needed.
- VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
final Arguments args = new Arguments(argv);
diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl
index 897b982406dc..13cc98be5d5a 100644
--- a/core/java/com/android/internal/widget/ILockSettings.aidl
+++ b/core/java/com/android/internal/widget/ILockSettings.aidl
@@ -43,7 +43,7 @@ interface ILockSettings {
long getLong(in String key, in long defaultValue, in int userId);
@UnsupportedAppUsage
String getString(in String key, in String defaultValue, in int userId);
- boolean setLockCredential(in LockscreenCredential credential, in LockscreenCredential savedCredential, int userId, boolean allowUntrustedChange);
+ boolean setLockCredential(in LockscreenCredential credential, in LockscreenCredential savedCredential, int userId);
void resetKeyStore(int userId);
VerifyCredentialResponse checkCredential(in LockscreenCredential credential, int userId,
in ICheckCredentialProgressCallback progressCallback);
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index b534213ec859..cff39f120dd7 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -636,35 +636,16 @@ public class LockPatternUtils {
*
* @param newCredential The new credential to save
* @param savedCredential The current credential
- * @param userId the user whose lockscreen credential is to be changed
- *
- * @return whether this method saved the new password successfully or not. This flow will fail
- * and return false if the given credential is wrong.
- * @throws RuntimeException if password change encountered an unrecoverable error.
- */
- public boolean setLockCredential(@NonNull LockscreenCredential newCredential,
- @NonNull LockscreenCredential savedCredential, int userId) {
- return setLockCredential(newCredential, savedCredential, userId, false);
- }
-
- /**
- * Save a new lockscreen credential.
- * <p> This method will fail (returning {@code false}) if the previously saved pattern provided
- * is incorrect and allowUntrustedChange is false, or if the lockscreen verification is still
- * being throttled.
- * @param newCredential The new credential to save
- * @param savedCredential The current credential
* @param userHandle the user whose lockscreen credential is to be changed
- * @param allowUntrustedChange whether we want to allow saving a new pattern if the existing
- * credentialt being provided is incorrect.
*
* @return whether this method saved the new password successfully or not. This flow will fail
- * and return false if the given credential is wrong and allowUntrustedChange is false.
+ * and return false if the given credential is wrong.
* @throws RuntimeException if password change encountered an unrecoverable error.
+ * @throws UnsupportedOperationException secure lockscreen is not supported on this device.
+ * @throws IllegalArgumentException if new credential is too short.
*/
public boolean setLockCredential(@NonNull LockscreenCredential newCredential,
- @NonNull LockscreenCredential savedCredential, int userHandle,
- boolean allowUntrustedChange) {
+ @NonNull LockscreenCredential savedCredential, int userHandle) {
if (!hasSecureLockScreen()) {
throw new UnsupportedOperationException(
"This operation requires the lock screen feature.");
@@ -672,8 +653,7 @@ public class LockPatternUtils {
newCredential.checkLength();
try {
- if (!getLockSettings().setLockCredential(
- newCredential, savedCredential, userHandle, allowUntrustedChange)) {
+ if (!getLockSettings().setLockCredential(newCredential, savedCredential, userHandle)) {
return false;
}
} catch (RemoteException e) {
diff --git a/core/java/com/android/server/BootReceiver.java b/core/java/com/android/server/BootReceiver.java
index dc4f09a2af6f..13bfc1bf72b8 100644
--- a/core/java/com/android/server/BootReceiver.java
+++ b/core/java/com/android/server/BootReceiver.java
@@ -66,10 +66,15 @@ import org.xmlpull.v1.XmlSerializer;
public class BootReceiver extends BroadcastReceiver {
private static final String TAG = "BootReceiver";
+ private static final String TAG_TRUNCATED = "[[TRUNCATED]]\n";
+
// Maximum size of a logged event (files get truncated if they're longer).
// Give userdebug builds a larger max to capture extra debug, esp. for last_kmsg.
private static final int LOG_SIZE =
SystemProperties.getInt("ro.debuggable", 0) == 1 ? 98304 : 65536;
+ private static final int LASTK_LOG_SIZE =
+ SystemProperties.getInt("ro.debuggable", 0) == 1 ? 196608 : 65536;
+ private static final int GMSCORE_LASTK_LOG_SIZE = 196608;
private static final File TOMBSTONE_DIR = new File("/data/tombstones");
private static final String TAG_TOMBSTONE = "SYSTEM_TOMBSTONE";
@@ -224,12 +229,12 @@ public class BootReceiver extends BroadcastReceiver {
if (db != null) db.addText("SYSTEM_BOOT", headers);
// Negative sizes mean to take the *tail* of the file (see FileUtils.readTextFile())
- addFileWithFootersToDropBox(db, timestamps, headers, lastKmsgFooter,
- "/proc/last_kmsg", -LOG_SIZE, "SYSTEM_LAST_KMSG");
- addFileWithFootersToDropBox(db, timestamps, headers, lastKmsgFooter,
- "/sys/fs/pstore/console-ramoops", -LOG_SIZE, "SYSTEM_LAST_KMSG");
- addFileWithFootersToDropBox(db, timestamps, headers, lastKmsgFooter,
- "/sys/fs/pstore/console-ramoops-0", -LOG_SIZE, "SYSTEM_LAST_KMSG");
+ addLastkToDropBox(db, timestamps, headers, lastKmsgFooter,
+ "/proc/last_kmsg", -LASTK_LOG_SIZE, "SYSTEM_LAST_KMSG");
+ addLastkToDropBox(db, timestamps, headers, lastKmsgFooter,
+ "/sys/fs/pstore/console-ramoops", -LASTK_LOG_SIZE, "SYSTEM_LAST_KMSG");
+ addLastkToDropBox(db, timestamps, headers, lastKmsgFooter,
+ "/sys/fs/pstore/console-ramoops-0", -LASTK_LOG_SIZE, "SYSTEM_LAST_KMSG");
addFileToDropBox(db, timestamps, headers, "/cache/recovery/log", -LOG_SIZE,
"SYSTEM_RECOVERY_LOG");
addFileToDropBox(db, timestamps, headers, "/cache/recovery/last_kmsg",
@@ -278,6 +283,23 @@ public class BootReceiver extends BroadcastReceiver {
sTombstoneObserver.startWatching();
}
+ private static void addLastkToDropBox(
+ DropBoxManager db, HashMap<String, Long> timestamps,
+ String headers, String footers, String filename, int maxSize,
+ String tag) throws IOException {
+ int extraSize = headers.length() + TAG_TRUNCATED.length() + footers.length();
+ // GMSCore will do 2nd truncation to be 192KiB
+ // LASTK_LOG_SIZE + extraSize must be less than GMSCORE_LASTK_LOG_SIZE
+ if (LASTK_LOG_SIZE + extraSize > GMSCORE_LASTK_LOG_SIZE) {
+ if (GMSCORE_LASTK_LOG_SIZE > extraSize) {
+ maxSize = -(GMSCORE_LASTK_LOG_SIZE - extraSize);
+ } else {
+ maxSize = 0;
+ }
+ }
+ addFileWithFootersToDropBox(db, timestamps, headers, footers, filename, maxSize, tag);
+ }
+
private static void addFileToDropBox(
DropBoxManager db, HashMap<String, Long> timestamps,
String headers, String filename, int maxSize, String tag) throws IOException {
@@ -301,7 +323,7 @@ public class BootReceiver extends BroadcastReceiver {
timestamps.put(filename, fileTime);
- String fileContents = FileUtils.readTextFile(file, maxSize, "[[TRUNCATED]]\n");
+ String fileContents = FileUtils.readTextFile(file, maxSize, TAG_TRUNCATED);
String text = headers + fileContents + footers;
// Create an additional report for system server native crashes, with a special tag.
if (tag.equals(TAG_TOMBSTONE) && fileContents.contains(">>> system_server <<<")) {
@@ -345,7 +367,7 @@ public class BootReceiver extends BroadcastReceiver {
timestamps.put(tag, fileTime);
- String log = FileUtils.readTextFile(file, maxSize, "[[TRUNCATED]]\n");
+ String log = FileUtils.readTextFile(file, maxSize, TAG_TRUNCATED);
StringBuilder sb = new StringBuilder();
for (String line : log.split("\n")) {
if (line.contains("audit")) {
@@ -370,7 +392,7 @@ public class BootReceiver extends BroadcastReceiver {
long fileTime = file.lastModified();
if (fileTime <= 0) return; // File does not exist
- String log = FileUtils.readTextFile(file, maxSize, "[[TRUNCATED]]\n");
+ String log = FileUtils.readTextFile(file, maxSize, TAG_TRUNCATED);
Pattern pattern = Pattern.compile(FS_STAT_PATTERN);
String lines[] = log.split("\n");
int lineNumber = 0;
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 378e125a3a3e..97451a2c4cfd 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -648,6 +648,7 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote, bool p
char methodTraceFileSizeBuf[sizeof("-Xmethod-trace-file-size:") + PROPERTY_VALUE_MAX];
std::string fingerprintBuf;
char jdwpProviderBuf[sizeof("-XjdwpProvider:") - 1 + PROPERTY_VALUE_MAX];
+ char opaqueJniIds[sizeof("-Xopaque-jni-ids:") - 1 + PROPERTY_VALUE_MAX];
char bootImageBuf[sizeof("-Ximage:") - 1 + PROPERTY_VALUE_MAX];
// Read if we are using the profile configuration, do this at the start since the last ART args
@@ -839,6 +840,14 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote, bool p
"default");
}
+ // Only pass an explicit opaque-jni-ids to apps forked from zygote
+ if (zygote) {
+ parseRuntimeOption("dalvik.vm.opaque-jni-ids",
+ opaqueJniIds,
+ "-Xopaque-jni-ids:",
+ "swapable");
+ }
+
parseRuntimeOption("dalvik.vm.lockprof.threshold",
lockProfThresholdBuf,
"-Xlockprofthreshold:");
diff --git a/core/jni/android_content_res_ApkAssets.cpp b/core/jni/android_content_res_ApkAssets.cpp
index f3a626e1e193..5d13cf82141b 100644
--- a/core/jni/android_content_res_ApkAssets.cpp
+++ b/core/jni/android_content_res_ApkAssets.cpp
@@ -32,6 +32,11 @@ using ::android::base::unique_fd;
namespace android {
+static struct overlayableinfo_offsets_t {
+ jclass classObject;
+ jmethodID constructor;
+} gOverlayableInfoOffsets;
+
static jlong NativeLoad(JNIEnv* env, jclass /*clazz*/, jstring java_path, jboolean system,
jboolean force_shared_lib, jboolean overlay, jboolean for_loader) {
ScopedUtfChars path(env, java_path);
@@ -222,12 +227,9 @@ static jobject NativeGetOverlayableInfo(JNIEnv* env, jclass /*clazz*/, jlong ptr
return 0;
}
- jclass overlayable_class = env->FindClass("android/content/om/OverlayableInfo");
- jmethodID overlayable_constructor = env->GetMethodID(overlayable_class, "<init>",
- "(Ljava/lang/String;Ljava/lang/String;I)V");
return env->NewObject(
- overlayable_class,
- overlayable_constructor,
+ gOverlayableInfoOffsets.classObject,
+ gOverlayableInfoOffsets.constructor,
overlayable_name,
actor_string
);
@@ -267,6 +269,11 @@ static const JNINativeMethod gApkAssetsMethods[] = {
};
int register_android_content_res_ApkAssets(JNIEnv* env) {
+ jclass overlayableInfoClass = FindClassOrDie(env, "android/content/om/OverlayableInfo");
+ gOverlayableInfoOffsets.classObject = MakeGlobalRefOrDie(env, overlayableInfoClass);
+ gOverlayableInfoOffsets.constructor = GetMethodIDOrDie(env, gOverlayableInfoOffsets.classObject,
+ "<init>", "(Ljava/lang/String;Ljava/lang/String;)V");
+
return RegisterMethodsOrDie(env, "android/content/res/ApkAssets", gApkAssetsMethods,
arraysize(gApkAssetsMethods));
}
diff --git a/core/proto/android/service/notification.proto b/core/proto/android/service/notification.proto
index 1ec05fb5e9fc..ecb4193a2c6c 100644
--- a/core/proto/android/service/notification.proto
+++ b/core/proto/android/service/notification.proto
@@ -264,3 +264,14 @@ message ZenPolicyProto {
optional Sender priority_calls = 16;
optional Sender priority_messages = 17;
}
+
+// Next Tag: 2
+message PackageRemoteViewInfoProto {
+ optional string package_name = 1;
+ // add per-package additional info here (like channels)
+}
+
+// Next Tag: 2
+message NotificationRemoteViewsProto {
+ repeated PackageRemoteViewInfoProto package_remote_view_info = 1;
+} \ No newline at end of file
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 307d754a1ad8..bfbd959df1a8 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2851,9 +2851,6 @@
<!-- String array containing numbers that shouldn't be logged. Country-specific. -->
<string-array name="unloggable_phone_numbers" />
- <!-- Flag specifying whether or not IMS will use the dynamic ImsResolver -->
- <bool name="config_dynamic_bind_ims">false</bool>
-
<!-- Cellular data service package name to bind to by default. If none is specified in an overlay, an
empty string is passed in -->
<string name="config_wwan_data_service_package" translatable="false">com.android.phone</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 083f33cc8035..ee9287c7d64c 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -294,7 +294,6 @@
<java-symbol type="bool" name="config_hotswapCapable" />
<java-symbol type="bool" name="config_mms_content_disposition_support" />
<java-symbol type="string" name="config_ims_package" />
- <java-symbol type="bool" name="config_dynamic_bind_ims" />
<java-symbol type="string" name="config_wwan_network_service_package" />
<java-symbol type="string" name="config_wlan_network_service_package" />
<java-symbol type="string" name="config_wwan_network_service_class" />
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index 0c52029b93f8..cef21db1e0f8 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -1735,6 +1735,7 @@ easier.
<item name="colorBackground">@color/background_device_default_light</item>
<item name="colorBackgroundFloating">@color/background_device_default_light</item>
<item name="layout_gravity">center</item>
+ <item name="windowAnimationStyle">@style/Animation.DeviceDefault.Dialog</item>
</style>
<style name="Theme.DeviceDefault.Notification" parent="@style/Theme.Material.Notification">
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index cf3f51d6599a..322cbd798203 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -204,7 +204,7 @@ applications that come with the platform
<permission name="android.permission.UPDATE_DEVICE_STATS"/>
</privapp-permissions>
- <privapp-permissions package="com.android.providers.media">
+ <privapp-permissions package="com.android.providers.media.module">
<permission name="android.permission.INTERACT_ACROSS_USERS"/>
<permission name="android.permission.MANAGE_USERS"/>
<permission name="android.permission.USE_RESERVED_DISK"/>
@@ -369,4 +369,7 @@ applications that come with the platform
<permission name="android.permission.REBOOT"/>
<permission name="android.permission.MANAGE_DYNAMIC_SYSTEM"/>
</privapp-permissions>
+ <privapp-permissions package="com.android.settings">
+ <permission name="android.permission.INSTALL_DYNAMIC_SYSTEM"/>
+ </privapp-permissions>
</permissions>
diff --git a/data/sounds/AudioPackageGo.mk b/data/sounds/AudioPackageGo.mk
index e3b27f2cd962..e3fb45f6f055 100644
--- a/data/sounds/AudioPackageGo.mk
+++ b/data/sounds/AudioPackageGo.mk
@@ -47,3 +47,7 @@ PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/effects/ogg/KeypressDelete.ogg:$(TARGET_COPY_OUT_PRODUCT)/media/audio/ui/KeypressDelete.ogg \
$(LOCAL_PATH)/effects/ogg/KeypressInvalid.ogg:$(TARGET_COPY_OUT_PRODUCT)/media/audio/ui/KeypressInvalid.ogg \
$(LOCAL_PATH)/effects/ogg/KeypressReturn.ogg:$(TARGET_COPY_OUT_PRODUCT)/media/audio/ui/KeypressReturn.ogg \
+ $(LOCAL_PATH)/effects/ogg/Lock.ogg:$(TARGET_COPY_OUT_PRODUCT)/media/audio/ui/Lock.ogg \
+ $(LOCAL_PATH)/effects/ogg/Unlock.ogg:$(TARGET_COPY_OUT_PRODUCT)/media/audio/ui/Unlock.ogg \
+ $(LOCAL_PATH)/effects/ogg/Trusted_48k.ogg:$(TARGET_COPY_OUT_PRODUCT)/media/audio/ui/Trusted.ogg \
+
diff --git a/drm/java/android/drm/DrmManagerClient.java b/drm/java/android/drm/DrmManagerClient.java
index fcebad339f2b..041300c4b1b0 100644
--- a/drm/java/android/drm/DrmManagerClient.java
+++ b/drm/java/android/drm/DrmManagerClient.java
@@ -16,6 +16,7 @@
package android.drm;
+import android.annotation.NonNull;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
@@ -37,6 +38,8 @@ import java.io.FileInputStream;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
import java.util.HashMap;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -370,6 +373,17 @@ public class DrmManagerClient implements AutoCloseable {
}
/**
+ * Retrieves information about all the DRM plug-ins (agents) that are
+ * registered with the DRM framework.
+ *
+ * @return List of all the DRM plug-ins (agents) that are registered with
+ * the DRM framework.
+ */
+ public @NonNull Collection<DrmSupportInfo> getAvailableDrmSupportInfo() {
+ return Arrays.asList(_getAllSupportInfo(mUniqueId));
+ }
+
+ /**
* Retrieves constraint information for rights-protected content.
*
* @param path Path to the content from which you are retrieving DRM constraints.
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index c0041722c475..1f8c1d5352b0 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -164,25 +164,52 @@ public class LocationManager {
* Broadcast intent action when the set of enabled location providers changes. To check the
* status of a provider, use {@link #isProviderEnabled(String)}. From Android Q and above, will
* include a string intent extra, {@link #EXTRA_PROVIDER_NAME}, with the name of the provider
- * whose state has changed.
+ * whose state has changed. From Android R and above, will include a boolean intent extra,
+ * {@link #EXTRA_PROVIDER_ENABLED}, with the enabled state of the provider.
*
* @see #EXTRA_PROVIDER_NAME
+ * @see #EXTRA_PROVIDER_ENABLED
+ * @see #isProviderEnabled(String)
*/
public static final String PROVIDERS_CHANGED_ACTION = "android.location.PROVIDERS_CHANGED";
/**
* Intent extra included with {@link #PROVIDERS_CHANGED_ACTION} broadcasts, containing the name
- * of the location provider that has changed, to be used with location provider APIs.
+ * of the location provider that has changed.
+ *
+ * @see #PROVIDERS_CHANGED_ACTION
+ * @see #EXTRA_PROVIDER_ENABLED
*/
public static final String EXTRA_PROVIDER_NAME = "android.location.extra.PROVIDER_NAME";
/**
- * Broadcast intent action when the device location mode changes. To check the location mode,
- * use {@link #isLocationEnabled()}.
+ * Intent extra included with {@link #PROVIDERS_CHANGED_ACTION} broadcasts, containing the
+ * boolean enabled state of the location provider that has changed.
+ *
+ * @see #PROVIDERS_CHANGED_ACTION
+ * @see #EXTRA_PROVIDER_NAME
+ */
+ public static final String EXTRA_PROVIDER_ENABLED = "android.location.extra.PROVIDER_ENABLED";
+
+ /**
+ * Broadcast intent action when the device location enabled state changes. From Android R and
+ * above, will include a boolean intent extra, {@link #EXTRA_LOCATION_ENABLED}, with the enabled
+ * state of location.
+ *
+ * @see #EXTRA_LOCATION_ENABLED
+ * @see #isLocationEnabled()
*/
public static final String MODE_CHANGED_ACTION = "android.location.MODE_CHANGED";
/**
+ * Intent extra included with {@link #MODE_CHANGED_ACTION} broadcasts, containing the boolean
+ * enabled state of location.
+ *
+ * @see #MODE_CHANGED_ACTION
+ */
+ public static final String EXTRA_LOCATION_ENABLED = "android.location.extra.LOCATION_ENABLED";
+
+ /**
* Broadcast intent action indicating that a high power location requests
* has either started or stopped being active. The current state of
* active location requests should be read from AppOpsManager using
diff --git a/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java b/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
index c20dc615529b..751bb6a70880 100644
--- a/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
+++ b/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
@@ -103,10 +103,6 @@ public class GnssMetrics {
mPositionAccuracyMeterStatistics = new Statistics();
mTopFourAverageCn0Statistics = new Statistics();
mTopFourAverageCn0StatisticsL5 = new Statistics();
- mNumSvStatus = 0;
- mNumL5SvStatus = 0;
- mNumSvStatusUsedInFix = 0;
- mNumL5SvStatusUsedInFix = 0;
reset();
}
@@ -410,6 +406,11 @@ public class GnssMetrics {
mPositionAccuracyMeterStatistics.reset();
mTopFourAverageCn0Statistics.reset();
resetConstellationTypes();
+ mTopFourAverageCn0StatisticsL5.reset();
+ mNumSvStatus = 0;
+ mNumL5SvStatus = 0;
+ mNumSvStatusUsedInFix = 0;
+ mNumL5SvStatusUsedInFix = 0;
}
/** Resets {@link #mConstellationTypes} as an all-false boolean array. */
diff --git a/media/java/android/media/MediaScannerConnection.java b/media/java/android/media/MediaScannerConnection.java
index 8d857243bc05..515f6a8ce8a2 100644
--- a/media/java/android/media/MediaScannerConnection.java
+++ b/media/java/android/media/MediaScannerConnection.java
@@ -164,7 +164,7 @@ public class MediaScannerConnection implements ServiceConnection {
/**
* Convenience for constructing a {@link MediaScannerConnection}, calling
- * {@link #connect} on it, and calling {@link #scanFile} with the given
+ * {@link #connect} on it, and calling {@link #scanFile(String, String)} with the given
* <var>path</var> and <var>mimeType</var> when the connection is
* established.
* @param context The caller's Context, required for establishing a connection to
diff --git a/media/java/android/media/tv/tuner/FilterSettings.java b/media/java/android/media/tv/tuner/FilterSettings.java
new file mode 100644
index 000000000000..d5f100341dc6
--- /dev/null
+++ b/media/java/android/media/tv/tuner/FilterSettings.java
@@ -0,0 +1,383 @@
+/*
+ * Copyright 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.media.tv.tuner;
+
+import android.annotation.Nullable;
+import android.hardware.tv.tuner.V1_0.Constants;
+import android.media.tv.tuner.TunerConstants.FilterSettingsType;
+
+import java.util.List;
+
+/**
+ * Demux Filter settings.
+ *
+ * @hide
+ */
+public abstract class FilterSettings {
+ @Nullable
+ protected final Settings mSettings;
+
+ protected FilterSettings(Settings settings) {
+ mSettings = settings;
+ }
+
+ /**
+ * Gets filter settings type
+ */
+ @FilterSettingsType public abstract int getType();
+
+ // TODO: more builders and getters
+
+ /**
+ * Filter Settings for a TS filter.
+ */
+ public static class TsFilterSettings extends FilterSettings {
+ private int mTpid;
+
+ private TsFilterSettings(Settings settings, int tpid) {
+ super(settings);
+ mTpid = tpid;
+ }
+
+ @Override
+ public int getType() {
+ return TunerConstants.FILTER_SETTINGS_TS;
+ }
+
+ /**
+ * Creates a new builder.
+ */
+ public static Builder newBuilder() {
+ return new Builder();
+ }
+
+ /**
+ * Builder for TsFilterSettings.
+ */
+ public static class Builder {
+ private Settings mSettings;
+ private int mTpid;
+
+ /**
+ * Sets settings.
+ */
+ public Builder setSettings(Settings settings) {
+ mSettings = settings;
+ return this;
+ }
+
+ /**
+ * Sets TPID.
+ */
+ public Builder setTpid(int tpid) {
+ mTpid = tpid;
+ return this;
+ }
+
+ /**
+ * Builds a TsFilterSettings instance.
+ */
+ public TsFilterSettings build() {
+ return new TsFilterSettings(mSettings, mTpid);
+ }
+ }
+ }
+
+ /**
+ * Filter Settings for a MMTP filter.
+ */
+ public static class MmtpFilterSettings extends FilterSettings {
+ private int mMmtpPid;
+
+ public MmtpFilterSettings(Settings settings) {
+ super(settings);
+ }
+
+ @Override
+ public int getType() {
+ return TunerConstants.FILTER_SETTINGS_MMTP;
+ }
+ }
+
+
+ /**
+ * Filter Settings for a IP filter.
+ */
+ public static class IpFilterSettings extends FilterSettings {
+ private byte[] mSrcIpAddress;
+ private byte[] mDstIpAddress;
+ private int mSrcPort;
+ private int mDstPort;
+ private boolean mPassthrough;
+
+ public IpFilterSettings(Settings settings) {
+ super(settings);
+ }
+
+ @Override
+ public int getType() {
+ return TunerConstants.FILTER_SETTINGS_IP;
+ }
+ }
+
+
+ /**
+ * Filter Settings for a TLV filter.
+ */
+ public static class TlvFilterSettings extends FilterSettings {
+ private int mPacketType;
+ private boolean mIsCompressedIpPacket;
+ private boolean mPassthrough;
+
+ public TlvFilterSettings(Settings settings) {
+ super(settings);
+ }
+
+ @Override
+ public int getType() {
+ return TunerConstants.FILTER_SETTINGS_TLV;
+ }
+ }
+
+
+ /**
+ * Filter Settings for a ALP filter.
+ */
+ public static class AlpFilterSettings extends FilterSettings {
+ private int mPacketType;
+ private int mLengthType;
+
+ public AlpFilterSettings(Settings settings) {
+ super(settings);
+ }
+
+ @Override
+ public int getType() {
+ return TunerConstants.FILTER_SETTINGS_ALP;
+ }
+ }
+
+
+ /**
+ * Settings for filters of different subtypes.
+ */
+ public abstract static class Settings {
+ protected final int mType;
+
+ protected Settings(int type) {
+ mType = type;
+ }
+
+ /**
+ * Gets filter settings type.
+ * @return
+ */
+ int getType() {
+ return mType;
+ }
+ }
+
+ /**
+ * Filter Settings for Section data according to ISO/IEC 13818-1.
+ */
+ public static class SectionSettings extends Settings {
+
+ private SectionSettings(int mainType) {
+ super(SectionSettings.findType(mainType));
+ }
+
+ private static int findType(int mainType) {
+ switch (mainType) {
+ case TunerConstants.FILTER_SETTINGS_TS:
+ return Constants.DemuxTsFilterType.SECTION;
+ case TunerConstants.FILTER_SETTINGS_MMTP:
+ return Constants.DemuxMmtpFilterType.SECTION;
+ case TunerConstants.FILTER_SETTINGS_IP:
+ return Constants.DemuxIpFilterType.SECTION;
+ case TunerConstants.FILTER_SETTINGS_TLV:
+ return Constants.DemuxTlvFilterType.SECTION;
+ case TunerConstants.FILTER_SETTINGS_ALP:
+ return Constants.DemuxAlpFilterType.SECTION;
+ }
+ // UNDEFINED
+ return 0;
+ }
+ }
+
+ /**
+ * Bits Settings for Section Filter.
+ */
+ public static class SectionSettingsWithSectionBits extends SectionSettings {
+ private List<Byte> mFilter;
+ private List<Byte> mMask;
+ private List<Byte> mMode;
+
+ private SectionSettingsWithSectionBits(int mainType) {
+ super(mainType);
+ }
+ }
+
+ /**
+ * Table information for Section Filter.
+ */
+ public static class SectionSettingsWithTableInfo extends SectionSettings {
+ private int mTableId;
+ private int mVersion;
+
+ private SectionSettingsWithTableInfo(int mainType) {
+ super(mainType);
+ }
+ }
+
+ /**
+ * Filter Settings for a PES Data.
+ */
+ public static class PesSettings extends Settings {
+ private int mStreamId;
+ private boolean mIsRaw;
+
+ private PesSettings(int mainType, int streamId, boolean isRaw) {
+ super(PesSettings.findType(mainType));
+ mStreamId = streamId;
+ mIsRaw = isRaw;
+ }
+
+ private static int findType(int mainType) {
+ switch (mainType) {
+ case TunerConstants.FILTER_SETTINGS_TS:
+ return Constants.DemuxTsFilterType.PES;
+ case TunerConstants.FILTER_SETTINGS_MMTP:
+ return Constants.DemuxMmtpFilterType.PES;
+ }
+ // UNDEFINED
+ return 0;
+ }
+
+ /**
+ * Creates a builder for PesSettings.
+ */
+ public static Builder newBuilder(int mainType) {
+ return new Builder(mainType);
+ }
+
+ /**
+ * Builder for PesSettings.
+ */
+ public static class Builder {
+ private final int mMainType;
+ private int mStreamId;
+ private boolean mIsRaw;
+
+ public Builder(int mainType) {
+ mMainType = mainType;
+ }
+
+ /**
+ * Sets stream ID.
+ */
+ public Builder setStreamId(int streamId) {
+ mStreamId = streamId;
+ return this;
+ }
+
+ /**
+ * Sets whether it's raw.
+ * true if the filter send onFilterStatus instead of onFilterEvent.
+ */
+ public Builder setIsRaw(boolean isRaw) {
+ mIsRaw = isRaw;
+ return this;
+ }
+
+ /**
+ * Builds a PesSettings instance.
+ */
+ public PesSettings build() {
+ return new PesSettings(mMainType, mStreamId, mIsRaw);
+ }
+ }
+ }
+
+ /**
+ * Filter Settings for a Video and Audio.
+ */
+ public static class AvSettings extends Settings {
+ private boolean mIsPassthrough;
+
+ private AvSettings(int mainType, boolean isAudio) {
+ super(AvSettings.findType(mainType, isAudio));
+ }
+
+ private static int findType(int mainType, boolean isAudio) {
+ switch (mainType) {
+ case TunerConstants.FILTER_SETTINGS_TS:
+ return isAudio
+ ? Constants.DemuxTsFilterType.AUDIO
+ : Constants.DemuxTsFilterType.VIDEO;
+ case TunerConstants.FILTER_SETTINGS_MMTP:
+ return isAudio
+ ? Constants.DemuxMmtpFilterType.AUDIO
+ : Constants.DemuxMmtpFilterType.VIDEO;
+ }
+ // UNDEFINED
+ return 0;
+ }
+ }
+
+ /**
+ * Filter Settings for a Download.
+ */
+ public static class DownloadSettings extends Settings {
+ private int mDownloadId;
+
+ public DownloadSettings(int mainType) {
+ super(DownloadSettings.findType(mainType));
+ }
+
+ private static int findType(int mainType) {
+ if (mainType == TunerConstants.FILTER_SETTINGS_MMTP) {
+ return Constants.DemuxMmtpFilterType.DOWNLOAD;
+ }
+ // UNDEFINED
+ return 0;
+ }
+ }
+
+ /**
+ * The Settings for the record in DVR.
+ */
+ public static class RecordSettings extends Settings {
+ private int mIndexType;
+ private int mIndexMask;
+
+ public RecordSettings(int mainType) {
+ super(RecordSettings.findType(mainType));
+ }
+
+ private static int findType(int mainType) {
+ switch (mainType) {
+ case TunerConstants.FILTER_SETTINGS_TS:
+ return Constants.DemuxTsFilterType.RECORD;
+ case TunerConstants.FILTER_SETTINGS_MMTP:
+ return Constants.DemuxMmtpFilterType.RECORD;
+ }
+ // UNDEFINED
+ return 0;
+ }
+ }
+
+}
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index 82cef2e43307..6537f6fb5a2b 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -243,9 +243,11 @@ public final class Tuner implements AutoCloseable {
private FilterCallback mCallback;
int mId;
+ private native int nativeConfigureFilter(int type, int subType, FilterSettings settings);
private native boolean nativeStartFilter();
private native boolean nativeStopFilter();
private native boolean nativeFlushFilter();
+ private native int nativeRead(byte[] buffer, int offset, int size);
private Filter(int id) {
mId = id;
@@ -258,6 +260,14 @@ public final class Tuner implements AutoCloseable {
}
}
+ public int configure(FilterSettings settings) {
+ int subType = -1;
+ if (settings.mSettings != null) {
+ subType = settings.mSettings.getType();
+ }
+ return nativeConfigureFilter(settings.getType(), subType, settings);
+ }
+
public boolean start() {
return nativeStartFilter();
}
@@ -269,6 +279,11 @@ public final class Tuner implements AutoCloseable {
public boolean flush() {
return nativeFlushFilter();
}
+
+ public int read(@NonNull byte[] buffer, int offset, int size) {
+ size = Math.min(size, buffer.length - offset);
+ return nativeRead(buffer, offset, size);
+ }
}
private Filter openFilter(int type, int subType, int bufferSize, FilterCallback cb) {
diff --git a/media/java/android/media/tv/tuner/TunerConstants.java b/media/java/android/media/tv/tuner/TunerConstants.java
index 458cb1678ded..f2d5e939f532 100644
--- a/media/java/android/media/tv/tuner/TunerConstants.java
+++ b/media/java/android/media/tv/tuner/TunerConstants.java
@@ -90,6 +90,17 @@ final class TunerConstants {
public static final int FRONTEND_SETTINGS_ISDBS3 = 8;
public static final int FRONTEND_SETTINGS_ISDBT = 9;
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({FILTER_SETTINGS_TS, FILTER_SETTINGS_MMTP, FILTER_SETTINGS_IP, FILTER_SETTINGS_TLV,
+ FILTER_SETTINGS_ALP})
+ public @interface FilterSettingsType {}
+
+ public static final int FILTER_SETTINGS_TS = Constants.DemuxFilterMainType.TS;
+ public static final int FILTER_SETTINGS_MMTP = Constants.DemuxFilterMainType.MMTP;
+ public static final int FILTER_SETTINGS_IP = Constants.DemuxFilterMainType.IP;
+ public static final int FILTER_SETTINGS_TLV = Constants.DemuxFilterMainType.TLV;
+ public static final int FILTER_SETTINGS_ALP = Constants.DemuxFilterMainType.ALP;
+
private TunerConstants() {
}
}
diff --git a/media/jni/Android.bp b/media/jni/Android.bp
index 12b3e6735d81..4ca23a1084a2 100644
--- a/media/jni/Android.bp
+++ b/media/jni/Android.bp
@@ -135,6 +135,8 @@ cc_library_shared {
shared_libs: [
"android.hardware.tv.tuner@1.0",
"libandroid_runtime",
+ "libcutils",
+ "libfmq",
"libhidlbase",
"liblog",
"libutils",
diff --git a/media/jni/android_media_MediaMetricsJNI.cpp b/media/jni/android_media_MediaMetricsJNI.cpp
index 5ddfcfce072e..d3151545333c 100644
--- a/media/jni/android_media_MediaMetricsJNI.cpp
+++ b/media/jni/android_media_MediaMetricsJNI.cpp
@@ -16,213 +16,112 @@
#define LOG_TAG "MediaMetricsJNI"
+#include <binder/Parcel.h>
#include <jni.h>
+#include <media/MediaAnalyticsItem.h>
#include <nativehelper/JNIHelp.h>
#include "android_media_MediaMetricsJNI.h"
#include "android_os_Parcel.h"
-#include <media/MediaAnalyticsItem.h>
-#include <binder/Parcel.h>
-
// This source file is compiled and linked into:
// core/jni/ (libandroid_runtime.so)
namespace android {
-// place the attributes into a java PersistableBundle object
-jobject MediaMetricsJNI::writeMetricsToBundle(JNIEnv* env, MediaAnalyticsItem *item, jobject mybundle) {
-
- jclass clazzBundle = env->FindClass("android/os/PersistableBundle");
- if (clazzBundle==NULL) {
- ALOGE("can't find android/os/PersistableBundle");
- return NULL;
+namespace {
+struct BundleHelper {
+ BundleHelper(JNIEnv* _env, jobject _bundle)
+ : env(_env)
+ , clazzBundle(env->FindClass("android/os/PersistableBundle"))
+ , putIntID(env->GetMethodID(clazzBundle, "putInt", "(Ljava/lang/String;I)V"))
+ , putLongID(env->GetMethodID(clazzBundle, "putLong", "(Ljava/lang/String;J)V"))
+ , putDoubleID(env->GetMethodID(clazzBundle, "putDouble", "(Ljava/lang/String;D)V"))
+ , putStringID(env->GetMethodID(clazzBundle,
+ "putString", "(Ljava/lang/String;Ljava/lang/String;)V"))
+ , constructID(env->GetMethodID(clazzBundle, "<init>", "()V"))
+ , bundle(_bundle == nullptr ? env->NewObject(clazzBundle, constructID) : _bundle)
+ { }
+
+ JNIEnv* const env;
+ const jclass clazzBundle;
+ const jmethodID putIntID;
+ const jmethodID putLongID;
+ const jmethodID putDoubleID;
+ const jmethodID putStringID;
+ const jmethodID constructID;
+ jobject const bundle;
+
+ // We use templated put to access MediaAnalyticsItem based on data type not type enum.
+ // See std::variant and std::visit.
+ template<typename T>
+ void put(jstring keyName, const T& value) = delete;
+
+ template<>
+ void put(jstring keyName, const int32_t& value) {
+ env->CallVoidMethod(bundle, putIntID, keyName, (jint)value);
}
- // sometimes the caller provides one for us to fill
- if (mybundle == NULL) {
- // create the bundle
- jmethodID constructID = env->GetMethodID(clazzBundle, "<init>", "()V");
- mybundle = env->NewObject(clazzBundle, constructID);
- if (mybundle == NULL) {
- return NULL;
- }
- }
-
- // grab methods that we can invoke
- jmethodID setIntID = env->GetMethodID(clazzBundle, "putInt", "(Ljava/lang/String;I)V");
- jmethodID setLongID = env->GetMethodID(clazzBundle, "putLong", "(Ljava/lang/String;J)V");
- jmethodID setDoubleID = env->GetMethodID(clazzBundle, "putDouble", "(Ljava/lang/String;D)V");
- jmethodID setStringID = env->GetMethodID(clazzBundle, "putString", "(Ljava/lang/String;Ljava/lang/String;)V");
- // env, class, method, {parms}
- //env->CallVoidMethod(env, mybundle, setIntID, jstr, jint);
-
- // iterate through my attributes
- // -- get name, get type, get value
- // -- insert appropriately into the bundle
- for (size_t i = 0 ; i < item->mPropCount; i++ ) {
- MediaAnalyticsItem::Prop *prop = &item->mProps[i];
- // build the key parameter from prop->mName
- jstring keyName = env->NewStringUTF(prop->mName);
- // invoke the appropriate method to insert
- switch (prop->mType) {
- case MediaAnalyticsItem::kTypeInt32:
- env->CallVoidMethod(mybundle, setIntID,
- keyName, (jint) prop->u.int32Value);
- break;
- case MediaAnalyticsItem::kTypeInt64:
- env->CallVoidMethod(mybundle, setLongID,
- keyName, (jlong) prop->u.int64Value);
- break;
- case MediaAnalyticsItem::kTypeDouble:
- env->CallVoidMethod(mybundle, setDoubleID,
- keyName, (jdouble) prop->u.doubleValue);
- break;
- case MediaAnalyticsItem::kTypeCString:
- env->CallVoidMethod(mybundle, setStringID, keyName,
- env->NewStringUTF(prop->u.CStringValue));
- break;
- default:
- ALOGE("to_String bad item type: %d for %s",
- prop->mType, prop->mName);
- break;
- }
+ template<>
+ void put(jstring keyName, const int64_t& value) {
+ env->CallVoidMethod(bundle, putLongID, keyName, (jlong)value);
}
- return mybundle;
-}
-
-// convert the specified batch metrics attributes to a persistent bundle.
-// The encoding of the byte array is specified in
-// frameworks/av/media/libmediametrics/MediaAnalyticsItem.cpp
-//
-// type encodings; matches frameworks/av/media/libmediametrics/MediaAnalyticsItem.cpp
-enum { kInt32 = 0, kInt64, kDouble, kRate, kCString};
-
-jobject MediaMetricsJNI::writeAttributesToBundle(JNIEnv* env, jobject mybundle, char *buffer, size_t length) {
- ALOGV("writeAttributes()");
-
- if (buffer == NULL || length <= 0) {
- ALOGW("bad parameters to writeAttributesToBundle()");
- return NULL;
+ template<>
+ void put(jstring keyName, const double& value) {
+ env->CallVoidMethod(bundle, putDoubleID, keyName, (jdouble)value);
}
- jclass clazzBundle = env->FindClass("android/os/PersistableBundle");
- if (clazzBundle==NULL) {
- ALOGE("can't find android/os/PersistableBundle");
- return NULL;
- }
- // sometimes the caller provides one for us to fill
- if (mybundle == NULL) {
- // create the bundle
- jmethodID constructID = env->GetMethodID(clazzBundle, "<init>", "()V");
- mybundle = env->NewObject(clazzBundle, constructID);
- if (mybundle == NULL) {
- ALOGD("unable to create mybundle");
- return NULL;
- }
+ template<>
+ void put(jstring keyName, const char * const& value) {
+ env->CallVoidMethod(bundle, putStringID, keyName, env->NewStringUTF(value));
}
- int left = length;
- char *buf = buffer;
+ template<>
+ void put(jstring keyName, char * const& value) {
+ env->CallVoidMethod(bundle, putStringID, keyName, env->NewStringUTF(value));
+ }
- // grab methods that we can invoke
- jmethodID setIntID = env->GetMethodID(clazzBundle, "putInt", "(Ljava/lang/String;I)V");
- jmethodID setLongID = env->GetMethodID(clazzBundle, "putLong", "(Ljava/lang/String;J)V");
- jmethodID setDoubleID = env->GetMethodID(clazzBundle, "putDouble", "(Ljava/lang/String;D)V");
- jmethodID setStringID = env->GetMethodID(clazzBundle, "putString", "(Ljava/lang/String;Ljava/lang/String;)V");
+ template<>
+ void put(jstring keyName, const std::pair<int64_t, int64_t>& value) {
+ ; // rate is currently ignored
+ }
+ // We allow both jstring and non-jstring variants.
+ template<typename T>
+ void put(const char *keyName, const T& value) {
+ put(env->NewStringUTF(keyName), value);
+ }
+};
+} // namespace
-#define _EXTRACT(size, val) \
- { if ((size) > left) goto badness; memcpy(&val, buf, (size)); buf += (size); left -= (size);}
-#define _SKIP(size) \
- { if ((size) > left) goto badness; buf += (size); left -= (size);}
+// place the attributes into a java PersistableBundle object
+jobject MediaMetricsJNI::writeMetricsToBundle(
+ JNIEnv* env, MediaAnalyticsItem *item, jobject bundle)
+{
+ BundleHelper bh(env, bundle);
+
+ if (bh.bundle == nullptr) {
+ ALOGE("%s: unable to create Bundle", __func__);
+ return nullptr;
+ }
- int32_t bufsize;
- _EXTRACT(sizeof(int32_t), bufsize);
- if (bufsize != length) {
- goto badness;
+ bh.put("__key", item->getKey().c_str());
+ if (item->getPid() != -1) {
+ bh.put("__pid", (int32_t)item->getPid());
}
- int32_t proto;
- _EXTRACT(sizeof(int32_t), proto);
- if (proto != 0) {
- ALOGE("unsupported wire protocol %d", proto);
- goto badness;
+ if (item->getTimestamp() > 0) {
+ bh.put("__timestamp", (int64_t)item->getTimestamp());
}
-
- int32_t count;
- _EXTRACT(sizeof(int32_t), count);
-
- // iterate through my attributes
- // -- get name, get type, get value, insert into bundle appropriately.
- for (int i = 0 ; i < count; i++ ) {
- // prop name len (int16)
- int16_t keylen;
- _EXTRACT(sizeof(int16_t), keylen);
- if (keylen <= 0) goto badness;
- // prop name itself
- char *key = buf;
- jstring keyName = env->NewStringUTF(buf);
- _SKIP(keylen);
-
- // prop type (int8_t)
- int8_t attrType;
- _EXTRACT(sizeof(int8_t), attrType);
-
- int16_t attrSize;
- _EXTRACT(sizeof(int16_t), attrSize);
-
- switch (attrType) {
- case kInt32:
- {
- int32_t i32;
- _EXTRACT(sizeof(int32_t), i32);
- env->CallVoidMethod(mybundle, setIntID,
- keyName, (jint) i32);
- break;
- }
- case kInt64:
- {
- int64_t i64;
- _EXTRACT(sizeof(int64_t), i64);
- env->CallVoidMethod(mybundle, setLongID,
- keyName, (jlong) i64);
- break;
- }
- case kDouble:
- {
- double d64;
- _EXTRACT(sizeof(double), d64);
- env->CallVoidMethod(mybundle, setDoubleID,
- keyName, (jdouble) d64);
- break;
- }
- case kCString:
- {
- jstring value = env->NewStringUTF(buf);
- env->CallVoidMethod(mybundle, setStringID,
- keyName, value);
- _SKIP(attrSize);
- break;
- }
- default:
- ALOGW("ignoring Attribute '%s' unknown type: %d",
- key, attrType);
- _SKIP(attrSize);
- break;
- }
+ if (item->getUid() != -1) {
+ bh.put("__uid", (int32_t)item->getUid());
}
-
- // should have consumed it all
- if (left != 0) {
- ALOGW("did not consume entire buffer; left(%d) != 0", left);
- goto badness;
+ for (const auto &prop : *item) {
+ const char *name = prop.getName();
+ if (name == nullptr) continue;
+ prop.visit([&] (auto &value) { bh.put(name, value); });
}
-
- return mybundle;
-
- badness:
- return NULL;
+ return bh.bundle;
}
// Helper function to convert a native PersistableBundle to a Java
diff --git a/media/jni/android_media_MediaMetricsJNI.h b/media/jni/android_media_MediaMetricsJNI.h
index e879da01c6ef..63ec27aa58ee 100644
--- a/media/jni/android_media_MediaMetricsJNI.h
+++ b/media/jni/android_media_MediaMetricsJNI.h
@@ -28,7 +28,6 @@ namespace android {
class MediaMetricsJNI {
public:
static jobject writeMetricsToBundle(JNIEnv* env, MediaAnalyticsItem *item, jobject mybundle);
- static jobject writeAttributesToBundle(JNIEnv* env, jobject mybundle, char *buffer, size_t length);
static jobject nativeToJavaPersistableBundle(JNIEnv*, os::PersistableBundle*);
};
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index 5216906d5ec5..a0be12ebecfc 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -28,8 +28,12 @@
using ::android::hardware::Void;
using ::android::hardware::hidl_vec;
using ::android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterPesDataSettings;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterSettings;
using ::android::hardware::tv::tuner::V1_0::DemuxMmtpPid;
+using ::android::hardware::tv::tuner::V1_0::DemuxQueueNotifyBits;
using ::android::hardware::tv::tuner::V1_0::DemuxTpid;
+using ::android::hardware::tv::tuner::V1_0::DemuxTsFilterSettings;
using ::android::hardware::tv::tuner::V1_0::DemuxTsFilterType;
using ::android::hardware::tv::tuner::V1_0::FrontendAnalogSettings;
using ::android::hardware::tv::tuner::V1_0::FrontendAnalogSifStandard;
@@ -112,6 +116,26 @@ void FilterCallback::setFilter(const jobject filter) {
mFilter = env->NewWeakGlobalRef(filter);
}
+/////////////// Filter ///////////////////////
+
+Filter::Filter(sp<IFilter> sp, jweak obj) : mFilterSp(sp), mFilterObj(obj) {}
+
+Filter::~Filter() {
+ EventFlag::deleteEventFlag(&mFilterMQEventFlag);
+}
+
+int Filter::close() {
+ Result r = mFilterSp->close();
+ if (r == Result::SUCCESS) {
+ EventFlag::deleteEventFlag(&mFilterMQEventFlag);
+ }
+ return (int)r;
+}
+
+sp<IFilter> Filter::getIFilter() {
+ return mFilterSp;
+}
+
/////////////// FrontendCallback ///////////////////////
FrontendCallback::FrontendCallback(jweak tunerObj, FrontendId id) : mObject(tunerObj), mId(id) {}
@@ -211,6 +235,7 @@ jobject JTuner::openFrontendById(int id) {
fe->setCallback(feCb);
jint jId = (jint) id;
+
JNIEnv *env = AndroidRuntime::getJNIEnv();
// TODO: add more fields to frontend
return env->NewObject(
@@ -327,18 +352,18 @@ jobject JTuner::openFilter(DemuxFilterType type, int bufferSize) {
}
}
- sp<IFilter> filterSp;
+ sp<IFilter> iFilterSp;
sp<FilterCallback> callback = new FilterCallback();
mDemux->openFilter(type, bufferSize, callback,
[&](Result, const sp<IFilter>& filter) {
- filterSp = filter;
+ iFilterSp = filter;
});
- if (filterSp == NULL) {
+ if (iFilterSp == NULL) {
ALOGD("Failed to open filter, type = %d", type.mainType);
return NULL;
}
int fId;
- filterSp->getId([&](Result, uint32_t filterId) {
+ iFilterSp->getId([&](Result, uint32_t filterId) {
fId = filterId;
});
@@ -350,6 +375,7 @@ jobject JTuner::openFilter(DemuxFilterType type, int bufferSize) {
mObject,
(jint) fId);
+ sp<Filter> filterSp = new Filter(iFilterSp, filterObj);
filterSp->incStrong(filterObj);
env->SetLongField(filterObj, gFields.filterContext, (jlong)filterSp.get());
@@ -432,7 +458,7 @@ static DemuxPid getDemuxPid(int pidType, int pid) {
static FrontendSettings getFrontendSettings(JNIEnv *env, int type, jobject settings) {
FrontendSettings frontendSettings;
jclass clazz = env->FindClass("android/media/tv/tuner/FrontendSettings");
- jfieldID freqField = env->GetFieldID(clazz, "frequency", "I");
+ jfieldID freqField = env->GetFieldID(clazz, "mFrequency", "I");
uint32_t freq = static_cast<uint32_t>(env->GetIntField(clazz, freqField));
// TODO: handle the other 8 types of settings
@@ -455,8 +481,8 @@ static FrontendSettings getFrontendSettings(JNIEnv *env, int type, jobject setti
return frontendSettings;
}
-static sp<IFilter> getFilter(JNIEnv *env, jobject filter) {
- return (IFilter *)env->GetLongField(filter, gFields.filterContext);
+static sp<Filter> getFilter(JNIEnv *env, jobject filter) {
+ return (Filter *)env->GetLongField(filter, gFields.filterContext);
}
static sp<IDvr> getDvr(JNIEnv *env, jobject dvr) {
@@ -542,8 +568,100 @@ static jobject android_media_tv_Tuner_open_filter(
return tuner->openFilter(filterType, bufferSize);
}
+static DemuxFilterSettings getFilterSettings(
+ JNIEnv *env, int type, int subtype, jobject filterSettingsObj) {
+ DemuxFilterSettings filterSettings;
+ // TODO: more setting types
+ jobject settingsObj =
+ env->GetObjectField(
+ filterSettingsObj,
+ env->GetFieldID(
+ env->FindClass("android/media/tv/tuner/FilterSettings"),
+ "mSettings",
+ "Landroid/media/tv/tuner/FilterSettings$Settings;"));
+ if (type == (int)DemuxFilterMainType::TS) {
+ // DemuxTsFilterSettings
+ jclass clazz = env->FindClass("android/media/tv/tuner/FilterSettings$TsFilterSettings");
+ int tpid = env->GetIntField(filterSettingsObj, env->GetFieldID(clazz, "mTpid", "I"));
+ if (subtype == (int)DemuxTsFilterType::PES) {
+ // DemuxFilterPesDataSettings
+ jclass settingClazz =
+ env->FindClass("android/media/tv/tuner/FilterSettings$PesSettings");
+ int streamId = env->GetIntField(
+ settingsObj, env->GetFieldID(settingClazz, "mStreamId", "I"));
+ bool isRaw = (bool)env->GetBooleanField(
+ settingsObj, env->GetFieldID(settingClazz, "mIsRaw", "Z"));
+ DemuxFilterPesDataSettings filterPesDataSettings {
+ .streamId = static_cast<uint16_t>(streamId),
+ .isRaw = isRaw,
+ };
+ DemuxTsFilterSettings tsFilterSettings {
+ .tpid = static_cast<uint16_t>(tpid),
+ };
+ tsFilterSettings.filterSettings.pesData(filterPesDataSettings);
+ filterSettings.ts(tsFilterSettings);
+ }
+ }
+ return filterSettings;
+}
+
+static int copyData(JNIEnv *env, sp<Filter> filter, jbyteArray buffer, jint offset, int size) {
+ ALOGD("copyData, size=%d, offset=%d", size, offset);
+
+ int available = filter->mFilterMQ->availableToRead();
+ ALOGD("copyData, available=%d", available);
+ size = std::min(size, available);
+
+ jboolean isCopy;
+ jbyte *dst = env->GetByteArrayElements(buffer, &isCopy);
+ ALOGD("copyData, isCopy=%d", isCopy);
+ if (dst == nullptr) {
+ ALOGD("Failed to GetByteArrayElements");
+ return 0;
+ }
+
+ if (filter->mFilterMQ->read(reinterpret_cast<unsigned char*>(dst) + offset, size)) {
+ env->ReleaseByteArrayElements(buffer, dst, 0);
+ filter->mFilterMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED));
+ } else {
+ ALOGD("Failed to read FMQ");
+ env->ReleaseByteArrayElements(buffer, dst, 0);
+ return 0;
+ }
+ return size;
+}
+
+static int android_media_tv_Tuner_configure_filter(
+ JNIEnv *env, jobject filter, int type, int subtype, jobject settings) {
+ ALOGD("configure filter type=%d, subtype=%d", type, subtype);
+ sp<Filter> filterSp = getFilter(env, filter);
+ sp<IFilter> iFilterSp = filterSp->getIFilter();
+ if (iFilterSp == NULL) {
+ ALOGD("Failed to configure filter: filter not found");
+ return (int)Result::INVALID_STATE;
+ }
+ DemuxFilterSettings filterSettings = getFilterSettings(env, type, subtype, settings);
+ Result res = iFilterSp->configure(filterSettings);
+ MQDescriptorSync<uint8_t> filterMQDesc;
+ if (res == Result::SUCCESS && filterSp->mFilterMQ == NULL) {
+ Result getQueueDescResult = Result::UNKNOWN_ERROR;
+ iFilterSp->getQueueDesc(
+ [&](Result r, const MQDescriptorSync<uint8_t>& desc) {
+ filterMQDesc = desc;
+ getQueueDescResult = r;
+ ALOGD("getFilterQueueDesc");
+ });
+ if (getQueueDescResult == Result::SUCCESS) {
+ filterSp->mFilterMQ = std::make_unique<FilterMQ>(filterMQDesc, true);
+ EventFlag::createEventFlag(
+ filterSp->mFilterMQ->getEventFlagWord(), &(filterSp->mFilterMQEventFlag));
+ }
+ }
+ return (int)res;
+}
+
static bool android_media_tv_Tuner_start_filter(JNIEnv *env, jobject filter) {
- sp<IFilter> filterSp = getFilter(env, filter);
+ sp<IFilter> filterSp = getFilter(env, filter)->getIFilter();
if (filterSp == NULL) {
ALOGD("Failed to start filter: filter not found");
return false;
@@ -552,7 +670,7 @@ static bool android_media_tv_Tuner_start_filter(JNIEnv *env, jobject filter) {
}
static bool android_media_tv_Tuner_stop_filter(JNIEnv *env, jobject filter) {
- sp<IFilter> filterSp = getFilter(env, filter);
+ sp<IFilter> filterSp = getFilter(env, filter)->getIFilter();
if (filterSp == NULL) {
ALOGD("Failed to stop filter: filter not found");
return false;
@@ -561,7 +679,7 @@ static bool android_media_tv_Tuner_stop_filter(JNIEnv *env, jobject filter) {
}
static bool android_media_tv_Tuner_flush_filter(JNIEnv *env, jobject filter) {
- sp<IFilter> filterSp = getFilter(env, filter);
+ sp<IFilter> filterSp = getFilter(env, filter)->getIFilter();
if (filterSp == NULL) {
ALOGD("Failed to flush filter: filter not found");
return false;
@@ -569,6 +687,16 @@ static bool android_media_tv_Tuner_flush_filter(JNIEnv *env, jobject filter) {
return filterSp->flush() == Result::SUCCESS;
}
+static int android_media_tv_Tuner_read_filter_fmq(
+ JNIEnv *env, jobject filter, jbyteArray buffer, jint offset, jint size) {
+ sp<Filter> filterSp = getFilter(env, filter);
+ if (filterSp == NULL) {
+ ALOGD("Failed to read filter FMQ: filter not found");
+ return 0;
+ }
+ return copyData(env, filterSp, buffer, offset, size);
+}
+
static jobject android_media_tv_Tuner_open_descrambler(JNIEnv *env, jobject thiz) {
sp<JTuner> tuner = getTuner(env, thiz);
return tuner->openDescrambler();
@@ -580,7 +708,7 @@ static bool android_media_tv_Tuner_add_pid(
if (descramblerSp == NULL) {
return false;
}
- sp<IFilter> filterSp = getFilter(env, filter);
+ sp<IFilter> filterSp = getFilter(env, filter)->getIFilter();
Result result = descramblerSp->addPid(getDemuxPid((int)pidType, (int)pid), filterSp);
return result == Result::SUCCESS;
}
@@ -591,7 +719,7 @@ static bool android_media_tv_Tuner_remove_pid(
if (descramblerSp == NULL) {
return false;
}
- sp<IFilter> filterSp = getFilter(env, filter);
+ sp<IFilter> filterSp = getFilter(env, filter)->getIFilter();
Result result = descramblerSp->removePid(getDemuxPid((int)pidType, (int)pid), filterSp);
return result == Result::SUCCESS;
}
@@ -603,7 +731,7 @@ static jobject android_media_tv_Tuner_open_dvr(JNIEnv *env, jobject thiz, jint t
static bool android_media_tv_Tuner_attach_filter(JNIEnv *env, jobject dvr, jobject filter) {
sp<IDvr> dvrSp = getDvr(env, dvr);
- sp<IFilter> filterSp = getFilter(env, filter);
+ sp<IFilter> filterSp = getFilter(env, filter)->getIFilter();
if (dvrSp == NULL || filterSp == NULL) {
return false;
}
@@ -613,7 +741,7 @@ static bool android_media_tv_Tuner_attach_filter(JNIEnv *env, jobject dvr, jobje
static bool android_media_tv_Tuner_detach_filter(JNIEnv *env, jobject dvr, jobject filter) {
sp<IDvr> dvrSp = getDvr(env, dvr);
- sp<IFilter> filterSp = getFilter(env, filter);
+ sp<IFilter> filterSp = getFilter(env, filter)->getIFilter();
if (dvrSp == NULL || filterSp == NULL) {
return false;
}
@@ -670,9 +798,12 @@ static const JNINativeMethod gTunerMethods[] = {
};
static const JNINativeMethod gFilterMethods[] = {
+ { "nativeConfigureFilter", "(IILandroid/media/tv/tuner/FilterSettings;)I",
+ (void *)android_media_tv_Tuner_configure_filter },
{ "nativeStartFilter", "()Z", (void *)android_media_tv_Tuner_start_filter },
{ "nativeStopFilter", "()Z", (void *)android_media_tv_Tuner_stop_filter },
{ "nativeFlushFilter", "()Z", (void *)android_media_tv_Tuner_flush_filter },
+ { "nativeRead", "([BII)I", (void *)android_media_tv_Tuner_read_filter_fmq },
};
static const JNINativeMethod gDescramblerMethods[] = {
diff --git a/media/jni/android_media_tv_Tuner.h b/media/jni/android_media_tv_Tuner.h
index f856791e2618..467acb8cdbdd 100644
--- a/media/jni/android_media_tv_Tuner.h
+++ b/media/jni/android_media_tv_Tuner.h
@@ -18,13 +18,18 @@
#define _ANDROID_MEDIA_TV_TUNER_H_
#include <android/hardware/tv/tuner/1.0/ITuner.h>
+#include <fmq/MessageQueue.h>
#include <unordered_map>
#include <utils/RefBase.h>
#include "jni.h"
+using ::android::hardware::EventFlag;
+using ::android::hardware::MQDescriptorSync;
+using ::android::hardware::MessageQueue;
using ::android::hardware::Return;
using ::android::hardware::hidl_vec;
+using ::android::hardware::kSynchronizedReadWrite;
using ::android::hardware::tv::tuner::V1_0::DemuxFilterEvent;
using ::android::hardware::tv::tuner::V1_0::DemuxFilterStatus;
using ::android::hardware::tv::tuner::V1_0::DemuxFilterType;
@@ -51,6 +56,8 @@ using ::android::hardware::tv::tuner::V1_0::LnbId;
using ::android::hardware::tv::tuner::V1_0::PlaybackStatus;
using ::android::hardware::tv::tuner::V1_0::RecordStatus;
+using FilterMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
+
namespace android {
struct LnbCallback : public ILnbCallback {
@@ -91,6 +98,17 @@ struct FrontendCallback : public IFrontendCallback {
FrontendId mId;
};
+struct Filter : public RefBase {
+ Filter(sp<IFilter> sp, jweak obj);
+ ~Filter();
+ int close();
+ sp<IFilter> getIFilter();
+ sp<IFilter> mFilterSp;
+ std::unique_ptr<FilterMQ> mFilterMQ;
+ EventFlag* mFilterMQEventFlag;
+ jweak mFilterObj;
+};
+
struct JTuner : public RefBase {
JTuner(JNIEnv *env, jobject thiz);
sp<ITuner> getTunerService();
diff --git a/media/jni/soundpool/StreamManager.cpp b/media/jni/soundpool/StreamManager.cpp
index 79e4d8ae6e26..c8f0ff10ca3f 100644
--- a/media/jni/soundpool/StreamManager.cpp
+++ b/media/jni/soundpool/StreamManager.cpp
@@ -38,7 +38,7 @@ static constexpr bool kStealActiveStream_OldestFirst = true;
// kPlayOnCallingThread = true prior to R.
// Changing to false means calls to play() are almost instantaneous instead of taking around
// ~10ms to launch the AudioTrack. It is perhaps 100x faster.
-static constexpr bool kPlayOnCallingThread = true;
+static constexpr bool kPlayOnCallingThread = false;
// Amount of time for a StreamManager thread to wait before closing.
static constexpr int64_t kWaitTimeBeforeCloseNs = 9 * NANOS_PER_SECOND;
@@ -170,7 +170,6 @@ int32_t StreamManager::queueForPlay(const std::shared_ptr<Sound> &sound,
if (stream->getSoundID() == soundID) {
ALOGV("%s: found soundID %d in restart queue", __func__, soundID);
newStream = stream;
- fromAvailableQueue = false;
break;
} else if (newStream == nullptr) {
ALOGV("%s: found stream in restart queue", __func__);
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
index 45430197fdd8..291cdd5ea3d8 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
@@ -35,6 +35,7 @@ import android.view.ViewStub;
import androidx.recyclerview.widget.GridLayoutManager;
+import com.android.internal.widget.LockPatternUtils;
import com.android.systemui.R;
import com.android.systemui.car.CarServiceProvider;
import com.android.systemui.dagger.qualifiers.MainResources;
@@ -135,8 +136,9 @@ public class FullscreenUserSwitcher {
/* isAddUser= */ false,
/* isForeground= */ true);
- // If the initial user has trusted device, display the unlock dialog on the keyguard.
- if (hasTrustedDevice(initialUser)) {
+ // If the initial user has screen lock and trusted device, display the unlock dialog on the
+ // keyguard.
+ if (hasScreenLock(initialUser) && hasTrustedDevice(initialUser)) {
mUnlockDialogHelper.showUnlockDialogAfterDelay(initialUser,
mOnHideListener);
} else {
@@ -178,7 +180,7 @@ public class FullscreenUserSwitcher {
*/
private void onUserSelected(UserGridRecyclerView.UserRecord record) {
mSelectedUser = record;
- if (hasTrustedDevice(record.mInfo.id)) {
+ if (hasScreenLock(record.mInfo.id) && hasTrustedDevice(record.mInfo.id)) {
mUnlockDialogHelper.showUnlockDialog(record.mInfo.id, mOnHideListener);
return;
}
@@ -216,6 +218,12 @@ public class FullscreenUserSwitcher {
}
+ private boolean hasScreenLock(int uid) {
+ LockPatternUtils lockPatternUtils = new LockPatternUtils(mContext);
+ return lockPatternUtils.getCredentialTypeForUser(uid)
+ != LockPatternUtils.CREDENTIAL_TYPE_NONE;
+ }
+
private boolean hasTrustedDevice(int uid) {
if (mEnrollmentManager == null) { // car service not ready, so it cannot be available.
return false;
diff --git a/packages/SystemUI/TEST_MAPPING b/packages/SystemUI/TEST_MAPPING
index 26ec5726a4a2..9f13a7b861a0 100644
--- a/packages/SystemUI/TEST_MAPPING
+++ b/packages/SystemUI/TEST_MAPPING
@@ -9,12 +9,6 @@
"include-filter": "android.platform.test.scenario.sysui"
},
{
- "include-filter": "android.platform.test.scenario.quicksettings"
- },
- {
- "include-filter": "android.platform.test.scenario.notification"
- },
- {
"include-annotation": "android.platform.test.scenario.annotation.Scenario"
},
{
diff --git a/packages/SystemUI/docs/executors.md b/packages/SystemUI/docs/executors.md
new file mode 100644
index 000000000000..8520ce228c9d
--- /dev/null
+++ b/packages/SystemUI/docs/executors.md
@@ -0,0 +1,321 @@
+# Executors
+
+go/sysui-executors
+
+[TOC]
+
+## TLDR
+
+In SystemUI, we are encouraging the use of Java's [Executor][Executor] over
+Android's [Handler][Handler] when shuffling a [Runnable][Runnable] between
+threads or delaying the execution of a Runnable. We have an implementation of
+Executor available, as well as our own sub-interface,
+[DelayableExecutor][DelayableExecutor] available. For test,
+[FakeExecutor][FakeExecutor] is available.
+
+[Executor]: https://developer.android.com/reference/java/util/concurrent/Executor.html
+[Handler]: https://developer.android.com/reference/android/os/Handler
+[Runnable]: https://developer.android.com/reference/java/lang/Runnable.html
+[DelayableExecutor]: /packages/SystemUI/src/com/android/systemui/util/concurrency/DelayableExecutor.java
+[FakeExecutor]: /packages/SystemUI/tests/src/com/android/systemui/util/concurrency/FakeExecutor.java
+
+## Rationale
+
+Executors make testing easier and are generally more flexible than Handlers.
+They are defined as an interface, making it easy to swap in fake implementations
+for testing. This also makes it easier to supply alternate implementations
+generally speaking - shared thread pools; priority queues; etc.
+
+For testing, whereas a handler involves trying to directly control its
+underlying Looper (using things like `Thread.sleep()` as well as overriding
+internal behaviors), an Executor implementation can be made to be directly
+controllable and inspectable.
+
+See also go/executors-for-the-android-engineer
+
+## Available Executors
+
+At present, there are two interfaces of Executor avaiable, each implemented, and
+each with two instances - `@Background` and `@Main`.
+
+### Executor
+
+The simplest Executor available implements the interface directly, making
+available one method: `Executor.execute()`. You can access an implementation of
+this Executor through Dependency Injection:
+
+```java
+ public class Foobar {
+ @Inject
+ public Foobar(@Background Executor bgExecutor) {
+ bgExecutor.execute(new Runnable() {
+ // ...
+ });
+ }
+ }
+```
+
+`@Main` will give you an Executor that runs on the ui thread. `@Background` will
+give you one that runs on a _shared_ non-ui thread. If you ask for an
+non-annotated Executor, you will get the `@Background` Executor.
+
+We do not currently have support for creating an Executor on a new, virgin
+thread. We do not currently support any sort of shared pooling of threads. If
+you require either of these, please reach out.
+
+### DelayableExecutor
+
+[DelayableExecutor][DelayableExecutor] is the closest analogue we provide to
+Handler. It adds `executeDelayed(Runnable r, long delayMillis)` and
+`executeAtTime(Runnable r, long uptimeMillis)` to the interface, just like
+Handler's [postDelayed][postDelayed] and [postAtTime][postAttime]. It also adds
+the option to supply a [TimeUnit][TimeUnit] as a third argument.
+
+A DelayableExecutor can be accessed via Injection just like a standard Executor.
+In fact, at this time, it shares the same underlying thread as our basic
+Executor.
+
+```java
+ public class Foobar {
+ @Inject
+ public Foobar(@Background DelayableExecutor bgExecutor) {
+ bgExecutor.executeDelayed(new Runnable() {
+ // ...
+ }, 1, TimeUnit.MINUTES);
+ }
+ }
+```
+
+Unlike Handler, the added methods return a Runnable that, when run, cancels the
+originally supplied Runnable if it has not yet started execution:
+
+```java
+ public class Foobar {
+ @Inject
+ public Foobar(@Background DelayableExecutor bgExecutor) {
+ Runnable cancel = bgExecutor.executeDelayed(new Runnable() {
+ // ...
+ }, 1, TimeUnit.MINUTES);
+
+ cancel.run(); // The supplied Runnable will (probably) not run.
+ }
+ }
+```
+
+[postDelayed]: https://developer.android.com/reference/android/os/Handler#postDelayed(java.lang.Runnable,%20long)
+[postAttime]: https://developer.android.com/reference/android/os/Handler#postAtTime(java.lang.Runnable,%20long)
+[TimeUnit]: https://developer.android.com/reference/java/util/concurrent/TimeUnit
+
+## Moving From Handler
+
+Most use cases of Handlers can easily be handled by the above two interfaces
+above. A minor refactor makes the switch:
+
+Handler | Executor | DelayableExecutor
+------------- | --------- | -----------------
+post() | execute() | execute()
+postDelayed() | `none` | executeDelayed()
+postAtTime() | `none` | executeAtTime()
+
+There is one notable gap in this implementation: `Handler.postAtFrontOfQueue()`.
+If you require this method, or similar, please reach out. The idea of a
+PriorityQueueExecutor has been floated, but will not be implemented until there
+is a clear need.
+
+Note also that "canceling" semantics are different. Instead of passing a `token`
+object to `Handler.postDelayed()`, you receive a Runnable that, when run,
+cancels the originally supplied Runnable.
+
+### Message Handling
+
+Executors have no concept of message handling. This is an oft used feature of
+Handlers. There are (as of 2019-12-05) 37 places where we subclass Handler to
+take advantage of this. However, by-and-large, these subclases take the
+following form:
+
+```Java
+mHandler = new Handler(looper) {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_A:
+ handleMessageA();
+ break;
+ case MSG_B:
+ handleMessageB((String) msg.obj);
+ break;
+ case MSG_C:
+ handleMessageC((Foobar) msg.obj);
+ break;
+ // ...
+ }
+ }
+};
+
+// Elsewhere in the class
+void doSomething() {
+ mHandler.obtainMessage(MSG_B, "some string");
+ mHandler.sendMessage(msg);
+}
+```
+
+This could easily be replaced by equivalent, more direct Executor code:
+
+```Java
+void doSomething() {
+ mExecutor.execute(() -> handleMessageB("some string"));
+}
+```
+
+If you are posting Runnables frequently and you worry that the cost of creating
+anonymous Runnables is too high, consider creating pre-defined Runnables as
+fields in your class.
+
+If you feel that you have a use case that this does not cover, please reach out.
+
+### Handlers Are Still Necessary
+
+Handlers aren't going away. There are Android APIs that still require them (even
+if future API development discourages them). A simple example is
+[ContentObserver][ContentObserver]. Use them where necessary.
+
+[ContentObserver]: https://developer.android.com/reference/android/database/ContentObserver
+
+## Testing (FakeExecutor)
+
+We have a [FakeExecutor][FakeExecutor] available. It implements
+DelayableExecutor (which in turn is an Executor). It takes a FakeSystemClock in
+its constructor that allows you to control the flow of time, executing supplied
+Runnables in a deterministic manner.
+
+The implementation is well documented and tested. You are encouraged to read and
+reference it, but here is a quick overview:
+
+<table>
+ <tr>
+ <th>Method</th>
+ <th>Description</th>
+ </tr>
+ <tr>
+ <td>execute()</td>
+ <td>
+ Queues a Runnable so that it is "ready"
+ to run. (A Runnable is "ready" when its
+ scheduled time is less than or equal to
+ the clock.)
+ </td>
+ </tr>
+ <tr>
+ <td>postDelayed() & postAtTime()</td>
+ <td>
+ Queues a runnable to be run at some
+ point in the future.
+ </td>
+ </tr>
+ <tr>
+ <td>runNextReady()</td>
+ <td>
+ Run one runnable if it is ready to run
+ according to the supplied clock.
+ </td>
+ </tr>
+ <tr>
+ <td>runAllReady()</td>
+ <td>
+ Calls runNextReady() in a loop until
+ there are no more "ready" runnables.
+ </td>
+ </tr>
+ <tr>
+ <td>advanceClockToNext()</td>
+ <td>
+ Move the internal clock to the item at
+ the front of the queue, making it
+ "ready".
+ </td>
+ </tr>
+ <tr>
+ <td>advanceClockToLast()</td>
+ <td>
+ Makes all currently queued items ready.
+ </td>
+ </tr>
+ <tr>
+ <td>numPending()</td>
+ <td>
+ The number of runnables waiting to be run
+ They are not necessarily "ready".
+ </td>
+ </tr>
+ <tr>
+ <td>(static method) exhaustExecutors()</td>
+ <td>
+ Given a number of FakeExecutors, it
+ calls runAllReady() repeated on them
+ until none of them have ready work.
+ Useful if you have Executors that post
+ work to one another back and forth.
+ </td>
+ </tr>
+</table>
+
+_If you advance the supplied FakeSystemClock directly, the FakeExecutor will
+execute pending Runnables accordingly._ If you use the FakeExecutors
+`advanceClockToNext()` and `advanceClockToLast()`, this behavior will not be
+seen. You will need to tell the Executor to run its ready items. A quick example
+shows the difference:
+
+Here we advance the clock directly:
+
+```java
+FakeSystemClock clock = new FakeSystemClock();
+FakeExecutor executor = new FakeExecutor(clock);
+executor.execute(() -> {}); // Nothing run yet. Runs at time-0
+executor.executeDelayed(() -> {}, 100); // Nothing run yet. Runs at time-100.
+executor.executeDelayed(() -> {}, 500); // Nothing run yet. Runs at time-500.
+
+clock.synchronizeListeners(); // The clock just told the Executor it's time-0.
+ // One thing run.
+clock.setUptimeMillis(500); // The clock just told the Executor it's time-500.
+ // Two more items run.
+```
+
+Here we have more fine-grained control:
+
+```java
+FakeSystemClock clock = new FakeSystemClock();
+FakeExecutor executor = new FakeExecutor(clock);
+executor.execute(() -> {}); // Nothing run yet. Runs at time-0
+executor.executeDelayed(() -> {}, 100); // Nothing run yet. Runs at time-100.
+executor.executeDelayed(() -> {}, 500); // Nothing run yet. Runs at time-500.
+
+executor.runNextReady(); // One thing run.
+executor.advanceClockToNext(); // One more thing ready to run.
+executor.runNextReady(); // One thing run.
+executor.runNextReady(); // Extra calls do nothing. (Returns false).
+executor.advanceClockToNext(); // One more thing ready to run.
+executor.runNextReady(); // Last item run.
+```
+
+One gotcha of direct-clock-advancement: If you have interleaved Runnables split
+between two executors like the following:
+
+```java
+FakeSystemClock clock = new FakeSystemClock();
+FakeExecutor executorA = new FakeExecutor(clock);
+FakeExecutor executorB = new FakeExecutor(clock);
+executorA.executeDelayed(() -> {}, 100);
+executorB.executeDelayed(() -> {}, 200);
+executorA.executeDelayed(() -> {}, 300);
+executorB.executeDelayed(() -> {}, 400);
+clock.setUptimeMillis(500);
+```
+
+The Runnables _will not_ interleave. All of one Executor's callbacks will run,
+then all of the other's.
+
+### TestableLooper.RunWithLooper
+
+As long as you're using FakeExecutors in all the code under test (and no
+Handlers or Loopers) you don't need it. Get rid of it. No more TestableLooper;
+no more Looper at all, for that matter.
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/StatusBarStateController.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/StatusBarStateController.java
index b21a9f7c4d05..6c4cbdf27fa5 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/StatusBarStateController.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/StatusBarStateController.java
@@ -34,7 +34,8 @@ public interface StatusBarStateController {
int getState();
/**
- * Is device dozing
+ * Is device dozing. Dozing is when the screen is in AOD or asleep given that
+ * {@link com.android.systemui.doze.DozeService} is configured.
*/
boolean isDozing();
diff --git a/packages/SystemUI/res/layout/bubble_menu_view.xml b/packages/SystemUI/res/layout/bubble_menu_view.xml
new file mode 100644
index 000000000000..24608d3e9611
--- /dev/null
+++ b/packages/SystemUI/res/layout/bubble_menu_view.xml
@@ -0,0 +1,43 @@
+<?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.
+ -->
+<com.android.systemui.bubbles.BubbleMenuView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:background="#66000000"
+ android:visibility="gone"
+ android:id="@+id/bubble_menu_container">
+
+ <FrameLayout
+ android:layout_height="@dimen/individual_bubble_size"
+ android:layout_width="wrap_content"
+ android:background="#FFFFFF"
+ android:id="@+id/bubble_menu_view">
+
+ <ImageView
+ android:id="@*android:id/icon"
+ android:layout_width="@dimen/global_actions_grid_item_icon_width"
+ android:layout_height="@dimen/global_actions_grid_item_icon_height"
+ android:layout_marginTop="@dimen/global_actions_grid_item_icon_top_margin"
+ android:layout_marginBottom="@dimen/global_actions_grid_item_icon_bottom_margin"
+ android:layout_marginLeft="@dimen/global_actions_grid_item_icon_side_margin"
+ android:layout_marginRight="@dimen/global_actions_grid_item_icon_side_margin"
+ android:scaleType="centerInside"
+ android:tint="@color/global_actions_text"
+ />
+ </FrameLayout>
+</com.android.systemui.bubbles.BubbleMenuView>
diff --git a/packages/SystemUI/res/values-television/config.xml b/packages/SystemUI/res/values-television/config.xml
new file mode 100644
index 000000000000..27db294a98d8
--- /dev/null
+++ b/packages/SystemUI/res/values-television/config.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+ for different hardware and product builds. -->
+<resources>
+ <!-- SystemUI Services: The classes of the stuff to start. -->
+ <string-array name="config_systemUIServiceComponents" translatable="false">
+ <item>com.android.systemui.volume.VolumeUI</item>
+ <item>com.android.systemui.stackdivider.Divider</item>
+ <item>com.android.systemui.statusbar.tv.TvStatusBar</item>
+ <item>com.android.systemui.usb.StorageNotification</item>
+ <item>com.android.systemui.power.PowerUI</item>
+ <item>com.android.systemui.media.RingtonePlayer</item>
+ <item>com.android.systemui.keyboard.KeyboardUI</item>
+ <item>com.android.systemui.pip.PipUI</item>
+ <item>com.android.systemui.shortcut.ShortcutKeyDispatcher</item>
+ <item>@string/config_systemUIVendorServiceComponent</item>
+ <item>com.android.systemui.SliceBroadcastRelayHandler</item>
+ <item>com.android.systemui.SizeCompatModeActivityController</item>
+ <item>com.android.systemui.statusbar.notification.InstantAppNotifier</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index dbb193669083..19381940543e 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -44,13 +44,19 @@ import static java.lang.annotation.RetentionPolicy.SOURCE;
import android.annotation.UserIdInt;
import android.app.ActivityManager.RunningTaskInfo;
+import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
+import android.app.RemoteInput;
import android.content.Context;
+import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
+import android.content.pm.ShortcutManager;
import android.content.res.Configuration;
import android.graphics.Rect;
+import android.net.Uri;
+import android.os.Handler;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.service.notification.NotificationListenerService.RankingMap;
@@ -69,6 +75,7 @@ import androidx.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.statusbar.IStatusBarService;
+import com.android.internal.util.ScreenshotHelper;
import com.android.systemui.R;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -86,6 +93,7 @@ import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.StatusBarWindowController;
import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.RemoteInputUriController;
import com.android.systemui.statusbar.policy.ZenModeController;
import java.io.FileDescriptor;
@@ -93,8 +101,10 @@ import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.function.Consumer;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -138,6 +148,8 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
@Nullable private BubbleStackView.SurfaceSynchronizer mSurfaceSynchronizer;
private final NotificationGroupManager mNotificationGroupManager;
private final Lazy<ShadeController> mShadeController;
+ private final RemoteInputUriController mRemoteInputUriController;
+ private Handler mHandler = new Handler() {};
private BubbleData mBubbleData;
@Nullable private BubbleStackView mStackView;
@@ -155,6 +167,8 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
private final StatusBarWindowController mStatusBarWindowController;
private final ZenModeController mZenModeController;
private StatusBarStateListener mStatusBarStateListener;
+ private final ScreenshotHelper mScreenshotHelper;
+
private final NotificationInterruptionStateProvider mNotificationInterruptionStateProvider;
private IStatusBarService mBarService;
@@ -192,6 +206,16 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
}
/**
+ * Listener for handling bubble screenshot events.
+ */
+ public interface BubbleScreenshotListener {
+ /**
+ * Called to trigger taking a screenshot and sending the result to a bubble.
+ */
+ void onBubbleScreenshot(Bubble bubble);
+ }
+
+ /**
* Listens for the current state of the status bar and updates the visibility state
* of bubbles as needed.
*/
@@ -226,10 +250,12 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
ZenModeController zenModeController,
NotificationLockscreenUserManager notifUserManager,
NotificationGroupManager groupManager,
- NotificationEntryManager entryManager) {
+ NotificationEntryManager entryManager,
+ RemoteInputUriController remoteInputUriController) {
this(context, statusBarWindowController, statusBarStateController, shadeController,
data, null /* synchronizer */, configurationController, interruptionStateProvider,
- zenModeController, notifUserManager, groupManager, entryManager);
+ zenModeController, notifUserManager, groupManager, entryManager,
+ remoteInputUriController);
}
public BubbleController(Context context,
@@ -243,11 +269,13 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
ZenModeController zenModeController,
NotificationLockscreenUserManager notifUserManager,
NotificationGroupManager groupManager,
- NotificationEntryManager entryManager) {
+ NotificationEntryManager entryManager,
+ RemoteInputUriController remoteInputUriController) {
mContext = context;
mNotificationInterruptionStateProvider = interruptionStateProvider;
mNotifUserManager = notifUserManager;
mZenModeController = zenModeController;
+ mRemoteInputUriController = remoteInputUriController;
mZenModeController.addCallback(new ZenModeController.Callback() {
@Override
public void onZenChanged(int zen) {
@@ -320,6 +348,8 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
});
mUserCreatedBubbles = new HashSet<>();
+
+ mScreenshotHelper = new ScreenshotHelper(context);
}
/**
@@ -337,6 +367,9 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
if (mExpandListener != null) {
mStackView.setExpandListener(mExpandListener);
}
+ if (mBubbleScreenshotListener != null) {
+ mStackView.setBubbleScreenshotListener(mBubbleScreenshotListener);
+ }
}
}
@@ -1058,4 +1091,71 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
}
}
}
+
+ // TODO: Copied from RemoteInputView. Consolidate RemoteInput intent logic.
+ private Intent prepareRemoteInputFromData(String contentType, Uri data,
+ RemoteInput remoteInput, NotificationEntry entry) {
+ HashMap<String, Uri> results = new HashMap<>();
+ results.put(contentType, data);
+ mRemoteInputUriController.grantInlineReplyUriPermission(entry.getSbn(), data);
+ Intent fillInIntent = new Intent().addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+ RemoteInput.addDataResultToIntent(remoteInput, fillInIntent, results);
+
+ return fillInIntent;
+ }
+
+ // TODO: Copied from RemoteInputView. Consolidate RemoteInput intent logic.
+ private void sendRemoteInput(Intent intent, NotificationEntry entry,
+ PendingIntent pendingIntent) {
+ // Tell ShortcutManager that this package has been "activated". ShortcutManager
+ // will reset the throttling for this package.
+ // Strictly speaking, the intent receiver may be different from the notification publisher,
+ // but that's an edge case, and also because we can't always know which package will receive
+ // an intent, so we just reset for the publisher.
+ mContext.getSystemService(ShortcutManager.class).onApplicationActive(
+ entry.getSbn().getPackageName(),
+ entry.getSbn().getUser().getIdentifier());
+
+ try {
+ pendingIntent.send(mContext, 0, intent);
+ } catch (PendingIntent.CanceledException e) {
+ Log.i(TAG, "Unable to send remote input result", e);
+ }
+ }
+
+ private void sendScreenshotToBubble(Bubble bubble) {
+ // delay allows the bubble menu to disappear before the screenshot
+ // done here because we already have a Handler to delay with.
+ // TODO: Hide bubble + menu UI from screenshots entirely instead of just delaying.
+ mHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ mScreenshotHelper.takeScreenshot(
+ android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN,
+ true /* hasStatus */,
+ true /* hasNav */,
+ mHandler,
+ new Consumer<Uri>() {
+ @Override
+ public void accept(Uri uri) {
+ if (uri != null) {
+ NotificationEntry entry = bubble.getEntry();
+ Pair<RemoteInput, Notification.Action> pair = entry.getSbn()
+ .getNotification().findRemoteInputActionPair(false);
+ RemoteInput remoteInput = pair.first;
+ Notification.Action action = pair.second;
+ Intent dataIntent = prepareRemoteInputFromData("image/png", uri,
+ remoteInput, entry);
+ sendRemoteInput(dataIntent, entry, action.actionIntent);
+ mBubbleData.setSelectedBubble(bubble);
+ mBubbleData.setExpanded(true);
+ }
+ }
+ });
+ }
+ }, 200);
+ }
+
+ private final BubbleScreenshotListener mBubbleScreenshotListener =
+ bubble -> sendScreenshotToBubble(bubble);
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExperimentConfig.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExperimentConfig.java
index e138d9387ca6..8299f2261b8e 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExperimentConfig.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExperimentConfig.java
@@ -68,6 +68,9 @@ public class BubbleExperimentConfig {
private static final String WHITELISTED_AUTO_BUBBLE_APPS = "whitelisted_auto_bubble_apps";
+ private static final String ALLOW_BUBBLE_MENU = "allow_bubble_screenshot_menu";
+ private static final boolean ALLOW_BUBBLE_MENU_DEFAULT = false;
+
/**
* When true, if a notification has the information necessary to bubble (i.e. valid
* contentIntent and an icon or image), then a {@link android.app.Notification.BubbleMetadata}
@@ -123,6 +126,16 @@ public class BubbleExperimentConfig {
}
/**
+ * When true, show a menu when a bubble is long-pressed, which will allow the user to take
+ * actions on that bubble.
+ */
+ static boolean allowBubbleScreenshotMenu(Context context) {
+ return Settings.Secure.getInt(context.getContentResolver(),
+ ALLOW_BUBBLE_MENU,
+ ALLOW_BUBBLE_MENU_DEFAULT ? 1 : 0) != 0;
+ }
+
+ /**
* If {@link #allowAnyNotifToBubble(Context)} is true, this method creates and adds
* {@link android.app.Notification.BubbleMetadata} to the notification entry as long as
* the notification has necessary info for BubbleMetadata.
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleMenuView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleMenuView.java
new file mode 100644
index 000000000000..e8eb72e8392f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleMenuView.java
@@ -0,0 +1,81 @@
+/*
+ * 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.bubbles;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+
+import com.android.systemui.R;
+
+/**
+ * Menu which allows users to take actions on bubbles, ex. screenshots.
+ */
+public class BubbleMenuView extends FrameLayout {
+ private FrameLayout mMenu;
+ private boolean mShowing = false;
+
+ public BubbleMenuView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public BubbleMenuView(Context context) {
+ super(context);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mMenu = findViewById(R.id.bubble_menu_view);
+ ImageView icon = findViewById(com.android.internal.R.id.icon);
+ icon.setImageDrawable(mContext.getDrawable(com.android.internal.R.drawable.ic_screenshot));
+ }
+
+ /**
+ * Get the bubble menu view.
+ */
+ public View getMenuView() {
+ return mMenu;
+ }
+
+ /**
+ * Checks whether the bubble menu is currently displayed.
+ */
+ public boolean isShowing() {
+ return mShowing;
+ }
+
+ /**
+ * Show the bubble menu at the specified position on the screen.
+ */
+ public void show(float x, float y) {
+ mShowing = true;
+ this.setVisibility(VISIBLE);
+ mMenu.setTranslationX(x);
+ mMenu.setTranslationY(y);
+ }
+
+ /**
+ * Hide the bubble menu.
+ */
+ public void hide() {
+ mShowing = false;
+ this.setVisibility(GONE);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index 29de2f049690..29a4bb1fca84 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -110,6 +110,7 @@ public class BubbleStackView extends FrameLayout {
/** How long to wait, in milliseconds, before hiding the flyout. */
@VisibleForTesting
static final int FLYOUT_HIDE_AFTER = 5000;
+ private BubbleController.BubbleScreenshotListener mBubbleScreenshotListener;
/**
* Interface to synchronize {@link View} state and the screen.
@@ -163,6 +164,7 @@ public class BubbleStackView extends FrameLayout {
private ExpandedAnimationController mExpandedAnimationController;
private FrameLayout mExpandedViewContainer;
+ @Nullable private BubbleMenuView mBubbleMenuView;
private BubbleFlyoutView mFlyout;
/** Runnable that fades out the flyout and then sets it to GONE. */
@@ -194,6 +196,7 @@ public class BubbleStackView extends FrameLayout {
private int mPointerHeight;
private int mStatusBarHeight;
private int mImeOffset;
+ private int mBubbleMenuOffset = 252;
private BubbleIconFactory mBubbleIconFactory;
private Bubble mExpandedBubble;
private boolean mIsExpanded;
@@ -492,6 +495,9 @@ public class BubbleStackView extends FrameLayout {
mDesaturateAndDarkenPaint.setColorFilter(new ColorMatrixColorFilter(animatedMatrix));
mDesaturateAndDarkenTargetView.setLayerPaint(mDesaturateAndDarkenPaint);
});
+
+ mInflater.inflate(R.layout.bubble_menu_view, this);
+ mBubbleMenuView = findViewById(R.id.bubble_menu_container);
}
private void setUpFlyout() {
@@ -683,6 +689,13 @@ public class BubbleStackView extends FrameLayout {
}
/**
+ * Sets the screenshot listener.
+ */
+ public void setBubbleScreenshotListener(BubbleController.BubbleScreenshotListener listener) {
+ mBubbleScreenshotListener = listener;
+ }
+
+ /**
* Whether the stack of bubbles is expanded or not.
*/
public boolean isExpanded() {
@@ -870,6 +883,12 @@ public class BubbleStackView extends FrameLayout {
public View getTargetView(MotionEvent event) {
float x = event.getRawX();
float y = event.getRawY();
+ if (mBubbleMenuView.isShowing()) {
+ if (isIntersecting(mBubbleMenuView.getMenuView(), x, y)) {
+ return mBubbleMenuView;
+ }
+ return null;
+ }
if (mIsExpanded) {
if (isIntersecting(mBubbleContainer, x, y)) {
// Could be tapping or dragging a bubble while expanded
@@ -1074,6 +1093,7 @@ public class BubbleStackView extends FrameLayout {
return;
}
+ hideBubbleMenu();
mStackAnimationController.cancelStackPositionAnimations();
mBubbleContainer.setActiveController(mStackAnimationController);
hideFlyoutImmediate();
@@ -1473,6 +1493,11 @@ public class BubbleStackView extends FrameLayout {
@Override
public void getBoundsOnScreen(Rect outRect) {
+ // If the bubble menu is open, the entire screen should capture touch events.
+ if (mBubbleMenuView.isShowing()) {
+ outRect.set(0, 0, getWidth(), getHeight());
+ return;
+ }
if (!mIsExpanded) {
if (mBubbleContainer.getChildCount() > 0) {
mBubbleContainer.getChildAt(0).getBoundsOnScreen(outRect);
@@ -1700,4 +1725,43 @@ public class BubbleStackView extends FrameLayout {
}
return bubbles;
}
+
+ /**
+ * Show the bubble menu, positioned relative to the stack.
+ */
+ public void showBubbleMenu() {
+ PointF currentPos = mStackAnimationController.getStackPosition();
+ float yPos = currentPos.y;
+ float xPos = currentPos.x;
+ if (mStackAnimationController.isStackOnLeftSide()) {
+ xPos += mBubbleSize;
+ } else {
+ //TODO: Use the width of the menu instead of this fixed offset. Offset used for now
+ // because menu width isn't correct the first time the menu is shown.
+ xPos -= mBubbleMenuOffset;
+ }
+
+ mBubbleMenuView.show(xPos, yPos);
+ }
+
+ /**
+ * Hide the bubble menu.
+ */
+ public void hideBubbleMenu() {
+ mBubbleMenuView.hide();
+ }
+
+ /**
+ * Determines whether the bubble menu is currently showing.
+ */
+ public boolean isShowingBubbleMenu() {
+ return mBubbleMenuView.isShowing();
+ }
+
+ /**
+ * Take a screenshot and send it to the specified bubble.
+ */
+ public void sendScreenshotToBubble(Bubble bubble) {
+ mBubbleScreenshotListener.onBubbleScreenshot(bubble);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleTouchHandler.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleTouchHandler.java
index 44e013a34f54..b1d205c79c99 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleTouchHandler.java
@@ -57,6 +57,7 @@ class BubbleTouchHandler implements View.OnTouchListener {
private final PointF mViewPositionOnTouchDown = new PointF();
private final BubbleStackView mStack;
private final BubbleData mBubbleData;
+ private final Context mContext;
private BubbleController mController = Dependency.get(BubbleController.class);
@@ -75,6 +76,7 @@ class BubbleTouchHandler implements View.OnTouchListener {
mTouchSlopSquared = touchSlop * touchSlop;
mBubbleData = bubbleData;
mStack = stackView;
+ mContext = context;
}
@Override
@@ -91,15 +93,24 @@ class BubbleTouchHandler implements View.OnTouchListener {
// anything, collapse the stack.
if (action == MotionEvent.ACTION_OUTSIDE || mTouchedView == null) {
mBubbleData.setExpanded(false);
+ mStack.hideBubbleMenu();
resetForNextGesture();
return false;
}
+ if (mTouchedView instanceof BubbleMenuView) {
+ mStack.hideBubbleMenu();
+ resetForNextGesture();
+ mStack.sendScreenshotToBubble(mBubbleData.getSelectedBubble());
+ return false;
+ }
+
if (!(mTouchedView instanceof BadgedImageView)
&& !(mTouchedView instanceof BubbleStackView)
&& !(mTouchedView instanceof BubbleFlyoutView)) {
// Not touching anything touchable, but we shouldn't collapse (e.g. touching edge
// of expanded view).
+ mStack.hideBubbleMenu();
resetForNextGesture();
return false;
}
@@ -132,6 +143,10 @@ class BubbleTouchHandler implements View.OnTouchListener {
break;
case MotionEvent.ACTION_MOVE:
+ // block all further touch inputs once the menu is open
+ if (mStack.isShowingBubbleMenu()) {
+ return true;
+ }
trackMovement(event);
final float deltaX = rawX - mTouchDown.x;
final float deltaY = rawY - mTouchDown.y;
@@ -148,6 +163,13 @@ class BubbleTouchHandler implements View.OnTouchListener {
} else {
mStack.onBubbleDragged(mTouchedView, viewX, viewY);
}
+ } else {
+ float touchTime = event.getEventTime() - event.getDownTime();
+ if (touchTime > ViewConfiguration.getLongPressTimeout() && !mStack.isExpanded()
+ && BubbleExperimentConfig.allowBubbleScreenshotMenu(mContext)) {
+ mStack.showBubbleMenu();
+ return true;
+ }
}
final boolean currentlyInDismissTarget = mStack.isInDismissTarget(event);
@@ -171,6 +193,10 @@ class BubbleTouchHandler implements View.OnTouchListener {
break;
case MotionEvent.ACTION_UP:
+ if (mStack.isShowingBubbleMenu()) {
+ resetForNextGesture();
+ return true;
+ }
trackMovement(event);
mVelocityTracker.computeCurrentVelocity(/* maxVelocity */ 1000);
final float velX = mVelocityTracker.getXVelocity();
@@ -261,7 +287,6 @@ class BubbleTouchHandler implements View.OnTouchListener {
mVelocityTracker.recycle();
mVelocityTracker = null;
}
-
mTouchedView = null;
mMovedEnough = false;
mInDismissTarget = false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
index d3a9c2c3c87d..246b0f0e19ff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
@@ -61,7 +61,6 @@ import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.LockscreenWallpaper;
import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.phone.ScrimState;
-import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.StatusBarWindowController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -105,9 +104,6 @@ public class NotificationMediaManager implements Dumpable {
private final NotificationEntryManager mEntryManager;
- // Late binding, also @Nullable due to being in com.android.systemui.statusbar.phone package
- @Nullable
- private Lazy<ShadeController> mShadeController;
@Nullable
private Lazy<StatusBarWindowController> mStatusBarWindowController;
@@ -183,7 +179,6 @@ public class NotificationMediaManager implements Dumpable {
@Inject
public NotificationMediaManager(
Context context,
- Lazy<ShadeController> shadeController,
Lazy<StatusBar> statusBarLazy,
Lazy<StatusBarWindowController> statusBarWindowController,
NotificationEntryManager notificationEntryManager,
@@ -193,11 +188,10 @@ public class NotificationMediaManager implements Dumpable {
mMediaArtworkProcessor = mediaArtworkProcessor;
mKeyguardBypassController = keyguardBypassController;
mMediaListeners = new ArrayList<>();
- mMediaSessionManager
- = (MediaSessionManager) mContext.getSystemService(Context.MEDIA_SESSION_SERVICE);
// TODO: use MediaSessionManager.SessionListener to hook us up to future updates
// in session state
- mShadeController = shadeController;
+ mMediaSessionManager = (MediaSessionManager) mContext.getSystemService(
+ Context.MEDIA_SESSION_SERVICE);
// TODO: use KeyguardStateController#isOccluded to remove this dependency
mStatusBarLazy = statusBarLazy;
mStatusBarWindowController = statusBarWindowController;
@@ -603,9 +597,7 @@ public class NotificationMediaManager implements Dumpable {
if (DEBUG_MEDIA) {
Log.v(TAG, "DEBUG_MEDIA: Fading out album artwork");
}
- ShadeController shadeController = mShadeController.get();
- boolean cannotAnimateDoze = shadeController != null
- && shadeController.isDozing()
+ boolean cannotAnimateDoze = mStatusBarStateController.isDozing()
&& !ScrimState.AOD.getAnimateChange();
boolean needsBypassFading = mKeyguardStateController.isBypassFadingAnimation();
if (((mBiometricUnlockController != null && mBiometricUnlockController.getMode()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
index c556bc0b39d1..f6f3ac1b5aaf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
@@ -58,7 +58,7 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntry.EditedSuggestionInfo;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
-import com.android.systemui.statusbar.phone.ShadeController;
+import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.RemoteInputUriController;
import com.android.systemui.statusbar.policy.RemoteInputView;
@@ -116,7 +116,7 @@ public class NotificationRemoteInputManager implements Dumpable {
private final NotificationEntryManager mEntryManager;
private final Handler mMainHandler;
- private final Lazy<ShadeController> mShadeController;
+ private final Lazy<StatusBar> mStatusBarLazy;
protected final Context mContext;
private final UserManager mUserManager;
@@ -136,7 +136,7 @@ public class NotificationRemoteInputManager implements Dumpable {
@Override
public boolean onClickHandler(
View view, PendingIntent pendingIntent, RemoteViews.RemoteResponse response) {
- mShadeController.get().wakeUpIfDozing(SystemClock.uptimeMillis(), view,
+ mStatusBarLazy.get().wakeUpIfDozing(SystemClock.uptimeMillis(), view,
"NOTIFICATION_CLICK");
if (handleRemoteInput(view, pendingIntent)) {
@@ -261,7 +261,7 @@ public class NotificationRemoteInputManager implements Dumpable {
NotificationLockscreenUserManager lockscreenUserManager,
SmartReplyController smartReplyController,
NotificationEntryManager notificationEntryManager,
- Lazy<ShadeController> shadeController,
+ Lazy<StatusBar> statusBarLazy,
StatusBarStateController statusBarStateController,
@MainHandler Handler mainHandler,
RemoteInputUriController remoteInputUriController) {
@@ -269,7 +269,7 @@ public class NotificationRemoteInputManager implements Dumpable {
mLockscreenUserManager = lockscreenUserManager;
mSmartReplyController = smartReplyController;
mEntryManager = notificationEntryManager;
- mShadeController = shadeController;
+ mStatusBarLazy = statusBarLazy;
mMainHandler = mainHandler;
mBarService = IStatusBarService.Stub.asInterface(
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt b/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
index e516af590e34..88f148b00cdc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
@@ -211,7 +211,7 @@ constructor(
setUserLocked(mStartingChild!!, false)
mStartingChild = null
}
- if (shadeController.isDozing) {
+ if (statusBarStateController.isDozing) {
isWakingToShadeLocked = true
wakeUpCoordinator.willWakeUp = true
mPowerManager!!.wakeUp(SystemClock.uptimeMillis(), WAKE_REASON_GESTURE,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java
index 65f3fa94374b..31b7cb0fb5a0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java
@@ -24,18 +24,16 @@ import android.service.notification.StatusBarNotification;
import android.util.Log;
import com.android.internal.statusbar.NotificationVisibility;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag;
-import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import javax.inject.Inject;
import javax.inject.Singleton;
-import dagger.Lazy;
-
/** Handles heads-up and pulsing behavior driven by notification changes. */
@Singleton
public class NotificationAlertingManager {
@@ -44,7 +42,7 @@ public class NotificationAlertingManager {
private final NotificationRemoteInputManager mRemoteInputManager;
private final VisualStabilityManager mVisualStabilityManager;
- private final Lazy<ShadeController> mShadeController;
+ private final StatusBarStateController mStatusBarStateController;
private final NotificationInterruptionStateProvider mNotificationInterruptionStateProvider;
private final NotificationListener mNotificationListener;
@@ -55,12 +53,12 @@ public class NotificationAlertingManager {
NotificationEntryManager notificationEntryManager,
NotificationRemoteInputManager remoteInputManager,
VisualStabilityManager visualStabilityManager,
- Lazy<ShadeController> shadeController,
+ StatusBarStateController statusBarStateController,
NotificationInterruptionStateProvider notificationInterruptionStateProvider,
NotificationListener notificationListener) {
mRemoteInputManager = remoteInputManager;
mVisualStabilityManager = visualStabilityManager;
- mShadeController = shadeController;
+ mStatusBarStateController = statusBarStateController;
mNotificationInterruptionStateProvider = notificationInterruptionStateProvider;
mNotificationListener = notificationListener;
@@ -102,7 +100,7 @@ public class NotificationAlertingManager {
// If it does and we no longer need to heads up, we should free the view.
if (mNotificationInterruptionStateProvider.shouldHeadsUp(entry)) {
mHeadsUpManager.showNotification(entry);
- if (!mShadeController.get().isDozing()) {
+ if (!mStatusBarStateController.isDozing()) {
// Mark as seen immediately
setNotificationShown(entry.getSbn());
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClicker.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClicker.java
index b5c664116944..8ecf2b8421f0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClicker.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClicker.java
@@ -24,7 +24,7 @@ import android.view.View;
import com.android.systemui.DejankUtils;
import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
-import com.android.systemui.statusbar.phone.ShadeController;
+import com.android.systemui.statusbar.phone.StatusBar;
/**
* Click handler for generic clicks on notifications. Clicks on specific areas (expansion caret,
@@ -33,14 +33,14 @@ import com.android.systemui.statusbar.phone.ShadeController;
public final class NotificationClicker implements View.OnClickListener {
private static final String TAG = "NotificationClicker";
- private final ShadeController mShadeController;
+ private final StatusBar mStatusBar;
private final BubbleController mBubbleController;
private final NotificationActivityStarter mNotificationActivityStarter;
- public NotificationClicker(ShadeController shadeController,
+ public NotificationClicker(StatusBar statusBar,
BubbleController bubbleController,
NotificationActivityStarter notificationActivityStarter) {
- mShadeController = shadeController;
+ mStatusBar = statusBar;
mBubbleController = bubbleController;
mNotificationActivityStarter = notificationActivityStarter;
}
@@ -52,7 +52,7 @@ public final class NotificationClicker implements View.OnClickListener {
return;
}
- mShadeController.wakeUpIfDozing(SystemClock.uptimeMillis(), v, "NOTIFICATION_CLICK");
+ mStatusBar.wakeUpIfDozing(SystemClock.uptimeMillis(), v, "NOTIFICATION_CLICK");
final ExpandableNotificationRow row = (ExpandableNotificationRow) v;
final StatusBarNotification sbn = row.getEntry().getSbn();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java
index b61c1ef50cae..6c61923332ea 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java
@@ -27,6 +27,7 @@ import android.service.notification.StatusBarNotification;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.Dependency;
import com.android.systemui.ForegroundServiceController;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
@@ -45,6 +46,7 @@ public class NotificationFilter {
private final NotificationGroupManager mGroupManager = Dependency.get(
NotificationGroupManager.class);
+ private final StatusBarStateController mStatusBarStateController;
private NotificationEntryManager.KeyguardEnvironment mEnvironment;
private ShadeController mShadeController;
@@ -52,7 +54,9 @@ public class NotificationFilter {
private NotificationLockscreenUserManager mUserManager;
@Inject
- public NotificationFilter() {}
+ public NotificationFilter(StatusBarStateController statusBarStateController) {
+ mStatusBarStateController = statusBarStateController;
+ }
private NotificationEntryManager.KeyguardEnvironment getEnvironment() {
if (mEnvironment == null) {
@@ -104,11 +108,11 @@ public class NotificationFilter {
return true;
}
- if (getShadeController().isDozing() && entry.shouldSuppressAmbient()) {
+ if (mStatusBarStateController.isDozing() && entry.shouldSuppressAmbient()) {
return true;
}
- if (!getShadeController().isDozing() && entry.shouldSuppressNotificationList()) {
+ if (!mStatusBarStateController.isDozing() && entry.shouldSuppressNotificationList()) {
return true;
}
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 35407c6df690..ed2fb0fdcb1a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -2989,7 +2989,7 @@ public class NotificationPanelView extends PanelView implements
return true;
case StatusBarState.SHADE_LOCKED:
if (!mQsExpanded) {
- mShadeController.goToKeyguard();
+ mStatusBarStateController.setState(StatusBarState.KEYGUARD);
}
return true;
case StatusBarState.SHADE:
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeController.java
index b31ce6afc281..deea3f17aad0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeController.java
@@ -14,11 +14,9 @@
package com.android.systemui.statusbar.phone;
-import android.annotation.NonNull;
import android.view.View;
import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
/**
* {@link ShadeController} is an abstraction of the work that used to be hard-coded in
@@ -30,14 +28,6 @@ import com.android.systemui.statusbar.notification.row.ActivatableNotificationVi
public interface ShadeController {
/**
- * Shows the keyguard bouncer - the password challenge on the lock screen
- *
- * @param scrimmed true when the bouncer should show scrimmed, false when the user will be
- * dragging it and translation should be deferred {@see KeyguardBouncer#show(boolean, boolean)}
- */
- void showBouncer(boolean scrimmed);
-
- /**
* Make our window larger and the panel expanded
*/
void instantExpandNotificationsPanel();
@@ -71,12 +61,6 @@ public interface ShadeController {
void addPostCollapseAction(Runnable action);
/**
- * Ask shade controller to set the state to {@link StatusBarState#KEYGUARD}, but only from
- * {@link StatusBarState#SHADE_LOCKED}
- */
- void goToKeyguard();
-
- /**
* Notify the shade controller that the current user changed
*
* @param newUserId userId of the new user
@@ -84,22 +68,6 @@ public interface ShadeController {
void setLockscreenUser(int newUserId);
/**
- * Dozing is when the screen is in AOD or asleep
- *
- * @return true if we are dozing
- */
- boolean isDozing();
-
- /**
- * Ask the display to wake up if currently dozing, else do nothing
- *
- * @param time when to wake up
- * @param view the view requesting the wakeup
- * @param why the reason for the wake up
- */
- void wakeUpIfDozing(long time, View view, @NonNull String why);
-
- /**
* If secure with redaction: Show bouncer, go to unlocked shade.
*
* <p>If secure without redaction or no security: Go to {@link StatusBarState#SHADE_LOCKED}.</p>
@@ -109,11 +77,6 @@ public interface ShadeController {
void goToLockedShade(View startingChild);
/**
- * Adds a {@param runnable} to be executed after Keyguard is gone.
- */
- void addAfterKeyguardGoneRunnable(Runnable runnable);
-
- /**
* Close the shade if it was open
*
* @return true if the shade was open, else false
@@ -127,16 +90,4 @@ public interface ShadeController {
* @param animate
*/
void collapsePanel(boolean animate);
-
- /**
- * Callback to tell the shade controller that an activity launch animation was canceled
- */
- void onLaunchAnimationCancelled();
-
- /**
- * Callback to notify the shade controller that a {@link ActivatableNotificationView} has become
- * inactive
- */
- void onActivationReset();
-
}
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 5575d10c7fe1..709143d7275a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -1239,6 +1239,7 @@ public class StatusBar extends SystemUI implements DemoMode,
mHeadsUpManager, mStatusBarWindow, mStackScroller, mDozeScrimController,
mScrimController, mActivityLaunchAnimator, mDynamicPrivacyController,
mNotificationAlertingManager, rowBinder, mKeyguardStateController,
+ mKeyguardIndicationController,
this /* statusBar */, mCommandQueue);
mNotificationListController =
@@ -1282,17 +1283,13 @@ public class StatusBar extends SystemUI implements DemoMode,
mCommandQueue.disable(mDisplayId, state1, state2, false /* animate */);
}
- @Override
- public void addAfterKeyguardGoneRunnable(Runnable runnable) {
- mStatusBarKeyguardViewManager.addAfterKeyguardGoneRunnable(runnable);
- }
-
- @Override
- public boolean isDozing() {
- return mDozing;
- }
-
- @Override
+ /**
+ * Ask the display to wake up if currently dozing, else do nothing
+ *
+ * @param time when to wake up
+ * @param where the view requesting the wakeup
+ * @param why the reason for the wake up
+ */
public void wakeUpIfDozing(long time, View where, String why) {
if (mDozing) {
mPowerManager.wakeUp(
@@ -1708,7 +1705,7 @@ public class StatusBar extends SystemUI implements DemoMode,
@Override
public void onHeadsUpStateChanged(NotificationEntry entry, boolean isHeadsUp) {
mEntryManager.updateNotifications("onHeadsUpStateChanged");
- if (isDozing() && isHeadsUp) {
+ if (mStatusBarStateController.isDozing() && isHeadsUp) {
entry.setPulseSuppressed(false);
mDozeServiceHost.fireNotificationPulse(entry);
if (mDozeServiceHost.isPulsing()) {
@@ -3453,16 +3450,11 @@ public class StatusBar extends SystemUI implements DemoMode,
private void showBouncerIfKeyguard() {
if ((mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED)
&& !mKeyguardViewMediator.isHiding()) {
- showBouncer(true /* scrimmed */);
+ mStatusBarKeyguardViewManager.showBouncer(true /* scrimmed */);
}
}
@Override
- public void showBouncer(boolean scrimmed) {
- mStatusBarKeyguardViewManager.showBouncer(scrimmed);
- }
-
- @Override
public void instantExpandNotificationsPanel() {
// Make our window larger and the panel expanded.
makeExpandedVisible(true);
@@ -3583,10 +3575,6 @@ public class StatusBar extends SystemUI implements DemoMode,
mStatusBarKeyguardViewManager.isOccluded());
}
- public void onActivationReset() {
- mKeyguardIndicationController.hideTransientIndication();
- }
-
public void onTrackingStarted() {
runPostCollapseRunnables();
}
@@ -3628,7 +3616,7 @@ public class StatusBar extends SystemUI implements DemoMode,
public void onTrackingStopped(boolean expand) {
if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) {
if (!expand && !mKeyguardStateController.canDismissLockScreen()) {
- showBouncer(false /* scrimmed */);
+ mStatusBarKeyguardViewManager.showBouncer(false /* scrimmed */);
}
}
}
@@ -3688,15 +3676,6 @@ public class StatusBar extends SystemUI implements DemoMode,
}
/**
- * Goes back to the keyguard after hanging around in {@link StatusBarState#SHADE_LOCKED}.
- */
- public void goToKeyguard() {
- if (mState == StatusBarState.SHADE_LOCKED) {
- mStatusBarStateController.setState(StatusBarState.KEYGUARD);
- }
- }
-
- /**
* Propagation of the bouncer state, indicating that it's fully visible.
*/
public void setBouncerShowing(boolean bouncerShowing) {
@@ -4019,7 +3998,8 @@ public class StatusBar extends SystemUI implements DemoMode,
}
public boolean shouldIgnoreTouch() {
- return isDozing() && mDozeServiceHost.getIgnoreTouchWhilePulsing();
+ return mStatusBarStateController.isDozing()
+ && mDozeServiceHost.getIgnoreTouchWhilePulsing();
}
// Begin Extra BaseStatusBar methods.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 31d03621d23b..dac4e585c1ac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -365,6 +365,12 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
cancelPendingWakeupAction();
}
+ /**
+ * Shows the keyguard bouncer - the password challenge on the lock screen
+ *
+ * @param scrimmed true when the bouncer should show scrimmed, false when the user will be
+ * dragging it and translation should be deferred {@see KeyguardBouncer#show(boolean, boolean)}
+ */
public void showBouncer(boolean scrimmed) {
if (mShowing && !mBouncer.isShowing()) {
mBouncer.show(false /* resetSecuritySelection */, scrimmed);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
index e2832587e2ea..1988b42be14f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -105,6 +105,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
private final NotificationPresenter mPresenter;
private final LockPatternUtils mLockPatternUtils;
private final HeadsUpManagerPhone mHeadsUpManager;
+ private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
private final KeyguardManager mKeyguardManager;
private final ActivityLaunchAnimator mActivityLaunchAnimator;
private final IStatusBarService mBarService;
@@ -122,7 +123,9 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
NotificationPresenter presenter, NotificationEntryManager entryManager,
HeadsUpManagerPhone headsUpManager, ActivityStarter activityStarter,
ActivityLaunchAnimator activityLaunchAnimator, IStatusBarService statusBarService,
- StatusBarStateController statusBarStateController, KeyguardManager keyguardManager,
+ StatusBarStateController statusBarStateController,
+ StatusBarKeyguardViewManager statusBarKeyguardViewManager,
+ KeyguardManager keyguardManager,
IDreamManager dreamManager, NotificationRemoteInputManager remoteInputManager,
StatusBarRemoteInputCallback remoteInputCallback, NotificationGroupManager groupManager,
NotificationLockscreenUserManager lockscreenUserManager,
@@ -139,6 +142,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
mActivityLaunchAnimator = activityLaunchAnimator;
mBarService = statusBarService;
mCommandQueue = commandQueue;
+ mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
mKeyguardManager = keyguardManager;
mDreamManager = dreamManager;
mRemoteInputManager = remoteInputManager;
@@ -258,7 +262,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
mShadeController.collapsePanel(true /* animate */);
} else if (mKeyguardStateController.isShowing()
&& mStatusBar.isOccluded()) {
- mShadeController.addAfterKeyguardGoneRunnable(runnable);
+ mStatusBarKeyguardViewManager.addAfterKeyguardGoneRunnable(runnable);
mShadeController.collapsePanel();
} else {
mBackgroundHandler.postAtFrontOfQueue(runnable);
@@ -504,6 +508,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
private final ActivityStarter mActivityStarter;
private final IStatusBarService mStatusBarService;
private final StatusBarStateController mStatusBarStateController;
+ private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
private final KeyguardManager mKeyguardManager;
private final IDreamManager mDreamManager;
private final NotificationRemoteInputManager mRemoteInputManager;
@@ -533,6 +538,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
ActivityStarter activityStarter,
IStatusBarService statusBarService,
StatusBarStateController statusBarStateController,
+ StatusBarKeyguardViewManager statusBarKeyguardViewManager,
KeyguardManager keyguardManager,
IDreamManager dreamManager,
NotificationRemoteInputManager remoteInputManager,
@@ -556,6 +562,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
mActivityStarter = activityStarter;
mStatusBarService = statusBarService;
mStatusBarStateController = statusBarStateController;
+ mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
mKeyguardManager = keyguardManager;
mDreamManager = dreamManager;
mRemoteInputManager = remoteInputManager;
@@ -601,6 +608,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
mActivityLaunchAnimator,
mStatusBarService,
mStatusBarStateController,
+ mStatusBarKeyguardViewManager,
mKeyguardManager,
mDreamManager,
mRemoteInputManager,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
index 6650cf6a5af6..2649166bfcbf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
@@ -49,6 +49,7 @@ import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.KeyguardIndicationController;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.NotificationPresenter;
@@ -113,6 +114,7 @@ public class StatusBarNotificationPresenter implements NotificationPresenter,
private final DozeScrimController mDozeScrimController;
private final ScrimController mScrimController;
private final Context mContext;
+ private final KeyguardIndicationController mKeyguardIndicationController;
private final StatusBar mStatusBar;
private final CommandQueue mCommandQueue;
@@ -141,6 +143,7 @@ public class StatusBarNotificationPresenter implements NotificationPresenter,
NotificationAlertingManager notificationAlertingManager,
NotificationRowBinderImpl notificationRowBinder,
KeyguardStateController keyguardStateController,
+ KeyguardIndicationController keyguardIndicationController,
StatusBar statusBar,
CommandQueue commandQueue) {
mContext = context;
@@ -148,6 +151,7 @@ public class StatusBarNotificationPresenter implements NotificationPresenter,
mNotificationPanel = panel;
mHeadsUpManager = headsUp;
mDynamicPrivacyController = dynamicPrivacyController;
+ mKeyguardIndicationController = keyguardIndicationController;
// TODO: use KeyguardStateController#isOccluded to remove this dependency
mStatusBar = statusBar;
mCommandQueue = commandQueue;
@@ -323,7 +327,7 @@ public class StatusBarNotificationPresenter implements NotificationPresenter,
mCommandQueue.animateCollapsePanels();
} else if (mStatusBarStateController.getState() == StatusBarState.SHADE_LOCKED
&& !isCollapsing()) {
- mShadeController.goToKeyguard();
+ mStatusBarStateController.setState(StatusBarState.KEYGUARD);
}
}
}
@@ -420,7 +424,7 @@ public class StatusBarNotificationPresenter implements NotificationPresenter,
public void onActivationReset(ActivatableNotificationView view) {
if (view == mNotificationPanel.getActivatedChild()) {
mNotificationPanel.setActivatedChild(null);
- mShadeController.onActivationReset();
+ mKeyguardIndicationController.hideTransientIndication();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
index 3e6ba4dacb71..2012b5703504 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
@@ -64,6 +64,7 @@ public class StatusBarRemoteInputCallback implements Callback, Callbacks,
private final ActivityStarter mActivityStarter;
private final Lazy<ShadeController> mShadeControllerLazy;
private final Context mContext;
+ private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
private final ActivityIntentHelper mActivityIntentHelper;
private final NotificationGroupManager mGroupManager;
private View mPendingWorkRemoteInputView;
@@ -81,9 +82,11 @@ public class StatusBarRemoteInputCallback implements Callback, Callbacks,
NotificationLockscreenUserManager notificationLockscreenUserManager,
KeyguardStateController keyguardStateController,
StatusBarStateController statusBarStateController,
+ StatusBarKeyguardViewManager statusBarKeyguardViewManager,
ActivityStarter activityStarter, Lazy<ShadeController> shadeControllerLazy,
CommandQueue commandQueue) {
mContext = context;
+ mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
mContext.registerReceiverAsUser(mChallengeReceiver, UserHandle.ALL,
new IntentFilter(ACTION_DEVICE_LOCKED_CHANGED), null, null);
mLockscreenUserManager = notificationLockscreenUserManager;
@@ -118,7 +121,7 @@ public class StatusBarRemoteInputCallback implements Callback, Callbacks,
if (!row.isPinned()) {
mStatusBarStateController.setLeaveOpenOnKeyguardHide(true);
}
- mShadeControllerLazy.get().showBouncer(true /* scrimmed */);
+ mStatusBarKeyguardViewManager.showBouncer(true /* scrimmed */);
mPendingRemoteInputView = clicked;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowViewController.java
index 3935df02fd91..f8929e01adb8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowViewController.java
@@ -263,7 +263,7 @@ public class StatusBarWindowViewController {
if (isDown) {
mStackScrollLayout.closeControlsIfOutsideTouch(ev);
}
- if (mService.isDozing()) {
+ if (mStatusBarStateController.isDozing()) {
mService.mDozeScrimController.extendPulse();
}
// In case we start outside of the view bounds (below the status bar), we need to
@@ -284,7 +284,8 @@ public class StatusBarWindowViewController {
@Override
public boolean shouldInterceptTouchEvent(MotionEvent ev) {
- if (mService.isDozing() && !mService.isPulsing() && !mDockManager.isDocked()) {
+ if (mStatusBarStateController.isDozing() && !mService.isPulsing()
+ && !mDockManager.isDocked()) {
// Capture all touch events in always-on.
return true;
}
@@ -292,7 +293,7 @@ public class StatusBarWindowViewController {
if (notificationPanelView.isFullyExpanded()
&& mDragDownHelper.isDragDownEnabled()
&& !mService.isBouncerShowing()
- && !mService.isDozing()) {
+ && !mStatusBarStateController.isDozing()) {
intercept = mDragDownHelper.onInterceptTouchEvent(ev);
}
@@ -312,7 +313,7 @@ public class StatusBarWindowViewController {
@Override
public boolean handleTouchEvent(MotionEvent ev) {
boolean handled = false;
- if (mService.isDozing()) {
+ if (mStatusBarStateController.isDozing()) {
handled = !mService.isPulsing();
}
if ((mDragDownHelper.isDragDownEnabled() && !handled)
@@ -358,7 +359,7 @@ public class StatusBarWindowViewController {
break;
case KeyEvent.KEYCODE_VOLUME_DOWN:
case KeyEvent.KEYCODE_VOLUME_UP:
- if (mService.isDozing()) {
+ if (mStatusBarStateController.isDozing()) {
MediaSessionLegacyHelper.getHelper(mView.getContext())
.sendVolumeKeyEvent(
event, AudioManager.USE_DEFAULT_STREAM_TYPE, true);
diff --git a/packages/SystemUI/src/com/android/systemui/util/concurrency/DelayableExecutor.java b/packages/SystemUI/src/com/android/systemui/util/concurrency/DelayableExecutor.java
index 2d6c4a62047d..ac15e2dd6df9 100644
--- a/packages/SystemUI/src/com/android/systemui/util/concurrency/DelayableExecutor.java
+++ b/packages/SystemUI/src/com/android/systemui/util/concurrency/DelayableExecutor.java
@@ -62,11 +62,4 @@ public interface DelayableExecutor extends Executor {
* @return A Runnable that, when run, removes the supplied argument from the Executor queue.
*/
Runnable executeAtTime(Runnable r, long uptimeMillis, TimeUnit unit);
-
- /**
- * Remove all pending Runnables.
- *
- */
- void removeAll();
-
}
diff --git a/packages/SystemUI/src/com/android/systemui/util/concurrency/ExecutorImpl.java b/packages/SystemUI/src/com/android/systemui/util/concurrency/ExecutorImpl.java
index 2a99de3ac5ad..7e7732135e3a 100644
--- a/packages/SystemUI/src/com/android/systemui/util/concurrency/ExecutorImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/util/concurrency/ExecutorImpl.java
@@ -50,9 +50,4 @@ public class ExecutorImpl extends HandlerExecutor implements DelayableExecutor {
return () -> mHandler.removeCallbacksAndMessages(token);
}
-
- @Override
- public void removeAll() {
- mHandler.removeCallbacksAndMessages(null);
- }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
index 4c707f45efc1..ae43aa2f4118 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
@@ -82,6 +82,7 @@ import com.android.systemui.statusbar.phone.StatusBarWindowController;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
+import com.android.systemui.statusbar.policy.RemoteInputUriController;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.util.InjectionInflationController;
@@ -153,6 +154,8 @@ public class BubbleControllerTest extends SysuiTestCase {
private Resources mResources;
@Mock
private Lazy<ShadeController> mShadeController;
+ @Mock
+ private RemoteInputUriController mRemoteInputUriController;
private SuperStatusBarViewFactory mSuperStatusBarViewFactory;
private BubbleData mBubbleData;
@@ -212,7 +215,8 @@ public class BubbleControllerTest extends SysuiTestCase {
mZenModeController,
mLockscreenUserManager,
mNotificationGroupManager,
- mNotificationEntryManager);
+ mNotificationEntryManager,
+ mRemoteInputUriController);
mBubbleController.setBubbleStateChangeListener(mBubbleStateChangeListener);
mBubbleController.setExpandListener(mBubbleExpandListener);
@@ -708,11 +712,13 @@ public class BubbleControllerTest extends SysuiTestCase {
ZenModeController zenModeController,
NotificationLockscreenUserManager lockscreenUserManager,
NotificationGroupManager groupManager,
- NotificationEntryManager entryManager) {
+ NotificationEntryManager entryManager,
+ RemoteInputUriController remoteInputUriController) {
super(context,
statusBarWindowController, statusBarStateController, shadeController,
data, Runnable::run, configurationController, interruptionStateProvider,
- zenModeController, lockscreenUserManager, groupManager, entryManager);
+ zenModeController, lockscreenUserManager, groupManager, entryManager,
+ remoteInputUriController);
}
}
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 a754a00df940..8aac1891a5e4 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,7 @@ 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.ShadeController;
+import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.RemoteInputUriController;
import com.google.android.collect.Sets;
@@ -76,7 +76,7 @@ public class NotificationRemoteInputManagerTest extends SysuiTestCase {
mRemoteInputManager = new TestableNotificationRemoteInputManager(mContext,
mLockscreenUserManager, mSmartReplyController, mEntryManager,
- () -> mock(ShadeController.class),
+ () -> mock(StatusBar.class),
mStateController,
Handler.createAsync(Looper.myLooper()),
mRemoteInputUriController);
@@ -212,12 +212,12 @@ public class NotificationRemoteInputManagerTest extends SysuiTestCase {
NotificationLockscreenUserManager lockscreenUserManager,
SmartReplyController smartReplyController,
NotificationEntryManager notificationEntryManager,
- Lazy<ShadeController> shadeController,
+ Lazy<StatusBar> statusBarLazy,
StatusBarStateController statusBarStateController,
Handler mainHandler,
RemoteInputUriController remoteInputUriController) {
super(context, lockscreenUserManager, smartReplyController, notificationEntryManager,
- shadeController, statusBarStateController, mainHandler,
+ statusBarLazy, statusBarStateController, mainHandler,
remoteInputUriController);
}
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 95ce53c58e95..3f624128ac2c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java
@@ -41,7 +41,7 @@ import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.phone.ShadeController;
+import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.RemoteInputUriController;
import org.junit.Before;
@@ -88,7 +88,7 @@ public class SmartReplyControllerTest extends SysuiTestCase {
mRemoteInputManager = new NotificationRemoteInputManager(mContext,
mock(NotificationLockscreenUserManager.class), mSmartReplyController,
- mNotificationEntryManager, () -> mock(ShadeController.class),
+ mNotificationEntryManager, () -> mock(StatusBar.class),
mStatusBarStateController,
Handler.createAsync(Looper.myLooper()),
mRemoteInputUriController);
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 68730d12dee3..7fabb0fee8e2 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
@@ -100,7 +100,7 @@ public class NotificationFilterTest extends SysuiTestCase {
when(mEnvironment.isDeviceProvisioned()).thenReturn(true);
when(mEnvironment.isNotificationForCurrentProfiles(any())).thenReturn(true);
mRow = new NotificationTestHelper(getContext(), mDependency).createRow();
- mNotificationFilter = new NotificationFilter();
+ mNotificationFilter = new NotificationFilter(mock(StatusBarStateController.class));
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
index 61e5058b1a20..b27e84a37e3f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
@@ -126,7 +126,7 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
@Test
public void showBouncer_onlyWhenShowing() {
mStatusBarKeyguardViewManager.hide(0 /* startTime */, 0 /* fadeoutDuration */);
- mStatusBar.showBouncer(true /* scrimmed */);
+ mStatusBarKeyguardViewManager.showBouncer(true /* scrimmed */);
verify(mBouncer, never()).show(anyBoolean(), anyBoolean());
verify(mBouncer, never()).show(anyBoolean());
}
@@ -135,7 +135,7 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
public void showBouncer_notWhenBouncerAlreadyShowing() {
mStatusBarKeyguardViewManager.hide(0 /* startTime */, 0 /* fadeoutDuration */);
when(mBouncer.isSecure()).thenReturn(true);
- mStatusBar.showBouncer(true /* scrimmed */);
+ mStatusBarKeyguardViewManager.showBouncer(true /* scrimmed */);
verify(mBouncer, never()).show(anyBoolean(), anyBoolean());
verify(mBouncer, never()).show(anyBoolean());
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
index 77cdc025bbc9..d7c00cf3038d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
@@ -98,6 +98,8 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
@Mock
private StatusBarStateController mStatusBarStateController;
@Mock
+ private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
+ @Mock
private NotificationRemoteInputManager mRemoteInputManager;
@Mock
private RemoteInputController mRemoteInputController;
@@ -167,7 +169,8 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
getContext(), mock(CommandQueue.class), () -> mAssistManager,
mEntryManager, mock(HeadsUpManagerPhone.class),
mActivityStarter, mStatusBarService,
- mock(StatusBarStateController.class), mock(KeyguardManager.class),
+ mock(StatusBarStateController.class), mStatusBarKeyguardViewManager,
+ mock(KeyguardManager.class),
mock(IDreamManager.class), mRemoteInputManager,
mock(StatusBarRemoteInputCallback.class), mock(NotificationGroupManager.class),
mock(NotificationLockscreenUserManager.class),
@@ -186,7 +189,8 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
// set up addAfterKeyguardGoneRunnable to synchronously invoke the Runnable arg
doAnswer(answerVoid(Runnable::run))
- .when(mStatusBar).addAfterKeyguardGoneRunnable(any(Runnable.class));
+ .when(mStatusBarKeyguardViewManager)
+ .addAfterKeyguardGoneRunnable(any(Runnable.class));
// set up addPostCollapseAction to synchronously invoke the Runnable arg
doAnswer(answerVoid(Runnable::run))
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 14f5795c39f1..fb6e1684c376 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
@@ -39,6 +39,7 @@ import com.android.systemui.InitController;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.KeyguardIndicationController;
import com.android.systemui.statusbar.NotificationEntryBuilder;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationMediaManager;
@@ -113,6 +114,7 @@ public class StatusBarNotificationPresenterTest extends SysuiTestCase {
mock(ActivityLaunchAnimator.class), mock(DynamicPrivacyController.class),
mock(NotificationAlertingManager.class),
mock(NotificationRowBinderImpl.class), mock(KeyguardStateController.class),
+ mock(KeyguardIndicationController.class),
mStatusBar, mCommandQueue);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java
index 9d76b425725f..6dfd0828de9a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java
@@ -54,6 +54,7 @@ public class StatusBarRemoteInputCallbackTest extends SysuiTestCase {
@Mock private NotificationLockscreenUserManager mNotificationLockscreenUserManager;
@Mock private KeyguardStateController mKeyguardStateController;
@Mock private SysuiStatusBarStateController mStatusBarStateController;
+ @Mock private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
@Mock private ActivityStarter mActivityStarter;
private int mCurrentUserId = 0;
@@ -71,8 +72,8 @@ public class StatusBarRemoteInputCallbackTest extends SysuiTestCase {
mRemoteInputCallback = spy(new StatusBarRemoteInputCallback(mContext,
mock(NotificationGroupManager.class), mNotificationLockscreenUserManager,
- mKeyguardStateController, mStatusBarStateController, mActivityStarter,
- () -> mShadeController, new CommandQueue(mContext)));
+ mKeyguardStateController, mStatusBarStateController, mStatusBarKeyguardViewManager,
+ mActivityStarter, () -> mShadeController, new CommandQueue(mContext)));
mRemoteInputCallback.mChallengeReceiver = mRemoteInputCallback.new ChallengeReceiver();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowViewTest.java
index 529333effa2c..00ea18749de3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowViewTest.java
@@ -80,7 +80,7 @@ public class StatusBarWindowViewTest extends SysuiTestCase {
MockitoAnnotations.initMocks(this);
mView = new StatusBarWindowView(getContext(), null);
- when(mStatusBar.isDozing()).thenReturn(false);
+ when(mStatusBarStateController.isDozing()).thenReturn(false);
mDependency.injectTestDependency(ShadeController.class, mShadeController);
when(mDockManager.isDocked()).thenReturn(false);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/concurrency/FakeExecutor.java b/packages/SystemUI/tests/src/com/android/systemui/util/concurrency/FakeExecutor.java
index 3ed6c5b2b11b..f3c053058468 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/concurrency/FakeExecutor.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/concurrency/FakeExecutor.java
@@ -168,11 +168,6 @@ public class FakeExecutor implements DelayableExecutor {
executeDelayed(command, 0);
}
- @Override
- public void removeAll() {
- mQueuedRunnables.clear();
- }
-
/**
* Run all Executors in a loop until they all report they have no ready work to do.
*
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/concurrency/FakeExecutorTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/concurrency/FakeExecutorTest.java
index 7fd694244afa..b1716ff47129 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/concurrency/FakeExecutorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/concurrency/FakeExecutorTest.java
@@ -325,36 +325,6 @@ public class FakeExecutorTest extends SysuiTestCase {
assertEquals(1, runnable.mRunCount);
}
- /**
- * Test removing everything
- */
- @Test
- public void testRemoval_all() {
- FakeSystemClock clock = new FakeSystemClock();
- clock.setAutoIncrement(false);
- FakeExecutor fakeExecutor = new FakeExecutor(clock);
- RunnableImpl runnable = new RunnableImpl();
-
- // Nothing to remove.
- assertEquals(0, runnable.mRunCount);
- assertEquals(0, fakeExecutor.numPending());
-
- // Two pending items that have not yet run.
- fakeExecutor.executeDelayed(runnable, 100);
- fakeExecutor.executeDelayed(runnable, 200);
- assertEquals(2, fakeExecutor.numPending());
- assertEquals(0, runnable.mRunCount);
-
- // Remove the items.
- fakeExecutor.removeAll();
-
- // Nothing to run
- fakeExecutor.advanceClockToLast();
- assertEquals(0, fakeExecutor.runAllReady());
- assertEquals(0, fakeExecutor.numPending());
- assertEquals(0, runnable.mRunCount);
- }
-
private static class RunnableImpl implements Runnable {
int mRunCount;
diff --git a/packages/Tethering/apex/manifest.json b/packages/Tethering/apex/manifest.json
index 3fb62f3405a3..078302ac51a4 100644
--- a/packages/Tethering/apex/manifest.json
+++ b/packages/Tethering/apex/manifest.json
@@ -1,4 +1,4 @@
{
"name": "com.android.tethering.apex",
- "version": 290000000
+ "version": 300000000
}
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index a3188443591f..119b987f7ae7 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -614,22 +614,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
}
public boolean isEnabled() {
- if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!checkIfCallerIsForegroundUser())) {
- Slog.w(TAG, "isEnabled(): not allowed for non-active and non system user");
- return false;
- }
-
- try {
- mBluetoothLock.readLock().lock();
- if (mBluetooth != null) {
- return mBluetooth.isEnabled();
- }
- } catch (RemoteException e) {
- Slog.e(TAG, "isEnabled()", e);
- } finally {
- mBluetoothLock.readLock().unlock();
- }
- return false;
+ return getState() == BluetoothAdapter.STATE_ON;
}
public int getState() {
@@ -1796,14 +1781,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
//Do enable request
try {
- if (!mQuietEnable) {
- if (!mBluetooth.enable()) {
- Slog.e(TAG, "IBluetooth.enable() returned false");
- }
- } else {
- if (!mBluetooth.enableNoAutoConnect()) {
- Slog.e(TAG, "IBluetooth.enableNoAutoConnect() returned false");
- }
+ if (!mBluetooth.enable(mQuietEnable)) {
+ Slog.e(TAG, "IBluetooth.enable() returned false");
}
} catch (RemoteException e) {
Slog.e(TAG, "Unable to call enable()", e);
@@ -2078,14 +2057,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
} else if (mBluetooth != null) {
//Enable bluetooth
try {
- if (!mQuietEnable) {
- if (!mBluetooth.enable()) {
- Slog.e(TAG, "IBluetooth.enable() returned false");
- }
- } else {
- if (!mBluetooth.enableNoAutoConnect()) {
- Slog.e(TAG, "IBluetooth.enableNoAutoConnect() returned false");
- }
+ if (!mBluetooth.enable(mQuietEnable)) {
+ Slog.e(TAG, "IBluetooth.enable() returned false");
}
} catch (RemoteException e) {
Slog.e(TAG, "Unable to call enable()", e);
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index f3089c1092e6..54dfc98e888d 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -81,6 +81,7 @@ import android.text.TextUtils;
import android.util.EventLog;
import android.util.Log;
import android.util.Slog;
+import android.util.SparseArray;
import android.util.TimeUtils;
import com.android.internal.annotations.GuardedBy;
@@ -339,7 +340,7 @@ public class LocationManagerService extends ILocationManager.Stub {
mSettingsStore.addOnLocationEnabledChangedListener((userId) -> {
synchronized (mLock) {
- onLocationModeChangedLocked(userId, true);
+ onLocationModeChangedLocked(userId);
}
});
mSettingsStore.addOnLocationProvidersAllowedChangedListener((userId) -> {
@@ -467,36 +468,24 @@ public class LocationManagerService extends ILocationManager.Stub {
}
@GuardedBy("mLock")
- private void onLocationModeChangedLocked(int userId, boolean broadcast) {
- if (!isCurrentProfileLocked(userId)) {
- return;
- }
-
+ private void onLocationModeChangedLocked(int userId) {
if (D) {
- Log.d(TAG, "location enabled is now " + isLocationEnabled());
+ Log.d(TAG, "[u" + userId + "] location enabled = " + isLocationEnabledForUser(userId));
}
- for (LocationProvider p : mProviders) {
- p.onLocationModeChangedLocked();
- }
+ Intent intent = new Intent(LocationManager.MODE_CHANGED_ACTION);
+ intent.putExtra(LocationManager.EXTRA_LOCATION_ENABLED, isLocationEnabled());
+ mContext.sendBroadcastAsUser(intent, UserHandle.of(userId));
- if (broadcast) {
- // needs to be sent to everyone because we don't know which user may have changed
- // LOCATION_MODE state.
- mContext.sendBroadcastAsUser(
- new Intent(LocationManager.MODE_CHANGED_ACTION),
- UserHandle.ALL);
+ for (LocationProvider p : mProviders) {
+ p.onLocationModeChangedLocked(userId);
}
}
@GuardedBy("mLock")
private void onProviderAllowedChangedLocked(int userId) {
- if (!isCurrentProfileLocked(userId)) {
- return;
- }
-
for (LocationProvider p : mProviders) {
- p.onAllowedChangedLocked();
+ p.onAllowedChangedLocked(userId);
}
}
@@ -798,21 +787,14 @@ public class LocationManagerService extends ILocationManager.Stub {
Log.d(TAG, "foreground user is changing to " + userId);
}
- // let providers know the current user is on the way out before changing the user
- for (LocationProvider p : mProviders) {
- p.onUserChangingLocked();
- }
-
+ int oldUserId = userId;
mCurrentUserId = userId;
onUserProfilesChangedLocked();
- // if the user changes, per-user settings may also have changed
- onLocationModeChangedLocked(userId, false);
- onProviderAllowedChangedLocked(userId);
-
- // always force useability to be rechecked, even if no per-user settings have changed
+ // let providers know the current user has changed
for (LocationProvider p : mProviders) {
- p.onUseableChangedLocked(false);
+ p.onCurrentUserChangedLocked(oldUserId);
+ p.onCurrentUserChangedLocked(mCurrentUserId);
}
}
@@ -832,7 +814,7 @@ public class LocationManagerService extends ILocationManager.Stub {
protected AbstractLocationProvider mProvider;
@GuardedBy("mLock")
- private boolean mUseable; // combined state
+ private SparseArray<Boolean> mUseable; // combined state for each user id
@GuardedBy("mLock")
private boolean mAllowed; // state of LOCATION_PROVIDERS_ALLOWED
@GuardedBy("mLock")
@@ -851,7 +833,7 @@ public class LocationManagerService extends ILocationManager.Stub {
mIsManagedBySettings = isManagedBySettings;
mProvider = null;
- mUseable = false;
+ mUseable = new SparseArray<>(1);
mAllowed = !mIsManagedBySettings;
mEnabled = false;
mProperties = null;
@@ -876,7 +858,10 @@ public class LocationManagerService extends ILocationManager.Stub {
}
mProvider = provider;
- onUseableChangedLocked(false);
+
+ // it would be more correct to call this for all users, but we know this can only
+ // affect the current user since providers are disabled for non-current users
+ onUseableChangedLocked(false, mCurrentUserId);
}
public String getName() {
@@ -943,8 +928,8 @@ public class LocationManagerService extends ILocationManager.Stub {
pw.increaseIndent();
- pw.println("useable=" + mUseable);
- if (!mUseable) {
+ pw.println("useable=" + isUseableLocked(mCurrentUserId));
+ if (!isUseableLocked(mCurrentUserId)) {
pw.println("attached=" + (mProvider != null));
if (mIsManagedBySettings) {
pw.println("allowed=" + mAllowed);
@@ -1009,7 +994,10 @@ public class LocationManagerService extends ILocationManager.Stub {
}
mEnabled = enabled;
- onUseableChangedLocked(false);
+
+ // it would be more correct to call this for all users, but we know this can only
+ // affect the current user since providers are disabled for non-current users
+ onUseableChangedLocked(false, mCurrentUserId);
}
}
@@ -1021,12 +1009,20 @@ public class LocationManagerService extends ILocationManager.Stub {
}
@GuardedBy("mLock")
- public void onLocationModeChangedLocked() {
- onUseableChangedLocked(false);
+ public void onLocationModeChangedLocked(int userId) {
+ if (!isCurrentProfileLocked(userId)) {
+ return;
+ }
+
+ onUseableChangedLocked(false, userId);
}
@GuardedBy("mLock")
- public void onAllowedChangedLocked() {
+ public void onAllowedChangedLocked(int userId) {
+ if (!isCurrentProfileLocked(userId)) {
+ return;
+ }
+
if (mIsManagedBySettings) {
boolean allowed = mSettingsStore.getLocationProvidersAllowed(
mCurrentUserId).contains(mName);
@@ -1040,37 +1036,36 @@ public class LocationManagerService extends ILocationManager.Stub {
}
mAllowed = allowed;
- onUseableChangedLocked(true);
+ onUseableChangedLocked(true, userId);
}
}
@GuardedBy("mLock")
- public boolean isUseableLocked() {
- return isUseableForUserLocked(mCurrentUserId);
+ public void onCurrentUserChangedLocked(int userId) {
+ onUseableChangedLocked(false, userId);
}
@GuardedBy("mLock")
- public boolean isUseableForUserLocked(int userId) {
- return isCurrentProfileLocked(userId) && mUseable;
+ public boolean isUseableLocked() {
+ return isUseableLocked(mCurrentUserId);
}
@GuardedBy("mLock")
- private boolean isUseableIgnoringAllowedLocked() {
- return mProvider != null && mProviders.contains(this) && isLocationEnabled()
- && mEnabled;
+ public boolean isUseableLocked(int userId) {
+ return mUseable.get(userId, Boolean.FALSE);
}
@GuardedBy("mLock")
- public void onUseableChangedLocked(boolean isAllowedChanged) {
+ public void onUseableChangedLocked(boolean isAllowedChanged, int userId) {
// if any property that contributes to "useability" here changes state, it MUST result
// in a direct or indrect call to onUseableChangedLocked. this allows the provider to
// guarantee that it will always eventually reach the correct state.
- boolean useableIgnoringAllowed = isUseableIgnoringAllowedLocked();
+ boolean useableIgnoringAllowed = mProvider != null && mProviders.contains(this)
+ && isCurrentProfileLocked(userId) && isLocationEnabledForUser(userId)
+ && mEnabled;
boolean useable = useableIgnoringAllowed && mAllowed;
- // update deprecated provider allowed settings for backwards compatibility, and do this
- // even if there is no change in overall useability state. this may result in trying to
- // overwrite the same value, but Settings handles deduping this.
+ // update deprecated provider allowed settings for backwards compatibility
if (mIsManagedBySettings) {
// a "-" change derived from the allowed setting should not be overwritten, but a
// "+" change should be corrected if necessary
@@ -1079,33 +1074,31 @@ public class LocationManagerService extends ILocationManager.Stub {
mContext.getContentResolver(),
Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
"+" + mName,
- mCurrentUserId);
+ userId);
} else if (!useableIgnoringAllowed) {
Settings.Secure.putStringForUser(
mContext.getContentResolver(),
Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
"-" + mName,
- mCurrentUserId);
+ userId);
}
- // needs to be sent to all users because whether or not a provider is enabled for
- // a given user is complicated... we broadcast to everyone and let them figure it
- // out via isProviderEnabled()
Intent intent = new Intent(LocationManager.PROVIDERS_CHANGED_ACTION);
intent.putExtra(LocationManager.EXTRA_PROVIDER_NAME, mName);
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ intent.putExtra(LocationManager.EXTRA_PROVIDER_ENABLED, useable);
+ mContext.sendBroadcastAsUser(intent, UserHandle.of(userId));
}
- if (useable == mUseable) {
+ if (useable == isUseableLocked(userId)) {
return;
}
- mUseable = useable;
+ mUseable.put(userId, useable);
if (D) {
- Log.d(TAG, mName + " provider useable is now " + mUseable);
+ Log.d(TAG, "[u" + userId + "] " + mName + " provider useable = " + useable);
}
- if (!mUseable) {
+ if (!useable) {
// If any provider has been disabled, clear all last locations for all
// providers. This is to be on the safe side in case a provider has location
// derived from this disabled provider.
@@ -1115,15 +1108,6 @@ public class LocationManagerService extends ILocationManager.Stub {
updateProviderUseableLocked(this);
}
-
- @GuardedBy("mLock")
- public void onUserChangingLocked() {
- // when the user is about to change, we set this provider to un-useable, and notify all
- // of the current user clients. when the user is finished changing, useability will be
- // updated back via onLocationModeChanged() and onAllowedChanged().
- mUseable = false;
- updateProviderUseableLocked(this);
- }
}
private class MockLocationProvider extends LocationProvider {
@@ -1557,14 +1541,20 @@ public class LocationManagerService extends ILocationManager.Stub {
mProviders.add(provider);
- provider.onAllowedChangedLocked(); // allowed state may change while provider was inactive
- provider.onUseableChangedLocked(false);
+ // allowed state may change while provider was inactive
+ provider.onAllowedChangedLocked(mCurrentUserId);
+
+ // it would be more correct to call this for all users, but we know this can only
+ // affect the current user since providers are disabled for non-current users
+ provider.onUseableChangedLocked(false, mCurrentUserId);
}
@GuardedBy("mLock")
private void removeProviderLocked(LocationProvider provider) {
if (mProviders.remove(provider)) {
- provider.onUseableChangedLocked(false);
+ // it would be more correct to call this for all users, but we know this can only
+ // affect the current user since providers are disabled for non-current users
+ provider.onUseableChangedLocked(false, mCurrentUserId);
}
}
@@ -2851,7 +2841,7 @@ public class LocationManagerService extends ILocationManager.Stub {
synchronized (mLock) {
LocationProvider provider = getLocationProviderLocked(providerName);
- return provider != null && provider.isUseableForUserLocked(userId);
+ return provider != null && provider.isUseableLocked(userId);
}
}
@@ -3246,6 +3236,7 @@ public class LocationManagerService extends ILocationManager.Stub {
synchronized (mLock) {
if (mGnssManagerService != null && args.length > 0 && args[0].equals("--gnssmetrics")) {
mGnssManagerService.dump(fd, pw, args);
+ return;
}
ipw.println("Location Manager State:");
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index e79a2897d86a..840b7af19890 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -16,6 +16,7 @@
package com.android.server;
+import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
import static android.Manifest.permission.NETWORK_SETTINGS;
import static android.Manifest.permission.OBSERVE_NETWORK_POLICY;
import static android.Manifest.permission.SHUTDOWN;
@@ -737,7 +738,9 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
//
@Override
public String[] listInterfaces() {
- NetworkStack.checkNetworkStackPermission(mContext);
+ // TODO: Remove CONNECTIVITY_INTERNAL after bluetooth tethering has no longer called these
+ // APIs.
+ NetworkStack.checkNetworkStackPermissionOr(mContext, CONNECTIVITY_INTERNAL);
try {
return mNetdService.interfaceGetList();
} catch (RemoteException | ServiceSpecificException e) {
@@ -787,7 +790,9 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
@Override
public InterfaceConfiguration getInterfaceConfig(String iface) {
- NetworkStack.checkNetworkStackPermission(mContext);
+ // TODO: Remove CONNECTIVITY_INTERNAL after bluetooth tethering has no longer called these
+ // APIs.
+ NetworkStack.checkNetworkStackPermissionOr(mContext, CONNECTIVITY_INTERNAL);
final InterfaceConfigurationParcel result;
try {
result = mNetdService.interfaceGetCfg(iface);
@@ -805,7 +810,9 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
@Override
public void setInterfaceConfig(String iface, InterfaceConfiguration cfg) {
- NetworkStack.checkNetworkStackPermission(mContext);
+ // TODO: Remove CONNECTIVITY_INTERNAL after bluetooth tethering has no longer called these
+ // APIs.
+ NetworkStack.checkNetworkStackPermissionOr(mContext, CONNECTIVITY_INTERNAL);
LinkAddress linkAddr = cfg.getLinkAddress();
if (linkAddr == null || linkAddr.getAddress() == null) {
throw new IllegalStateException("Null LinkAddress given");
diff --git a/services/core/java/com/android/server/PackageWatchdog.java b/services/core/java/com/android/server/PackageWatchdog.java
index 12debbff3e90..521b39305d9d 100644
--- a/services/core/java/com/android/server/PackageWatchdog.java
+++ b/services/core/java/com/android/server/PackageWatchdog.java
@@ -57,6 +57,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
@@ -81,6 +82,22 @@ public class PackageWatchdog {
static final String PROPERTY_WATCHDOG_EXPLICIT_HEALTH_CHECK_ENABLED =
"watchdog_explicit_health_check_enabled";
+ public static final int FAILURE_REASON_UNKNOWN = 0;
+ public static final int FAILURE_REASON_NATIVE_CRASH = 1;
+ public static final int FAILURE_REASON_EXPLICIT_HEALTH_CHECK = 2;
+ public static final int FAILURE_REASON_APP_CRASH = 3;
+ public static final int FAILURE_REASON_APP_NOT_RESPONDING = 4;
+
+ @IntDef(prefix = { "FAILURE_REASON_" }, value = {
+ FAILURE_REASON_UNKNOWN,
+ FAILURE_REASON_NATIVE_CRASH,
+ FAILURE_REASON_EXPLICIT_HEALTH_CHECK,
+ FAILURE_REASON_APP_CRASH,
+ FAILURE_REASON_APP_NOT_RESPONDING
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface FailureReasons {}
+
// Duration to count package failures before it resets to 0
@VisibleForTesting
static final int DEFAULT_TRIGGER_FAILURE_DURATION_MS =
@@ -305,14 +322,15 @@ public class PackageWatchdog {
}
/**
- * Called when a process fails either due to a crash or ANR.
+ * Called when a process fails due to a crash, ANR or explicit health check.
*
* <p>For each package contained in the process, one registered observer with the least user
* impact will be notified for mitigation.
*
* <p>This method could be called frequently if there is a severe problem on the device.
*/
- public void onPackageFailure(List<VersionedPackage> packages) {
+ public void onPackageFailure(List<VersionedPackage> packages,
+ @FailureReasons int failureReason) {
mLongTaskHandler.post(() -> {
synchronized (mLock) {
if (mAllObservers.isEmpty()) {
@@ -343,7 +361,7 @@ public class PackageWatchdog {
// Execute action with least user impact
if (currentObserverToNotify != null) {
- currentObserverToNotify.execute(versionedPackage);
+ currentObserverToNotify.execute(versionedPackage, failureReason);
}
}
}
@@ -414,7 +432,7 @@ public class PackageWatchdog {
*
* @return {@code true} if action was executed successfully, {@code false} otherwise
*/
- boolean execute(VersionedPackage versionedPackage);
+ boolean execute(VersionedPackage versionedPackage, @FailureReasons int failureReason);
// TODO(b/120598832): Ensure uniqueness?
/**
@@ -659,7 +677,8 @@ public class PackageWatchdog {
while (it.hasNext()) {
VersionedPackage versionedPkg = it.next().mPackage;
Slog.i(TAG, "Explicit health check failed for package " + versionedPkg);
- registeredObserver.execute(versionedPkg);
+ registeredObserver.execute(versionedPkg,
+ PackageWatchdog.FAILURE_REASON_EXPLICIT_HEALTH_CHECK);
}
}
}
@@ -770,7 +789,7 @@ public class PackageWatchdog {
final List<VersionedPackage> pkgList = Collections.singletonList(pkg);
final long failureCount = getTriggerFailureCount();
for (int i = 0; i < failureCount; i++) {
- onPackageFailure(pkgList);
+ onPackageFailure(pkgList, FAILURE_REASON_EXPLICIT_HEALTH_CHECK);
}
});
}
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 1f7d9eab9675..6105c7422153 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -72,7 +72,6 @@ import com.android.internal.app.IBatteryStats;
import com.android.internal.telephony.IOnSubscriptionsChangedListener;
import com.android.internal.telephony.IPhoneStateListener;
import com.android.internal.telephony.ITelephonyRegistry;
-import com.android.internal.telephony.PhoneConstantConversions;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.telephony.TelephonyPermissions;
@@ -2215,8 +2214,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
Intent intent = new Intent(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
- intent.putExtra(PhoneConstants.STATE_KEY,
- PhoneConstantConversions.convertCallState(state).toString());
+ intent.putExtra(TelephonyManager.EXTRA_STATE, callStateToString(state));
// If a valid subId was specified, we should fire off a subId-specific state
// change intent and include the subId.
@@ -2249,6 +2247,18 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
android.Manifest.permission.READ_CALL_LOG});
}
+ /** Converts TelephonyManager#CALL_STATE_* to TelephonyManager#EXTRA_STATE_*. */
+ private static String callStateToString(int callState) {
+ switch (callState) {
+ case TelephonyManager.CALL_STATE_RINGING:
+ return TelephonyManager.EXTRA_STATE_RINGING;
+ case TelephonyManager.CALL_STATE_OFFHOOK:
+ return TelephonyManager.EXTRA_STATE_OFFHOOK;
+ default:
+ return TelephonyManager.EXTRA_STATE_IDLE;
+ }
+ }
+
private void broadcastDataConnectionStateChanged(int state, boolean isDataAllowed, String apn,
String apnType, LinkProperties linkProperties,
NetworkCapabilities networkCapabilities,
@@ -2257,8 +2267,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
// status bar takes care of that after taking into account all of the
// required info.
Intent intent = new Intent(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
- intent.putExtra(PhoneConstants.STATE_KEY,
- PhoneConstantConversions.convertDataState(state).toString());
+ intent.putExtra(TelephonyManager.EXTRA_STATE, dataStateToString(state));
if (!isDataAllowed) {
intent.putExtra(PhoneConstants.NETWORK_UNAVAILABLE_KEY, true);
}
@@ -2301,7 +2310,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
String apnType, String apn, LinkProperties linkProperties,
@DataFailureCause int failCause) {
Intent intent = new Intent(TelephonyManager.ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED);
- intent.putExtra(PhoneConstants.STATE_KEY, state);
+ intent.putExtra(TelephonyManager.EXTRA_STATE, state);
intent.putExtra(PhoneConstants.DATA_NETWORK_TYPE_KEY, networkType);
if (apnType != null) intent.putExtra(PhoneConstants.DATA_APN_TYPE_KEY, apnType);
if (apn != null) intent.putExtra(PhoneConstants.DATA_APN_KEY, apn);
@@ -2642,11 +2651,11 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
/**
- * Convert data state to string
+ * Convert TelephonyManager.DATA_* to string.
*
* @return The data state in string format.
*/
- private String dataStateToString(@TelephonyManager.DataState int state) {
+ private static String dataStateToString(int state) {
switch (state) {
case TelephonyManager.DATA_DISCONNECTED: return "DISCONNECTED";
case TelephonyManager.DATA_CONNECTING: return "CONNECTING";
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index b5702541432a..b1e2c0fe9586 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -866,14 +866,13 @@ final class UiModeManagerService extends SystemService {
if (!mHoldingConfiguration) {
mConfiguration.uiMode = uiMode;
}
- // load splash screen instead of screenshot
- mWindowManager.clearSnapshotCache();
}
private void sendConfigurationLocked() {
if (mSetUiMode != mConfiguration.uiMode) {
mSetUiMode = mConfiguration.uiMode;
-
+ // load splash screen instead of screenshot
+ mWindowManager.clearSnapshotCache();
try {
ActivityTaskManager.getService().updateConfiguration(mConfiguration);
} catch (RemoteException e) {
diff --git a/services/core/java/com/android/server/ZramWriteback.java b/services/core/java/com/android/server/ZramWriteback.java
index 49bf29bff284..5d97def129a4 100644
--- a/services/core/java/com/android/server/ZramWriteback.java
+++ b/services/core/java/com/android/server/ZramWriteback.java
@@ -60,6 +60,7 @@ public final class ZramWriteback extends JobService {
private static final String MARK_IDLE_DELAY_PROP = "ro.zram.mark_idle_delay_mins";
private static final String FIRST_WB_DELAY_PROP = "ro.zram.first_wb_delay_mins";
private static final String PERIODIC_WB_DELAY_PROP = "ro.zram.periodic_wb_delay_hours";
+ private static final String FORCE_WRITEBACK_PROP = "zram.force_writeback";
private void markPagesAsIdle() {
String idlePath = String.format(IDLE_SYS, sZramDeviceId);
@@ -122,11 +123,12 @@ public final class ZramWriteback extends JobService {
private static void schedNextWriteback(Context context) {
int nextWbDelay = SystemProperties.getInt(PERIODIC_WB_DELAY_PROP, 24);
+ boolean forceWb = SystemProperties.getBoolean(FORCE_WRITEBACK_PROP, false);
JobScheduler js = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
js.schedule(new JobInfo.Builder(WRITEBACK_IDLE_JOB_ID, sZramWriteback)
.setMinimumLatency(TimeUnit.HOURS.toMillis(nextWbDelay))
- .setRequiresDeviceIdle(true)
+ .setRequiresDeviceIdle(!forceWb)
.build());
}
@@ -167,6 +169,7 @@ public final class ZramWriteback extends JobService {
public static void scheduleZramWriteback(Context context) {
int markIdleDelay = SystemProperties.getInt(MARK_IDLE_DELAY_PROP, 20);
int firstWbDelay = SystemProperties.getInt(FIRST_WB_DELAY_PROP, 180);
+ boolean forceWb = SystemProperties.getBoolean(FORCE_WRITEBACK_PROP, false);
JobScheduler js = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
@@ -182,7 +185,7 @@ public final class ZramWriteback extends JobService {
// by ro.zram.periodic_wb_delay_hours.
js.schedule(new JobInfo.Builder(WRITEBACK_IDLE_JOB_ID, sZramWriteback)
.setMinimumLatency(TimeUnit.MINUTES.toMillis(firstWbDelay))
- .setRequiresDeviceIdle(true)
+ .setRequiresDeviceIdle(!forceWb)
.build());
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index b191338dc58c..01f3c2666ff7 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -6694,7 +6694,7 @@ public class ActivityManagerService extends IActivityManager.Stub
private final long[] mProcessStateStatsLongs = new long[1];
- private boolean isProcessAliveLocked(ProcessRecord proc) {
+ boolean isProcessAliveLocked(ProcessRecord proc) {
if (proc.pid <= 0) {
if (DEBUG_OOM_ADJ) Slog.d(TAG, "Process hasn't started yet: " + proc);
return false;
@@ -6711,7 +6711,10 @@ public class ActivityManagerService extends IActivityManager.Stub
final long state = mProcessStateStatsLongs[0];
if (DEBUG_OOM_ADJ) Slog.d(TAG, "RETRIEVED STATE FOR " + proc.procStatFile + ": "
+ (char)state);
- return state != 'Z' && state != 'X' && state != 'x' && state != 'K';
+ if (state != 'Z' && state != 'X' && state != 'x' && state != 'K') {
+ return Process.getUidForPid(proc.pid) == proc.uid;
+ }
+ return false;
}
private String checkContentProviderAssociation(ProcessRecord callingApp, int callingUid,
@@ -6784,14 +6787,14 @@ public class ActivityManagerService extends IActivityManager.Stub
// (See the commit message on I2c4ba1e87c2d47f2013befff10c49b3dc337a9a7 to see
// how to test this case.)
if (cpr.proc.killed && cpr.proc.killedByAm) {
- checkTime(startTime, "getContentProviderImpl: before appDied (killedByAm)");
final long iden = Binder.clearCallingIdentity();
try {
- appDiedLocked(cpr.proc);
+ mProcessList.killProcAndWaitIfNecessaryLocked(cpr.proc, false,
+ cpr.uid == cpr.proc.uid || cpr.proc.isolated,
+ "getContentProviderImpl: %s (killedByAm)", startTime);
} finally {
Binder.restoreCallingIdentity(iden);
}
- checkTime(startTime, "getContentProviderImpl: after appDied (killedByAm)");
}
}
@@ -6895,9 +6898,8 @@ public class ActivityManagerService extends IActivityManager.Stub
Slog.i(TAG, "Existing provider " + cpr.name.flattenToShortString()
+ " is crashing; detaching " + r);
boolean lastRef = decProviderCountLocked(conn, cpr, token, stable);
- checkTime(startTime, "getContentProviderImpl: before appDied");
- appDiedLocked(cpr.proc);
- checkTime(startTime, "getContentProviderImpl: after appDied");
+ mProcessList.killProcAndWaitIfNecessaryLocked(cpr.proc,
+ false, true, "getContentProviderImpl: %s", startTime);
if (!lastRef) {
// This wasn't the last ref our process had on
// the provider... we have now been killed, bail.
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index 51e1718d4c98..83a7341923fa 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -446,7 +446,8 @@ class AppErrors {
RescueParty.noteAppCrash(mContext, r.uid);
}
- mPackageWatchdog.onPackageFailure(r.getPackageListWithVersionCode());
+ mPackageWatchdog.onPackageFailure(r.getPackageListWithVersionCode(),
+ PackageWatchdog.FAILURE_REASON_APP_CRASH);
}
final int relaunchReason = r != null
@@ -900,7 +901,8 @@ class AppErrors {
}
// Notify PackageWatchdog without the lock held
if (packageList != null) {
- mPackageWatchdog.onPackageFailure(packageList);
+ mPackageWatchdog.onPackageFailure(packageList,
+ PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING);
}
}
diff --git a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
index 38030c248139..cf996a50d5c7 100644
--- a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
+++ b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
@@ -125,7 +125,7 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync {
// Keep the last WiFi stats so we can compute a delta.
@GuardedBy("mWorkerLock")
private WifiActivityEnergyInfo mLastInfo =
- new WifiActivityEnergyInfo(0, 0, 0, 0, 0, 0, 0);
+ new WifiActivityEnergyInfo(0, 0, 0, 0, 0, 0);
/**
* Timestamp at which all external stats were last collected in
diff --git a/services/core/java/com/android/server/am/CarUserSwitchingDialog.java b/services/core/java/com/android/server/am/CarUserSwitchingDialog.java
index 183e05979c5e..ebfc2a011e88 100644
--- a/services/core/java/com/android/server/am/CarUserSwitchingDialog.java
+++ b/services/core/java/com/android/server/am/CarUserSwitchingDialog.java
@@ -66,9 +66,7 @@ final class CarUserSwitchingDialog extends UserSwitchingDialog {
setCancelable(false);
Resources res = getContext().getResources();
// Custom view due to alignment and font size requirements
- // TODO (b/145021634): disabled because it's delaying user switch by 3 seconds
- // getContext()
- // .setTheme(R.style.Theme_DeviceDefault_Light_Dialog_Alert_UserSwitchingDialog);
+ getContext().setTheme(R.style.Theme_DeviceDefault_Light_Dialog_Alert_UserSwitchingDialog);
View view = LayoutInflater.from(getContext()).inflate(
R.layout.car_user_switching_dialog,
null);
diff --git a/services/core/java/com/android/server/am/OWNERS b/services/core/java/com/android/server/am/OWNERS
index 2f9a5c952659..7cc2e8eb2954 100644
--- a/services/core/java/com/android/server/am/OWNERS
+++ b/services/core/java/com/android/server/am/OWNERS
@@ -35,3 +35,5 @@ michaelwr@google.com
narayan@google.com
per-file SettingsToPropertiesMapper.java = omakoto@google.com, svetoslavganov@google.com, yamasani@google.com
+
+per-file CarUserSwitchingDialog.java = keunyoung@google.com, felipeal@google.com, gurunagarajan@google.com
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 2bb703545cad..32975d7792f5 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -78,6 +78,9 @@ import android.os.Trace;
import android.os.UserHandle;
import android.os.storage.StorageManager;
import android.os.storage.StorageManagerInternal;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.OsConstants;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.EventLog;
@@ -283,6 +286,16 @@ public final class ProcessList {
// lmkd reconnect delay in msecs
private final static long LMDK_RECONNECT_DELAY_MS = 1000;
+ /**
+ * How long between a process kill and we actually receive its death recipient
+ */
+ private static final long PROC_KILL_TIMEOUT = 2000; // 2 seconds;
+
+ /**
+ * How long between polls to check if the given process is dead or not.
+ */
+ private static final long PROC_DEATH_POLL_INTERVAL = 100;
+
ActivityManagerService mService = null;
// To kill process groups asynchronously
@@ -1421,7 +1434,7 @@ public final class ProcessList {
if (app.pendingStart) {
return true;
}
- long startTime = SystemClock.elapsedRealtime();
+ long startTime = SystemClock.uptimeMillis();
if (app.pid > 0 && app.pid != ActivityManagerService.MY_PID) {
checkSlow(startTime, "startProcess: removing from pids map");
mService.mPidsSelfLocked.remove(app);
@@ -1856,7 +1869,7 @@ public final class ProcessList {
boolean knownToBeDead, int intentFlags, HostingRecord hostingRecord,
boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge,
String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) {
- long startTime = SystemClock.elapsedRealtime();
+ long startTime = SystemClock.uptimeMillis();
ProcessRecord app;
if (!isolated) {
app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
@@ -1917,10 +1930,9 @@ public final class ProcessList {
// An application record is attached to a previous process,
// clean it up now.
if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES, "App died: " + app);
- checkSlow(startTime, "startProcess: bad proc running, killing");
- ProcessList.killProcessGroup(app.uid, app.pid);
- mService.handleAppDiedLocked(app, true, true);
- checkSlow(startTime, "startProcess: done killing old proc");
+ // do the killing
+ killProcAndWaitIfNecessaryLocked(app, true, app.uid == info.uid || app.isolated,
+ "startProcess: bad proc running, killing: %s", startTime);
}
if (app == null) {
@@ -1961,6 +1973,70 @@ public final class ProcessList {
return success ? app : null;
}
+ /**
+ * A lite version of checking if a process is alive or not, by using kill(2) with signal 0.
+ *
+ * <p>
+ * Note that, zombie processes are stil "alive" in this case, use the {@link
+ * ActivityManagerService#isProcessAliveLocked} if zombie processes need to be excluded.
+ * </p>
+ */
+ @GuardedBy("mService")
+ private boolean isProcessAliveLiteLocked(ProcessRecord app) {
+ try {
+ Os.kill(app.pid, 0);
+ } catch (ErrnoException e) {
+ return e.errno != OsConstants.ESRCH;
+ }
+ return true;
+ }
+
+ /**
+ * Kill (if asked to) and wait for the given process died if necessary
+ * @param app - The process record to kill
+ * @param doKill - Kill the given process record
+ * @param wait - Wait for the death of the given process
+ * @param formatString - The log message for slow operation
+ * @param startTime - The start timestamp of the operation
+ */
+ @GuardedBy("mService")
+ void killProcAndWaitIfNecessaryLocked(final ProcessRecord app, final boolean doKill,
+ final boolean wait, final String formatString, final long startTime) {
+
+ checkSlow(startTime, String.format(formatString, "before appDied"));
+
+ if (doKill) {
+ // do the killing
+ ProcessList.killProcessGroup(app.uid, app.pid);
+ }
+
+ // wait for the death
+ if (wait) {
+ boolean isAlive = true;
+ // ideally we should use pidfd_open(2) but it's available on kernel 5.3 or later
+
+ final long timeout = SystemClock.uptimeMillis() + PROC_KILL_TIMEOUT;
+ isAlive = isProcessAliveLiteLocked(app);
+ while (timeout > SystemClock.uptimeMillis() && isAlive) {
+ try {
+ Thread.sleep(PROC_DEATH_POLL_INTERVAL);
+ } catch (InterruptedException e) {
+ }
+ isAlive = isProcessAliveLiteLocked(app);
+ }
+
+ if (isAlive) {
+ // Maybe the process goes into zombie, use an expensive API to check again.
+ if (mService.isProcessAliveLocked(app)) {
+ Slog.w(TAG, String.format(formatString,
+ "waiting for app killing timed out"));
+ }
+ }
+ }
+
+ checkSlow(startTime, String.format(formatString, "after appDied"));
+ }
+
@GuardedBy("mService")
private String isProcStartValidLocked(ProcessRecord app, long expectedStartSeq) {
StringBuilder sb = null;
diff --git a/services/core/java/com/android/server/am/UserSwitchingDialog.java b/services/core/java/com/android/server/am/UserSwitchingDialog.java
index bbf57728a20a..3dbf2c667c2f 100644
--- a/services/core/java/com/android/server/am/UserSwitchingDialog.java
+++ b/services/core/java/com/android/server/am/UserSwitchingDialog.java
@@ -24,6 +24,7 @@ import android.os.Handler;
import android.os.Message;
import android.os.UserHandle;
import android.os.UserManager;
+import android.util.Slog;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewTreeObserver;
@@ -46,6 +47,9 @@ class UserSwitchingDialog extends AlertDialog
// Time to wait for the onWindowShown() callback before continuing the user switch
private static final int WINDOW_SHOWN_TIMEOUT_MS = 3000;
+ // User switching doesn't happen that frequently, so it doesn't hurt to have it always on
+ protected static final boolean DEBUG = true;
+
private final ActivityManagerService mService;
private final int mUserId;
private static final int MSG_START_USER = 1;
@@ -118,7 +122,7 @@ class UserSwitchingDialog extends AlertDialog
@Override
public void show() {
- // Slog.v(TAG, "show called");
+ if (DEBUG) Slog.d(TAG, "show called");
super.show();
final View decorView = getWindow().getDecorView();
if (decorView != null) {
@@ -132,13 +136,14 @@ class UserSwitchingDialog extends AlertDialog
@Override
public void onWindowShown() {
- // Slog.v(TAG, "onWindowShown called");
+ if (DEBUG) Slog.d(TAG, "onWindowShown called");
startUser();
}
void startUser() {
synchronized (this) {
if (!mStartedUser) {
+ Slog.i(TAG, "starting user " + mUserId);
mService.mUserController.startUserInForeground(mUserId);
dismiss();
mStartedUser = true;
@@ -147,6 +152,8 @@ class UserSwitchingDialog extends AlertDialog
decorView.getViewTreeObserver().removeOnWindowShownListener(this);
}
mHandler.removeMessages(MSG_START_USER);
+ } else {
+ Slog.i(TAG, "user " + mUserId + " already started");
}
}
}
@@ -156,6 +163,8 @@ class UserSwitchingDialog extends AlertDialog
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_START_USER:
+ Slog.w(TAG, "user switch window not shown in "
+ + WINDOW_SHOWN_TIMEOUT_MS + " ms");
startUser();
break;
}
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index a2b3574880c4..37add3da5a48 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -35,7 +35,6 @@ import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.UserHandle;
import android.text.TextUtils;
-import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
import android.util.Slog;
@@ -45,6 +44,7 @@ import com.android.internal.annotations.VisibleForTesting;
import java.util.ArrayList;
import java.util.HashSet;
+import java.util.LinkedHashMap;
import java.util.Set;
/**
@@ -58,7 +58,7 @@ public class AudioDeviceInventory {
// Actual list of connected devices
// Key for map created from DeviceInfo.makeDeviceListKey()
- private final ArrayMap<String, DeviceInfo> mConnectedDevices = new ArrayMap<>();
+ private final LinkedHashMap<String, DeviceInfo> mConnectedDevices = new LinkedHashMap<>();
private @NonNull AudioDeviceBroker mDeviceBroker;
@@ -148,8 +148,7 @@ public class AudioDeviceInventory {
*/
/*package*/ void onRestoreDevices() {
synchronized (mConnectedDevices) {
- for (int i = 0; i < mConnectedDevices.size(); i++) {
- DeviceInfo di = mConnectedDevices.valueAt(i);
+ for (DeviceInfo di : mConnectedDevices.values()) {
AudioSystem.setDeviceConnectionState(
di.mDeviceType,
AudioSystem.DEVICE_STATE_AVAILABLE,
@@ -799,11 +798,10 @@ public class AudioDeviceInventory {
}
int delay = 0;
Set<Integer> devices = new HashSet<>();
- for (int i = 0; i < mConnectedDevices.size(); i++) {
- int dev = mConnectedDevices.valueAt(i).mDeviceType;
- if (((dev & AudioSystem.DEVICE_BIT_IN) == 0)
- && BECOMING_NOISY_INTENT_DEVICES_SET.contains(dev)) {
- devices.add(dev);
+ for (DeviceInfo di : mConnectedDevices.values()) {
+ if (((di.mDeviceType & AudioSystem.DEVICE_BIT_IN) == 0)
+ && BECOMING_NOISY_INTENT_DEVICES_SET.contains(di.mDeviceType)) {
+ devices.add(di.mDeviceType);
}
}
if (musicDevice == AudioSystem.DEVICE_NONE) {
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index c4ea81a83fdb..1d7c942e8224 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -848,7 +848,7 @@ final class LocalDisplayAdapter extends DisplayAdapter {
int[] ports = res.getIntArray(
com.android.internal.R.array.config_localPrivateDisplayPorts);
if (ports != null) {
- int port = physicalAddress.getPort();
+ int port = Byte.toUnsignedInt(physicalAddress.getPort());
for (int p : ports) {
if (p == port) {
return true;
diff --git a/services/core/java/com/android/server/integrity/model/BitInputStream.java b/services/core/java/com/android/server/integrity/model/BitInputStream.java
index 09bc7e8b9861..e768fe6626ac 100644
--- a/services/core/java/com/android/server/integrity/model/BitInputStream.java
+++ b/services/core/java/com/android/server/integrity/model/BitInputStream.java
@@ -16,15 +16,29 @@
package com.android.server.integrity.model;
+import java.io.IOException;
+import java.io.InputStream;
+
/** A wrapper class for reading a stream of bits. */
public class BitInputStream {
- private byte[] mRuleBytes;
private long mBitPointer;
+ private boolean mReadFromStream;
+
+ private byte[] mRuleBytes;
+ private InputStream mRuleInputStream;
+
+ private byte mCurrentRuleByte;
public BitInputStream(byte[] ruleBytes) {
this.mRuleBytes = ruleBytes;
this.mBitPointer = 0;
+ this.mReadFromStream = false;
+ }
+
+ public BitInputStream(InputStream ruleInputStream) {
+ this.mRuleInputStream = ruleInputStream;
+ this.mReadFromStream = true;
}
/**
@@ -33,34 +47,43 @@ public class BitInputStream {
* @param numOfBits The number of bits to read.
* @return The value read from the stream.
*/
- public int getNext(int numOfBits) {
+ public int getNext(int numOfBits) throws IOException {
int component = 0;
int count = 0;
- int idx = (int) (mBitPointer / 8);
- int offset = 7 - (int) (mBitPointer % 8);
-
while (count++ < numOfBits) {
- if (idx >= mRuleBytes.length) {
- throw new IllegalArgumentException(String.format("Invalid byte index: %d", idx));
+ if (mBitPointer % 8 == 0) {
+ mCurrentRuleByte = getNextByte();
}
+ int offset = 7 - (int) (mBitPointer % 8);
component <<= 1;
- component |= (mRuleBytes[idx] >>> offset) & 1;
+ component |= (mCurrentRuleByte >>> offset) & 1;
- offset--;
- if (offset == -1) {
- idx++;
- offset = 7;
- }
+ mBitPointer++;
}
- mBitPointer += numOfBits;
return component;
}
/** Check if there are bits left in the stream. */
- public boolean hasNext() {
- return mBitPointer / 8 < mRuleBytes.length;
+ public boolean hasNext() throws IOException {
+ if (mReadFromStream) {
+ return mRuleInputStream.available() > 0;
+ } else {
+ return mBitPointer / 8 < mRuleBytes.length;
+ }
+ }
+
+ private byte getNextByte() throws IOException {
+ if (mReadFromStream) {
+ return (byte) mRuleInputStream.read();
+ } else {
+ int idx = (int) (mBitPointer / 8);
+ if (idx >= mRuleBytes.length) {
+ throw new IllegalArgumentException(String.format("Invalid byte index: %d", idx));
+ }
+ return mRuleBytes[idx];
+ }
}
}
diff --git a/services/core/java/com/android/server/integrity/parser/RuleBinaryParser.java b/services/core/java/com/android/server/integrity/parser/RuleBinaryParser.java
index 8aa0751af11c..3ef45a637bc1 100644
--- a/services/core/java/com/android/server/integrity/parser/RuleBinaryParser.java
+++ b/services/core/java/com/android/server/integrity/parser/RuleBinaryParser.java
@@ -36,6 +36,7 @@ import android.content.integrity.Rule;
import com.android.server.integrity.model.BitInputStream;
+import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
@@ -56,15 +57,14 @@ public class RuleBinaryParser implements RuleParser {
@Override
public List<Rule> parse(InputStream inputStream) throws RuleParseException {
try {
- byte[] ruleBytes = new byte[inputStream.available()];
- inputStream.read(ruleBytes);
- return parse(ruleBytes);
+ BitInputStream bitInputStream = new BitInputStream(inputStream);
+ return parseRules(bitInputStream);
} catch (Exception e) {
throw new RuleParseException(e.getMessage(), e);
}
}
- private List<Rule> parseRules(BitInputStream bitInputStream) {
+ private List<Rule> parseRules(BitInputStream bitInputStream) throws IOException {
List<Rule> parsedRules = new ArrayList<>();
// Read the rule binary file format version.
@@ -79,7 +79,7 @@ public class RuleBinaryParser implements RuleParser {
return parsedRules;
}
- private Rule parseRule(BitInputStream bitInputStream) {
+ private Rule parseRule(BitInputStream bitInputStream) throws IOException {
Formula formula = parseFormula(bitInputStream);
int effect = bitInputStream.getNext(EFFECT_BITS);
@@ -90,7 +90,7 @@ public class RuleBinaryParser implements RuleParser {
return new Rule(formula, effect);
}
- private Formula parseFormula(BitInputStream bitInputStream) {
+ private Formula parseFormula(BitInputStream bitInputStream) throws IOException {
int separator = bitInputStream.getNext(SEPARATOR_BITS);
switch (separator) {
case ATOMIC_FORMULA_START:
@@ -105,7 +105,7 @@ public class RuleBinaryParser implements RuleParser {
}
}
- private CompoundFormula parseCompoundFormula(BitInputStream bitInputStream) {
+ private CompoundFormula parseCompoundFormula(BitInputStream bitInputStream) throws IOException {
int connector = bitInputStream.getNext(CONNECTOR_BITS);
List<Formula> formulas = new ArrayList<>();
@@ -118,7 +118,7 @@ public class RuleBinaryParser implements RuleParser {
return new CompoundFormula(connector, formulas);
}
- private AtomicFormula parseAtomicFormula(BitInputStream bitInputStream) {
+ private AtomicFormula parseAtomicFormula(BitInputStream bitInputStream) throws IOException {
int key = bitInputStream.getNext(KEY_BITS);
int operator = bitInputStream.getNext(OPERATOR_BITS);
diff --git a/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java b/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java
index b988fd4c40f1..fdbb7d9df293 100644
--- a/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java
+++ b/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java
@@ -127,7 +127,7 @@ public class RuleBinarySerializer implements RuleSerializer {
bitOutputStream.setNext(SEPARATOR_BITS, ATOMIC_FORMULA_START);
bitOutputStream.setNext(KEY_BITS, atomicFormula.getKey());
- if (atomicFormula instanceof AtomicFormula.StringAtomicFormula) {
+ if (atomicFormula.getTag() == AtomicFormula.STRING_ATOMIC_FORMULA_TAG) {
AtomicFormula.StringAtomicFormula stringAtomicFormula =
(AtomicFormula.StringAtomicFormula) atomicFormula;
bitOutputStream.setNext(OPERATOR_BITS, AtomicFormula.EQ);
@@ -135,7 +135,7 @@ public class RuleBinarySerializer implements RuleSerializer {
stringAtomicFormula.getValue(),
stringAtomicFormula.getIsHashedValue(),
bitOutputStream);
- } else if (atomicFormula instanceof AtomicFormula.IntAtomicFormula) {
+ } else if (atomicFormula.getTag() == AtomicFormula.INT_ATOMIC_FORMULA_TAG) {
AtomicFormula.IntAtomicFormula intAtomicFormula =
(AtomicFormula.IntAtomicFormula) atomicFormula;
bitOutputStream.setNext(OPERATOR_BITS, intAtomicFormula.getOperator());
@@ -143,7 +143,7 @@ public class RuleBinarySerializer implements RuleSerializer {
String.valueOf(intAtomicFormula.getValue()),
/* isHashedValue= */ false,
bitOutputStream);
- } else if (atomicFormula instanceof AtomicFormula.BooleanAtomicFormula) {
+ } else if (atomicFormula.getTag() == AtomicFormula.BOOLEAN_ATOMIC_FORMULA_TAG) {
AtomicFormula.BooleanAtomicFormula booleanAtomicFormula =
(AtomicFormula.BooleanAtomicFormula) atomicFormula;
bitOutputStream.setNext(OPERATOR_BITS, AtomicFormula.EQ);
diff --git a/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java b/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java
index 72068ceeb4f0..cfe50c6c8ac9 100644
--- a/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java
+++ b/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java
@@ -127,7 +127,7 @@ public class RuleXmlSerializer implements RuleSerializer {
xmlSerializer.startTag(NAMESPACE, ATOMIC_FORMULA_TAG);
serializeAttributeValue(
KEY_ATTRIBUTE, String.valueOf(atomicFormula.getKey()), xmlSerializer);
- if (atomicFormula instanceof AtomicFormula.StringAtomicFormula) {
+ if (atomicFormula.getTag() == AtomicFormula.STRING_ATOMIC_FORMULA_TAG) {
serializeAttributeValue(
VALUE_ATTRIBUTE,
((AtomicFormula.StringAtomicFormula) atomicFormula).getValue(),
@@ -137,7 +137,7 @@ public class RuleXmlSerializer implements RuleSerializer {
String.valueOf(
((AtomicFormula.StringAtomicFormula) atomicFormula).getIsHashedValue()),
xmlSerializer);
- } else if (atomicFormula instanceof AtomicFormula.IntAtomicFormula) {
+ } else if (atomicFormula.getTag() == AtomicFormula.INT_ATOMIC_FORMULA_TAG) {
serializeAttributeValue(
OPERATOR_ATTRIBUTE,
String.valueOf(((AtomicFormula.IntAtomicFormula) atomicFormula).getOperator()),
@@ -146,7 +146,7 @@ public class RuleXmlSerializer implements RuleSerializer {
VALUE_ATTRIBUTE,
String.valueOf(((AtomicFormula.IntAtomicFormula) atomicFormula).getValue()),
xmlSerializer);
- } else if (atomicFormula instanceof AtomicFormula.BooleanAtomicFormula) {
+ } else if (atomicFormula.getTag() == AtomicFormula.BOOLEAN_ATOMIC_FORMULA_TAG) {
serializeAttributeValue(
VALUE_ATTRIBUTE,
String.valueOf(((AtomicFormula.BooleanAtomicFormula) atomicFormula).getValue()),
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 83b62159f9b0..ec4aedd01cea 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -379,7 +379,7 @@ public class LockSettingsService extends ILockSettings.Stub {
if (DEBUG) Slog.v(TAG, "Tie managed profile to parent now!");
try (LockscreenCredential unifiedProfilePassword = generateRandomProfilePassword()) {
setLockCredentialInternal(unifiedProfilePassword, managedUserPassword, managedUserId,
- false, /* isLockTiedToParent= */ true);
+ /* isLockTiedToParent= */ true);
tieProfileLockToParent(managedUserId, unifiedProfilePassword);
}
}
@@ -1473,17 +1473,12 @@ public class LockSettingsService extends ILockSettings.Stub {
setLockCredentialInternal(LockscreenCredential.createNone(),
profilePasswordMap.get(managedUserId),
managedUserId,
- false, /* isLockTiedToParent= */ true);
+ /* isLockTiedToParent= */ true);
+ mStorage.removeChildProfileLock(managedUserId);
+ removeKeystoreProfileKey(managedUserId);
} else {
- Slog.wtf(TAG, "clear tied profile challenges, but no password supplied.");
- // Attempt an untrusted reset by supplying an empty credential.
- setLockCredentialInternal(LockscreenCredential.createNone(),
- LockscreenCredential.createNone(),
- managedUserId,
- true, /* isLockTiedToParent= */ true);
+ Slog.wtf(TAG, "Attempt to clear tied challenge, but no password supplied.");
}
- mStorage.removeChildProfileLock(managedUserId);
- removeKeystoreProfileKey(managedUserId);
}
}
}
@@ -1567,7 +1562,7 @@ public class LockSettingsService extends ILockSettings.Stub {
// should call setLockCredentialInternal.
@Override
public boolean setLockCredential(LockscreenCredential credential,
- LockscreenCredential savedCredential, int userId, boolean allowUntrustedChange) {
+ LockscreenCredential savedCredential, int userId) {
if (!mLockPatternUtils.hasSecureLockScreen()) {
throw new UnsupportedOperationException(
@@ -1576,7 +1571,7 @@ public class LockSettingsService extends ILockSettings.Stub {
checkWritePermission(userId);
synchronized (mSeparateChallengeLock) {
if (!setLockCredentialInternal(credential, savedCredential,
- userId, allowUntrustedChange, /* isLockTiedToParent= */ false)) {
+ userId, /* isLockTiedToParent= */ false)) {
return false;
}
setSeparateProfileChallengeEnabledLocked(userId, true, /* unused */ null);
@@ -1598,14 +1593,13 @@ public class LockSettingsService extends ILockSettings.Stub {
* credentials are being tied to its parent's credentials.
*/
private boolean setLockCredentialInternal(LockscreenCredential credential,
- LockscreenCredential savedCredential, int userId,
- boolean allowUntrustedChange, boolean isLockTiedToParent) {
+ LockscreenCredential savedCredential, int userId, boolean isLockTiedToParent) {
Preconditions.checkNotNull(credential);
Preconditions.checkNotNull(savedCredential);
synchronized (mSpManager) {
if (isSyntheticPasswordBasedCredentialLocked(userId)) {
return spBasedSetLockCredentialInternalLocked(credential, savedCredential, userId,
- allowUntrustedChange, isLockTiedToParent);
+ isLockTiedToParent);
}
}
@@ -1653,7 +1647,7 @@ public class LockSettingsService extends ILockSettings.Stub {
if (shouldMigrateToSyntheticPasswordLocked(userId)) {
initializeSyntheticPasswordLocked(currentHandle.hash, savedCredential, userId);
return spBasedSetLockCredentialInternalLocked(credential, savedCredential, userId,
- allowUntrustedChange, isLockTiedToParent);
+ isLockTiedToParent);
}
}
if (DEBUG) Slog.d(TAG, "setLockCredentialInternal: user=" + userId);
@@ -2075,7 +2069,7 @@ public class LockSettingsService extends ILockSettings.Stub {
}
if (shouldReEnroll) {
setLockCredentialInternal(credential, credential,
- userId, false, /* isLockTiedToParent= */ false);
+ userId, /* isLockTiedToParent= */ false);
} else {
// Now that we've cleared of all required GK migration, let's do the final
// migration to synthetic password.
@@ -2210,7 +2204,6 @@ public class LockSettingsService extends ILockSettings.Stub {
Slog.i(TAG, "RemoveUser: " + userId);
mSpManager.removeUser(userId);
mStrongAuth.removeUser(userId);
- tryRemoveUserFromSpCacheLater(userId);
final KeyStore ks = KeyStore.getInstance();
ks.onUserRemoved(userId);
@@ -2471,25 +2464,7 @@ public class LockSettingsService extends ILockSettings.Stub {
}
}
- /**
- * A user's synthetic password does not change so it must be cached in certain circumstances to
- * enable untrusted credential reset.
- *
- * Untrusted credential reset will be removed in a future version (b/68036371) at which point
- * this cache is no longer needed as the SP will always be known when changing the user's
- * credential.
- */
- @GuardedBy("mSpManager")
- private SparseArray<AuthenticationToken> mSpCache = new SparseArray<>();
-
private void onAuthTokenKnownForUser(@UserIdInt int userId, AuthenticationToken auth) {
- // Preemptively cache the SP and then try to remove it in a handler.
- Slog.i(TAG, "Caching SP for user " + userId);
- synchronized (mSpManager) {
- mSpCache.put(userId, auth);
- }
- tryRemoveUserFromSpCacheLater(userId);
-
if (mInjector.isGsiRunning()) {
Slog.w(TAG, "AuthSecret disabled in GSI");
return;
@@ -2510,42 +2485,6 @@ public class LockSettingsService extends ILockSettings.Stub {
}
}
- private void tryRemoveUserFromSpCacheLater(@UserIdInt int userId) {
- mHandler.post(() -> {
- if (!shouldCacheSpForUser(userId)) {
- // The transition from 'should not cache' to 'should cache' can only happen if
- // certain admin apps are installed after provisioning e.g. via adb. This is not
- // a common case and we do not seamlessly support; it may result in the SP not
- // being cached when it is needed. The cache can be re-populated by verifying
- // the credential again.
- Slog.i(TAG, "Removing SP from cache for user " + userId);
- synchronized (mSpManager) {
- mSpCache.remove(userId);
- }
- }
- });
- }
-
- /** Do not hold any of the locks from this service when calling. */
- private boolean shouldCacheSpForUser(@UserIdInt int userId) {
- // Before the user setup has completed, an admin could be installed that requires the SP to
- // be cached (see below).
- if (Settings.Secure.getIntForUser(mContext.getContentResolver(),
- Settings.Secure.USER_SETUP_COMPLETE, 0, userId) == 0) {
- return true;
- }
-
- // If the user has an admin which can perform an untrusted credential reset, the SP needs to
- // be cached. If there isn't a DevicePolicyManager then there can't be an admin in the first
- // place so caching is not necessary.
- final DevicePolicyManagerInternal dpmi = LocalServices.getService(
- DevicePolicyManagerInternal.class);
- if (dpmi == null) {
- return false;
- }
- return dpmi.canUserHaveUntrustedCredentialReset(userId);
- }
-
/**
* Precondition: vold and keystore unlocked.
*
@@ -2579,8 +2518,8 @@ public class LockSettingsService extends ILockSettings.Stub {
* This could also happen during an untrusted reset to clear password.
*
* 3. credentialhash == null and credential != null
- * This is the untrusted credential reset, OR the user sets a new lockscreen password
- * FOR THE FIRST TIME on a SP-enabled device. New credential and new SID will be created
+ * The user sets a new lockscreen password FOR THE FIRST TIME on a SP-enabled device.
+ * New credential and new SID will be created
*/
@GuardedBy("mSpManager")
@VisibleForTesting
@@ -2905,8 +2844,7 @@ public class LockSettingsService extends ILockSettings.Stub {
*/
@GuardedBy("mSpManager")
private boolean spBasedSetLockCredentialInternalLocked(LockscreenCredential credential,
- LockscreenCredential savedCredential, int userId,
- boolean allowUntrustedChange, boolean isLockTiedToParent) {
+ LockscreenCredential savedCredential, int userId, boolean isLockTiedToParent) {
if (DEBUG) Slog.d(TAG, "spBasedSetLockCredentialInternalLocked: user=" + userId);
if (savedCredential.isNone() && isManagedProfileWithUnifiedLock(userId)) {
// get credential from keystore when managed profile has unified lock
@@ -2927,50 +2865,24 @@ public class LockSettingsService extends ILockSettings.Stub {
VerifyCredentialResponse response = authResult.gkResponse;
AuthenticationToken auth = authResult.authToken;
- // If existing credential is provided, the existing credential must match.
- if (!savedCredential.isNone() && auth == null) {
- Slog.w(TAG, "Failed to enroll: incorrect credential");
- return false;
- }
- boolean untrustedReset = false;
- if (auth != null) {
- onAuthTokenKnownForUser(userId, auth);
- } else if (response == null) {
- throw new IllegalStateException("Password change failed.");
- } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_ERROR) {
- // We are performing an untrusted credential change, by DevicePolicyManager or other
- // internal callers that don't provide the existing credential
- Slog.w(TAG, "Untrusted credential change invoked");
- // Try to get a cached auth token, so we can keep SP unchanged.
- auth = mSpCache.get(userId);
- if (!allowUntrustedChange) {
- throw new IllegalStateException("Untrusted credential change was invoked but it was"
- + " not allowed. This is likely a bug. Auth token is null: "
- + Boolean.toString(auth == null));
- }
- untrustedReset = true;
- } else /* responseCode == VerifyCredentialResponse.RESPONSE_RETRY */ {
- Slog.w(TAG, "Rate limit exceeded, so password was not changed.");
- return false;
- }
- if (auth != null) {
- if (untrustedReset) {
- // Force change the current SID to mantain existing behaviour that an untrusted
- // reset leads to a change of SID. If the untrusted reset is for clearing the
- // current password, the nuking of the SID will be done in
- // setLockCredentialWithAuthTokenLocked next
- mSpManager.newSidForUser(getGateKeeperService(), auth, userId);
+ if (auth == null) {
+ if (response == null
+ || response.getResponseCode() == VerifyCredentialResponse.RESPONSE_ERROR) {
+ Slog.w(TAG, "Failed to enroll: incorrect credential.");
+ return false;
}
- setLockCredentialWithAuthTokenLocked(credential, auth, userId);
- mSpManager.destroyPasswordBasedSyntheticPassword(handle, userId);
- } else {
- throw new IllegalStateException(
- "Untrusted credential reset not possible without cached SP");
- // Could call initializeSyntheticPasswordLocked(null, credential, credentialType,
- // requestedQuality, userId) instead if we still allow untrusted reset that changes
- // synthetic password. That would invalidate existing escrow tokens though.
+ if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) {
+ Slog.w(TAG, "Failed to enroll: rate limit exceeded.");
+ return false;
+ }
+ // Should not be reachable, but just in case.
+ throw new IllegalStateException("password change failed");
}
+
+ onAuthTokenKnownForUser(userId, auth);
+ setLockCredentialWithAuthTokenLocked(credential, auth, userId);
+ mSpManager.destroyPasswordBasedSyntheticPassword(handle, userId);
sendCredentialsOnChangeIfRequired(credential, userId, isLockTiedToParent);
return true;
}
@@ -3125,11 +3037,10 @@ public class LockSettingsService extends ILockSettings.Stub {
+ "verification.");
return false;
}
+ onAuthTokenKnownForUser(userId, result.authToken);
long oldHandle = getSyntheticPasswordHandleLocked(userId);
setLockCredentialWithAuthTokenLocked(credential, result.authToken, userId);
mSpManager.destroyPasswordBasedSyntheticPassword(oldHandle, userId);
-
- onAuthTokenKnownForUser(userId, result.authToken);
return true;
}
@@ -3248,8 +3159,6 @@ public class LockSettingsService extends ILockSettings.Stub {
private class DeviceProvisionedObserver extends ContentObserver {
private final Uri mDeviceProvisionedUri = Settings.Global.getUriFor(
Settings.Global.DEVICE_PROVISIONED);
- private final Uri mUserSetupCompleteUri = Settings.Secure.getUriFor(
- Settings.Secure.USER_SETUP_COMPLETE);
private boolean mRegistered;
@@ -3267,8 +3176,6 @@ public class LockSettingsService extends ILockSettings.Stub {
reportDeviceSetupComplete();
clearFrpCredentialIfOwnerNotSecure();
}
- } else if (mUserSetupCompleteUri.equals(uri)) {
- tryRemoveUserFromSpCacheLater(userId);
}
}
@@ -3320,8 +3227,6 @@ public class LockSettingsService extends ILockSettings.Stub {
if (register) {
mContext.getContentResolver().registerContentObserver(mDeviceProvisionedUri,
false, this);
- mContext.getContentResolver().registerContentObserver(mUserSetupCompleteUri,
- false, this, UserHandle.USER_ALL);
} else {
mContext.getContentResolver().unregisterContentObserver(this);
}
diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
index e9a8085950b0..c53647d053bc 100644
--- a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
+++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
@@ -136,8 +136,13 @@ public class SyntheticPasswordManager {
"android-synthetic-password-personalization-context".getBytes();
static class AuthenticationResult {
- public AuthenticationToken authToken;
- public VerifyCredentialResponse gkResponse;
+ // Non-null if password/token passes verification, null otherwise
+ @Nullable public AuthenticationToken authToken;
+ // OK: password / token passes verification, user has a lockscreen
+ // null: user does not have a lockscreen (but password / token passes verification)
+ // ERROR: password / token fails verification
+ // RETRY: password / token verification is throttled at the moment.
+ @Nullable public VerifyCredentialResponse gkResponse;
}
/**
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index d0ad47d3d7a6..12afef2cf950 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -171,6 +171,7 @@ import android.os.IDeviceIdleController;
import android.os.IInterface;
import android.os.Looper;
import android.os.Message;
+import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
import android.os.ResultReceiver;
@@ -292,6 +293,9 @@ public class NotificationManagerService extends SystemService {
public static final boolean ENABLE_CHILD_NOTIFICATIONS
= SystemProperties.getBoolean("debug.child_notifs", true);
+ // pullStats report request: undecorated remote view stats
+ public static final int REPORT_REMOTE_VIEWS = 0x01;
+
static final boolean DEBUG_INTERRUPTIVENESS = SystemProperties.getBoolean(
"debug.notification.interruptiveness", false);
@@ -4080,6 +4084,8 @@ public class NotificationManagerService extends SystemService {
try {
if (filter.stats) {
dumpJson(pw, filter);
+ } else if (filter.rvStats) {
+ dumpRemoteViewStats(pw, filter);
} else if (filter.proto) {
dumpProto(fd, filter);
} else if (filter.criticalPriority) {
@@ -4556,6 +4562,49 @@ public class NotificationManagerService extends SystemService {
new NotificationShellCmd(NotificationManagerService.this)
.exec(this, in, out, err, args, callback, resultReceiver);
}
+
+ /**
+ * Get stats committed after startNs
+ *
+ * @param startNs Report stats committed after this time in nanoseconds.
+ * @param report Indicatess which section to include in the stats.
+ * @param doAgg Whether to aggregate the stats or keep them separated.
+ * @param out List of protos of individual commits or one representing the
+ * aggregate.
+ * @return the report time in nanoseconds, or 0 on error.
+ */
+ @Override
+ public long pullStats(long startNs, int report, boolean doAgg,
+ List<ParcelFileDescriptor> out) {
+ checkCallerIsSystemOrShell();
+ long startMs = TimeUnit.MILLISECONDS.convert(startNs, TimeUnit.NANOSECONDS);
+
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ switch (report) {
+ case REPORT_REMOTE_VIEWS:
+ Slog.e(TAG, "pullStats REPORT_REMOTE_VIEWS from: "
+ + startMs + " wtih " + doAgg);
+ PulledStats stats = mUsageStats.remoteViewStats(startMs, doAgg);
+ if (stats != null) {
+ out.add(stats.toParcelFileDescriptor(report));
+ Slog.e(TAG, "exiting pullStats with: " + out.size());
+ long endNs = TimeUnit.NANOSECONDS
+ .convert(stats.endTimeMs(), TimeUnit.MILLISECONDS);
+ return endNs;
+ }
+ Slog.e(TAG, "null stats for: " + report);
+ }
+ } catch (IOException e) {
+
+ Slog.e(TAG, "exiting pullStats: on error", e);
+ return 0;
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ Slog.e(TAG, "exiting pullStats: bad request");
+ return 0;
+ }
};
@VisibleForTesting
@@ -4773,6 +4822,15 @@ public class NotificationManagerService extends SystemService {
pw.println(dump);
}
+ private void dumpRemoteViewStats(PrintWriter pw, @NonNull DumpFilter filter) {
+ PulledStats stats = mUsageStats.remoteViewStats(filter.since, true);
+ if (stats == null) {
+ pw.println("no remote view stats reported.");
+ return;
+ }
+ stats.dump(REPORT_REMOTE_VIEWS, pw, filter);
+ }
+
private void dumpProto(FileDescriptor fd, @NonNull DumpFilter filter) {
final ProtoOutputStream proto = new ProtoOutputStream(fd);
synchronized (mNotificationLock) {
@@ -9084,6 +9142,7 @@ public class NotificationManagerService extends SystemService {
public boolean zen;
public long since;
public boolean stats;
+ public boolean rvStats;
public boolean redact = true;
public boolean proto = false;
public boolean criticalPriority = false;
@@ -9119,6 +9178,14 @@ public class NotificationManagerService extends SystemService {
} else {
filter.since = 0;
}
+ } else if ("--remote-view-stats".equals(a)) {
+ filter.rvStats = true;
+ if (ai < args.length-1) {
+ ai++;
+ filter.since = Long.parseLong(args[ai]);
+ } else {
+ filter.since = 0;
+ }
} else if (PRIORITY_ARG.equals(a)) {
// Bugreport will call the service twice with priority arguments, first to dump
// critical sections and then non critical ones. Set approriate filters
diff --git a/services/core/java/com/android/server/notification/NotificationUsageStats.java b/services/core/java/com/android/server/notification/NotificationUsageStats.java
index fe3d0eb3e469..ac8d1a9a9ad4 100644
--- a/services/core/java/com/android/server/notification/NotificationUsageStats.java
+++ b/services/core/java/com/android/server/notification/NotificationUsageStats.java
@@ -149,6 +149,7 @@ public class NotificationUsageStats {
stats.numPostedByApp++;
stats.updateInterarrivalEstimate(now);
stats.countApiUse(notification);
+ stats.numUndecoratedRemoteViews += (isUndecoratedRemoteView(notification) ? 1 : 0);
}
releaseAggregatedStatsLocked(aggregatedStatsArray);
if (ENABLE_SQLITE_LOG) {
@@ -157,6 +158,13 @@ public class NotificationUsageStats {
}
/**
+ * Does this notification use RemoveViews without a platform decoration?
+ */
+ protected static boolean isUndecoratedRemoteView(NotificationRecord notification) {
+ return (notification.getNotification().getNotificationStyle() == null);
+ }
+
+ /**
* Called when a notification has been updated.
*/
public synchronized void registerUpdatedByApp(NotificationRecord notification,
@@ -337,6 +345,15 @@ public class NotificationUsageStats {
return dump;
}
+ public PulledStats remoteViewStats(long startMs, boolean aggregate) {
+ if (ENABLE_SQLITE_LOG) {
+ if (aggregate) {
+ return mSQLiteLog.remoteViewAggStats(startMs);
+ }
+ }
+ return null;
+ }
+
public synchronized void dump(PrintWriter pw, String indent, DumpFilter filter) {
if (ENABLE_AGGREGATED_IN_MEMORY_STATS) {
for (AggregatedStats as : mStats.values()) {
@@ -414,6 +431,7 @@ public class NotificationUsageStats {
public int numRateViolations;
public int numAlertViolations;
public int numQuotaViolations;
+ public int numUndecoratedRemoteViews;
public long mLastAccessTime;
public int numImagesRemoved;
@@ -685,6 +703,8 @@ public class NotificationUsageStats {
output.append(indentPlusTwo).append(noisyImportance.toString()).append("\n");
output.append(indentPlusTwo).append(quietImportance.toString()).append("\n");
output.append(indentPlusTwo).append(finalImportance.toString()).append("\n");
+ output.append(indentPlusTwo);
+ output.append("numUndecorateRVs=").append(numUndecoratedRemoteViews).append("\n");
output.append(indent).append("}");
return output.toString();
}
@@ -1044,7 +1064,7 @@ public class NotificationUsageStats {
private static final int MSG_DISMISS = 4;
private static final String DB_NAME = "notification_log.db";
- private static final int DB_VERSION = 5;
+ private static final int DB_VERSION = 7;
/** Age in ms after which events are pruned from the DB. */
private static final long HORIZON_MS = 7 * 24 * 60 * 60 * 1000L; // 1 week
@@ -1077,6 +1097,7 @@ public class NotificationUsageStats {
private static final String COL_FIRST_EXPANSIONTIME_MS = "first_expansion_time_ms";
private static final String COL_AIRTIME_EXPANDED_MS = "expansion_airtime_ms";
private static final String COL_EXPAND_COUNT = "expansion_count";
+ private static final String COL_UNDECORATED = "undecorated";
private static final int EVENT_TYPE_POST = 1;
@@ -1102,12 +1123,20 @@ public class NotificationUsageStats {
"COUNT(*) AS cnt, " +
"SUM(" + COL_MUTED + ") as muted, " +
"SUM(" + COL_NOISY + ") as noisy, " +
- "SUM(" + COL_DEMOTED + ") as demoted " +
+ "SUM(" + COL_DEMOTED + ") as demoted, " +
+ "SUM(" + COL_UNDECORATED + ") as undecorated " +
"FROM " + TAB_LOG + " " +
"WHERE " +
COL_EVENT_TYPE + "=" + EVENT_TYPE_POST +
" AND " + COL_EVENT_TIME + " > %d " +
" GROUP BY " + COL_EVENT_USER_ID + ", day, " + COL_PKG;
+ private static final String UNDECORATED_QUERY = "SELECT " +
+ COL_PKG + ", " +
+ "MAX(" + COL_EVENT_TIME + ") as max_time " +
+ "FROM " + TAB_LOG + " " +
+ "WHERE " + COL_UNDECORATED + "> 0 " +
+ " AND " + COL_EVENT_TIME + " > %d " +
+ "GROUP BY " + COL_PKG;
public SQLiteLog(Context context) {
HandlerThread backgroundThread = new HandlerThread("notification-sqlite-log",
@@ -1163,7 +1192,8 @@ public class NotificationUsageStats {
COL_AIRTIME_MS + " INT," +
COL_FIRST_EXPANSIONTIME_MS + " INT," +
COL_AIRTIME_EXPANDED_MS + " INT," +
- COL_EXPAND_COUNT + " INT" +
+ COL_EXPAND_COUNT + " INT," +
+ COL_UNDECORATED + " INT" +
")");
}
@@ -1273,6 +1303,7 @@ public class NotificationUsageStats {
} else {
putPosttimeVisibility(r, cv);
}
+ cv.put(COL_UNDECORATED, (isUndecoratedRemoteView(r) ? 1 : 0));
SQLiteDatabase db = mHelper.getWritableDatabase();
if (db.insert(TAB_LOG, null, cv) < 0) {
Log.wtf(TAG, "Error while trying to insert values: " + cv);
@@ -1353,5 +1384,22 @@ public class NotificationUsageStats {
}
return dump;
}
+
+ public PulledStats remoteViewAggStats(long startMs) {
+ PulledStats stats = new PulledStats(startMs);
+ SQLiteDatabase db = mHelper.getReadableDatabase();
+ String q = String.format(UNDECORATED_QUERY, startMs);
+ Cursor cursor = db.rawQuery(q, null);
+ try {
+ for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
+ String pkg = cursor.getString(0);
+ long maxTimeMs = cursor.getLong(1);
+ stats.addUndecoratedPackage(pkg, maxTimeMs);
+ }
+ } finally {
+ cursor.close();
+ }
+ return stats;
+ }
}
}
diff --git a/services/core/java/com/android/server/notification/PulledStats.java b/services/core/java/com/android/server/notification/PulledStats.java
new file mode 100644
index 000000000000..ada890a10361
--- /dev/null
+++ b/services/core/java/com/android/server/notification/PulledStats.java
@@ -0,0 +1,129 @@
+/*
+ * 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.notification;
+
+import static com.android.server.notification.NotificationManagerService.REPORT_REMOTE_VIEWS;
+
+import android.os.ParcelFileDescriptor;
+import android.service.notification.NotificationRemoteViewsProto;
+import android.service.notification.PackageRemoteViewInfoProto;
+import android.util.Slog;
+import android.util.proto.ProtoOutputStream;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+public class PulledStats {
+ static final String TAG = "PulledStats";
+
+ private final long mTimePeriodStartMs;
+ private long mTimePeriodEndMs;
+ private List<String> mUndecoratedPackageNames;
+
+ public PulledStats(long startMs) {
+ mTimePeriodEndMs = mTimePeriodStartMs = startMs;
+ mUndecoratedPackageNames = new ArrayList<>();
+ }
+
+ ParcelFileDescriptor toParcelFileDescriptor(int report)
+ throws IOException {
+ final ParcelFileDescriptor[] fds = ParcelFileDescriptor.createPipe();
+ switch(report) {
+ case REPORT_REMOTE_VIEWS:
+ Thread thr = new Thread("NotificationManager pulled metric output") {
+ public void run() {
+ try {
+ FileOutputStream fout = new ParcelFileDescriptor.AutoCloseOutputStream(
+ fds[1]);
+ final ProtoOutputStream proto = new ProtoOutputStream(fout);
+ writeToProto(report, proto);
+ proto.flush();
+ fout.close();
+ } catch (IOException e) {
+ Slog.w(TAG, "Failure writing pipe", e);
+ }
+ }
+ };
+ thr.start();
+ break;
+
+ default:
+ Slog.w(TAG, "Unknown pulled stats request: " + report);
+ break;
+ }
+ return fds[0];
+ }
+
+ /*
+ * @return the most recent timestamp in the report, as nanoseconds.
+ */
+ public long endTimeMs() {
+ return mTimePeriodEndMs;
+ }
+
+ public void dump(int report, PrintWriter pw, NotificationManagerService.DumpFilter filter) {
+ switch(report) {
+ case REPORT_REMOTE_VIEWS:
+ pw.print(" Packages with undecordated notifications (");
+ pw.print(mTimePeriodStartMs);
+ pw.print(" - ");
+ pw.print(mTimePeriodEndMs);
+ pw.println("):");
+ if (mUndecoratedPackageNames.size() == 0) {
+ pw.println(" none");
+ } else {
+ for (String pkg : mUndecoratedPackageNames) {
+ if (!filter.filtered || pkg.equals(filter.pkgFilter)) {
+ pw.println(" " + pkg);
+ }
+ }
+ }
+ break;
+
+ default:
+ pw.println("Unknown pulled stats request: " + report);
+ break;
+ }
+ }
+
+ @VisibleForTesting
+ void writeToProto(int report, ProtoOutputStream proto) {
+ switch(report) {
+ case REPORT_REMOTE_VIEWS:
+ for (String pkg: mUndecoratedPackageNames) {
+ long token = proto.start(NotificationRemoteViewsProto.PACKAGE_REMOTE_VIEW_INFO);
+ proto.write(PackageRemoteViewInfoProto.PACKAGE_NAME, pkg);
+ proto.end(token);
+ }
+ break;
+
+ default:
+ Slog.w(TAG, "Unknown pulled stats request: " + report);
+ break;
+ }
+ }
+
+ public void addUndecoratedPackage(String packageName, long timestampMs) {
+ mUndecoratedPackageNames.add(packageName);
+ mTimePeriodEndMs = Math.max(mTimePeriodEndMs, timestampMs);
+ }
+}
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index f5fcb77710ca..f1947ac15645 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -533,13 +533,13 @@ public final class OverlayManagerService extends SystemService {
private final IBinder mService = new IOverlayManager.Stub() {
@Override
- public Map<String, List<OverlayInfo>> getAllOverlays(int userId) throws RemoteException {
+ public Map<String, List<OverlayInfo>> getAllOverlays(final int userIdArg) {
try {
- traceBegin(TRACE_TAG_RRO, "OMS#getAllOverlays " + userId);
- userId = handleIncomingUser(userId, "getAllOverlays");
+ traceBegin(TRACE_TAG_RRO, "OMS#getAllOverlays " + userIdArg);
+ final int realUserId = handleIncomingUser(userIdArg, "getAllOverlays");
synchronized (mLock) {
- return mImpl.getOverlaysForUser(userId);
+ return mImpl.getOverlaysForUser(realUserId);
}
} finally {
traceEnd(TRACE_TAG_RRO);
@@ -548,16 +548,17 @@ public final class OverlayManagerService extends SystemService {
@Override
public List<OverlayInfo> getOverlayInfosForTarget(@Nullable final String targetPackageName,
- int userId) throws RemoteException {
+ final int userIdArg) {
+ if (targetPackageName == null) {
+ return Collections.emptyList();
+ }
+
try {
traceBegin(TRACE_TAG_RRO, "OMS#getOverlayInfosForTarget " + targetPackageName);
- userId = handleIncomingUser(userId, "getOverlayInfosForTarget");
- if (targetPackageName == null) {
- return Collections.emptyList();
- }
+ final int realUserId = handleIncomingUser(userIdArg, "getOverlayInfosForTarget");
synchronized (mLock) {
- return mImpl.getOverlayInfosForTarget(targetPackageName, userId);
+ return mImpl.getOverlayInfosForTarget(targetPackageName, realUserId);
}
} finally {
traceEnd(TRACE_TAG_RRO);
@@ -566,16 +567,17 @@ public final class OverlayManagerService extends SystemService {
@Override
public OverlayInfo getOverlayInfo(@Nullable final String packageName,
- int userId) throws RemoteException {
+ final int userIdArg) {
+ if (packageName == null) {
+ return null;
+ }
+
try {
traceBegin(TRACE_TAG_RRO, "OMS#getOverlayInfo " + packageName);
- userId = handleIncomingUser(userId, "getOverlayInfo");
- if (packageName == null) {
- return null;
- }
+ final int realUserId = handleIncomingUser(userIdArg, "getOverlayInfo");
synchronized (mLock) {
- return mImpl.getOverlayInfo(packageName, userId);
+ return mImpl.getOverlayInfo(packageName, realUserId);
}
} finally {
traceEnd(TRACE_TAG_RRO);
@@ -584,19 +586,20 @@ public final class OverlayManagerService extends SystemService {
@Override
public boolean setEnabled(@Nullable final String packageName, final boolean enable,
- int userId) throws RemoteException {
+ int userIdArg) {
+ if (packageName == null) {
+ return false;
+ }
+
try {
traceBegin(TRACE_TAG_RRO, "OMS#setEnabled " + packageName + " " + enable);
- enforceActor(packageName, "setEnabled", userId);
- userId = handleIncomingUser(userId, "setEnabled");
- if (packageName == null) {
- return false;
- }
+ final int realUserId = handleIncomingUser(userIdArg, "setEnabled");
+ enforceActor(packageName, "setEnabled", realUserId);
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
- return mImpl.setEnabled(packageName, enable, userId);
+ return mImpl.setEnabled(packageName, enable, realUserId);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -608,20 +611,21 @@ public final class OverlayManagerService extends SystemService {
@Override
public boolean setEnabledExclusive(@Nullable final String packageName, final boolean enable,
- int userId) throws RemoteException {
+ int userIdArg) {
+ if (packageName == null || !enable) {
+ return false;
+ }
+
try {
traceBegin(TRACE_TAG_RRO, "OMS#setEnabledExclusive " + packageName + " " + enable);
- enforceActor(packageName, "setEnabledExclusive", userId);
- userId = handleIncomingUser(userId, "setEnabledExclusive");
- if (packageName == null || !enable) {
- return false;
- }
+ final int realUserId = handleIncomingUser(userIdArg, "setEnabledExclusive");
+ enforceActor(packageName, "setEnabledExclusive", realUserId);
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
return mImpl.setEnabledExclusive(packageName, false /* withinCategory */,
- userId);
+ realUserId);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -632,21 +636,23 @@ public final class OverlayManagerService extends SystemService {
}
@Override
- public boolean setEnabledExclusiveInCategory(@Nullable String packageName, int userId)
- throws RemoteException {
+ public boolean setEnabledExclusiveInCategory(@Nullable String packageName,
+ final int userIdArg) {
+ if (packageName == null) {
+ return false;
+ }
+
try {
traceBegin(TRACE_TAG_RRO, "OMS#setEnabledExclusiveInCategory " + packageName);
- enforceActor(packageName, "setEnabledExclusiveInCategory", userId);
- userId = handleIncomingUser(userId, "setEnabledExclusiveInCategory");
- if (packageName == null) {
- return false;
- }
+ final int realUserId = handleIncomingUser(userIdArg,
+ "setEnabledExclusiveInCategory");
+ enforceActor(packageName, "setEnabledExclusiveInCategory", realUserId);
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
return mImpl.setEnabledExclusive(packageName, true /* withinCategory */,
- userId);
+ realUserId);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -658,20 +664,21 @@ public final class OverlayManagerService extends SystemService {
@Override
public boolean setPriority(@Nullable final String packageName,
- @Nullable final String parentPackageName, int userId) throws RemoteException {
+ @Nullable final String parentPackageName, final int userIdArg) {
+ if (packageName == null || parentPackageName == null) {
+ return false;
+ }
+
try {
traceBegin(TRACE_TAG_RRO, "OMS#setPriority " + packageName + " "
+ parentPackageName);
- enforceActor(packageName, "setPriority", userId);
- userId = handleIncomingUser(userId, "setPriority");
- if (packageName == null || parentPackageName == null) {
- return false;
- }
+ final int realUserId = handleIncomingUser(userIdArg, "setPriority");
+ enforceActor(packageName, "setPriority", realUserId);
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
- return mImpl.setPriority(packageName, parentPackageName, userId);
+ return mImpl.setPriority(packageName, parentPackageName, realUserId);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -682,20 +689,20 @@ public final class OverlayManagerService extends SystemService {
}
@Override
- public boolean setHighestPriority(@Nullable final String packageName, int userId)
- throws RemoteException {
+ public boolean setHighestPriority(@Nullable final String packageName, final int userIdArg) {
+ if (packageName == null) {
+ return false;
+ }
+
try {
traceBegin(TRACE_TAG_RRO, "OMS#setHighestPriority " + packageName);
- enforceActor(packageName, "setHighestPriority", userId);
- userId = handleIncomingUser(userId, "setHighestPriority");
- if (packageName == null) {
- return false;
- }
+ final int realUserId = handleIncomingUser(userIdArg, "setHighestPriority");
+ enforceActor(packageName, "setHighestPriority", realUserId);
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
- return mImpl.setHighestPriority(packageName, userId);
+ return mImpl.setHighestPriority(packageName, realUserId);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -706,20 +713,20 @@ public final class OverlayManagerService extends SystemService {
}
@Override
- public boolean setLowestPriority(@Nullable final String packageName, int userId)
- throws RemoteException {
+ public boolean setLowestPriority(@Nullable final String packageName, final int userIdArg) {
+ if (packageName == null) {
+ return false;
+ }
+
try {
traceBegin(TRACE_TAG_RRO, "OMS#setLowestPriority " + packageName);
- enforceActor(packageName, "setLowestPriority", userId);
- userId = handleIncomingUser(userId, "setLowestPriority");
- if (packageName == null) {
- return false;
- }
+ final int realUserId = handleIncomingUser(userIdArg, "setLowestPriority");
+ enforceActor(packageName, "setLowestPriority", realUserId);
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
- return mImpl.setLowestPriority(packageName, userId);
+ return mImpl.setLowestPriority(packageName, realUserId);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -730,7 +737,7 @@ public final class OverlayManagerService extends SystemService {
}
@Override
- public String[] getDefaultOverlayPackages() throws RemoteException {
+ public String[] getDefaultOverlayPackages() {
try {
traceBegin(TRACE_TAG_RRO, "OMS#getDefaultOverlayPackages");
getContext().enforceCallingOrSelfPermission(
@@ -750,18 +757,17 @@ public final class OverlayManagerService extends SystemService {
}
@Override
- public void invalidateCachesForOverlay(@Nullable String packageName, int userId)
- throws RemoteException {
+ public void invalidateCachesForOverlay(@Nullable String packageName, final int userIdArg) {
if (packageName == null) {
return;
}
- enforceActor(packageName, "invalidateCachesForOverlay", userId);
- userId = handleIncomingUser(userId, "invalidateCachesForOverlay");
+ final int realUserId = handleIncomingUser(userIdArg, "invalidateCachesForOverlay");
+ enforceActor(packageName, "invalidateCachesForOverlay", realUserId);
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
- mImpl.removeIdmapForOverlay(packageName, userId);
+ mImpl.removeIdmapForOverlay(packageName, realUserId);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -876,11 +882,16 @@ public final class OverlayManagerService extends SystemService {
getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, message);
}
- private void enforceActor(String packageName, String methodName, int userId)
+ private void enforceActor(String packageName, String methodName, int realUserId)
throws SecurityException {
- OverlayInfo overlayInfo = mImpl.getOverlayInfo(packageName, userId);
+ OverlayInfo overlayInfo = mImpl.getOverlayInfo(packageName, realUserId);
+ if (overlayInfo == null) {
+ throw new IllegalArgumentException("Unable to retrieve overlay information for "
+ + packageName);
+ }
+
int callingUid = Binder.getCallingUid();
- mActorEnforcer.enforceActor(overlayInfo, methodName, callingUid, userId);
+ mActorEnforcer.enforceActor(overlayInfo, methodName, callingUid, realUserId);
}
};
diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java
index 1222d9a29baf..2b4b409f329a 100644
--- a/services/core/java/com/android/server/pm/ApexManager.java
+++ b/services/core/java/com/android/server/pm/ApexManager.java
@@ -36,6 +36,7 @@ import android.os.Environment;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.sysprop.ApexProperties;
+import android.util.Singleton;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
@@ -65,22 +66,31 @@ abstract class ApexManager {
static final int MATCH_ACTIVE_PACKAGE = 1 << 0;
static final int MATCH_FACTORY_PACKAGE = 1 << 1;
+ private static final Singleton<ApexManager> sApexManagerSingleton =
+ new Singleton<ApexManager>() {
+ @Override
+ protected ApexManager create() {
+ if (ApexProperties.updatable().orElse(false)) {
+ try {
+ return new ApexManagerImpl(IApexService.Stub.asInterface(
+ ServiceManager.getServiceOrThrow("apexservice")));
+ } catch (ServiceManager.ServiceNotFoundException e) {
+ throw new IllegalStateException(
+ "Required service apexservice not available");
+ }
+ } else {
+ return new ApexManagerFlattenedApex();
+ }
+ }
+ };
+
/**
* Returns an instance of either {@link ApexManagerImpl} or {@link ApexManagerFlattenedApex}
* depending on whether this device supports APEX, i.e. {@link ApexProperties#updatable()}
* evaluates to {@code true}.
*/
- static ApexManager create(Context systemContext) {
- if (ApexProperties.updatable().orElse(false)) {
- try {
- return new ApexManagerImpl(systemContext, IApexService.Stub.asInterface(
- ServiceManager.getServiceOrThrow("apexservice")));
- } catch (ServiceManager.ServiceNotFoundException e) {
- throw new IllegalStateException("Required service apexservice not available");
- }
- } else {
- return new ApexManagerFlattenedApex();
- }
+ static ApexManager getInstance() {
+ return sApexManagerSingleton.get();
}
/**
@@ -101,7 +111,7 @@ abstract class ApexManager {
*/
abstract List<ActiveApexInfo> getActiveApexInfos();
- abstract void systemReady();
+ abstract void systemReady(Context context);
/**
* Retrieves information about an APEX package.
@@ -248,7 +258,6 @@ abstract class ApexManager {
@VisibleForTesting
static class ApexManagerImpl extends ApexManager {
private final IApexService mApexService;
- private final Context mContext;
private final Object mLock = new Object();
/**
* A map from {@code APEX packageName} to the {@Link PackageInfo} generated from the {@code
@@ -260,8 +269,7 @@ abstract class ApexManager {
@GuardedBy("mLock")
private List<PackageInfo> mAllPackagesCache;
- ApexManagerImpl(Context context, IApexService apexService) {
- mContext = context;
+ ApexManagerImpl(IApexService apexService) {
mApexService = apexService;
}
@@ -302,14 +310,14 @@ abstract class ApexManager {
}
@Override
- void systemReady() {
- mContext.registerReceiver(new BroadcastReceiver() {
+ void systemReady(Context context) {
+ context.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// Post populateAllPackagesCacheIfNeeded to a background thread, since it's
// expensive to run it in broadcast handler thread.
BackgroundThread.getHandler().post(() -> populateAllPackagesCacheIfNeeded());
- mContext.unregisterReceiver(this);
+ context.unregisterReceiver(this);
}
}, new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
}
@@ -643,7 +651,7 @@ abstract class ApexManager {
}
@Override
- void systemReady() {
+ void systemReady(Context context) {
// No-op
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 75d5bffc87a1..73ab82dc01b2 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -2618,7 +2618,7 @@ public class PackageManagerService extends IPackageManager.Stub
mProtectedPackages = new ProtectedPackages(mContext);
- mApexManager = ApexManager.create(mContext);
+ mApexManager = ApexManager.getInstance();
mAppsFilter = mInjector.getAppsFilter();
mDirsToScanAsSystem = new ArrayList<>();
@@ -19849,7 +19849,7 @@ public class PackageManagerService extends IPackageManager.Stub
storage.registerListener(mStorageListener);
mInstallerService.systemReady();
- mApexManager.systemReady();
+ mApexManager.systemReady(mContext);
mPackageDexOptimizer.systemReady();
mInjector.getStorageManagerInternal().addExternalStoragePolicy(
diff --git a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
index 83891f60d4f7..a62616623cb5 100644
--- a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
+++ b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
@@ -16,6 +16,13 @@
package com.android.server.rollback;
+import static android.util.StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_APP_CRASH;
+import static android.util.StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_APP_NOT_RESPONDING;
+import static android.util.StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_EXPLICIT_HEALTH_CHECK;
+import static android.util.StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_NATIVE_CRASH;
+import static android.util.StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_UNKNOWN;
+
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -41,6 +48,7 @@ import android.util.StatsLog;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.server.PackageWatchdog;
+import com.android.server.PackageWatchdog.FailureReasons;
import com.android.server.PackageWatchdog.PackageHealthObserver;
import com.android.server.PackageWatchdog.PackageHealthObserverImpact;
@@ -106,10 +114,11 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve
}
@Override
- public boolean execute(VersionedPackage failedPackage) {
+ public boolean execute(VersionedPackage failedPackage, @FailureReasons int rollbackReason) {
RollbackManager rollbackManager = mContext.getSystemService(RollbackManager.class);
VersionedPackage moduleMetadataPackage = getModuleMetadataPackage();
RollbackInfo rollback = getAvailableRollback(rollbackManager, failedPackage);
+ int reasonToLog = mapFailureReasonToMetric(rollbackReason);
if (rollback == null) {
Slog.w(TAG, "Expected rollback but no valid rollback found for package: [ "
@@ -119,7 +128,8 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve
}
logEvent(moduleMetadataPackage,
- StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_INITIATE);
+ StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_INITIATE,
+ reasonToLog, failedPackage.getPackageName());
LocalIntentReceiver rollbackReceiver = new LocalIntentReceiver((Intent result) -> {
int status = result.getIntExtra(RollbackManager.EXTRA_STATUS,
RollbackManager.STATUS_FAILURE);
@@ -136,11 +146,13 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve
moduleMetadataPackage);
} else {
logEvent(moduleMetadataPackage,
- StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_SUCCESS);
+ StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_SUCCESS,
+ reasonToLog, failedPackage.getPackageName());
}
} else {
logEvent(moduleMetadataPackage,
- StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_FAILURE);
+ StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_FAILURE,
+ reasonToLog, failedPackage.getPackageName());
}
});
@@ -219,12 +231,14 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve
}
if (sessionInfo.isStagedSessionApplied()) {
logEvent(oldModuleMetadataPackage,
- StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_SUCCESS);
+ StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_SUCCESS,
+ WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_UNKNOWN, "");
} else if (sessionInfo.isStagedSessionReady()) {
// TODO: What do for staged session ready but not applied
} else {
logEvent(oldModuleMetadataPackage,
- StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_FAILURE);
+ StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_FAILURE,
+ WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_UNKNOWN, "");
}
}
@@ -303,12 +317,16 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve
saveLastStagedRollbackId(rollbackId);
logEvent(moduleMetadataPackage,
StatsLog
- .WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_BOOT_TRIGGERED);
+ .WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_BOOT_TRIGGERED,
+ WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_UNKNOWN,
+ "");
mContext.getSystemService(PowerManager.class).reboot("Rollback staged install");
} else if (sessionInfo.isStagedSessionFailed()
&& markStagedSessionHandled(rollbackId)) {
logEvent(moduleMetadataPackage,
- StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_FAILURE);
+ StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_FAILURE,
+ WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_UNKNOWN,
+ "");
mContext.unregisterReceiver(listener);
}
}
@@ -355,11 +373,12 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve
return rollbackId;
}
- private static void logEvent(@Nullable VersionedPackage moduleMetadataPackage, int type) {
+ private static void logEvent(@Nullable VersionedPackage moduleMetadataPackage, int type,
+ int rollbackReason, @NonNull String failingPackageName) {
Slog.i(TAG, "Watchdog event occurred of type: " + type);
if (moduleMetadataPackage != null) {
StatsLog.logWatchdogRollbackOccurred(type, moduleMetadataPackage.getPackageName(),
- moduleMetadataPackage.getVersionCode());
+ moduleMetadataPackage.getVersionCode(), rollbackReason, failingPackageName);
}
}
@@ -371,7 +390,7 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve
mNumberOfNativeCrashPollsRemaining--;
// Check if native watchdog reported a crash
if ("1".equals(SystemProperties.get("sys.init.updatable_crashing"))) {
- execute(getModuleMetadataPackage());
+ execute(getModuleMetadataPackage(), PackageWatchdog.FAILURE_REASON_NATIVE_CRASH);
// we stop polling after an attempt to execute rollback, regardless of whether the
// attempt succeeds or not
} else {
@@ -392,4 +411,20 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve
+ "and mitigate native crashes");
mHandler.post(()->checkAndMitigateNativeCrashes());
}
+
+ private int mapFailureReasonToMetric(@FailureReasons int failureReason) {
+ switch (failureReason) {
+ case PackageWatchdog.FAILURE_REASON_NATIVE_CRASH:
+ return WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_NATIVE_CRASH;
+ case PackageWatchdog.FAILURE_REASON_EXPLICIT_HEALTH_CHECK:
+ return WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_EXPLICIT_HEALTH_CHECK;
+ case PackageWatchdog.FAILURE_REASON_APP_CRASH:
+ return WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_APP_CRASH;
+ case PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING:
+ return WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_APP_NOT_RESPONDING;
+ default:
+ return WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_UNKNOWN;
+ }
+ }
+
}
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 5d796055dcc7..83c854bae4b5 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -620,10 +620,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// TODO: Make this final
int mTargetSdk;
- // Set to true when this app creates a surface while in the middle of an animation. In that
- // case do not clear allDrawn until the animation completes.
- boolean deferClearAllDrawn;
-
// Is this window's surface needed? This is almost like visible, except
// it will sometimes be true a little earlier: when the activity record has
// been shown, but is still waiting for its app transition to execute
@@ -771,10 +767,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
pw.print(" primaryColor=");
pw.println(Integer.toHexString(taskDescription.getPrimaryColor()));
pw.print(prefix + " backgroundColor=");
- pw.println(Integer.toHexString(taskDescription.getBackgroundColor()));
- pw.print(prefix + " statusBarColor=");
- pw.println(Integer.toHexString(taskDescription.getStatusBarColor()));
- pw.print(prefix + " navigationBarColor=");
+ pw.print(Integer.toHexString(taskDescription.getBackgroundColor()));
+ pw.print(" statusBarColor=");
+ pw.print(Integer.toHexString(taskDescription.getStatusBarColor()));
+ pw.print(" navigationBarColor=");
pw.println(Integer.toHexString(taskDescription.getNavigationBarColor()));
}
}
@@ -847,14 +843,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
pw.println(requestedVrComponent);
}
super.dump(pw, prefix, dumpAll);
- pw.print(" visible="); pw.print(mVisible);
- if (appToken != null) {
- pw.println(prefix + "app=true mVoiceInteraction=" + mVoiceInteraction);
+ if (mVoiceInteraction) {
+ pw.println(prefix + "mVoiceInteraction=true");
}
- pw.print(prefix); pw.print(" mOccludesParent="); pw.print(mOccludesParent);
+ pw.print(prefix); pw.print("mOccludesParent="); pw.print(mOccludesParent);
pw.print(" mOrientation="); pw.println(mOrientation);
pw.println(prefix + "mVisibleRequested=" + mVisibleRequested
- + " mClientVisible=" + mClientVisible
+ + " mVisible=" + mVisible + " mClientVisible=" + mClientVisible
+ ((mDeferHidingClient) ? " mDeferHidingClient=" + mDeferHidingClient : "")
+ " reportedDrawn=" + reportedDrawn + " reportedVisible=" + reportedVisible);
if (paused) {
@@ -901,7 +896,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
pw.println(prefix + "mRemovingFromDisplay=" + mRemovingFromDisplay);
}
if (lastVisibleTime != 0 || nowVisible) {
- pw.print(prefix); pw.print(" nowVisible="); pw.print(nowVisible);
+ pw.print(prefix); pw.print("nowVisible="); pw.print(nowVisible);
pw.print(" lastVisibleTime=");
if (lastVisibleTime == 0) pw.print("0");
else TimeUtils.formatDuration(lastVisibleTime, now, pw);
@@ -3235,7 +3230,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// to move that animation to the new one.
if (fromActivity.allDrawn) {
allDrawn = true;
- deferClearAllDrawn = fromActivity.deferClearAllDrawn;
}
if (fromActivity.firstWindowDrawn) {
firstWindowDrawn = true;
@@ -3719,7 +3713,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
void clearAllDrawn() {
allDrawn = false;
- deferClearAllDrawn = false;
}
/**
diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java
index e9ad0d361b07..d7f4b34ba56d 100644
--- a/services/core/java/com/android/server/wm/AppTransitionController.java
+++ b/services/core/java/com/android/server/wm/AppTransitionController.java
@@ -389,7 +389,6 @@ public class AppTransitionController {
// this guy's animations regardless of whether it's
// gotten drawn.
wtoken.allDrawn = true;
- wtoken.deferClearAllDrawn = false;
// Ensure that apps that are mid-starting are also scheduled to have their
// starting windows removed after the animation is complete
if (wtoken.startingWindow != null && !wtoken.startingWindow.mAnimatingExit) {
diff --git a/services/core/java/com/android/server/wm/DisplayWindowSettings.java b/services/core/java/com/android/server/wm/DisplayWindowSettings.java
index df7c07055e87..470a02e5bd44 100644
--- a/services/core/java/com/android/server/wm/DisplayWindowSettings.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowSettings.java
@@ -642,7 +642,8 @@ class DisplayWindowSettings {
if (mIdentifier == IDENTIFIER_PORT && displayInfo.address != null) {
// Config suggests using port as identifier for physical displays.
if (displayInfo.address instanceof DisplayAddress.Physical) {
- return "port:" + ((DisplayAddress.Physical) displayInfo.address).getPort();
+ byte port = ((DisplayAddress.Physical) displayInfo.address).getPort();
+ return "port:" + Byte.toUnsignedInt(port);
}
}
return displayInfo.uniqueId;
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index c42029155bd0..175fccbdd0ba 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -439,10 +439,6 @@ class WindowStateAnimator {
if (!mWin.mActivityRecord.isAnimating(TRANSITION)) {
mWin.mActivityRecord.clearAllDrawn();
- } else {
- // Currently animating, persist current state of allDrawn until animation
- // is complete.
- mWin.mActivityRecord.deferClearAllDrawn = true;
}
}
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index f81713ed4385..53edf9d3086a 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -280,10 +280,11 @@ class WindowToken extends WindowContainer<WindowState> {
super.dump(pw, prefix, dumpAll);
pw.print(prefix); pw.print("windows="); pw.println(mChildren);
pw.print(prefix); pw.print("windowType="); pw.print(windowType);
- pw.print(" hasVisible="); pw.println(hasVisible);
+ pw.print(" hasVisible="); pw.print(hasVisible);
if (waitingToShow) {
- pw.print(prefix); pw.print("waitingToShow="); pw.print(waitingToShow);
+ pw.print(" waitingToShow=true");
}
+ pw.println();
}
@Override
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index cb599be82aa6..ee0449d95e00 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -4345,6 +4345,40 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
}
+ /**
+ * Get the list of active admins for an affected user:
+ * <ul>
+ * <li>The active admins associated with the userHandle itself</li>
+ * <li>The parent active admins for each managed profile associated with the userHandle</li>
+ * </ul>
+ *
+ * @param userHandle the affected user for whom to get the active admins
+ * @param parent whether the parent active admins should be included in the list of active
+ * admins or not
+ * @return the list of active admins for the affected user
+ */
+ private List<ActiveAdmin> getActiveAdminsForAffectedUser(int userHandle, boolean parent) {
+ if (!parent) {
+ return getUserDataUnchecked(userHandle).mAdminList;
+ }
+ ArrayList<ActiveAdmin> admins = new ArrayList<>();
+ for (UserInfo userInfo : mUserManager.getProfiles(userHandle)) {
+ DevicePolicyData policy = getUserData(userInfo.id);
+ if (!userInfo.isManagedProfile()) {
+ admins.addAll(policy.mAdminList);
+ } else {
+ // For managed profiles, policies set on the parent profile will be included
+ for (int i = 0; i < policy.mAdminList.size(); i++) {
+ ActiveAdmin admin = policy.mAdminList.get(i);
+ if (admin.hasParentActiveAdmin()) {
+ admins.add(admin.getParentActiveAdmin());
+ }
+ }
+ }
+ }
+ return admins;
+ }
+
private boolean isSeparateProfileChallengeEnabled(int userHandle) {
long ident = mInjector.binderClearCallingIdentity();
try {
@@ -5096,118 +5130,58 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
}
- private boolean canPOorDOCallResetPassword(ActiveAdmin admin, @UserIdInt int userId) {
- // Only if the admins targets a pre-O SDK
- return getTargetSdk(admin.info.getPackageName(), userId) < Build.VERSION_CODES.O;
- }
-
- /* PO or DO could do an untrusted reset in certain conditions. */
- private boolean canUserHaveUntrustedCredentialReset(@UserIdInt int userId) {
- synchronized (getLockObject()) {
- // An active DO or PO might be able to fo an untrusted credential reset
- for (final ActiveAdmin admin : getUserData(userId).mAdminList) {
- if (!isActiveAdminWithPolicyForUserLocked(admin,
- DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, userId)) {
- continue;
- }
- if (canPOorDOCallResetPassword(admin, userId)) {
- return true;
- }
- }
- return false;
+ private boolean setPasswordPrivileged(@NonNull String password, int flags, int callingUid) {
+ // Only allow setting password on an unsecured user
+ if (isLockScreenSecureUnchecked(UserHandle.getUserId(callingUid))) {
+ throw new SecurityException("Cannot change current password");
}
+ return resetPasswordInternal(password, 0, null, flags, callingUid);
}
+
@Override
- public boolean resetPassword(String passwordOrNull, int flags) throws RemoteException {
+ public boolean resetPassword(@Nullable String password, int flags) throws RemoteException {
if (!mLockPatternUtils.hasSecureLockScreen()) {
Slog.w(LOG_TAG, "Cannot reset password when the device has no lock screen");
return false;
}
-
+ if (password == null) password = "";
final int callingUid = mInjector.binderGetCallingUid();
final int userHandle = mInjector.userHandleGetCallingUserId();
- String password = passwordOrNull != null ? passwordOrNull : "";
-
- // Password resetting to empty/null is not allowed for managed profiles.
- if (TextUtils.isEmpty(password)) {
- enforceNotManagedProfile(userHandle, "clear the active password");
+ // As of R, only privlleged caller holding RESET_PASSWORD can call resetPassword() to
+ // set password to an unsecured user.
+ if (mContext.checkCallingPermission(permission.RESET_PASSWORD)
+ == PackageManager.PERMISSION_GRANTED) {
+ return setPasswordPrivileged(password, flags, callingUid);
}
synchronized (getLockObject()) {
- // If caller has PO (or DO) it can change the password, so see if that's the case first.
+ // If caller has PO (or DO) throw or fail silently depending on its target SDK level.
ActiveAdmin admin = getActiveAdminWithPolicyForUidLocked(
null, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, callingUid);
- final boolean preN;
if (admin != null) {
- if (!canPOorDOCallResetPassword(admin, userHandle)) {
- throw new SecurityException("resetPassword() is deprecated for DPC targeting O"
- + " or later");
- }
- preN = getTargetSdk(admin.info.getPackageName(),
- userHandle) <= android.os.Build.VERSION_CODES.M;
- } else {
- // Otherwise, make sure the caller has any active admin with the right policy or
- // the required permission.
- admin = getActiveAdminOrCheckPermissionForCallerLocked(
- null,
- DeviceAdminInfo.USES_POLICY_RESET_PASSWORD,
- android.Manifest.permission.RESET_PASSWORD);
- // Cannot be preN if admin is null because an exception would have been
- // thrown before getting here
- preN = admin == null ? false : getTargetSdk(admin.info.getPackageName(),
- userHandle) <= android.os.Build.VERSION_CODES.M;
-
- // As of N, password resetting to empty/null is not allowed anymore.
- // TODO Should we allow DO/PO to set an empty password?
- if (TextUtils.isEmpty(password)) {
- if (!preN) {
- throw new SecurityException("Cannot call with null password");
- } else {
- Slog.e(LOG_TAG, "Cannot call with null password");
- return false;
- }
- }
- // As of N, password cannot be changed by the admin if it is already set.
- if (isLockScreenSecureUnchecked(userHandle)) {
- if (!preN) {
- throw new SecurityException("Cannot change current password");
- } else {
- Slog.e(LOG_TAG, "Cannot change current password");
- return false;
- }
- }
- }
- // Do not allow to reset password when current user has a managed profile
- if (!isManagedProfile(userHandle)) {
- for (UserInfo userInfo : mUserManager.getProfiles(userHandle)) {
- if (userInfo.isManagedProfile()) {
- if (!preN) {
- throw new IllegalStateException(
- "Cannot reset password on user has managed profile");
- } else {
- Slog.e(LOG_TAG, "Cannot reset password on user has managed profile");
- return false;
- }
- }
- }
- }
- // Do not allow to reset password when user is locked
- if (!mUserManager.isUserUnlocked(userHandle)) {
- if (!preN) {
- throw new IllegalStateException("Cannot reset password when user is locked");
- } else {
- Slog.e(LOG_TAG, "Cannot reset password when user is locked");
+ if (getTargetSdk(admin.info.getPackageName(), userHandle) < Build.VERSION_CODES.O) {
+ Slog.e(LOG_TAG, "DPC can no longer call resetPassword()");
return false;
}
+ throw new SecurityException("Device admin can no longer call resetPassword()");
}
- }
- return resetPasswordInternal(password, 0, null, flags, callingUid, userHandle);
+ // Legacy device admin cannot call resetPassword either
+ admin = getActiveAdminForCallerLocked(
+ null, DeviceAdminInfo.USES_POLICY_RESET_PASSWORD, false);
+ if (getTargetSdk(admin.info.getPackageName(),
+ userHandle) <= android.os.Build.VERSION_CODES.M) {
+ Slog.e(LOG_TAG, "Device admin can no longer call resetPassword()");
+ return false;
+ }
+ throw new SecurityException("Device admin can no longer call resetPassword()");
+ }
}
private boolean resetPasswordInternal(String password, long tokenHandle, byte[] token,
- int flags, int callingUid, int userHandle) {
+ int flags, int callingUid) {
+ final int userHandle = UserHandle.getUserId(callingUid);
synchronized (getLockObject()) {
final PasswordMetrics minMetrics = getPasswordMinimumMetrics(userHandle);
final List<PasswordValidationError> validationErrors;
@@ -5245,21 +5219,19 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
// Don't do this with the lock held, because it is going to call
// back in to the service.
final long ident = mInjector.binderClearCallingIdentity();
- final boolean result;
final LockscreenCredential newCredential =
LockscreenCredential.createPasswordOrNone(password);
try {
- if (token == null) {
- // This is the legacy reset password for DPM. Here we want to be able to override
- // the old device password without necessarily knowing it.
- mLockPatternUtils.setLockCredential(
- newCredential,
- LockscreenCredential.createNone(),
- userHandle, /*allowUntrustedChange */true);
- result = true;
+ if (tokenHandle == 0 || token == null) {
+ if (!mLockPatternUtils.setLockCredential(newCredential,
+ LockscreenCredential.createNone(), userHandle)) {
+ return false;
+ }
} else {
- result = mLockPatternUtils.setLockCredentialWithToken(newCredential, tokenHandle,
- token, userHandle);
+ if (!mLockPatternUtils.setLockCredentialWithToken(newCredential, tokenHandle,
+ token, userHandle)) {
+ return false;
+ }
}
boolean requireEntry = (flags & DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY) != 0;
if (requireEntry) {
@@ -5276,7 +5248,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
} finally {
mInjector.binderRestoreCallingIdentity(ident);
}
- return result;
+ return true;
}
private boolean isLockScreenSecureUnchecked(int userId) {
@@ -7769,22 +7741,25 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
* Disables all device cameras according to the specified admin.
*/
@Override
- public void setCameraDisabled(ComponentName who, boolean disabled) {
+ public void setCameraDisabled(ComponentName who, boolean disabled, boolean parent) {
if (!mHasFeature) {
return;
}
Preconditions.checkNotNull(who, "ComponentName is null");
- final int userHandle = mInjector.userHandleGetCallingUserId();
+ int userHandle = mInjector.userHandleGetCallingUserId();
synchronized (getLockObject()) {
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
- DeviceAdminInfo.USES_POLICY_DISABLE_CAMERA);
+ DeviceAdminInfo.USES_POLICY_DISABLE_CAMERA, parent);
+ if (parent) {
+ enforceProfileOwnerOfOrganizationOwnedDevice(ap);
+ }
if (ap.disableCamera != disabled) {
ap.disableCamera = disabled;
saveSettingsLocked(userHandle);
}
}
// Tell the user manager that the restrictions have changed.
- pushUserRestrictions(userHandle);
+ pushUserRestrictions(parent ? getProfileParentId(userHandle) : userHandle);
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.SET_CAMERA_DISABLED)
.setAdmin(who)
@@ -7797,18 +7772,23 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
* active admins.
*/
@Override
- public boolean getCameraDisabled(ComponentName who, int userHandle) {
- return getCameraDisabled(who, userHandle, /* mergeDeviceOwnerRestriction= */ true);
+ public boolean getCameraDisabled(ComponentName who, int userHandle, boolean parent) {
+ return getCameraDisabled(who, userHandle, /* mergeDeviceOwnerRestriction= */ true, parent);
}
private boolean getCameraDisabled(ComponentName who, int userHandle,
- boolean mergeDeviceOwnerRestriction) {
+ boolean mergeDeviceOwnerRestriction, boolean parent) {
if (!mHasFeature) {
return false;
}
+ if (parent) {
+ ActiveAdmin ap = getActiveAdminForCallerLocked(who,
+ DeviceAdminInfo.USES_POLICY_DISABLE_CAMERA, parent);
+ enforceProfileOwnerOfOrganizationOwnedDevice(ap);
+ }
synchronized (getLockObject()) {
if (who != null) {
- ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
+ ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle, parent);
return (admin != null) ? admin.disableCamera : false;
}
// First, see if DO has set it. If so, it's device-wide.
@@ -7818,13 +7798,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return true;
}
}
-
- // Then check each device admin on the user.
- DevicePolicyData policy = getUserData(userHandle);
+ // Return the strictest policy across all participating admins.
+ List<ActiveAdmin> admins = getActiveAdminsForAffectedUser(userHandle, parent);
// Determine whether or not the device camera is disabled for any active admins.
- final int N = policy.mAdminList.size();
- for (int i = 0; i < N; i++) {
- ActiveAdmin admin = policy.mAdminList.get(i);
+ for (ActiveAdmin admin: admins) {
if (admin.disableCamera) {
return true;
}
@@ -8636,6 +8613,25 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return null;
}
+ @GuardedBy("getLockObject()")
+ ActiveAdmin getProfileOwnerOfOrganizationOwnedDeviceLocked(int userHandle) {
+ final long ident = mInjector.binderClearCallingIdentity();
+ try {
+ for (UserInfo userInfo : mUserManager.getProfiles(userHandle)) {
+ if (userInfo.isManagedProfile()) {
+ if (getProfileOwner(userInfo.id) != null
+ && canProfileOwnerAccessDeviceIds(userInfo.id)) {
+ ComponentName who = getProfileOwner(userInfo.id);
+ return getActiveAdminUncheckedLocked(who, userInfo.id);
+ }
+ }
+ }
+ } finally {
+ mInjector.binderRestoreCallingIdentity(ident);
+ }
+ return null;
+ }
+
@Override
public String getProfileOwnerName(int userHandle) {
if (!mHasFeature) {
@@ -10323,7 +10319,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
private void pushUserRestrictions(int userId) {
synchronized (getLockObject()) {
final boolean isDeviceOwner = mOwners.isDeviceOwnerUserId(userId);
- final Bundle userRestrictions;
+ Bundle userRestrictions = null;
final int restrictionOwnerType;
if (isDeviceOwner) {
@@ -10335,42 +10331,60 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
addOrRemoveDisableCameraRestriction(userRestrictions, deviceOwner);
restrictionOwnerType = UserManagerInternal.OWNER_TYPE_DEVICE_OWNER;
} else {
- final ActiveAdmin profileOwner = getProfileOwnerAdminLocked(userId);
- userRestrictions = profileOwner != null ? profileOwner.userRestrictions : null;
- addOrRemoveDisableCameraRestriction(userRestrictions, userId);
+ final ActiveAdmin profileOwnerOfOrganizationOwnedDevice =
+ getProfileOwnerOfOrganizationOwnedDeviceLocked(userId);
- if (isProfileOwnerOfOrganizationOwnedDevice(profileOwner)) {
+ // If profile owner of an organization owned device, the restrictions will be
+ // pushed to the parent instance.
+ if (profileOwnerOfOrganizationOwnedDevice != null && !isManagedProfile(userId)) {
restrictionOwnerType =
UserManagerInternal.OWNER_TYPE_PROFILE_OWNER_OF_ORGANIZATION_OWNED_DEVICE;
- } else if (profileOwner != null) {
- restrictionOwnerType = UserManagerInternal.OWNER_TYPE_PROFILE_OWNER;
+ final ActiveAdmin parent = profileOwnerOfOrganizationOwnedDevice
+ .getParentActiveAdmin();
+ userRestrictions = parent.userRestrictions;
+ userRestrictions = addOrRemoveDisableCameraRestriction(userRestrictions,
+ parent);
} else {
- restrictionOwnerType = UserManagerInternal.OWNER_TYPE_NO_OWNER;
+ final ActiveAdmin profileOwner = getProfileOwnerAdminLocked(userId);
+
+ if (profileOwner != null) {
+ userRestrictions = profileOwner.userRestrictions;
+ restrictionOwnerType = UserManagerInternal.OWNER_TYPE_PROFILE_OWNER;
+ } else {
+ restrictionOwnerType = UserManagerInternal.OWNER_TYPE_NO_OWNER;
+ }
+ userRestrictions = addOrRemoveDisableCameraRestriction(
+ userRestrictions, userId);
}
}
-
mUserManagerInternal.setDevicePolicyUserRestrictions(userId, userRestrictions,
restrictionOwnerType);
}
}
- private void addOrRemoveDisableCameraRestriction(Bundle userRestrictions, ActiveAdmin admin) {
- if (userRestrictions == null) return;
+ private Bundle addOrRemoveDisableCameraRestriction(Bundle userRestrictions, ActiveAdmin admin) {
+ if (userRestrictions == null) {
+ userRestrictions = new Bundle();
+ }
if (admin.disableCamera) {
userRestrictions.putBoolean(UserManager.DISALLOW_CAMERA, true);
} else {
userRestrictions.remove(UserManager.DISALLOW_CAMERA);
}
+ return userRestrictions;
}
- private void addOrRemoveDisableCameraRestriction(Bundle userRestrictions, int userId) {
- if (userRestrictions == null) return;
+ private Bundle addOrRemoveDisableCameraRestriction(Bundle userRestrictions, int userId) {
+ if (userRestrictions == null) {
+ userRestrictions = new Bundle();
+ }
if (getCameraDisabled(/* who= */ null, userId, /* mergeDeviceOwnerRestriction= */
false)) {
userRestrictions.putBoolean(UserManager.DISALLOW_CAMERA, true);
} else {
userRestrictions.remove(UserManager.DISALLOW_CAMERA);
}
+ return userRestrictions;
}
@Override
@@ -11673,11 +11687,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
@Override
- public boolean canUserHaveUntrustedCredentialReset(@UserIdInt int userId) {
- return DevicePolicyManagerService.this.canUserHaveUntrustedCredentialReset(userId);
- }
-
- @Override
public CharSequence getPrintingDisabledReasonForUser(@UserIdInt int userId) {
synchronized (getLockObject()) {
if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_PRINTING,
@@ -13890,7 +13899,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (policy.mPasswordTokenHandle != 0) {
final String password = passwordOrNull != null ? passwordOrNull : "";
return resetPasswordInternal(password, policy.mPasswordTokenHandle, token,
- flags, mInjector.binderGetCallingUid(), userHandle);
+ flags, mInjector.binderGetCallingUid());
} else {
Slog.w(LOG_TAG, "No saved token handle");
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 66f01f367493..21cacd45dcb5 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -47,6 +47,7 @@ import android.net.TetheringManager;
import android.os.BaseBundle;
import android.os.Binder;
import android.os.Build;
+import android.os.Debug;
import android.os.Environment;
import android.os.FactoryTest;
import android.os.FileUtils;
@@ -447,10 +448,6 @@ public final class SystemServer {
// Mmmmmm... more memory!
VMRuntime.getRuntime().clearGrowthLimit();
- // The system server has to run all of the time, so it needs to be
- // as efficient as possible with its memory usage.
- VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);
-
// Some devices rely on runtime fingerprint generation, so make sure
// we've defined it before booting further.
Build.ensureFingerprintProperty();
@@ -502,6 +499,24 @@ public final class SystemServer {
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
// Prepare the thread pool for init tasks that can be parallelized
SystemServerInitThreadPool.start();
+ // Attach JVMTI agent if this is a debuggable build and the system property is set.
+ if (Build.IS_DEBUGGABLE) {
+ // Property is of the form "library_path=parameters".
+ String jvmtiAgent = SystemProperties.get("persist.sys.dalvik.jvmtiagent");
+ if (!jvmtiAgent.isEmpty()) {
+ int equalIndex = jvmtiAgent.indexOf('=');
+ String libraryPath = jvmtiAgent.substring(0, equalIndex);
+ String parameterList =
+ jvmtiAgent.substring(equalIndex + 1, jvmtiAgent.length());
+ // Attach the agent.
+ try {
+ Debug.attachJvmtiAgent(libraryPath, parameterList, null);
+ } catch (Exception e) {
+ Slog.e("System", "*************************************************");
+ Slog.e("System", "********** Failed to load jvmti plugin: " + jvmtiAgent);
+ }
+ }
+ }
} finally {
t.traceEnd(); // InitBeforeStartServices
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
index 9e255fe19881..3518dc599cef 100644
--- a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
@@ -53,9 +53,12 @@ import java.util.LinkedList;
@SmallTest
@RunWith(AndroidJUnit4.class)
public class LocalDisplayAdapterTest {
- private static final long HANDLER_WAIT_MS = 100;
+ private static final Long DISPLAY_MODEL = Long.valueOf(0xAAAAAAAAL);
+ private static final int PORT_A = 0;
+ private static final int PORT_B = 0x80;
+ private static final int PORT_C = 0xFF;
- private static final int PHYSICAL_DISPLAY_ID_MODEL_SHIFT = 8;
+ private static final long HANDLER_WAIT_MS = 100;
private StaticMockitoSession mMockitoSession;
@@ -74,7 +77,7 @@ public class LocalDisplayAdapterTest {
private TestListener mListener = new TestListener();
- private LinkedList<Long> mDisplayIds = new LinkedList<>();
+ private LinkedList<DisplayAddress.Physical> mAddresses = new LinkedList<>();
@Before
public void setUp() throws Exception {
@@ -106,30 +109,22 @@ public class LocalDisplayAdapterTest {
*/
@Test
public void testPrivateDisplay() throws Exception {
- // needs default one always
- final long displayId0 = 0;
- setUpDisplay(new DisplayConfig(displayId0, createDummyDisplayInfo()));
- final long displayId1 = 1;
- setUpDisplay(new DisplayConfig(displayId1, createDummyDisplayInfo()));
- final long displayId2 = 2;
- setUpDisplay(new DisplayConfig(displayId2, createDummyDisplayInfo()));
+ setUpDisplay(new DisplayConfig(createDisplayAddress(PORT_A), createDummyDisplayInfo()));
+ setUpDisplay(new DisplayConfig(createDisplayAddress(PORT_B), createDummyDisplayInfo()));
+ setUpDisplay(new DisplayConfig(createDisplayAddress(PORT_C), createDummyDisplayInfo()));
updateAvailableDisplays();
- // display 1 should be marked as private while display 2 is not.
- doReturn(new int[]{(int) displayId1}).when(mMockedResources)
+ doReturn(new int[]{ PORT_B }).when(mMockedResources)
.getIntArray(com.android.internal.R.array.config_localPrivateDisplayPorts);
mAdapter.registerLocked();
waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
// This should be public
- assertDisplay(mListener.addedDisplays.get(0).getDisplayDeviceInfoLocked(), displayId0,
- false);
+ assertDisplay(mListener.addedDisplays.get(0).getDisplayDeviceInfoLocked(), PORT_A, false);
// This should be private
- assertDisplay(mListener.addedDisplays.get(1).getDisplayDeviceInfoLocked(), displayId1,
- true);
+ assertDisplay(mListener.addedDisplays.get(1).getDisplayDeviceInfoLocked(), PORT_B, true);
// This should be public
- assertDisplay(mListener.addedDisplays.get(2).getDisplayDeviceInfoLocked(), displayId2,
- false);
+ assertDisplay(mListener.addedDisplays.get(2).getDisplayDeviceInfoLocked(), PORT_C, false);
}
/**
@@ -137,11 +132,8 @@ public class LocalDisplayAdapterTest {
*/
@Test
public void testPublicDisplaysForNoConfigLocalPrivateDisplayPorts() throws Exception {
- // needs default one always
- final long displayId0 = 0;
- setUpDisplay(new DisplayConfig(displayId0, createDummyDisplayInfo()));
- final long displayId1 = 1;
- setUpDisplay(new DisplayConfig(displayId1, createDummyDisplayInfo()));
+ setUpDisplay(new DisplayConfig(createDisplayAddress(PORT_A), createDummyDisplayInfo()));
+ setUpDisplay(new DisplayConfig(createDisplayAddress(PORT_C), createDummyDisplayInfo()));
updateAvailableDisplays();
// config_localPrivateDisplayPorts is null
mAdapter.registerLocked();
@@ -149,35 +141,36 @@ public class LocalDisplayAdapterTest {
waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
// This should be public
- assertDisplay(mListener.addedDisplays.get(0).getDisplayDeviceInfoLocked(), displayId0,
- false);
+ assertDisplay(mListener.addedDisplays.get(0).getDisplayDeviceInfoLocked(), PORT_A, false);
// This should be public
- assertDisplay(mListener.addedDisplays.get(1).getDisplayDeviceInfoLocked(), displayId1,
- false);
+ assertDisplay(mListener.addedDisplays.get(1).getDisplayDeviceInfoLocked(), PORT_C, false);
}
- private void assertDisplay(DisplayDeviceInfo info, long expectedPort, boolean shouldBePrivate) {
- DisplayAddress.Physical physical = (DisplayAddress.Physical) info.address;
- assertNotNull(physical);
- assertEquals(expectedPort, physical.getPort());
+ private static void assertDisplay(
+ DisplayDeviceInfo info, int expectedPort, boolean shouldBePrivate) {
+ final DisplayAddress.Physical address = (DisplayAddress.Physical) info.address;
+ assertNotNull(address);
+ assertEquals((byte) expectedPort, address.getPort());
+ assertEquals(DISPLAY_MODEL, address.getModel());
assertEquals(shouldBePrivate, (info.flags & DisplayDeviceInfo.FLAG_PRIVATE) != 0);
}
private class DisplayConfig {
- public final long displayId;
+ public final DisplayAddress.Physical address;
public final IBinder displayToken = new Binder();
public final SurfaceControl.PhysicalDisplayInfo displayInfo;
- private DisplayConfig(long displayId, SurfaceControl.PhysicalDisplayInfo displayInfo) {
- this.displayId = displayId | (0x1 << PHYSICAL_DISPLAY_ID_MODEL_SHIFT);
+ private DisplayConfig(
+ DisplayAddress.Physical address, SurfaceControl.PhysicalDisplayInfo displayInfo) {
+ this.address = address;
this.displayInfo = displayInfo;
}
}
private void setUpDisplay(DisplayConfig config) {
- mDisplayIds.add(config.displayId);
- doReturn(config.displayToken).when(
- () -> SurfaceControl.getPhysicalDisplayToken(config.displayId));
+ mAddresses.add(config.address);
+ doReturn(config.displayToken).when(() ->
+ SurfaceControl.getPhysicalDisplayToken(config.address.getPhysicalDisplayId()));
doReturn(new SurfaceControl.PhysicalDisplayInfo[]{
config.displayInfo
}).when(() -> SurfaceControl.getDisplayConfigs(config.displayToken));
@@ -192,16 +185,20 @@ public class LocalDisplayAdapterTest {
}
private void updateAvailableDisplays() {
- long[] ids = new long[mDisplayIds.size()];
+ long[] ids = new long[mAddresses.size()];
int i = 0;
- for (long id : mDisplayIds) {
- ids[i] = id;
+ for (DisplayAddress.Physical address : mAddresses) {
+ ids[i] = address.getPhysicalDisplayId();
i++;
}
doReturn(ids).when(() -> SurfaceControl.getPhysicalDisplayIds());
}
- private SurfaceControl.PhysicalDisplayInfo createDummyDisplayInfo() {
+ private static DisplayAddress.Physical createDisplayAddress(int port) {
+ return DisplayAddress.fromPortAndModel((byte) port, DISPLAY_MODEL);
+ }
+
+ private static SurfaceControl.PhysicalDisplayInfo createDummyDisplayInfo() {
SurfaceControl.PhysicalDisplayInfo info = new SurfaceControl.PhysicalDisplayInfo();
info.density = 100;
info.xDpi = 100;
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java
index c5fb0bde579f..5f1f3083361b 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java
@@ -23,7 +23,6 @@ import static org.mockito.Mockito.when;
import android.app.admin.DevicePolicyManagerInternal;
import android.content.pm.PackageManager;
-import android.content.pm.UserInfo;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
@@ -39,6 +38,9 @@ import java.util.Map;
import java.util.Set;
public class DevicePolicyManagerServiceMigrationTest extends DpmTestBase {
+
+ private static final String USER_TYPE_EMPTY = "";
+
private DpmMockContext mContext;
@Override
@@ -52,9 +54,10 @@ public class DevicePolicyManagerServiceMigrationTest extends DpmTestBase {
}
public void testMigration() throws Exception {
- final File user10dir = getServices().addUser(10, 0);
- final File user11dir = getServices().addUser(11, UserInfo.FLAG_MANAGED_PROFILE);
- getServices().addUser(12, 0);
+ final File user10dir = getServices().addUser(10, 0, USER_TYPE_EMPTY);
+ final File user11dir = getServices().addUser(11, 0,
+ UserManager.USER_TYPE_PROFILE_MANAGED);
+ getServices().addUser(12, 0, USER_TYPE_EMPTY);
setUpPackageManagerForAdmin(admin1, DpmMockContext.CALLER_SYSTEM_USER_UID);
setUpPackageManagerForAdmin(admin2, UserHandle.getUid(10, 123));
@@ -273,7 +276,8 @@ public class DevicePolicyManagerServiceMigrationTest extends DpmTestBase {
// Test setting default restrictions for managed profile.
public void testMigration3_managedProfileOwner() throws Exception {
// Create a managed profile user.
- final File user10dir = getServices().addUser(10, UserInfo.FLAG_MANAGED_PROFILE);
+ final File user10dir = getServices().addUser(10, 0,
+ UserManager.USER_TYPE_PROFILE_MANAGED);
// Profile owner package for managed profile user.
setUpPackageManagerForAdmin(admin1, UserHandle.getUid(10, 123));
// Set up fake UserManager to make it look like a managed profile.
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 06b8716c0926..43d8f927a57e 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -151,6 +151,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
private DpmMockContext mServiceContext;
private DpmMockContext mAdmin1Context;
public DevicePolicyManager dpm;
+ public DevicePolicyManager parentDpm;
public DevicePolicyManagerServiceTestable dpms;
/*
@@ -240,6 +241,9 @@ public class DevicePolicyManagerTest extends DpmTestBase {
dpm = new DevicePolicyManagerTestable(mContext, dpms);
+ parentDpm = new DevicePolicyManagerTestable(mServiceContext, dpms,
+ /* parentInstance= */true);
+
mContext.binder.restoreCallingIdentity(ident);
}
@@ -269,7 +273,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
anyString(), any(UserHandle.class));
// Add the first secondary user.
- getServices().addUser(DpmMockContext.CALLER_USER_HANDLE, 0);
+ getServices().addUser(DpmMockContext.CALLER_USER_HANDLE, 0,
+ UserManager.USER_TYPE_FULL_SECONDARY);
}
private void setAsProfileOwner(ComponentName admin) {
@@ -330,7 +335,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
public void testLoadAdminData_noAdmins() throws Exception {
final int ANOTHER_USER_ID = 15;
- getServices().addUser(ANOTHER_USER_ID, 0);
+ getServices().addUser(ANOTHER_USER_ID, 0, "");
initializeDpms();
@@ -477,7 +482,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
final int ANOTHER_USER_ID = 100;
final int ANOTHER_ADMIN_UID = UserHandle.getUid(ANOTHER_USER_ID, 20456);
- getServices().addUser(ANOTHER_USER_ID, 0); // Add one more user.
+ getServices().addUser(ANOTHER_USER_ID, 0, ""); // Add one more user.
// Set up pacakge manager for the other user.
setUpPackageManagerForAdmin(admin2, ANOTHER_ADMIN_UID);
@@ -1343,7 +1348,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
final int ANOTHER_USER_ID = 100;
final int ANOTHER_ADMIN_UID = UserHandle.getUid(ANOTHER_USER_ID, 456);
- getServices().addUser(ANOTHER_USER_ID, 0); // Add one more user.
+ getServices().addUser(ANOTHER_USER_ID, 0, ""); // Add one more user.
mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
mContext.callerPermissions.add(permission.MANAGE_USERS);
@@ -1961,35 +1966,30 @@ public class DevicePolicyManagerTest extends DpmTestBase {
// TODO Make sure restrictions are written to the file.
}
+ // TODO: (b/138709470) test addUserRestriction as PO of an organization-owned device
public void testSetUserRestriction_asPoOfOrgOwnedDevice() throws Exception {
- setupProfileOwner();
+ final int MANAGED_PROFILE_USER_ID = DpmMockContext.CALLER_USER_HANDLE;
+ final int MANAGED_PROFILE_ADMIN_UID =
+ UserHandle.getUid(MANAGED_PROFILE_USER_ID, DpmMockContext.SYSTEM_UID);
+ mContext.binder.callingUid = MANAGED_PROFILE_ADMIN_UID;
- final long ident = mServiceContext.binder.clearCallingIdentity();
- configureContextForAccess(mServiceContext, true);
+ addManagedProfile(admin1, MANAGED_PROFILE_ADMIN_UID, admin1);
+ configureProfileOwnerOfOrgOwnedDevice(admin1, DpmMockContext.CALLER_USER_HANDLE);
- mServiceContext.binder.callingUid =
- UserHandle.getUid(DpmMockContext.CALLER_USER_HANDLE,
- DpmMockContext.CALLER_MANAGED_PROVISIONING_UID);
- try {
- runAsCaller(mServiceContext, dpms, dpm -> {
- dpm.markProfileOwnerOnOrganizationOwnedDevice(admin1);
- });
- } finally {
- mServiceContext.binder.restoreCallingIdentity(ident);
- }
+ when(getServices().userManager.getProfileParent(MANAGED_PROFILE_USER_ID))
+ .thenReturn(new UserInfo(UserHandle.USER_SYSTEM, "user system", 0));
- dpm.addUserRestriction(admin1, UserManager.DISALLOW_CONFIG_DATE_TIME);
+ parentDpm.setCameraDisabled(admin1, true);
verify(getServices().userManagerInternal).setDevicePolicyUserRestrictions(
- eq(DpmMockContext.CALLER_USER_HANDLE),
- MockUtils.checkUserRestrictions(UserManager.DISALLOW_CONFIG_DATE_TIME),
+ eq(UserHandle.USER_SYSTEM),
+ MockUtils.checkUserRestrictions(UserManager.DISALLOW_CAMERA),
eq(UserManagerInternal.OWNER_TYPE_PROFILE_OWNER_OF_ORGANIZATION_OWNED_DEVICE));
reset(getServices().userManagerInternal);
- dpm.setCameraDisabled(admin1, true);
+ parentDpm.setCameraDisabled(admin1, false);
verify(getServices().userManagerInternal).setDevicePolicyUserRestrictions(
- eq(DpmMockContext.CALLER_USER_HANDLE),
- MockUtils.checkUserRestrictions(UserManager.DISALLOW_CONFIG_DATE_TIME,
- UserManager.DISALLOW_CAMERA),
+ eq(UserHandle.USER_SYSTEM),
+ MockUtils.checkUserRestrictions(),
eq(UserManagerInternal.OWNER_TYPE_PROFILE_OWNER_OF_ORGANIZATION_OWNED_DEVICE));
reset(getServices().userManagerInternal);
}
@@ -3861,7 +3861,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
// Add a secondary user, it should never talk with.
final int ANOTHER_USER_ID = 36;
- getServices().addUser(ANOTHER_USER_ID, 0);
+ getServices().addUser(ANOTHER_USER_ID, 0, UserManager.USER_TYPE_FULL_SECONDARY);
// Since the managed profile is not affiliated, they should not be allowed to talk to each
// other.
@@ -5206,8 +5206,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
}
public void testRevertProfileOwnership_adminAndProfileMigrated() throws Exception {
- getServices().addUser(DpmMockContext.CALLER_USER_HANDLE, UserInfo.FLAG_MANAGED_PROFILE,
- UserHandle.USER_SYSTEM);
+ getServices().addUser(DpmMockContext.CALLER_USER_HANDLE, 0,
+ UserManager.USER_TYPE_PROFILE_MANAGED, UserHandle.USER_SYSTEM);
DpmTestUtils.writeInputStreamToFile(
getRawStream(com.android.frameworks.servicestests.R.raw.active_admin_migrated),
getProfileOwnerPoliciesFile());
@@ -5218,8 +5218,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
}
public void testRevertProfileOwnership_profileNotMigrated() throws Exception {
- getServices().addUser(DpmMockContext.CALLER_USER_HANDLE, UserInfo.FLAG_MANAGED_PROFILE,
- UserHandle.USER_SYSTEM);
+ getServices().addUser(DpmMockContext.CALLER_USER_HANDLE, 0,
+ UserManager.USER_TYPE_PROFILE_MANAGED, UserHandle.USER_SYSTEM);
DpmTestUtils.writeInputStreamToFile(
getRawStream(com.android.frameworks.servicestests.R.raw.active_admin_migrated),
getProfileOwnerPoliciesFile());
@@ -5230,8 +5230,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
}
public void testRevertProfileOwnership_adminAndProfileNotMigrated() throws Exception {
- getServices().addUser(DpmMockContext.CALLER_USER_HANDLE, UserInfo.FLAG_MANAGED_PROFILE,
- UserHandle.USER_SYSTEM);
+ getServices().addUser(DpmMockContext.CALLER_USER_HANDLE, 0,
+ UserManager.USER_TYPE_PROFILE_MANAGED, UserHandle.USER_SYSTEM);
DpmTestUtils.writeInputStreamToFile(
getRawStream(com.android.frameworks.servicestests.R.raw.active_admin_not_migrated),
getProfileOwnerPoliciesFile());
@@ -5405,11 +5405,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
mServiceContext.permissions.add(permission.REQUEST_PASSWORD_COMPLEXITY);
setAsProfileOwner(admin1);
- new DevicePolicyManagerTestable(
- mServiceContext,
- dpms,
- /* parentInstance= */ true)
- .getPasswordComplexity();
+ parentDpm.getPasswordComplexity();
assertEquals(PASSWORD_COMPLEXITY_NONE, dpm.getPasswordComplexity());
}
@@ -5685,7 +5681,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
private void addManagedProfile(
ComponentName admin, int adminUid, ComponentName copyFromAdmin) throws Exception {
final int userId = UserHandle.getUserId(adminUid);
- getServices().addUser(userId, UserInfo.FLAG_MANAGED_PROFILE, UserHandle.USER_SYSTEM);
+ getServices().addUser(userId, 0, UserManager.USER_TYPE_PROFILE_MANAGED,
+ UserHandle.USER_SYSTEM);
mContext.callerPermissions.addAll(OWNER_SETUP_PERMISSIONS);
setUpPackageManagerForFakeAdmin(admin, adminUid, copyFromAdmin);
dpm.setActiveAdmin(admin, false, userId);
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 6a0d9265f594..7a2350eb4402 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
@@ -185,8 +185,8 @@ public class MockSystemServices {
// Add the system user with a fake profile group already set up (this can happen in the real
// world if a managed profile is added and then removed).
- systemUserDataDir =
- addUser(UserHandle.USER_SYSTEM, UserInfo.FLAG_PRIMARY, UserHandle.USER_SYSTEM);
+ systemUserDataDir = addUser(UserHandle.USER_SYSTEM, UserInfo.FLAG_PRIMARY,
+ UserManager.USER_TYPE_FULL_SYSTEM, UserHandle.USER_SYSTEM);
// System user is always running.
setUserRunning(UserHandle.USER_SYSTEM, true);
@@ -208,26 +208,21 @@ public class MockSystemServices {
mBroadcastReceivers.removeIf(r -> r.receiver == receiver);
}
- public File addUser(int userId, int flags) {
- return addUser(userId, flags, UserInfo.NO_PROFILE_GROUP_ID);
+ public File addUser(int userId, int flags, String type) {
+ return addUser(userId, flags, type, UserInfo.NO_PROFILE_GROUP_ID);
}
- public File addUser(int userId, int flags, int profileGroupId) {
+ public File addUser(int userId, int flags, String type, int profileGroupId) {
// Set up (default) UserInfo for CALLER_USER_HANDLE.
final UserInfo uh = new UserInfo(userId, "user" + userId, flags);
+
+ uh.userType = type;
uh.profileGroupId = profileGroupId;
when(userManager.getUserInfo(eq(userId))).thenReturn(uh);
-
mUserInfos.add(uh);
when(userManager.getUsers()).thenReturn(mUserInfos);
when(userManager.getUsers(anyBoolean())).thenReturn(mUserInfos);
when(userManager.isUserRunning(eq(new UserHandle(userId)))).thenReturn(true);
- when(userManager.getUserInfo(anyInt())).thenAnswer(
- invocation -> {
- final int userId1 = (int) invocation.getArguments()[0];
- return getUserInfo(userId1);
- }
- );
when(userManager.getProfileParent(anyInt())).thenAnswer(
invocation -> {
final int userId1 = (int) invocation.getArguments()[0];
@@ -308,7 +303,7 @@ public class MockSystemServices {
*/
public void addUsers(int... userIds) {
for (final int userId : userIds) {
- addUser(userId, 0);
+ addUser(userId, 0, "");
}
}
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/CachedSyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/CachedSyntheticPasswordTests.java
deleted file mode 100644
index d1c2fd0fa9dd..000000000000
--- a/services/tests/servicestests/src/com/android/server/locksettings/CachedSyntheticPasswordTests.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.server.locksettings;
-
-import static com.android.server.testutils.TestUtils.assertExpectException;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Mockito.anyInt;
-import static org.mockito.Mockito.atLeastOnce;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.os.RemoteException;
-import android.platform.test.annotations.Presubmit;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.internal.widget.LockscreenCredential;
-import com.android.internal.widget.VerifyCredentialResponse;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-
-import java.util.ArrayList;
-
-/**
- * Run the synthetic password tests with caching enabled.
- *
- * By default, those tests run without caching. Untrusted credential reset depends on caching so
- * this class included those tests.
- */
-@SmallTest
-@Presubmit
-@RunWith(AndroidJUnit4.class)
-public class CachedSyntheticPasswordTests extends SyntheticPasswordTests {
-
- @Before
- public void enableSpCache() throws Exception {
- enableSpCaching(true);
- }
-
- private void enableSpCaching(boolean enable) {
- when(mDevicePolicyManagerInternal
- .canUserHaveUntrustedCredentialReset(anyInt())).thenReturn(enable);
- }
-
- @Test
- public void testSyntheticPasswordClearCredentialUntrusted() throws RemoteException {
- final LockscreenCredential password = newPassword("password");
- final LockscreenCredential newPassword = newPassword("newpassword");
-
- initializeCredentialUnderSP(password, PRIMARY_USER_ID);
- long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
- // clear password
- mService.setLockCredential(nonePassword(), password, PRIMARY_USER_ID, true);
- assertEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
-
- // set a new password
- mService.setLockCredential(newPassword, nonePassword(), PRIMARY_USER_ID,
- false);
- assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
- newPassword, 0, PRIMARY_USER_ID)
- .getResponseCode());
- assertNotEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
- }
-
- @Test
- public void testSyntheticPasswordChangeCredentialUntrusted() throws RemoteException {
- final LockscreenCredential password = newPassword("password");
- final LockscreenCredential newPassword = newPassword("newpassword");
-
- initializeCredentialUnderSP(password, PRIMARY_USER_ID);
- long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
- // Untrusted change password
- mService.setLockCredential(newPassword, nonePassword(), PRIMARY_USER_ID,
- true);
- assertNotEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
- assertNotEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
-
- // Verify the password
- assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
- newPassword, 0, PRIMARY_USER_ID).getResponseCode());
- }
-
- @Test
- public void testUntrustedCredentialChangeMaintainsAuthSecret() throws RemoteException {
- final LockscreenCredential password = newPassword("password");
- final LockscreenCredential newPassword = newPassword("newpassword");
-
- initializeCredentialUnderSP(password, PRIMARY_USER_ID);
- // Untrusted change password
- mService.setLockCredential(newPassword, nonePassword(), PRIMARY_USER_ID,
- true);
-
- // Verify the password
- assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
- newPassword, 0, PRIMARY_USER_ID)
- .getResponseCode());
-
- // Ensure the same secret was passed each time
- ArgumentCaptor<ArrayList<Byte>> secret = ArgumentCaptor.forClass(ArrayList.class);
- verify(mAuthSecretService, atLeastOnce()).primaryUserCredential(secret.capture());
- assertEquals(1, secret.getAllValues().stream().distinct().count());
- }
-
- @Test
- public void testUntrustedCredentialChangeBlockedIfSpNotCached() throws RemoteException {
- final LockscreenCredential password = newPassword("password");
- final LockscreenCredential newPassword = newPassword("newpassword");
-
- // Disable caching for this test
- enableSpCaching(false);
-
- initializeCredentialUnderSP(password, PRIMARY_USER_ID);
- flushHandlerTasks();
-
- long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
- // Untrusted change password
- assertExpectException(
- IllegalStateException.class,
- /* messageRegex= */ "Untrusted credential reset not possible without cached SP",
- () -> mService.setLockCredential(newPassword, nonePassword(),
- PRIMARY_USER_ID, true));
- assertEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
-
- // Verify the new password doesn't work but the old one still does
- assertEquals(VerifyCredentialResponse.RESPONSE_ERROR, mService.verifyCredential(
- newPassword, 0, PRIMARY_USER_ID)
- .getResponseCode());
- assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
- password, 0, PRIMARY_USER_ID)
- .getResponseCode());
- }
-
-}
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java
index 8c8edfad231f..abfda7725b7d 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java
@@ -93,7 +93,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
initializeStorageWithCredential(PRIMARY_USER_ID, newPassword("password"), sid);
assertFalse(mService.setLockCredential(newPassword("newpwd"), newPassword("badpwd"),
- PRIMARY_USER_ID, false));
+ PRIMARY_USER_ID));
assertVerifyCredentials(PRIMARY_USER_ID, newPassword("password"), sid);
}
@@ -101,7 +101,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
public void testClearPasswordPrimaryUser() throws RemoteException {
initializeStorageWithCredential(PRIMARY_USER_ID, newPassword("password"), 1234);
assertTrue(mService.setLockCredential(nonePassword(), newPassword("password"),
- PRIMARY_USER_ID, false));
+ PRIMARY_USER_ID));
assertEquals(CREDENTIAL_TYPE_NONE, mService.getCredentialType(PRIMARY_USER_ID));
assertEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
}
@@ -111,7 +111,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
final LockscreenCredential firstUnifiedPassword = newPassword("pwd-1");
final LockscreenCredential secondUnifiedPassword = newPassword("pwd-2");
assertTrue(mService.setLockCredential(firstUnifiedPassword,
- nonePassword(), PRIMARY_USER_ID, false));
+ nonePassword(), PRIMARY_USER_ID));
mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
final long primarySid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
final long profileSid = mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID);
@@ -146,15 +146,14 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
mStorageManager.setIgnoreBadUnlock(true);
// Change primary password and verify that profile SID remains
assertTrue(mService.setLockCredential(
- secondUnifiedPassword, firstUnifiedPassword, PRIMARY_USER_ID, false));
+ secondUnifiedPassword, firstUnifiedPassword, PRIMARY_USER_ID));
mStorageManager.setIgnoreBadUnlock(false);
assertEquals(profileSid, mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID));
assertNull(mGateKeeperService.getAuthToken(TURNED_OFF_PROFILE_USER_ID));
// Clear unified challenge
assertTrue(mService.setLockCredential(nonePassword(),
- secondUnifiedPassword, PRIMARY_USER_ID,
- false));
+ secondUnifiedPassword, PRIMARY_USER_ID));
assertEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
assertEquals(0, mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID));
assertEquals(0, mGateKeeperService.getSecureUserId(TURNED_OFF_PROFILE_USER_ID));
@@ -166,7 +165,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
final LockscreenCredential profilePassword = newPassword("profile");
assertTrue(mService.setLockCredential(primaryPassword,
nonePassword(),
- PRIMARY_USER_ID, false));
+ PRIMARY_USER_ID));
/* Currently in LockSettingsService.setLockCredential, unlockUser() is called with the new
* credential as part of verifyCredential() before the new credential is committed in
* StorageManager. So we relax the check in our mock StorageManager to allow that.
@@ -174,7 +173,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
mStorageManager.setIgnoreBadUnlock(true);
assertTrue(mService.setLockCredential(profilePassword,
nonePassword(),
- MANAGED_PROFILE_USER_ID, false));
+ MANAGED_PROFILE_USER_ID));
mStorageManager.setIgnoreBadUnlock(false);
final long primarySid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
@@ -201,7 +200,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
// Change primary credential and make sure we don't affect profile
mStorageManager.setIgnoreBadUnlock(true);
assertTrue(mService.setLockCredential(
- newPassword("pwd"), primaryPassword, PRIMARY_USER_ID, false));
+ newPassword("pwd"), primaryPassword, PRIMARY_USER_ID));
mStorageManager.setIgnoreBadUnlock(false);
assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
profilePassword, 0, MANAGED_PROFILE_USER_ID)
@@ -214,8 +213,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
assertTrue(mService.setLockCredential(
newPassword("password"),
nonePassword(),
- PRIMARY_USER_ID,
- false));
+ PRIMARY_USER_ID));
verify(mRecoverableKeyStoreManager)
.lockScreenSecretChanged(CREDENTIAL_TYPE_PASSWORD, "password".getBytes(),
@@ -228,8 +226,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
assertTrue(mService.setLockCredential(
newPattern("12345"),
nonePassword(),
- MANAGED_PROFILE_USER_ID,
- false));
+ MANAGED_PROFILE_USER_ID));
verify(mRecoverableKeyStoreManager)
.lockScreenSecretChanged(CREDENTIAL_TYPE_PATTERN, "12345".getBytes(),
@@ -247,8 +244,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
assertTrue(mService.setLockCredential(
newPassword("newPassword"),
newPattern("12345"),
- MANAGED_PROFILE_USER_ID,
- false));
+ MANAGED_PROFILE_USER_ID));
verify(mRecoverableKeyStoreManager)
.lockScreenSecretChanged(CREDENTIAL_TYPE_PASSWORD, "newPassword".getBytes(),
@@ -263,8 +259,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
assertTrue(mService.setLockCredential(
newPattern("12345"),
nonePassword(),
- PRIMARY_USER_ID,
- false));
+ PRIMARY_USER_ID));
verify(mRecoverableKeyStoreManager, never())
.lockScreenSecretChanged(
@@ -284,8 +279,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
assertTrue(mService.setLockCredential(
newCredential,
oldCredential,
- PRIMARY_USER_ID,
- false));
+ PRIMARY_USER_ID));
verify(mRecoverableKeyStoreManager)
.lockScreenSecretChanged(CREDENTIAL_TYPE_PASSWORD, newCredential.getCredential(),
@@ -305,8 +299,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
assertTrue(mService.setLockCredential(
nonePassword(),
newPassword("oldPassword"),
- PRIMARY_USER_ID,
- false));
+ PRIMARY_USER_ID));
verify(mRecoverableKeyStoreManager)
.lockScreenSecretChanged(CREDENTIAL_TYPE_NONE, null, PRIMARY_USER_ID);
@@ -322,7 +315,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
1234);
mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
- mService.setLockCredential(nonePassword(), newPattern("123654"), PRIMARY_USER_ID, false);
+ mService.setLockCredential(nonePassword(), newPattern("123654"), PRIMARY_USER_ID);
// Verify fingerprint is removed
verify(mFingerprintManager).remove(any(), eq(PRIMARY_USER_ID), any());
@@ -343,8 +336,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
assertTrue(mService.setLockCredential(
profilePassword,
nonePassword(),
- MANAGED_PROFILE_USER_ID,
- false));
+ MANAGED_PROFILE_USER_ID));
verify(mRecoverableKeyStoreManager)
.lockScreenSecretChanged(CREDENTIAL_TYPE_PASSWORD, profilePassword.getCredential(),
@@ -390,8 +382,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
assertTrue(mService.setLockCredential(
pattern,
nonePassword(),
- MANAGED_PROFILE_USER_ID,
- false));
+ MANAGED_PROFILE_USER_ID));
reset(mRecoverableKeyStoreManager);
mService.verifyCredential(pattern, 1, MANAGED_PROFILE_USER_ID);
@@ -426,7 +417,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
private void testCreateCredential(int userId, LockscreenCredential credential)
throws RemoteException {
- assertTrue(mService.setLockCredential(credential, nonePassword(), userId, false));
+ assertTrue(mService.setLockCredential(credential, nonePassword(), userId));
assertVerifyCredentials(userId, credential, -1);
}
@@ -435,7 +426,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
mHasSecureLockScreen = false;
try {
- mService.setLockCredential(credential, null, userId, false);
+ mService.setLockCredential(credential, null, userId);
fail("An exception should have been thrown.");
} catch (UnsupportedOperationException e) {
// Success - the exception was expected.
@@ -448,7 +439,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
LockscreenCredential oldCredential) throws RemoteException {
final long sid = 1234;
initializeStorageWithCredential(userId, oldCredential, sid);
- assertTrue(mService.setLockCredential(newCredential, oldCredential, userId, false));
+ assertTrue(mService.setLockCredential(newCredential, oldCredential, userId));
assertVerifyCredentials(userId, newCredential, sid);
}
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockscreenFrpTest.java b/services/tests/servicestests/src/com/android/server/locksettings/LockscreenFrpTest.java
index 27af9e2dfd6f..4b3f7b5d08ef 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockscreenFrpTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockscreenFrpTest.java
@@ -48,7 +48,7 @@ public class LockscreenFrpTest extends BaseLockSettingsServiceTests {
@Test
public void testFrpCredential_setPin() {
- mService.setLockCredential(newPin("1234"), nonePassword(), PRIMARY_USER_ID, false);
+ mService.setLockCredential(newPin("1234"), nonePassword(), PRIMARY_USER_ID);
assertEquals(CREDENTIAL_TYPE_PIN, mService.getCredentialType(USER_FRP));
assertEquals(VerifyCredentialResponse.RESPONSE_OK,
@@ -57,7 +57,7 @@ public class LockscreenFrpTest extends BaseLockSettingsServiceTests {
@Test
public void testFrpCredential_setPattern() {
- mService.setLockCredential(newPattern("4321"), nonePassword(), PRIMARY_USER_ID, false);
+ mService.setLockCredential(newPattern("4321"), nonePassword(), PRIMARY_USER_ID);
assertEquals(CREDENTIAL_TYPE_PATTERN, mService.getCredentialType(USER_FRP));
assertEquals(VerifyCredentialResponse.RESPONSE_OK,
@@ -66,7 +66,7 @@ public class LockscreenFrpTest extends BaseLockSettingsServiceTests {
@Test
public void testFrpCredential_setPassword() {
- mService.setLockCredential(newPassword("4321"), nonePassword(), PRIMARY_USER_ID, false);
+ mService.setLockCredential(newPassword("4321"), nonePassword(), PRIMARY_USER_ID);
assertEquals(CREDENTIAL_TYPE_PASSWORD, mService.getCredentialType(USER_FRP));
assertEquals(VerifyCredentialResponse.RESPONSE_OK,
@@ -75,8 +75,8 @@ public class LockscreenFrpTest extends BaseLockSettingsServiceTests {
@Test
public void testFrpCredential_changeCredential() {
- mService.setLockCredential(newPassword("1234"), nonePassword(), PRIMARY_USER_ID, false);
- mService.setLockCredential(newPattern("5678"), newPassword("1234"), PRIMARY_USER_ID, false);
+ mService.setLockCredential(newPassword("1234"), nonePassword(), PRIMARY_USER_ID);
+ mService.setLockCredential(newPattern("5678"), newPassword("1234"), PRIMARY_USER_ID);
assertEquals(CREDENTIAL_TYPE_PATTERN, mService.getCredentialType(USER_FRP));
assertEquals(VerifyCredentialResponse.RESPONSE_OK,
@@ -85,16 +85,16 @@ public class LockscreenFrpTest extends BaseLockSettingsServiceTests {
@Test
public void testFrpCredential_removeCredential() {
- mService.setLockCredential(newPassword("1234"), nonePassword(), PRIMARY_USER_ID, false);
+ mService.setLockCredential(newPassword("1234"), nonePassword(), PRIMARY_USER_ID);
assertEquals(CREDENTIAL_TYPE_PASSWORD, mService.getCredentialType(USER_FRP));
- mService.setLockCredential(nonePassword(), newPassword("1234"), PRIMARY_USER_ID, false);
+ mService.setLockCredential(nonePassword(), newPassword("1234"), PRIMARY_USER_ID);
assertEquals(CREDENTIAL_TYPE_NONE, mService.getCredentialType(USER_FRP));
}
@Test
public void testFrpCredential_cannotVerifyAfterProvsioning() {
- mService.setLockCredential(newPin("1234"), nonePassword(), PRIMARY_USER_ID, false);
+ mService.setLockCredential(newPin("1234"), nonePassword(), PRIMARY_USER_ID);
mSettings.setDeviceProvisioned(true);
assertEquals(VerifyCredentialResponse.RESPONSE_ERROR,
@@ -103,7 +103,7 @@ public class LockscreenFrpTest extends BaseLockSettingsServiceTests {
@Test
public void testFrpCredential_legacyPinTypePersistentData() {
- mService.setLockCredential(newPin("1234"), nonePassword(), PRIMARY_USER_ID, false);
+ mService.setLockCredential(newPin("1234"), nonePassword(), PRIMARY_USER_ID);
PersistentData data = mStorage.readPersistentDataBlock();
// Tweak the existing persistent data to make it look like one with legacy credential type
assertEquals(CREDENTIAL_TYPE_PIN, data.payload[3]);
@@ -119,7 +119,7 @@ public class LockscreenFrpTest extends BaseLockSettingsServiceTests {
@Test
public void testFrpCredential_legacyPasswordTypePersistentData() {
- mService.setLockCredential(newPassword("1234"), nonePassword(), PRIMARY_USER_ID, false);
+ mService.setLockCredential(newPassword("1234"), nonePassword(), PRIMARY_USER_ID);
PersistentData data = mStorage.readPersistentDataBlock();
// Tweak the existing persistent data to make it look like one with legacy credential type
assertEquals(CREDENTIAL_TYPE_PASSWORD, data.payload[3]);
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 49858482fdf6..d6ef2d459769 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
@@ -106,7 +106,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
final LockscreenCredential password = newPassword("testPasswordMigration-password");
disableSyntheticPassword();
- assertTrue(mService.setLockCredential(password, nonePassword(), PRIMARY_USER_ID, false));
+ assertTrue(mService.setLockCredential(password, nonePassword(), PRIMARY_USER_ID));
long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
final byte[] primaryStorageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);
enableSyntheticPassword();
@@ -128,7 +128,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
protected void initializeCredentialUnderSP(LockscreenCredential password, int userId)
throws RemoteException {
enableSyntheticPassword();
- mService.setLockCredential(password, nonePassword(), userId, false);
+ mService.setLockCredential(password, nonePassword(), userId);
assertEquals(CREDENTIAL_TYPE_PASSWORD, mService.getCredentialType(userId));
assertTrue(mService.isSyntheticPasswordBasedCredential(userId));
}
@@ -140,7 +140,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
initializeCredentialUnderSP(password, PRIMARY_USER_ID);
long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
- mService.setLockCredential(newPassword, password, PRIMARY_USER_ID, false);
+ mService.setLockCredential(newPassword, password, PRIMARY_USER_ID);
assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
newPassword, 0, PRIMARY_USER_ID)
.getResponseCode());
@@ -170,12 +170,11 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
initializeCredentialUnderSP(password, PRIMARY_USER_ID);
long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
// clear password
- mService.setLockCredential(nonePassword(), password, PRIMARY_USER_ID, false);
+ mService.setLockCredential(nonePassword(), password, PRIMARY_USER_ID);
assertEquals(0 ,mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
// set a new password
- mService.setLockCredential(badPassword, nonePassword(),
- PRIMARY_USER_ID, false);
+ mService.setLockCredential(badPassword, nonePassword(), PRIMARY_USER_ID);
assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
badPassword, 0, PRIMARY_USER_ID)
.getResponseCode());
@@ -188,7 +187,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
LockscreenCredential badPassword = newPassword("new");
initializeCredentialUnderSP(password, PRIMARY_USER_ID);
- mService.setLockCredential(badPassword, password, PRIMARY_USER_ID, false);
+ mService.setLockCredential(badPassword, password, PRIMARY_USER_ID);
assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
badPassword, 0, PRIMARY_USER_ID)
.getResponseCode());
@@ -245,7 +244,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
public void testSyntheticPasswordButNoCredentialPassesAuthSecret() throws RemoteException {
LockscreenCredential password = newPassword("getASyntheticPassword");
initializeCredentialUnderSP(password, PRIMARY_USER_ID);
- mService.setLockCredential(nonePassword(), password, PRIMARY_USER_ID, false);
+ mService.setLockCredential(nonePassword(), password, PRIMARY_USER_ID);
reset(mAuthSecretService);
mService.onUnlockUser(PRIMARY_USER_ID);
@@ -257,7 +256,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
public void testManagedProfileUnifiedChallengeMigration() throws RemoteException {
LockscreenCredential UnifiedPassword = newPassword("unified-pwd");
disableSyntheticPassword();
- mService.setLockCredential(UnifiedPassword, nonePassword(), PRIMARY_USER_ID, false);
+ mService.setLockCredential(UnifiedPassword, nonePassword(), PRIMARY_USER_ID);
mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
final long primarySid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
final long profileSid = mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID);
@@ -292,9 +291,8 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
LockscreenCredential primaryPassword = newPassword("primary");
LockscreenCredential profilePassword = newPassword("profile");
disableSyntheticPassword();
- mService.setLockCredential(primaryPassword, nonePassword(), PRIMARY_USER_ID, false);
- mService.setLockCredential(profilePassword, nonePassword(),
- MANAGED_PROFILE_USER_ID, false);
+ mService.setLockCredential(primaryPassword, nonePassword(), PRIMARY_USER_ID);
+ mService.setLockCredential(profilePassword, nonePassword(), MANAGED_PROFILE_USER_ID);
final long primarySid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
final long profileSid = mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID);
byte[] primaryStorageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);
@@ -404,7 +402,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
mService.verifyCredential(password, 0, PRIMARY_USER_ID).getResponseCode();
assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
- mService.setLockCredential(pattern, password, PRIMARY_USER_ID, false);
+ mService.setLockCredential(pattern, password, PRIMARY_USER_ID);
mLocalService.setLockCredentialWithToken(newPassword, handle, token, PRIMARY_USER_ID);
@@ -433,7 +431,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
// initialized but the user currently has no password
initializeCredentialUnderSP(newPassword("password"), PRIMARY_USER_ID);
assertTrue(mService.setLockCredential(nonePassword(), newPassword("password"),
- PRIMARY_USER_ID, false));
+ PRIMARY_USER_ID));
assertTrue(mService.isSyntheticPasswordBasedCredential(PRIMARY_USER_ID));
long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null);
@@ -449,7 +447,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
LockscreenCredential password = newPassword("password");
// Set up pre-SP user password
disableSyntheticPassword();
- mService.setLockCredential(password, nonePassword(), PRIMARY_USER_ID, false);
+ mService.setLockCredential(password, nonePassword(), PRIMARY_USER_ID);
enableSyntheticPassword();
long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null);
@@ -507,11 +505,11 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
@Test
public void testGetHashFactorPrimaryUser() throws RemoteException {
LockscreenCredential password = newPassword("password");
- mService.setLockCredential(password, nonePassword(), PRIMARY_USER_ID, false);
+ mService.setLockCredential(password, nonePassword(), PRIMARY_USER_ID);
byte[] hashFactor = mService.getHashFactor(password, PRIMARY_USER_ID);
assertNotNull(hashFactor);
- mService.setLockCredential(nonePassword(), password, PRIMARY_USER_ID, false);
+ mService.setLockCredential(nonePassword(), password, PRIMARY_USER_ID);
byte[] newHashFactor = mService.getHashFactor(nonePassword(), PRIMARY_USER_ID);
assertNotNull(newHashFactor);
// Hash factor should never change after password change/removal
@@ -521,7 +519,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
@Test
public void testGetHashFactorManagedProfileUnifiedChallenge() throws RemoteException {
LockscreenCredential pattern = newPattern("1236");
- mService.setLockCredential(pattern, nonePassword(), PRIMARY_USER_ID, false);
+ mService.setLockCredential(pattern, nonePassword(), PRIMARY_USER_ID);
mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
assertNotNull(mService.getHashFactor(null, MANAGED_PROFILE_USER_ID));
}
@@ -530,9 +528,8 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
public void testGetHashFactorManagedProfileSeparateChallenge() throws RemoteException {
LockscreenCredential primaryPassword = newPassword("primary");
LockscreenCredential profilePassword = newPassword("profile");
- mService.setLockCredential(primaryPassword, nonePassword(), PRIMARY_USER_ID, false);
- mService.setLockCredential(profilePassword, nonePassword(),
- MANAGED_PROFILE_USER_ID, false);
+ mService.setLockCredential(primaryPassword, nonePassword(), PRIMARY_USER_ID);
+ mService.setLockCredential(profilePassword, nonePassword(), MANAGED_PROFILE_USER_ID);
assertNotNull(
mService.getHashFactor(profilePassword, MANAGED_PROFILE_USER_ID));
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java
index 178f38aac0b7..fb9c68a5b70d 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java
@@ -68,7 +68,7 @@ public class ApexManagerTest {
@Before
public void setUp() throws RemoteException {
mContext = InstrumentationRegistry.getInstrumentation().getContext();
- mApexManager = new ApexManager.ApexManagerImpl(mContext, mApexService);
+ mApexManager = new ApexManager.ApexManagerImpl(mApexService);
}
@Test
diff --git a/services/tests/uiservicestests/Android.bp b/services/tests/uiservicestests/Android.bp
index 92198fa8cb0c..f608babd062c 100644
--- a/services/tests/uiservicestests/Android.bp
+++ b/services/tests/uiservicestests/Android.bp
@@ -20,6 +20,7 @@ android_test {
"androidx.test.rules", "hamcrest-library",
"mockito-target-inline-minus-junit4",
"platform-test-annotations",
+ "platformprotosnano",
"hamcrest-library",
"testables",
"truth-prebuilt",
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PulledStatsTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PulledStatsTest.java
new file mode 100644
index 000000000000..f685c68f4160
--- /dev/null
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PulledStatsTest.java
@@ -0,0 +1,113 @@
+/*
+ * 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.notification;
+
+import static com.android.server.notification.NotificationManagerService.REPORT_REMOTE_VIEWS;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotSame;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.service.notification.nano.NotificationRemoteViewsProto;
+import android.test.MoreAsserts;
+import android.util.proto.ProtoOutputStream;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.server.UiServiceTestCase;
+
+import com.google.protobuf.nano.InvalidProtocolBufferNanoException;
+
+import org.junit.Test;
+
+import java.io.ByteArrayOutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+@SmallTest
+public class PulledStatsTest extends UiServiceTestCase {
+
+ @Test
+ public void testPulledStats_Empty() {
+ PulledStats stats = new PulledStats(0L);
+ assertEquals(0L, stats.endTimeMs());
+ }
+
+ @Test
+ public void testPulledStats_UnknownReport() {
+ PulledStats stats = new PulledStats(0L);
+ stats.addUndecoratedPackage("foo", 456);
+ stats.addUndecoratedPackage("bar", 123);
+
+ ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+ final ProtoOutputStream proto = new ProtoOutputStream(bytes);
+ stats.writeToProto(1023123, proto); // a very large number
+ proto.flush();
+
+ // expect empty output in response to an unrecognized request
+ assertEquals(0L, bytes.size());
+ }
+
+ @Test
+ public void testPulledStats_RemoteViewReportPackages() {
+ List<String> expectedPkgs = new ArrayList<>(2);
+ expectedPkgs.add("foo");
+ expectedPkgs.add("bar");
+
+ PulledStats stats = new PulledStats(0L);
+ for(String pkg: expectedPkgs) {
+ stats.addUndecoratedPackage(pkg, 111);
+ }
+
+ ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+ final ProtoOutputStream protoStream = new ProtoOutputStream(bytes);
+ stats.writeToProto(REPORT_REMOTE_VIEWS, protoStream);
+ protoStream.flush();
+
+ try {
+ NotificationRemoteViewsProto proto =
+ NotificationRemoteViewsProto.parseFrom(bytes.toByteArray());
+ List<String> actualPkgs = new ArrayList<>(2);
+ for(int i = 0 ; i < proto.packageRemoteViewInfo.length; i++) {
+ actualPkgs.add(proto.packageRemoteViewInfo[i].packageName);
+ }
+ assertEquals(2, actualPkgs.size());
+ assertTrue("missing packages", actualPkgs.containsAll(expectedPkgs));
+ assertTrue("unexpected packages", expectedPkgs.containsAll(actualPkgs));
+ } catch (InvalidProtocolBufferNanoException e) {
+ e.printStackTrace();
+ fail("writeToProto generated unparsable output");
+ }
+
+ }
+ @Test
+ public void testPulledStats_RemoteViewReportEndTime() {
+ List<String> expectedPkgs = new ArrayList<>(2);
+ expectedPkgs.add("foo");
+ expectedPkgs.add("bar");
+
+ PulledStats stats = new PulledStats(0L);
+ long t = 111;
+ for(String pkg: expectedPkgs) {
+ t += 1000;
+ stats.addUndecoratedPackage(pkg, t);
+ }
+ assertEquals(t, stats.endTimeMs());
+ }
+
+}
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java
index 4d2183b32392..856641228d80 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java
@@ -80,6 +80,9 @@ import java.nio.charset.StandardCharsets;
@RunWith(WindowTestRunner.class)
public class DisplayWindowSettingsTests extends WindowTestsBase {
+ private static final byte DISPLAY_PORT = (byte) 0xFF;
+ private static final long DISPLAY_MODEL = 0xEEEEEEEEL;
+
private static final File TEST_FOLDER = getInstrumentation().getTargetContext().getCacheDir();
private DisplayWindowSettings mTarget;
@@ -479,10 +482,11 @@ public class DisplayWindowSettingsTests extends WindowTestsBase {
@Test
public void testReadingDisplaySettingsFromStorage_UsePortAsId() {
- final DisplayAddress.Physical displayAddress = DisplayAddress.fromPhysicalDisplayId(123456);
+ final DisplayAddress.Physical displayAddress =
+ DisplayAddress.fromPortAndModel(DISPLAY_PORT, DISPLAY_MODEL);
mPrimaryDisplay.getDisplayInfo().address = displayAddress;
- final String displayIdentifier = "port:" + displayAddress.getPort();
+ final String displayIdentifier = "port:" + Byte.toUnsignedInt(DISPLAY_PORT);
prepareDisplaySettings(displayIdentifier, true /* usePortAsId */);
readAndAssertDisplaySettings(mPrimaryDisplay);
@@ -521,7 +525,8 @@ public class DisplayWindowSettingsTests extends WindowTestsBase {
@Test
public void testWritingDisplaySettingsToStorage_UsePortAsId() throws Exception {
// Store config to use port as identifier.
- final DisplayAddress.Physical displayAddress = DisplayAddress.fromPhysicalDisplayId(123456);
+ final DisplayAddress.Physical displayAddress =
+ DisplayAddress.fromPortAndModel(DISPLAY_PORT, DISPLAY_MODEL);
mSecondaryDisplay.getDisplayInfo().address = displayAddress;
prepareDisplaySettings(null /* displayIdentifier */, true /* usePortAsId */);
@@ -532,7 +537,7 @@ public class DisplayWindowSettingsTests extends WindowTestsBase {
assertTrue(mStorage.wasWriteSuccessful());
// Verify that settings were stored correctly.
- assertEquals("Attribute value must be stored", "port:" + displayAddress.getPort(),
+ assertEquals("Attribute value must be stored", "port:" + Byte.toUnsignedInt(DISPLAY_PORT),
getStoredDisplayAttributeValue("name"));
assertEquals("Attribute value must be stored", "true",
getStoredDisplayAttributeValue("shouldShowSystemDecors"));
diff --git a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
index e34824c57fb2..1996dd4f6545 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
@@ -236,7 +236,7 @@ public class UsageStatsDatabase {
return false;
}
}
- } catch (IOException e) {
+ } catch (Exception e) {
Slog.e(TAG, "Failed to check-in", e);
return false;
}
@@ -744,7 +744,7 @@ public class UsageStatsDatabase {
IntervalStats stats = new IntervalStats();
readLocked(f, stats);
return stats;
- } catch (IOException e) {
+ } catch (Exception e) {
Slog.e(TAG, "Failed to read usage stats file", e);
}
}
@@ -862,7 +862,7 @@ public class UsageStatsDatabase {
if (beginTime < stats.endTime) {
combiner.combine(stats, false, results);
}
- } catch (IOException e) {
+ } catch (Exception e) {
Slog.e(TAG, "Failed to read usage stats file", e);
// We continue so that we return results that are not
// corrupt.
@@ -1009,7 +1009,8 @@ public class UsageStatsDatabase {
}
}
- private void writeLocked(AtomicFile file, IntervalStats stats) throws IOException {
+ private void writeLocked(AtomicFile file, IntervalStats stats)
+ throws IOException, RuntimeException {
if (mCurrentVersion <= 3) {
Slog.wtf(TAG, "Attempting to write UsageStats as XML with version " + mCurrentVersion);
return;
@@ -1018,7 +1019,7 @@ public class UsageStatsDatabase {
}
private static void writeLocked(AtomicFile file, IntervalStats stats, int version,
- PackagesTokenData packagesTokenData) throws IOException {
+ PackagesTokenData packagesTokenData) throws IOException, RuntimeException {
FileOutputStream fos = file.startWrite();
try {
writeLocked(fos, stats, version, packagesTokenData);
@@ -1031,7 +1032,7 @@ public class UsageStatsDatabase {
}
private static void writeLocked(OutputStream out, IntervalStats stats, int version,
- PackagesTokenData packagesTokenData) throws IOException {
+ PackagesTokenData packagesTokenData) throws RuntimeException {
switch (version) {
case 1:
case 2:
@@ -1041,7 +1042,7 @@ public class UsageStatsDatabase {
case 4:
try {
UsageStatsProto.write(out, stats);
- } catch (IOException | IllegalArgumentException e) {
+ } catch (Exception e) {
Slog.e(TAG, "Unable to write interval stats to proto.", e);
}
break;
@@ -1049,7 +1050,7 @@ public class UsageStatsDatabase {
stats.obfuscateData(packagesTokenData);
try {
UsageStatsProtoV2.write(out, stats);
- } catch (IOException | IllegalArgumentException e) {
+ } catch (Exception e) {
Slog.e(TAG, "Unable to write interval stats to proto.", e);
}
break;
@@ -1060,7 +1061,8 @@ public class UsageStatsDatabase {
}
}
- private void readLocked(AtomicFile file, IntervalStats statsOut) throws IOException {
+ private void readLocked(AtomicFile file, IntervalStats statsOut)
+ throws IOException, RuntimeException {
if (mCurrentVersion <= 3) {
Slog.wtf(TAG, "Reading UsageStats as XML; current database version: "
+ mCurrentVersion);
@@ -1072,7 +1074,7 @@ public class UsageStatsDatabase {
* Returns {@code true} if any stats were omitted while reading, {@code false} otherwise.
*/
private static boolean readLocked(AtomicFile file, IntervalStats statsOut, int version,
- PackagesTokenData packagesTokenData) throws IOException {
+ PackagesTokenData packagesTokenData) throws IOException, RuntimeException {
boolean dataOmitted = false;
try {
FileInputStream in = file.openRead();
@@ -1098,7 +1100,7 @@ public class UsageStatsDatabase {
* Returns {@code true} if any stats were omitted while reading, {@code false} otherwise.
*/
private static boolean readLocked(InputStream in, IntervalStats statsOut, int version,
- PackagesTokenData packagesTokenData) throws IOException {
+ PackagesTokenData packagesTokenData) throws RuntimeException {
boolean dataOmitted = false;
switch (version) {
case 1:
@@ -1114,14 +1116,14 @@ public class UsageStatsDatabase {
case 4:
try {
UsageStatsProto.read(in, statsOut);
- } catch (IOException e) {
+ } catch (Exception e) {
Slog.e(TAG, "Unable to read interval stats from proto.", e);
}
break;
case 5:
try {
UsageStatsProtoV2.read(in, statsOut);
- } catch (IOException e) {
+ } catch (Exception e) {
Slog.e(TAG, "Unable to read interval stats from proto.", e);
}
dataOmitted = statsOut.deobfuscateData(packagesTokenData);
@@ -1145,7 +1147,7 @@ public class UsageStatsDatabase {
try (FileInputStream in = new AtomicFile(mPackageMappingsFile).openRead()) {
UsageStatsProtoV2.readObfuscatedData(in, mPackagesTokenData);
- } catch (IOException e) {
+ } catch (Exception e) {
Slog.e(TAG, "Failed to read the obfuscated packages mapping file.", e);
return;
}
@@ -1174,7 +1176,7 @@ public class UsageStatsDatabase {
UsageStatsProtoV2.writeObfuscatedData(fos, mPackagesTokenData);
file.finishWrite(fos);
fos = null;
- } catch (IOException | IllegalArgumentException e) {
+ } catch (Exception e) {
Slog.e(TAG, "Unable to write obfuscated data to proto.", e);
} finally {
file.failWrite(fos);
@@ -1414,8 +1416,8 @@ public class UsageStatsDatabase {
try {
stats.beginTime = in.readLong();
readLocked(in, stats, version, mPackagesTokenData);
- } catch (IOException ioe) {
- Slog.d(TAG, "DeSerializing IntervalStats Failed", ioe);
+ } catch (Exception e) {
+ Slog.d(TAG, "DeSerializing IntervalStats Failed", e);
stats = null;
}
return stats;
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 064922386773..c900f386b438 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -653,18 +653,20 @@ public class UsageStatsService extends SystemService implements
}
Arrays.sort(pendingEventsFiles);
- for (int i = 0; i < pendingEventsFiles.length; i++) {
+ final int numFiles = pendingEventsFiles.length;
+ for (int i = 0; i < numFiles; i++) {
final AtomicFile af = new AtomicFile(pendingEventsFiles[i]);
+ final LinkedList<Event> tmpEvents = new LinkedList<>();
try {
try (FileInputStream in = af.openRead()) {
- UsageStatsProtoV2.readPendingEvents(in, pendingEvents);
+ UsageStatsProtoV2.readPendingEvents(in, tmpEvents);
}
- } catch (IOException e) {
- // Even if one file read fails, exit here to keep all events in order on disk -
- // they will be read and processed the next time user is unlocked.
+ // only add to the pending events if the read was successful
+ pendingEvents.addAll(tmpEvents);
+ } catch (Exception e) {
+ // Most likely trying to read a corrupted file - log the failure and continue
+ // reading the other pending event files.
Slog.e(TAG, "Could not read " + pendingEventsFiles[i] + " for user " + userId);
- pendingEvents.clear();
- return;
}
}
}
@@ -691,7 +693,7 @@ public class UsageStatsService extends SystemService implements
af.finishWrite(fos);
fos = null;
pendingEvents.clear();
- } catch (IOException | IllegalArgumentException e) {
+ } catch (Exception e) {
Slog.e(TAG, "Failed to write " + pendingEventsFile.getAbsolutePath()
+ " for user " + userId);
} finally {
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 1b86c09ce86c..2e04730a5ea2 100755
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -2326,7 +2326,7 @@ public class CarrierConfigManager {
* Reference: 3GPP TS 38.215
*
* 4 threshold integers must be within the boundaries [-20 dB, -3 dB], and the levels are:
- * "NONE: [-23, threshold1]"
+ * "NONE: [-20, threshold1]"
* "POOR: (threshold1, threshold2]"
* "MODERATE: (threshold2, threshold3]"
* "GOOD: (threshold3, threshold4]"
@@ -2360,15 +2360,26 @@ public class CarrierConfigManager {
/**
* Bit-field integer to determine whether to use SS reference signal received power (SSRSRP),
* SS reference signal received quality (SSRSRQ), or/and SS signal-to-noise and interference
- * ratio (SSSINR) for the number of 5G NR signal bars. If multiple measures are set bit, the
- * parameter whose value is smallest is used to indicate the signal bar.
+ * ratio (SSSINR) for the number of 5G NR signal bars and signal criteria reporting enabling.
+ *
+ * <p> If a measure is not set, signal criteria reporting from modem will not be triggered and
+ * not be used for calculating signal level. If multiple measures are set bit, the parameter
+ * whose value is smallest is used to indicate the signal level.
*
* SSRSRP = 1 << 0,
* SSRSRQ = 1 << 1,
* SSSINR = 1 << 2,
*
+ * The value of this key must be bitwise OR of {@link CellSignalStrengthNr#USE_SSRSRP},
+ * {@link CellSignalStrengthNr#USE_SSRSRQ}, {@link CellSignalStrengthNr#USE_SSSINR}.
+ *
+ * For example, if both SSRSRP and SSSINR are used, the value of key is 5 (1 << 0 | 1 << 2).
+ * If the key is invalid or not configured, a default value (SSRSRP = 1 << 0) will apply.
+ *
* Reference: 3GPP TS 38.215,
* 3GPP TS 38.133 10.1.16.1
+ *
+ * @hide
*/
public static final String KEY_PARAMETERS_USE_FOR_5G_NR_SIGNAL_BAR_INT =
"parameters_use_for_5g_nr_signal_bar_int";
@@ -3748,6 +3759,32 @@ public class CarrierConfigManager {
-95, /* SIGNAL_STRENGTH_GOOD */
-85 /* SIGNAL_STRENGTH_GREAT */
});
+ sDefaults.putIntArray(KEY_5G_NR_SSRSRP_THRESHOLDS_INT_ARRAY,
+ // Boundaries: [-140 dB, -44 dB]
+ new int[] {
+ -125, /* SIGNAL_STRENGTH_POOR */
+ -115, /* SIGNAL_STRENGTH_MODERATE */
+ -105, /* SIGNAL_STRENGTH_GOOD */
+ -95, /* SIGNAL_STRENGTH_GREAT */
+ });
+ sDefaults.putIntArray(KEY_5G_NR_SSRSRQ_THRESHOLDS_INT_ARRAY,
+ // Boundaries: [-20 dB, -3 dB]
+ new int[] {
+ -14, /* SIGNAL_STRENGTH_POOR */
+ -12, /* SIGNAL_STRENGTH_MODERATE */
+ -10, /* SIGNAL_STRENGTH_GOOD */
+ -8 /* SIGNAL_STRENGTH_GREAT */
+ });
+ sDefaults.putIntArray(KEY_5G_NR_SSSINR_THRESHOLDS_INT_ARRAY,
+ // Boundaries: [-23 dB, 40 dB]
+ new int[] {
+ -8, /* SIGNAL_STRENGTH_POOR */
+ 0, /* SIGNAL_STRENGTH_MODERATE */
+ 8, /* SIGNAL_STRENGTH_GOOD */
+ 16 /* SIGNAL_STRENGTH_GREAT */
+ });
+ sDefaults.putInt(KEY_PARAMETERS_USE_FOR_5G_NR_SIGNAL_BAR_INT,
+ CellSignalStrengthNr.USE_SSRSRP);
sDefaults.putString(KEY_WCDMA_DEFAULT_SIGNAL_STRENGTH_MEASUREMENT_STRING, "rssi");
sDefaults.putBoolean(KEY_CONFIG_SHOW_ORIG_DIAL_STRING_FOR_CDMA_BOOL, false);
sDefaults.putBoolean(KEY_SHOW_CALL_BLOCKING_DISABLED_NOTIFICATION_ALWAYS_BOOL, false);
diff --git a/telephony/java/android/telephony/CellSignalStrengthNr.java b/telephony/java/android/telephony/CellSignalStrengthNr.java
index f9b7f6dbc193..f31fafe36508 100644
--- a/telephony/java/android/telephony/CellSignalStrengthNr.java
+++ b/telephony/java/android/telephony/CellSignalStrengthNr.java
@@ -16,11 +16,15 @@
package android.telephony;
+import android.annotation.IntDef;
import android.annotation.IntRange;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.PersistableBundle;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
import java.util.Objects;
/**
@@ -36,13 +40,67 @@ public final class CellSignalStrengthNr extends CellSignalStrength implements Pa
private static final String TAG = "CellSignalStrengthNr";
+ // Lifted from Default carrier configs and max range of SSRSRP
+ // Boundaries: [-140 dB, -44 dB]
+ private int[] mSsRsrpThresholds = new int[] {
+ -125, /* SIGNAL_STRENGTH_POOR */
+ -115, /* SIGNAL_STRENGTH_MODERATE */
+ -105, /* SIGNAL_STRENGTH_GOOD */
+ -95, /* SIGNAL_STRENGTH_GREAT */
+ };
+
+ // Lifted from Default carrier configs and max range of SSRSRQ
+ // Boundaries: [-20 dB, -3 dB]
+ private int[] mSsRsrqThresholds = new int[] {
+ -14, /* SIGNAL_STRENGTH_POOR */
+ -12, /* SIGNAL_STRENGTH_MODERATE */
+ -10, /* SIGNAL_STRENGTH_GOOD */
+ -8 /* SIGNAL_STRENGTH_GREAT */
+ };
+
+ // Lifted from Default carrier configs and max range of SSSINR
+ // Boundaries: [-23 dB, 40 dB]
+ private int[] mSsSinrThresholds = new int[] {
+ -8, /* SIGNAL_STRENGTH_POOR */
+ 0, /* SIGNAL_STRENGTH_MODERATE */
+ 8, /* SIGNAL_STRENGTH_GOOD */
+ 16 /* SIGNAL_STRENGTH_GREAT */
+ };
+
+ /**
+ * Indicates SSRSRP is considered for {@link #getLevel()} and reporting from modem.
+ *
+ * @hide
+ */
+ public static final int USE_SSRSRP = 1 << 0;
+ /**
+ * Indicates SSRSRQ is considered for {@link #getLevel()} and reporting from modem.
+ *
+ * @hide
+ */
+ public static final int USE_SSRSRQ = 1 << 1;
/**
- * These threshold values are copied from LTE.
- * TODO: make it configurable via CarrierConfig.
+ * Indicates SSSINR is considered for {@link #getLevel()} and reporting from modem.
+ *
+ * @hide
*/
- private static final int SIGNAL_GREAT_THRESHOLD = -95;
- private static final int SIGNAL_GOOD_THRESHOLD = -105;
- private static final int SIGNAL_MODERATE_THRESHOLD = -115;
+ public static final int USE_SSSINR = 1 << 2;
+
+ /**
+ * Bit-field integer to determine whether to use SS reference signal received power (SSRSRP),
+ * SS reference signal received quality (SSRSRQ), or/and SS signal-to-noise and interference
+ * ratio (SSSINR) for the number of 5G NR signal bars. If multiple measures are set bit, the
+ * parameter whose value is smallest is used to indicate the signal bar.
+ *
+ * @hide
+ */
+ @IntDef(flag = true, prefix = { "USE_" }, value = {
+ USE_SSRSRP,
+ USE_SSRSRQ,
+ USE_SSSINR
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SignalLevelAndReportCriteriaSource {}
private int mCsiRsrp;
private int mCsiRsrq;
@@ -52,6 +110,21 @@ public final class CellSignalStrengthNr extends CellSignalStrength implements Pa
private int mSsSinr;
private int mLevel;
+ /**
+ * Bit-field integer to determine whether to use SS reference signal received power (SSRSRP),
+ * SS reference signal received quality (SSRSRQ), or/and SS signal-to-noise and interference
+ * ratio (SSSINR) for the number of 5G NR signal bars. If multiple measures are set bit, the
+ * parameter whose value is smallest is used to indicate the signal bar.
+ *
+ * SSRSRP = 1 << 0,
+ * SSRSRQ = 1 << 1,
+ * SSSINR = 1 << 2,
+ *
+ * For example, if both SSRSRP and SSSINR are used, the value of key is 5 (1 << 0 | 1 << 2).
+ * If the key is invalid or not configured, a default value (SSRSRP = 1 << 0) will apply.
+ */
+ private int mParametersUseForLevel;
+
/** @hide */
public CellSignalStrengthNr() {
setDefaultValues();
@@ -182,6 +255,7 @@ public final class CellSignalStrengthNr extends CellSignalStrength implements Pa
mSsRsrq = CellInfo.UNAVAILABLE;
mSsSinr = CellInfo.UNAVAILABLE;
mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+ mParametersUseForLevel = USE_SSRSRP;
}
/** {@inheritDoc} */
@@ -191,20 +265,83 @@ public final class CellSignalStrengthNr extends CellSignalStrength implements Pa
return mLevel;
}
+ /**
+ * Checks if the given parameter type is considered to use for {@link #getLevel()}.
+ *
+ * Note: if multiple parameter types are considered, the smaller level for one of the
+ * parameters would be returned by {@link #getLevel()}
+ *
+ * @param parameterType bitwise OR of {@link #USE_SSRSRP}, {@link #USE_SSRSRQ},
+ * {@link #USE_SSSINR}
+ * @return {@code true} if the level is calculated based on the given parameter type;
+ * {@code false} otherwise.
+ *
+ */
+ private boolean isLevelForParameter(@SignalLevelAndReportCriteriaSource int parameterType) {
+ return (parameterType & mParametersUseForLevel) == parameterType;
+ }
+
/** @hide */
@Override
public void updateLevel(PersistableBundle cc, ServiceState ss) {
- if (mSsRsrp == CellInfo.UNAVAILABLE) {
- mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
- } else if (mSsRsrp >= SIGNAL_GREAT_THRESHOLD) {
- mLevel = SIGNAL_STRENGTH_GREAT;
- } else if (mSsRsrp >= SIGNAL_GOOD_THRESHOLD) {
- mLevel = SIGNAL_STRENGTH_GOOD;
- } else if (mSsRsrp >= SIGNAL_MODERATE_THRESHOLD) {
- mLevel = SIGNAL_STRENGTH_MODERATE;
+ if (cc == null) {
+ mParametersUseForLevel = USE_SSRSRP;
+ } else {
+ mParametersUseForLevel = cc.getInt(
+ CarrierConfigManager.KEY_PARAMETERS_USE_FOR_5G_NR_SIGNAL_BAR_INT, USE_SSRSRP);
+ Rlog.i(TAG, "Using SSRSRP for Level.");
+ mSsRsrpThresholds = cc.getIntArray(
+ CarrierConfigManager.KEY_5G_NR_SSRSRP_THRESHOLDS_INT_ARRAY);
+ Rlog.i(TAG, "Applying 5G NR SSRSRP Thresholds: " + Arrays.toString(mSsRsrpThresholds));
+ mSsRsrqThresholds = cc.getIntArray(
+ CarrierConfigManager.KEY_5G_NR_SSRSRQ_THRESHOLDS_INT_ARRAY);
+ Rlog.i(TAG, "Applying 5G NR SSRSRQ Thresholds: " + Arrays.toString(mSsRsrqThresholds));
+ mSsSinrThresholds = cc.getIntArray(
+ CarrierConfigManager.KEY_5G_NR_SSSINR_THRESHOLDS_INT_ARRAY);
+ Rlog.i(TAG, "Applying 5G NR SSSINR Thresholds: " + Arrays.toString(mSsSinrThresholds));
+ }
+ int ssRsrpLevel = SignalStrength.INVALID;
+ int ssRsrqLevel = SignalStrength.INVALID;
+ int ssSinrLevel = SignalStrength.INVALID;
+ if (isLevelForParameter(USE_SSRSRP)) {
+ ssRsrpLevel = updateLevelWithMeasure(mSsRsrp, mSsRsrpThresholds);
+ Rlog.i(TAG, "Updated 5G NR SSRSRP Level: " + ssRsrpLevel);
+ }
+ if (isLevelForParameter(USE_SSRSRQ)) {
+ ssRsrqLevel = updateLevelWithMeasure(mSsRsrq, mSsRsrqThresholds);
+ Rlog.i(TAG, "Updated 5G NR SSRSRQ Level: " + ssRsrqLevel);
+ }
+ if (isLevelForParameter(USE_SSSINR)) {
+ ssSinrLevel = updateLevelWithMeasure(mSsSinr, mSsSinrThresholds);
+ Rlog.i(TAG, "Updated 5G NR SSSINR Level: " + ssSinrLevel);
+ }
+ // Apply the smaller value among three levels of three measures.
+ mLevel = Math.min(Math.min(ssRsrpLevel, ssRsrqLevel), ssSinrLevel);
+ }
+
+ /**
+ * Update level with corresponding measure and thresholds.
+ *
+ * @param measure corresponding signal measure
+ * @param thresholds corresponding signal thresholds
+ * @return level of the signal strength
+ */
+ private int updateLevelWithMeasure(int measure, int[] thresholds) {
+ int level;
+ if (measure == CellInfo.UNAVAILABLE) {
+ level = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+ } else if (measure > thresholds[3]) {
+ level = SIGNAL_STRENGTH_GREAT;
+ } else if (measure > thresholds[2]) {
+ level = SIGNAL_STRENGTH_GOOD;
+ } else if (measure > thresholds[1]) {
+ level = SIGNAL_STRENGTH_MODERATE;
+ } else if (measure > thresholds[0]) {
+ level = SIGNAL_STRENGTH_POOR;
} else {
- mLevel = SIGNAL_STRENGTH_POOR;
+ level = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
}
+ return level;
}
/**
@@ -247,6 +384,7 @@ public final class CellSignalStrengthNr extends CellSignalStrength implements Pa
mSsRsrq = s.mSsRsrq;
mSsSinr = s.mSsSinr;
mLevel = s.mLevel;
+ mParametersUseForLevel = s.mParametersUseForLevel;
}
/** @hide */
@@ -290,6 +428,7 @@ public final class CellSignalStrengthNr extends CellSignalStrength implements Pa
.append(" ssRsrq = " + mSsRsrq)
.append(" ssSinr = " + mSsSinr)
.append(" level = " + mLevel)
+ .append(" parametersUseForLevel = " + mParametersUseForLevel)
.append(" }")
.toString();
}
diff --git a/telephony/java/android/telephony/SignalThresholdInfo.java b/telephony/java/android/telephony/SignalThresholdInfo.java
new file mode 100644
index 000000000000..f6f6d75c37c6
--- /dev/null
+++ b/telephony/java/android/telephony/SignalThresholdInfo.java
@@ -0,0 +1,256 @@
+/*
+ * 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.telephony;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
+import java.util.Objects;
+
+/**
+ * Defines the threshold value of the signal strength.
+ * @hide
+ */
+public class SignalThresholdInfo implements Parcelable {
+ /**
+ * Received Signal Strength Indication.
+ * Range: -113 dBm and -51 dBm
+ * Used RAN: GERAN, CDMA2000
+ * Reference: 3GPP TS 27.007 section 8.5.
+ */
+ public static final int SIGNAL_RSSI = 1;
+
+ /**
+ * Received Signal Code Power.
+ * Range: -120 dBm to -25 dBm;
+ * Used RAN: UTRAN
+ * Reference: 3GPP TS 25.123, section 9.1.1.1
+ */
+ public static final int SIGNAL_RSCP = 2;
+
+ /**
+ * Reference Signal Received Power.
+ * Range: -140 dBm to -44 dBm;
+ * Used RAN: EUTRAN
+ * Reference: 3GPP TS 36.133 9.1.4
+ */
+ public static final int SIGNAL_RSRP = 3;
+
+ /**
+ * Reference Signal Received Quality
+ * Range: -20 dB to -3 dB;
+ * Used RAN: EUTRAN
+ * Reference: 3GPP TS 36.133 9.1.7
+ */
+ public static final int SIGNAL_RSRQ = 4;
+
+ /**
+ * Reference Signal Signal to Noise Ratio
+ * Range: -20 dB to 30 dB;
+ * Used RAN: EUTRAN
+ */
+ public static final int SIGNAL_RSSNR = 5;
+
+ /**
+ * 5G SS reference signal received power.
+ * Range: -140 dBm to -44 dBm.
+ * Used RAN: NGRAN
+ * Reference: 3GPP TS 38.215.
+ */
+ public static final int SIGNAL_SSRSRP = 6;
+
+ /**
+ * 5G SS reference signal received quality.
+ * Range: -20 dB to -3 dB.
+ * Used RAN: NGRAN
+ * Reference: 3GPP TS 38.215.
+ */
+ public static final int SIGNAL_SSRSRQ = 7;
+
+ /**
+ * 5G SS signal-to-noise and interference ratio.
+ * Range: -23 dB to 40 dB
+ * Used RAN: NGRAN
+ * Reference: 3GPP TS 38.215 section 5.1.*, 3GPP TS 38.133 section 10.1.16.1.
+ */
+ public static final int SIGNAL_SSSINR = 8;
+
+ /** @hide */
+ @IntDef(prefix = { "SIGNAL_" }, value = {
+ SIGNAL_RSSI,
+ SIGNAL_RSCP,
+ SIGNAL_RSRP,
+ SIGNAL_RSRQ,
+ SIGNAL_RSSNR,
+ SIGNAL_SSRSRP,
+ SIGNAL_SSRSRQ,
+ SIGNAL_SSSINR
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SignalMeasurementType {}
+
+ @SignalMeasurementType
+ private int mSignalMeasurement;
+
+ /**
+ * A hysteresis time in milliseconds to prevent flapping.
+ * A value of 0 disables hysteresis
+ */
+ private int mHysteresisMs;
+
+ /**
+ * An interval in dB defining the required magnitude change between reports.
+ * hysteresisDb must be smaller than the smallest threshold delta.
+ * An interval value of 0 disables hysteresis.
+ */
+ private int mHysteresisDb;
+
+ /**
+ * List of threshold values.
+ * Range and unit must reference specific SignalMeasurementType
+ * The threshold values for which to apply criteria.
+ * A vector size of 0 disables the use of thresholds for reporting.
+ */
+ private int[] mThresholds = null;
+
+ /**
+ * {@code true} means modem must trigger the report based on the criteria;
+ * {@code false} means modem must not trigger the report based on the criteria.
+ */
+ private boolean mIsEnabled = true;
+
+ /**
+ * Indicates the hysteresisMs is disabled.
+ */
+ public static final int HYSTERESIS_MS_DISABLED = 0;
+
+ /**
+ * Indicates the hysteresisDb is disabled.
+ */
+ public static final int HYSTERESIS_DB_DISABLED = 0;
+
+ /**
+ * Constructor
+ *
+ * @param signalMeasurement Signal Measurement Type
+ * @param hysteresisMs hysteresisMs
+ * @param hysteresisDb hysteresisDb
+ * @param thresholds threshold value
+ * @param isEnabled isEnabled
+ */
+ public SignalThresholdInfo(@SignalMeasurementType int signalMeasurement,
+ int hysteresisMs, int hysteresisDb, @NonNull int [] thresholds, boolean isEnabled) {
+ mSignalMeasurement = signalMeasurement;
+ mHysteresisMs = hysteresisMs < 0 ? HYSTERESIS_MS_DISABLED : hysteresisMs;
+ mHysteresisDb = hysteresisDb < 0 ? HYSTERESIS_DB_DISABLED : hysteresisDb;
+ mThresholds = thresholds == null ? null : thresholds.clone();
+ mIsEnabled = isEnabled;
+ }
+
+ public @SignalMeasurementType int getSignalMeasurement() {
+ return mSignalMeasurement;
+ }
+
+ public int getHysteresisMs() {
+ return mHysteresisMs;
+ }
+
+ public int getHysteresisDb() {
+ return mHysteresisDb;
+ }
+
+ public boolean isEnabled() {
+ return mIsEnabled;
+ }
+
+ public int[] getThresholds() {
+ return mThresholds == null ? null : mThresholds.clone();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(mSignalMeasurement);
+ out.writeInt(mHysteresisMs);
+ out.writeInt(mHysteresisDb);
+ out.writeIntArray(mThresholds);
+ out.writeBoolean(mIsEnabled);
+ }
+
+ private SignalThresholdInfo(Parcel in) {
+ mSignalMeasurement = in.readInt();
+ mHysteresisMs = in.readInt();
+ mHysteresisDb = in.readInt();
+ mThresholds = in.createIntArray();
+ mIsEnabled = in.readBoolean();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+
+ if (!(o instanceof SignalThresholdInfo)) {
+ return false;
+ }
+
+ SignalThresholdInfo other = (SignalThresholdInfo) o;
+ return mSignalMeasurement == other.mSignalMeasurement
+ && mHysteresisMs == other.mHysteresisMs
+ && mHysteresisDb == other.mHysteresisDb
+ && Arrays.equals(mThresholds, other.mThresholds)
+ && mIsEnabled == other.mIsEnabled;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(
+ mSignalMeasurement, mHysteresisMs, mHysteresisDb, mThresholds, mIsEnabled);
+ }
+
+ public static final @NonNull Parcelable.Creator<SignalThresholdInfo> CREATOR =
+ new Parcelable.Creator<SignalThresholdInfo>() {
+ @Override
+ public SignalThresholdInfo createFromParcel(Parcel in) {
+ return new SignalThresholdInfo(in);
+ }
+
+ @Override
+ public SignalThresholdInfo[] newArray(int size) {
+ return new SignalThresholdInfo[size];
+ }
+ };
+
+ @Override
+ public String toString() {
+ return new StringBuilder("SignalThresholdInfo{")
+ .append("mSignalMeasurement=").append(mSignalMeasurement)
+ .append("mHysteresisMs=").append(mSignalMeasurement)
+ .append("mHysteresisDb=").append(mHysteresisDb)
+ .append("mThresholds=").append(Arrays.toString(mThresholds))
+ .append("mIsEnabled=").append(mIsEnabled)
+ .append("}").toString();
+ }
+}
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index 9eff809eaf5d..ebb517596b6c 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -89,8 +89,8 @@ public class SubscriptionInfo implements Parcelable {
private int mCarrierId;
/**
- * The source of the name, NAME_SOURCE_DEFAULT_SOURCE, NAME_SOURCE_SIM_SOURCE or
- * NAME_SOURCE_USER_INPUT.
+ * The source of the name, NAME_SOURCE_DEFAULT_SOURCE, NAME_SOURCE_SIM_SPN,
+ * NAME_SOURCE_SIM_PNN, or NAME_SOURCE_USER_INPUT.
*/
private int mNameSource;
@@ -334,7 +334,7 @@ public class SubscriptionInfo implements Parcelable {
}
/**
- * @return the source of the name, eg NAME_SOURCE_DEFAULT_SOURCE, NAME_SOURCE_SIM_SOURCE or
+ * @return the source of the name, eg NAME_SOURCE_DEFAULT_SOURCE, NAME_SOURCE_SIM_SPN or
* NAME_SOURCE_USER_INPUT.
* @hide
*/
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index fbbf75a85a9b..cf705f466e48 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -54,6 +54,7 @@ import android.os.ParcelUuid;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.provider.Telephony.SimInfo;
import android.telephony.euicc.EuiccManager;
import android.telephony.ims.ImsMmTelManager;
import android.util.DisplayMetrics;
@@ -129,7 +130,7 @@ public class SubscriptionManager {
/** @hide */
@UnsupportedAppUsage
- public static final Uri CONTENT_URI = Uri.parse("content://telephony/siminfo");
+ public static final Uri CONTENT_URI = SimInfo.CONTENT_URI;
/**
* Generates a content {@link Uri} used to receive updates on simInfo change
@@ -400,19 +401,19 @@ public class SubscriptionManager {
public static final String NAME_SOURCE = "name_source";
/**
- * The name_source is the default
+ * The name_source is the default, which is from the carrier id.
* @hide
*/
public static final int NAME_SOURCE_DEFAULT_SOURCE = 0;
/**
- * The name_source is from the SIM
+ * The name_source is from SIM EF_SPN.
* @hide
*/
- public static final int NAME_SOURCE_SIM_SOURCE = 1;
+ public static final int NAME_SOURCE_SIM_SPN = 1;
/**
- * The name_source is from the user
+ * The name_source is from user input
* @hide
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
@@ -425,6 +426,24 @@ public class SubscriptionManager {
public static final int NAME_SOURCE_CARRIER = 3;
/**
+ * The name_source is from SIM EF_PNN.
+ * @hide
+ */
+ public static final int NAME_SOURCE_SIM_PNN = 4;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = {"NAME_SOURCE_"},
+ value = {
+ NAME_SOURCE_DEFAULT_SOURCE,
+ NAME_SOURCE_SIM_SPN,
+ NAME_SOURCE_USER_INPUT,
+ NAME_SOURCE_CARRIER,
+ NAME_SOURCE_SIM_PNN
+ })
+ public @interface SimDisplayNameSource {}
+
+ /**
* TelephonyProvider column name for the color of a SIM.
* <P>Type: INTEGER (int)</P>
*/
@@ -1667,13 +1686,12 @@ public class SubscriptionManager {
* Set display name by simInfo index with name source
* @param displayName the display name of SIM card
* @param subId the unique SubscriptionInfo index in database
- * @param nameSource 0: NAME_SOURCE_DEFAULT_SOURCE, 1: NAME_SOURCE_SIM_SOURCE,
- * 2: NAME_SOURCE_USER_INPUT
+ * @param nameSource SIM display name source
* @return the number of records updated or < 0 if invalid subId
* @hide
*/
@UnsupportedAppUsage
- public int setDisplayName(String displayName, int subId, int nameSource) {
+ public int setDisplayName(String displayName, int subId, @SimDisplayNameSource int nameSource) {
if (VDBG) {
logd("[setDisplayName]+ displayName:" + displayName + " subId:" + subId
+ " nameSource:" + nameSource);
diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java
index 5fd0af564d34..057d22cd7eae 100644
--- a/telephony/java/android/telephony/ims/ImsMmTelManager.java
+++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java
@@ -161,9 +161,13 @@ public class ImsMmTelManager implements RegistrationManager {
public void onCapabilitiesStatusChanged(int config) {
if (mLocalCallback == null) return;
- Binder.withCleanCallingIdentity(() ->
- mExecutor.execute(() -> mLocalCallback.onCapabilitiesStatusChanged(
- new MmTelFeature.MmTelCapabilities(config))));
+ long callingIdentity = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() -> mLocalCallback.onCapabilitiesStatusChanged(
+ new MmTelFeature.MmTelCapabilities(config)));
+ } finally {
+ restoreCallingIdentity(callingIdentity);
+ }
}
@Override
diff --git a/telephony/java/android/telephony/ims/ImsRcsManager.java b/telephony/java/android/telephony/ims/ImsRcsManager.java
index 21707b0d7cfd..b37d7c759be3 100644
--- a/telephony/java/android/telephony/ims/ImsRcsManager.java
+++ b/telephony/java/android/telephony/ims/ImsRcsManager.java
@@ -67,9 +67,13 @@ public class ImsRcsManager implements RegistrationManager {
public void onCapabilitiesStatusChanged(int config) {
if (mLocalCallback == null) return;
- Binder.withCleanCallingIdentity(() ->
- mExecutor.execute(() -> mLocalCallback.onAvailabilityChanged(
- new RcsFeature.RcsImsCapabilities(config))));
+ long callingIdentity = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() -> mLocalCallback.onAvailabilityChanged(
+ new RcsFeature.RcsImsCapabilities(config)));
+ } finally {
+ restoreCallingIdentity(callingIdentity);
+ }
}
@Override
diff --git a/telephony/java/android/telephony/ims/ProvisioningManager.java b/telephony/java/android/telephony/ims/ProvisioningManager.java
index e16085e30465..e4d63355625d 100644
--- a/telephony/java/android/telephony/ims/ProvisioningManager.java
+++ b/telephony/java/android/telephony/ims/ProvisioningManager.java
@@ -136,17 +136,24 @@ public class ProvisioningManager {
@Override
public final void onIntConfigChanged(int item, int value) {
- Binder.withCleanCallingIdentity(() ->
- mExecutor.execute(() ->
- mLocalConfigurationCallback.onProvisioningIntChanged(item, value)));
+ long callingIdentity = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() ->
+ mLocalConfigurationCallback.onProvisioningIntChanged(item, value));
+ } finally {
+ restoreCallingIdentity(callingIdentity);
+ }
}
@Override
public final void onStringConfigChanged(int item, String value) {
- Binder.withCleanCallingIdentity(() ->
- mExecutor.execute(() ->
- mLocalConfigurationCallback.onProvisioningStringChanged(item,
- value)));
+ long callingIdentity = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() ->
+ mLocalConfigurationCallback.onProvisioningStringChanged(item, value));
+ } finally {
+ restoreCallingIdentity(callingIdentity);
+ }
}
private void setExecutor(Executor executor) {
diff --git a/telephony/java/android/telephony/ims/RcsUceAdapter.java b/telephony/java/android/telephony/ims/RcsUceAdapter.java
index b47bcb9b119b..75e3f0a6393d 100644
--- a/telephony/java/android/telephony/ims/RcsUceAdapter.java
+++ b/telephony/java/android/telephony/ims/RcsUceAdapter.java
@@ -245,15 +245,22 @@ public class RcsUceAdapter {
IRcsUceControllerCallback internalCallback = new IRcsUceControllerCallback.Stub() {
@Override
public void onCapabilitiesReceived(List<RcsContactUceCapability> contactCapabilities) {
- Binder.withCleanCallingIdentity(() ->
- executor.execute(() ->
- c.onCapabilitiesReceived(contactCapabilities)));
+ long callingIdentity = Binder.clearCallingIdentity();
+ try {
+ executor.execute(() ->
+ c.onCapabilitiesReceived(contactCapabilities));
+ } finally {
+ restoreCallingIdentity(callingIdentity);
+ }
}
@Override
public void onError(int errorCode) {
- Binder.withCleanCallingIdentity(() ->
- executor.execute(() ->
- c.onError(errorCode)));
+ long callingIdentity = Binder.clearCallingIdentity();
+ try {
+ executor.execute(() -> c.onError(errorCode));
+ } finally {
+ restoreCallingIdentity(callingIdentity);
+ }
}
};
diff --git a/telephony/java/android/telephony/ims/RegistrationManager.java b/telephony/java/android/telephony/ims/RegistrationManager.java
index 99bb259602e5..ca081ec1ea51 100644
--- a/telephony/java/android/telephony/ims/RegistrationManager.java
+++ b/telephony/java/android/telephony/ims/RegistrationManager.java
@@ -110,42 +110,63 @@ public interface RegistrationManager {
public void onRegistered(int imsRadioTech) {
if (mLocalCallback == null) return;
- Binder.withCleanCallingIdentity(() -> mExecutor.execute(() ->
- mLocalCallback.onRegistered(getAccessType(imsRadioTech))));
+ long callingIdentity = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() ->
+ mLocalCallback.onRegistered(getAccessType(imsRadioTech)));
+ } finally {
+ restoreCallingIdentity(callingIdentity);
+ }
}
@Override
public void onRegistering(int imsRadioTech) {
if (mLocalCallback == null) return;
- Binder.withCleanCallingIdentity(() -> mExecutor.execute(() ->
- mLocalCallback.onRegistering(getAccessType(imsRadioTech))));
+ long callingIdentity = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() ->
+ mLocalCallback.onRegistering(getAccessType(imsRadioTech)));
+ } finally {
+ restoreCallingIdentity(callingIdentity);
+ }
}
@Override
public void onDeregistered(ImsReasonInfo info) {
if (mLocalCallback == null) return;
- Binder.withCleanCallingIdentity(() ->
- mExecutor.execute(() -> mLocalCallback.onUnregistered(info)));
+ long callingIdentity = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() -> mLocalCallback.onUnregistered(info));
+ } finally {
+ restoreCallingIdentity(callingIdentity);
+ }
}
@Override
public void onTechnologyChangeFailed(int imsRadioTech, ImsReasonInfo info) {
if (mLocalCallback == null) return;
- Binder.withCleanCallingIdentity(() ->
- mExecutor.execute(() -> mLocalCallback.onTechnologyChangeFailed(
- getAccessType(imsRadioTech), info)));
+ long callingIdentity = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() -> mLocalCallback.onTechnologyChangeFailed(
+ getAccessType(imsRadioTech), info));
+ } finally {
+ restoreCallingIdentity(callingIdentity);
+ }
}
@Override
public void onSubscriberAssociatedUriChanged(Uri[] uris) {
if (mLocalCallback == null) return;
- Binder.withCleanCallingIdentity(() ->
- mExecutor.execute(() ->
- mLocalCallback.onSubscriberAssociatedUriChanged(uris)));
+ long callingIdentity = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() -> mLocalCallback.onSubscriberAssociatedUriChanged(uris));
+ } finally {
+ restoreCallingIdentity(callingIdentity);
+ }
}
private void setExecutor(Executor executor) {
diff --git a/telephony/java/android/telephony/ims/feature/RcsFeature.java b/telephony/java/android/telephony/ims/feature/RcsFeature.java
index e96d082ca953..0eaf8dc2fd51 100644
--- a/telephony/java/android/telephony/ims/feature/RcsFeature.java
+++ b/telephony/java/android/telephony/ims/feature/RcsFeature.java
@@ -22,7 +22,6 @@ import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.net.Uri;
-import android.os.Binder;
import android.os.RemoteException;
import android.telephony.ims.RcsContactUceCapability;
import android.telephony.ims.aidl.IImsCapabilityCallback;
@@ -33,7 +32,7 @@ import android.telephony.ims.stub.RcsPresenceExchangeImplBase;
import android.telephony.ims.stub.RcsSipOptionsImplBase;
import android.util.Log;
-import com.android.internal.util.FunctionalUtils;
+import com.android.internal.telephony.util.TelephonyUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -43,6 +42,7 @@ import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
+import java.util.function.Supplier;
/**
* Base implementation of the RcsFeature APIs. Any ImsService wishing to support RCS should extend
@@ -150,13 +150,13 @@ public class RcsFeature extends ImsFeature {
// Call the methods with a clean calling identity on the executor and wait indefinitely for
// the future to return.
- private void executeMethodAsync(FunctionalUtils.ThrowingRunnable r, String errorLogName)
+ private void executeMethodAsync(Runnable r, String errorLogName)
throws RemoteException {
// call with a clean calling identity on the executor and wait indefinitely for the
// future to return.
try {
CompletableFuture.runAsync(
- () -> Binder.withCleanCallingIdentity(r), mExecutor).join();
+ () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join();
} catch (CancellationException | CompletionException e) {
Log.w(LOG_TAG, "RcsFeatureBinder - " + errorLogName + " exception: "
+ e.getMessage());
@@ -164,12 +164,12 @@ public class RcsFeature extends ImsFeature {
}
}
- private <T> T executeMethodAsyncForResult(FunctionalUtils.ThrowingSupplier<T> r,
+ private <T> T executeMethodAsyncForResult(Supplier<T> r,
String errorLogName) throws RemoteException {
// call with a clean calling identity on the executor and wait indefinitely for the
// future to return.
CompletableFuture<T> future = CompletableFuture.supplyAsync(
- () -> Binder.withCleanCallingIdentity(r), mExecutor);
+ () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor);
try {
return future.get();
} catch (ExecutionException | InterruptedException e) {
diff --git a/telephony/java/com/android/internal/telephony/util/TelephonyUtils.java b/telephony/java/com/android/internal/telephony/util/TelephonyUtils.java
index a28d65c9abb6..306b9eeca6e3 100644
--- a/telephony/java/com/android/internal/telephony/util/TelephonyUtils.java
+++ b/telephony/java/com/android/internal/telephony/util/TelephonyUtils.java
@@ -26,6 +26,7 @@ import android.os.RemoteException;
import android.os.SystemProperties;
import java.io.PrintWriter;
+import java.util.function.Supplier;
/**
* This class provides various util functions
@@ -71,4 +72,40 @@ public final class TelephonyUtils {
if (resolveInfo.providerInfo != null) return resolveInfo.providerInfo;
throw new IllegalStateException("Missing ComponentInfo!");
}
+
+ /**
+ * Convenience method for running the provided action enclosed in
+ * {@link Binder#clearCallingIdentity}/{@link Binder#restoreCallingIdentity}
+ *
+ * Any exception thrown by the given action will need to be handled by caller.
+ *
+ */
+ public static void runWithCleanCallingIdentity(
+ @NonNull Runnable action) {
+ long callingIdentity = Binder.clearCallingIdentity();
+ try {
+ action.run();
+ } finally {
+ Binder.restoreCallingIdentity(callingIdentity);
+ }
+ }
+
+
+ /**
+ * Convenience method for running the provided action enclosed in
+ * {@link Binder#clearCallingIdentity}/{@link Binder#restoreCallingIdentity} and return
+ * the result.
+ *
+ * Any exception thrown by the given action will need to be handled by caller.
+ *
+ */
+ public static <T> T runWithCleanCallingIdentity(
+ @NonNull Supplier<T> action) {
+ long callingIdentity = Binder.clearCallingIdentity();
+ try {
+ return action.get();
+ } finally {
+ Binder.restoreCallingIdentity(callingIdentity);
+ }
+ }
}
diff --git a/tests/FlickerTests/AndroidTest.xml b/tests/FlickerTests/AndroidTest.xml
index d433df56bc00..d1da47f0f9d8 100644
--- a/tests/FlickerTests/AndroidTest.xml
+++ b/tests/FlickerTests/AndroidTest.xml
@@ -25,6 +25,6 @@
<metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
<option name="directory-keys" value="/sdcard/flicker" />
<option name="collect-on-run-ended-only" value="true" />
- <option name="clean-up" value="false" />
+ <option name="clean-up" value="true" />
</metrics_collector>
</configuration>
diff --git a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
index e30878157a26..ef8facec9752 100644
--- a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
+++ b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
@@ -118,7 +118,8 @@ public class PackageWatchdogTest {
watchdog.startObservingHealth(observer, Arrays.asList(APP_A), SHORT_DURATION);
raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// The failed packages should be the same as the registered ones to ensure registration is
// done successfully
@@ -135,7 +136,8 @@ public class PackageWatchdogTest {
watchdog.startObservingHealth(observer2, Arrays.asList(APP_A, APP_B), SHORT_DURATION);
raiseFatalFailureAndDispatch(watchdog,
Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE),
- new VersionedPackage(APP_B, VERSION_CODE)));
+ new VersionedPackage(APP_B, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// The failed packages should be the same as the registered ones to ensure registration is
// done successfully
@@ -151,7 +153,8 @@ public class PackageWatchdogTest {
watchdog.startObservingHealth(observer, Arrays.asList(APP_A), SHORT_DURATION);
watchdog.unregisterHealthObserver(observer);
raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// We should have no failed packages to ensure unregistration is done successfully
assertThat(observer.mHealthCheckFailedPackages).isEmpty();
@@ -167,7 +170,8 @@ public class PackageWatchdogTest {
watchdog.startObservingHealth(observer2, Arrays.asList(APP_A), SHORT_DURATION);
watchdog.unregisterHealthObserver(observer2);
raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// observer1 should receive failed packages as intended.
assertThat(observer1.mHealthCheckFailedPackages).containsExactly(APP_A);
@@ -183,7 +187,8 @@ public class PackageWatchdogTest {
watchdog.startObservingHealth(observer, Arrays.asList(APP_A), SHORT_DURATION);
moveTimeForwardAndDispatch(SHORT_DURATION);
raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// We should have no failed packages for the fatal failure is raised after expiration
assertThat(observer.mHealthCheckFailedPackages).isEmpty();
@@ -199,7 +204,8 @@ public class PackageWatchdogTest {
watchdog.startObservingHealth(observer2, Arrays.asList(APP_A), LONG_DURATION);
moveTimeForwardAndDispatch(SHORT_DURATION);
raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// We should have no failed packages for the fatal failure is raised after expiration
assertThat(observer1.mHealthCheckFailedPackages).isEmpty();
@@ -226,7 +232,8 @@ public class PackageWatchdogTest {
moveTimeForwardAndDispatch((SHORT_DURATION / 2) + 1);
raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// Verify that we receive failed packages as expected for APP_A not expired
assertThat(observer.mHealthCheckFailedPackages).containsExactly(APP_A);
@@ -252,7 +259,8 @@ public class PackageWatchdogTest {
watchdog2.registerHealthObserver(observer2);
raiseFatalFailureAndDispatch(watchdog2,
Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE),
- new VersionedPackage(APP_B, VERSION_CODE)));
+ new VersionedPackage(APP_B, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// We should receive failed packages as expected to ensure observers are persisted and
// resumed correctly
@@ -274,7 +282,8 @@ public class PackageWatchdogTest {
// Then fail APP_A below the threshold
for (int i = 0; i < watchdog.getTriggerFailureCount() - 1; i++) {
- watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
}
// Run handler so package failures are dispatched to observers
@@ -301,7 +310,8 @@ public class PackageWatchdogTest {
// Then fail APP_C (not observed) above the threshold
raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_C, VERSION_CODE)));
+ Arrays.asList(new VersionedPackage(APP_C, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// Verify that observers are not notified
assertThat(observer1.mHealthCheckFailedPackages).isEmpty();
@@ -331,7 +341,8 @@ public class PackageWatchdogTest {
// Then fail APP_A (different version) above the threshold
raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_A, differentVersionCode)));
+ Arrays.asList(new VersionedPackage(APP_A, differentVersionCode)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// Verify that observers are not notified
assertThat(observer.mHealthCheckFailedPackages).isEmpty();
@@ -368,7 +379,8 @@ public class PackageWatchdogTest {
Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE),
new VersionedPackage(APP_B, VERSION_CODE),
new VersionedPackage(APP_C, VERSION_CODE),
- new VersionedPackage(APP_D, VERSION_CODE)));
+ new VersionedPackage(APP_D, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// Verify least impact observers are notifed of package failures
List<String> observerNonePackages = observerNone.mMitigatedPackages;
@@ -411,7 +423,8 @@ public class PackageWatchdogTest {
// Then fail APP_A above the threshold
raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// Verify only observerFirst is notifed
assertThat(observerFirst.mMitigatedPackages).containsExactly(APP_A);
@@ -424,7 +437,8 @@ public class PackageWatchdogTest {
// Then fail APP_A again above the threshold
raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// Verify only observerSecond is notifed cos it has least impact
assertThat(observerSecond.mMitigatedPackages).containsExactly(APP_A);
@@ -437,7 +451,8 @@ public class PackageWatchdogTest {
// Then fail APP_A again above the threshold
raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// Verify only observerFirst is notifed cos it has the only action
assertThat(observerFirst.mMitigatedPackages).containsExactly(APP_A);
@@ -450,7 +465,8 @@ public class PackageWatchdogTest {
// Then fail APP_A again above the threshold
raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// Verify no observer is notified cos no actions left
assertThat(observerFirst.mMitigatedPackages).isEmpty();
@@ -474,7 +490,8 @@ public class PackageWatchdogTest {
// Then fail APP_A above the threshold
raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// Verify only one observer is notifed
assertThat(observer1.mMitigatedPackages).containsExactly(APP_A);
@@ -746,13 +763,15 @@ public class PackageWatchdogTest {
watchdog.startObservingHealth(observer, Arrays.asList(APP_A), SHORT_DURATION);
// Fail APP_A below the threshold which should not trigger package failures
for (int i = 0; i < PackageWatchdog.DEFAULT_TRIGGER_FAILURE_COUNT - 1; i++) {
- watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
}
mTestLooper.dispatchAll();
assertThat(observer.mHealthCheckFailedPackages).isEmpty();
// One more to trigger the package failure
- watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
mTestLooper.dispatchAll();
assertThat(observer.mHealthCheckFailedPackages).containsExactly(APP_A);
}
@@ -773,20 +792,24 @@ public class PackageWatchdogTest {
TestObserver observer = new TestObserver(OBSERVER_NAME_1);
watchdog.startObservingHealth(observer, Arrays.asList(APP_A, APP_B), Long.MAX_VALUE);
- watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
mTestLooper.dispatchAll();
moveTimeForwardAndDispatch(PackageWatchdog.DEFAULT_TRIGGER_FAILURE_DURATION_MS + 1);
- watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
mTestLooper.dispatchAll();
// We shouldn't receive APP_A since the interval of 2 failures is greater than
// DEFAULT_TRIGGER_FAILURE_DURATION_MS.
assertThat(observer.mHealthCheckFailedPackages).isEmpty();
- watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_B, VERSION_CODE)));
+ watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_B, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
mTestLooper.dispatchAll();
moveTimeForwardAndDispatch(PackageWatchdog.DEFAULT_TRIGGER_FAILURE_DURATION_MS - 1);
- watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_B, VERSION_CODE)));
+ watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_B, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
mTestLooper.dispatchAll();
// We should receive APP_B since the interval of 2 failures is less than
@@ -809,7 +832,8 @@ public class PackageWatchdogTest {
// small timeouts.
moveTimeForwardAndDispatch(PackageWatchdog.DEFAULT_OBSERVING_DURATION_MS - 100);
raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// We should receive APP_A since the observer hasn't expired
assertThat(observer.mHealthCheckFailedPackages).containsExactly(APP_A);
@@ -827,7 +851,8 @@ public class PackageWatchdogTest {
watchdog.startObservingHealth(observer, Arrays.asList(APP_A), -1);
moveTimeForwardAndDispatch(PackageWatchdog.DEFAULT_OBSERVING_DURATION_MS + 1);
raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// We should receive nothing since the observer has expired
assertThat(observer.mHealthCheckFailedPackages).isEmpty();
@@ -850,22 +875,59 @@ public class PackageWatchdogTest {
watchdog.startObservingHealth(observer, Arrays.asList(APP_A), Long.MAX_VALUE);
// Raise 2 failures at t=0 and t=900 respectively
- watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
mTestLooper.dispatchAll();
moveTimeForwardAndDispatch(900);
- watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
mTestLooper.dispatchAll();
// Raise 2 failures at t=1100
moveTimeForwardAndDispatch(200);
- watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
- watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
+ watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
mTestLooper.dispatchAll();
// We should receive APP_A since there are 3 failures within 1000ms window
assertThat(observer.mHealthCheckFailedPackages).containsExactly(APP_A);
}
+ /** Test that observers execute correctly for different failure reasons */
+ @Test
+ public void testFailureReasons() {
+ PackageWatchdog watchdog = createWatchdog();
+ TestObserver observer1 = new TestObserver(OBSERVER_NAME_1);
+ TestObserver observer2 = new TestObserver(OBSERVER_NAME_2);
+ TestObserver observer3 = new TestObserver(OBSERVER_NAME_3);
+ TestObserver observer4 = new TestObserver(OBSERVER_NAME_4);
+
+ watchdog.startObservingHealth(observer1, Arrays.asList(APP_A), SHORT_DURATION);
+ watchdog.startObservingHealth(observer2, Arrays.asList(APP_B), SHORT_DURATION);
+ watchdog.startObservingHealth(observer3, Arrays.asList(APP_C), SHORT_DURATION);
+ watchdog.startObservingHealth(observer4, Arrays.asList(APP_D), SHORT_DURATION);
+
+ raiseFatalFailureAndDispatch(watchdog, Arrays.asList(new VersionedPackage(APP_A,
+ VERSION_CODE)), PackageWatchdog.FAILURE_REASON_NATIVE_CRASH);
+ raiseFatalFailureAndDispatch(watchdog, Arrays.asList(new VersionedPackage(APP_B,
+ VERSION_CODE)), PackageWatchdog.FAILURE_REASON_EXPLICIT_HEALTH_CHECK);
+ raiseFatalFailureAndDispatch(watchdog, Arrays.asList(new VersionedPackage(APP_C,
+ VERSION_CODE)), PackageWatchdog.FAILURE_REASON_APP_CRASH);
+ raiseFatalFailureAndDispatch(watchdog, Arrays.asList(new VersionedPackage(APP_D,
+ VERSION_CODE)), PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING);
+
+ assertThat(observer1.getLastFailureReason()).isEqualTo(
+ PackageWatchdog.FAILURE_REASON_NATIVE_CRASH);
+ assertThat(observer2.getLastFailureReason()).isEqualTo(
+ PackageWatchdog.FAILURE_REASON_EXPLICIT_HEALTH_CHECK);
+ assertThat(observer3.getLastFailureReason()).isEqualTo(
+ PackageWatchdog.FAILURE_REASON_APP_CRASH);
+ assertThat(observer4.getLastFailureReason()).isEqualTo(
+ PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING);
+ }
+
private void adoptShellPermissions(String... permissions) {
InstrumentationRegistry
.getInstrumentation()
@@ -900,9 +962,9 @@ public class PackageWatchdogTest {
/** Trigger package failures above the threshold. */
private void raiseFatalFailureAndDispatch(PackageWatchdog watchdog,
- List<VersionedPackage> packages) {
+ List<VersionedPackage> packages, int failureReason) {
for (int i = 0; i < watchdog.getTriggerFailureCount(); i++) {
- watchdog.onPackageFailure(packages);
+ watchdog.onPackageFailure(packages, failureReason);
}
mTestLooper.dispatchAll();
}
@@ -936,6 +998,7 @@ public class PackageWatchdogTest {
private static class TestObserver implements PackageHealthObserver {
private final String mName;
private int mImpact;
+ private int mLastFailureReason;
final List<String> mHealthCheckFailedPackages = new ArrayList<>();
final List<String> mMitigatedPackages = new ArrayList<>();
@@ -954,14 +1017,19 @@ public class PackageWatchdogTest {
return mImpact;
}
- public boolean execute(VersionedPackage versionedPackage) {
+ public boolean execute(VersionedPackage versionedPackage, int failureReason) {
mMitigatedPackages.add(versionedPackage.getPackageName());
+ mLastFailureReason = failureReason;
return true;
}
public String getName() {
return mName;
}
+
+ public int getLastFailureReason() {
+ return mLastFailureReason;
+ }
}
private static class TestController extends ExplicitHealthCheckController {
diff --git a/tools/aapt2/java/JavaClassGenerator.cpp b/tools/aapt2/java/JavaClassGenerator.cpp
index 6c3bcf039be1..bb541fe2490b 100644
--- a/tools/aapt2/java/JavaClassGenerator.cpp
+++ b/tools/aapt2/java/JavaClassGenerator.cpp
@@ -304,9 +304,11 @@ void JavaClassGenerator::ProcessStyleable(const ResourceNameRef& name, const Res
auto documentation_remove_iter = std::remove_if(documentation_attrs.begin(),
documentation_attrs.end(),
[&](StyleableAttr entry) -> bool {
- StringPiece attr_comment_line = entry.symbol.value().attribute->GetComment();
- return SkipSymbol(entry.symbol) || attr_comment_line.contains("@removed")
- || attr_comment_line.contains("@hide");
+ if (SkipSymbol(entry.symbol)) {
+ return true;
+ }
+ const StringPiece attr_comment_line = entry.symbol.value().attribute->GetComment();
+ return attr_comment_line.contains("@removed") || attr_comment_line.contains("@hide");
});
documentation_attrs.erase(documentation_remove_iter, documentation_attrs.end());
diff --git a/tools/stats_log_api_gen/java_writer.cpp b/tools/stats_log_api_gen/java_writer.cpp
index 4899fbd3b669..d45c4e7efb12 100644
--- a/tools/stats_log_api_gen/java_writer.cpp
+++ b/tools/stats_log_api_gen/java_writer.cpp
@@ -83,7 +83,7 @@ static int write_java_methods(
// Print method body.
string indent("");
if (DEFAULT_MODULE_NAME != moduleName) {
- fprintf(out, " if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {\n");
+ fprintf(out, " if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) {\n");
indent = " ";
}
@@ -116,16 +116,19 @@ static int write_java_methods(
fprintf(out, "%s builder.writeString(arg%d);\n", indent.c_str(), argIndex);
break;
case JAVA_TYPE_BYTE_ARRAY:
- fprintf(out, "%s builder.writeByteArray(arg%d);\n",
- indent.c_str(), argIndex);
+ fprintf(out, "%s builder.writeByteArray(null == arg%d ? new byte[0] : arg%d);\n",
+ indent.c_str(), argIndex, argIndex);
break;
case JAVA_TYPE_ATTRIBUTION_CHAIN:
{
const char* uidName = attributionDecl.fields.front().name.c_str();
const char* tagName = attributionDecl.fields.back().name.c_str();
- fprintf(out, "%s builder.writeAttributionChain(%s, %s);\n",
- indent.c_str(), uidName, tagName);
+ fprintf(out, "%s builder.writeAttributionChain(\n", indent.c_str());
+ fprintf(out, "%s null == %s ? new int[0] : %s,\n",
+ indent.c_str(), uidName, uidName);
+ fprintf(out, "%s null == %s ? new String[0] : %s);\n",
+ indent.c_str(), tagName, tagName);
break;
}
case JAVA_TYPE_KEY_VALUE_PAIR:
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index fccbcf7c101f..b52880e29e30 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -44,7 +44,6 @@ import android.net.wifi.WifiNetworkSuggestion;
import android.os.Messenger;
import android.os.ResultReceiver;
import android.os.WorkSource;
-import android.os.connectivity.WifiActivityEnergyInfo;
/**
* Interface that allows controlling and querying Wi-Fi connectivity.
@@ -55,8 +54,6 @@ interface IWifiManager
{
long getSupportedFeatures();
- WifiActivityEnergyInfo reportActivityInfo();
-
oneway void getWifiActivityEnergyInfoAsync(in IOnWifiActivityEnergyInfoListener listener);
ParceledListSlice getConfiguredNetworks(String packageName, String featureId);
diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index f3f873b4ead8..f728491d33cd 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -21,7 +21,7 @@ import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.UnsupportedAppUsage;
import android.net.NetworkInfo.DetailedState;
-import android.net.NetworkUtils;
+import android.net.shared.Inet4AddressUtils;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
@@ -708,7 +708,7 @@ public class WifiInfo implements Parcelable {
public int getIpAddress() {
int result = 0;
if (mIpAddress instanceof Inet4Address) {
- result = NetworkUtils.inetAddressToInt((Inet4Address)mIpAddress);
+ result = Inet4AddressUtils.inet4AddressToIntHTL((Inet4Address) mIpAddress);
}
return result;
}
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 0108d5aa936c..86c398b770b7 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -2379,25 +2379,6 @@ public class WifiManager {
}
/**
- * Return the record of {@link WifiActivityEnergyInfo} object that
- * has the activity and energy info. This can be used to ascertain what
- * the controller has been up to, since the last sample.
- *
- * @return a record with {@link WifiActivityEnergyInfo} or null if
- * report is unavailable or unsupported
- * @hide
- */
- public WifiActivityEnergyInfo getControllerActivityEnergyInfo() {
- try {
- synchronized(this) {
- return mService.reportActivityInfo();
- }
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
* Interface for Wi-Fi activity energy info listener. Should be implemented by applications and
* set when calling {@link WifiManager#getWifiActivityEnergyInfoAsync}.
*
diff --git a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
index e78104d3da38..9fd29ae8d14a 100644
--- a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
+++ b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
@@ -23,12 +23,10 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
-import android.app.ActivityThread;
import android.net.MacAddress;
import android.net.wifi.hotspot2.PasspointConfiguration;
import android.os.Parcel;
import android.os.Parcelable;
-import android.os.Process;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
@@ -46,7 +44,6 @@ import java.util.Objects;
* {@link WifiManager#addNetworkSuggestions(List)}.
*/
public final class WifiNetworkSuggestion implements Parcelable {
-
/**
* Builder used to create {@link WifiNetworkSuggestion} objects.
*/
@@ -563,9 +560,7 @@ public final class WifiNetworkSuggestion implements Parcelable {
mPasspointConfiguration,
mIsAppInteractionRequired,
mIsUserInteractionRequired,
- mIsUserAllowed,
- Process.myUid(),
- ActivityThread.currentApplication().getApplicationContext().getOpPackageName());
+ mIsUserAllowed);
}
}
@@ -592,19 +587,6 @@ public final class WifiNetworkSuggestion implements Parcelable {
* @hide
*/
public final boolean isUserInteractionRequired;
-
- /**
- * The UID of the process initializing this network suggestion.
- * @hide
- */
- public final int suggestorUid;
-
- /**
- * The package name of the process initializing this network suggestion.
- * @hide
- */
- public final String suggestorPackageName;
-
/**
* Whether app share credential with the user, allow user use provided credential to
* connect network manually.
@@ -619,8 +601,6 @@ public final class WifiNetworkSuggestion implements Parcelable {
this.isAppInteractionRequired = false;
this.isUserInteractionRequired = false;
this.isUserAllowedToManuallyConnect = true;
- this.suggestorUid = -1;
- this.suggestorPackageName = null;
}
/** @hide */
@@ -628,18 +608,14 @@ public final class WifiNetworkSuggestion implements Parcelable {
@Nullable PasspointConfiguration passpointConfiguration,
boolean isAppInteractionRequired,
boolean isUserInteractionRequired,
- boolean isUserAllowedToManuallyConnect,
- int suggestorUid, @NonNull String suggestorPackageName) {
+ boolean isUserAllowedToManuallyConnect) {
checkNotNull(networkConfiguration);
- checkNotNull(suggestorPackageName);
this.wifiConfiguration = networkConfiguration;
this.passpointConfiguration = passpointConfiguration;
this.isAppInteractionRequired = isAppInteractionRequired;
this.isUserInteractionRequired = isUserInteractionRequired;
this.isUserAllowedToManuallyConnect = isUserAllowedToManuallyConnect;
- this.suggestorUid = suggestorUid;
- this.suggestorPackageName = suggestorPackageName;
}
public static final @NonNull Creator<WifiNetworkSuggestion> CREATOR =
@@ -651,9 +627,7 @@ public final class WifiNetworkSuggestion implements Parcelable {
in.readParcelable(null), // PasspointConfiguration
in.readBoolean(), // isAppInteractionRequired
in.readBoolean(), // isUserInteractionRequired
- in.readBoolean(), // isSharedCredentialWithUser
- in.readInt(), // suggestorUid
- in.readString() // suggestorPackageName
+ in.readBoolean() // isSharedCredentialWithUser
);
}
@@ -675,15 +649,12 @@ public final class WifiNetworkSuggestion implements Parcelable {
dest.writeBoolean(isAppInteractionRequired);
dest.writeBoolean(isUserInteractionRequired);
dest.writeBoolean(isUserAllowedToManuallyConnect);
- dest.writeInt(suggestorUid);
- dest.writeString(suggestorPackageName);
}
@Override
public int hashCode() {
return Objects.hash(wifiConfiguration.SSID, wifiConfiguration.BSSID,
- wifiConfiguration.allowedKeyManagement, wifiConfiguration.FQDN,
- suggestorUid, suggestorPackageName);
+ wifiConfiguration.allowedKeyManagement, wifiConfiguration.FQDN);
}
/**
@@ -706,23 +677,19 @@ public final class WifiNetworkSuggestion implements Parcelable {
&& TextUtils.equals(this.wifiConfiguration.BSSID, lhs.wifiConfiguration.BSSID)
&& Objects.equals(this.wifiConfiguration.allowedKeyManagement,
lhs.wifiConfiguration.allowedKeyManagement)
- && TextUtils.equals(this.wifiConfiguration.FQDN, lhs.wifiConfiguration.FQDN)
- && this.suggestorUid == lhs.suggestorUid
- && TextUtils.equals(this.suggestorPackageName, lhs.suggestorPackageName);
+ && TextUtils.equals(this.wifiConfiguration.FQDN, lhs.wifiConfiguration.FQDN);
}
@Override
public String toString() {
- StringBuilder sb = new StringBuilder("WifiNetworkSuggestion [")
- .append(", SSID=").append(wifiConfiguration.SSID)
+ StringBuilder sb = new StringBuilder("WifiNetworkSuggestion[ ")
+ .append("SSID=").append(wifiConfiguration.SSID)
.append(", BSSID=").append(wifiConfiguration.BSSID)
.append(", FQDN=").append(wifiConfiguration.FQDN)
.append(", isAppInteractionRequired=").append(isAppInteractionRequired)
.append(", isUserInteractionRequired=").append(isUserInteractionRequired)
.append(", isUserAllowedToManuallyConnect=").append(isUserAllowedToManuallyConnect)
- .append(", suggestorUid=").append(suggestorUid)
- .append(", suggestorPackageName=").append(suggestorPackageName)
- .append("]");
+ .append(" ]");
return sb.toString();
}
}
diff --git a/wifi/java/android/net/wifi/aware/PublishConfig.java b/wifi/java/android/net/wifi/aware/PublishConfig.java
index 1886b7ef4c8d..a8844c1d3812 100644
--- a/wifi/java/android/net/wifi/aware/PublishConfig.java
+++ b/wifi/java/android/net/wifi/aware/PublishConfig.java
@@ -19,11 +19,10 @@ package android.net.wifi.aware;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.net.wifi.util.HexEncoding;
import android.os.Parcel;
import android.os.Parcelable;
-import libcore.util.HexEncoding;
-
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.nio.charset.StandardCharsets;
diff --git a/wifi/java/android/net/wifi/aware/SubscribeConfig.java b/wifi/java/android/net/wifi/aware/SubscribeConfig.java
index f0f758170bf2..76780f421af2 100644
--- a/wifi/java/android/net/wifi/aware/SubscribeConfig.java
+++ b/wifi/java/android/net/wifi/aware/SubscribeConfig.java
@@ -19,11 +19,10 @@ package android.net.wifi.aware;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.net.wifi.util.HexEncoding;
import android.os.Parcel;
import android.os.Parcelable;
-import libcore.util.HexEncoding;
-
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.nio.charset.StandardCharsets;
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareAgentNetworkSpecifier.java b/wifi/java/android/net/wifi/aware/WifiAwareAgentNetworkSpecifier.java
index 5ec4c8b13ee8..c66733472d0e 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareAgentNetworkSpecifier.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareAgentNetworkSpecifier.java
@@ -17,12 +17,11 @@
package android.net.wifi.aware;
import android.net.NetworkSpecifier;
+import android.net.wifi.util.HexEncoding;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
-import libcore.util.HexEncoding;
-
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareManager.java b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
index 7b37d652426d..81bf81e40199 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareManager.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
@@ -19,6 +19,7 @@ package android.net.wifi.aware;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemService;
@@ -26,6 +27,7 @@ import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkRequest;
import android.net.NetworkSpecifier;
+import android.net.wifi.util.HexEncoding;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
@@ -36,8 +38,6 @@ import android.os.Process;
import android.os.RemoteException;
import android.util.Log;
-import libcore.util.HexEncoding;
-
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
@@ -397,6 +397,17 @@ public class WifiAwareManager {
}
/** @hide */
+ @RequiresPermission(android.Manifest.permission.NETWORK_STACK)
+ public void requestMacAddresses(int uid, List<Integer> peerIds,
+ IWifiAwareMacAddressProvider callback) {
+ try {
+ mService.requestMacAddresses(uid, peerIds, callback);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /** @hide */
public NetworkSpecifier createNetworkSpecifier(int clientId, int role, int sessionId,
@NonNull PeerHandle peerHandle, @Nullable byte[] pmk, @Nullable String passphrase) {
if (VDBG) {
diff --git a/wifi/java/android/net/wifi/util/HexEncoding.java b/wifi/java/android/net/wifi/util/HexEncoding.java
new file mode 100644
index 000000000000..9ebf947e2dc3
--- /dev/null
+++ b/wifi/java/android/net/wifi/util/HexEncoding.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2014 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.net.wifi.util;
+
+/**
+ * Hexadecimal encoding where each byte is represented by two hexadecimal digits.
+ *
+ * Note: this is copied from {@link libcore.util.HexEncoding}.
+ *
+ * @hide
+ */
+public class HexEncoding {
+
+ private static final char[] LOWER_CASE_DIGITS = {
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
+ };
+
+ private static final char[] UPPER_CASE_DIGITS = {
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
+ };
+
+ /** Hidden constructor to prevent instantiation. */
+ private HexEncoding() {}
+
+ /**
+ * Encodes the provided byte as a two-digit hexadecimal String value.
+ */
+ public static String encodeToString(byte b, boolean upperCase) {
+ char[] digits = upperCase ? UPPER_CASE_DIGITS : LOWER_CASE_DIGITS;
+ char[] buf = new char[2]; // We always want two digits.
+ buf[0] = digits[(b >> 4) & 0xf];
+ buf[1] = digits[b & 0xf];
+ return new String(buf, 0, 2);
+ }
+
+ /**
+ * Encodes the provided data as a sequence of hexadecimal characters.
+ */
+ public static char[] encode(byte[] data) {
+ return encode(data, 0, data.length, true /* upperCase */);
+ }
+
+ /**
+ * Encodes the provided data as a sequence of hexadecimal characters.
+ */
+ public static char[] encode(byte[] data, boolean upperCase) {
+ return encode(data, 0, data.length, upperCase);
+ }
+
+ /**
+ * Encodes the provided data as a sequence of hexadecimal characters.
+ */
+ public static char[] encode(byte[] data, int offset, int len) {
+ return encode(data, offset, len, true /* upperCase */);
+ }
+
+ /**
+ * Encodes the provided data as a sequence of hexadecimal characters.
+ */
+ private static char[] encode(byte[] data, int offset, int len, boolean upperCase) {
+ char[] digits = upperCase ? UPPER_CASE_DIGITS : LOWER_CASE_DIGITS;
+ char[] result = new char[len * 2];
+ for (int i = 0; i < len; i++) {
+ byte b = data[offset + i];
+ int resultIndex = 2 * i;
+ result[resultIndex] = (digits[(b >> 4) & 0x0f]);
+ result[resultIndex + 1] = (digits[b & 0x0f]);
+ }
+
+ return result;
+ }
+
+ /**
+ * Encodes the provided data as a sequence of hexadecimal characters.
+ */
+ public static String encodeToString(byte[] data) {
+ return encodeToString(data, true /* upperCase */);
+ }
+
+ /**
+ * Encodes the provided data as a sequence of hexadecimal characters.
+ */
+ public static String encodeToString(byte[] data, boolean upperCase) {
+ return new String(encode(data, upperCase));
+ }
+
+ /**
+ * Decodes the provided hexadecimal string into a byte array. Odd-length inputs
+ * are not allowed.
+ *
+ * Throws an {@code IllegalArgumentException} if the input is malformed.
+ */
+ public static byte[] decode(String encoded) throws IllegalArgumentException {
+ return decode(encoded.toCharArray());
+ }
+
+ /**
+ * Decodes the provided hexadecimal string into a byte array. If {@code allowSingleChar}
+ * is {@code true} odd-length inputs are allowed and the first character is interpreted
+ * as the lower bits of the first result byte.
+ *
+ * Throws an {@code IllegalArgumentException} if the input is malformed.
+ */
+ public static byte[] decode(String encoded, boolean allowSingleChar)
+ throws IllegalArgumentException {
+ return decode(encoded.toCharArray(), allowSingleChar);
+ }
+
+ /**
+ * Decodes the provided hexadecimal string into a byte array. Odd-length inputs
+ * are not allowed.
+ *
+ * Throws an {@code IllegalArgumentException} if the input is malformed.
+ */
+ public static byte[] decode(char[] encoded) throws IllegalArgumentException {
+ return decode(encoded, false);
+ }
+
+ /**
+ * Decodes the provided hexadecimal string into a byte array. If {@code allowSingleChar}
+ * is {@code true} odd-length inputs are allowed and the first character is interpreted
+ * as the lower bits of the first result byte.
+ *
+ * Throws an {@code IllegalArgumentException} if the input is malformed.
+ */
+ public static byte[] decode(char[] encoded, boolean allowSingleChar)
+ throws IllegalArgumentException {
+ int encodedLength = encoded.length;
+ int resultLengthBytes = (encodedLength + 1) / 2;
+ byte[] result = new byte[resultLengthBytes];
+
+ int resultOffset = 0;
+ int i = 0;
+ if (allowSingleChar) {
+ if ((encodedLength % 2) != 0) {
+ // Odd number of digits -- the first digit is the lower 4 bits of the first result
+ // byte.
+ result[resultOffset++] = (byte) toDigit(encoded, i);
+ i++;
+ }
+ } else {
+ if ((encodedLength % 2) != 0) {
+ throw new IllegalArgumentException("Invalid input length: " + encodedLength);
+ }
+ }
+
+ for (; i < encodedLength; i += 2) {
+ result[resultOffset++] = (byte) ((toDigit(encoded, i) << 4) | toDigit(encoded, i + 1));
+ }
+
+ return result;
+ }
+
+ private static int toDigit(char[] str, int offset) throws IllegalArgumentException {
+ // NOTE: that this isn't really a code point in the traditional sense, since we're
+ // just rejecting surrogate pairs outright.
+ int pseudoCodePoint = str[offset];
+
+ if ('0' <= pseudoCodePoint && pseudoCodePoint <= '9') {
+ return pseudoCodePoint - '0';
+ } else if ('a' <= pseudoCodePoint && pseudoCodePoint <= 'f') {
+ return 10 + (pseudoCodePoint - 'a');
+ } else if ('A' <= pseudoCodePoint && pseudoCodePoint <= 'F') {
+ return 10 + (pseudoCodePoint - 'A');
+ }
+
+ throw new IllegalArgumentException("Illegal char: " + str[offset] + " at offset " + offset);
+ }
+}
diff --git a/wifi/java/com/android/server/wifi/BaseWifiService.java b/wifi/java/com/android/server/wifi/BaseWifiService.java
index 367cfa069e74..2c27037d29aa 100644
--- a/wifi/java/com/android/server/wifi/BaseWifiService.java
+++ b/wifi/java/com/android/server/wifi/BaseWifiService.java
@@ -76,11 +76,14 @@ public class BaseWifiService extends IWifiManager.Stub {
throw new UnsupportedOperationException();
}
- @Override
+ /** @deprecated use {@link #getWifiActivityEnergyInfoAsync} instead */
+ @Deprecated
public WifiActivityEnergyInfo reportActivityInfo() {
throw new UnsupportedOperationException();
}
+ /** @deprecated use {@link #getWifiActivityEnergyInfoAsync} instead */
+ @Deprecated
public void requestActivityInfo(ResultReceiver result) {
throw new UnsupportedOperationException();
}
diff --git a/wifi/tests/src/android/net/wifi/WifiManagerTest.java b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
index de4514997b1c..f92d38c982b8 100644
--- a/wifi/tests/src/android/net/wifi/WifiManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
@@ -161,7 +161,7 @@ public class WifiManagerTest {
mRunnable.run();
}
};
- mWifiActivityEnergyInfo = new WifiActivityEnergyInfo(0, 0, 0, 0, 0, 0, 0);
+ mWifiActivityEnergyInfo = new WifiActivityEnergyInfo(0, 0, 0, 0, 0, 0);
}
/**
@@ -1708,18 +1708,6 @@ public class WifiManagerTest {
}
/**
- * Test behavior of {@link WifiManager#getControllerActivityEnergyInfo()}
- */
- @Test
- public void testGetControllerActivityEnergyInfo() throws Exception {
- WifiActivityEnergyInfo activityEnergyInfo =
- new WifiActivityEnergyInfo(5, 3, 3, 5, 5, 5, 5);
- when(mWifiService.reportActivityInfo()).thenReturn(activityEnergyInfo);
-
- assertEquals(activityEnergyInfo, mWifiManager.getControllerActivityEnergyInfo());
- }
-
- /**
* Tests that passing a null Executor to {@link WifiManager#getWifiActivityEnergyInfoAsync}
* throws an exception.
*/
diff --git a/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java b/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
index 8a5a0fd6805b..04aaa0bbcad0 100644
--- a/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
@@ -22,7 +22,6 @@ import android.net.MacAddress;
import android.net.wifi.hotspot2.PasspointConfiguration;
import android.net.wifi.hotspot2.PasspointTestUtils;
import android.os.Parcel;
-import android.os.Process;
import androidx.test.filters.SmallTest;
@@ -35,8 +34,6 @@ import org.junit.Test;
public class WifiNetworkSuggestionTest {
private static final int TEST_UID = 45677;
private static final int TEST_UID_OTHER = 45673;
- private static final String TEST_PACKAGE_NAME = "com.test.packagename";
- private static final String TEST_PACKAGE_NAME_OTHER = "com.test.packagenameother";
private static final String TEST_SSID = "\"Test123\"";
private static final String TEST_BSSID = "12:12:12:12:12:12";
private static final String TEST_SSID_1 = "\"Test1234\"";
@@ -55,7 +52,6 @@ public class WifiNetworkSuggestionTest {
.setIsAppInteractionRequired(true)
.build();
- assertEquals(Process.myUid(), suggestion.suggestorUid);
assertEquals("\"" + TEST_SSID + "\"", suggestion.wifiConfiguration.SSID);
assertTrue(suggestion.wifiConfiguration.allowedKeyManagement
.get(WifiConfiguration.KeyMgmt.NONE));
@@ -448,7 +444,7 @@ public class WifiNetworkSuggestionTest {
configuration.BSSID = TEST_BSSID;
configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion(
- configuration, null, false, true, true, TEST_UID, TEST_PACKAGE_NAME);
+ configuration, null, false, true, true);
Parcel parcelW = Parcel.obtain();
suggestion.writeToParcel(parcelW, 0);
@@ -515,16 +511,14 @@ public class WifiNetworkSuggestionTest {
configuration.BSSID = TEST_BSSID;
configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
WifiNetworkSuggestion suggestion =
- new WifiNetworkSuggestion(configuration, null, true, false, true, TEST_UID,
- TEST_PACKAGE_NAME);
+ new WifiNetworkSuggestion(configuration, null, true, false, true);
WifiConfiguration configuration1 = new WifiConfiguration();
configuration1.SSID = TEST_SSID;
configuration1.BSSID = TEST_BSSID;
configuration1.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
WifiNetworkSuggestion suggestion1 =
- new WifiNetworkSuggestion(configuration1, null, false, true, true, TEST_UID,
- TEST_PACKAGE_NAME);
+ new WifiNetworkSuggestion(configuration1, null, false, true, true);
assertEquals(suggestion, suggestion1);
assertEquals(suggestion.hashCode(), suggestion1.hashCode());
@@ -540,15 +534,13 @@ public class WifiNetworkSuggestionTest {
configuration.SSID = TEST_SSID;
configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
WifiNetworkSuggestion suggestion =
- new WifiNetworkSuggestion(configuration, null, false, false, true, TEST_UID,
- TEST_PACKAGE_NAME);
+ new WifiNetworkSuggestion(configuration, null, false, false, true);
WifiConfiguration configuration1 = new WifiConfiguration();
configuration1.SSID = TEST_SSID_1;
configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
WifiNetworkSuggestion suggestion1 =
- new WifiNetworkSuggestion(configuration1, null, false, false, true, TEST_UID,
- TEST_PACKAGE_NAME);
+ new WifiNetworkSuggestion(configuration1, null, false, false, true);
assertNotEquals(suggestion, suggestion1);
}
@@ -564,15 +556,13 @@ public class WifiNetworkSuggestionTest {
configuration.BSSID = TEST_BSSID;
configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
WifiNetworkSuggestion suggestion =
- new WifiNetworkSuggestion(configuration, null, false, false, true, TEST_UID,
- TEST_PACKAGE_NAME);
+ new WifiNetworkSuggestion(configuration, null, false, false, true);
WifiConfiguration configuration1 = new WifiConfiguration();
configuration1.SSID = TEST_SSID;
configuration1.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
WifiNetworkSuggestion suggestion1 =
- new WifiNetworkSuggestion(configuration1, null, false, false, true, TEST_UID,
- TEST_PACKAGE_NAME);
+ new WifiNetworkSuggestion(configuration1, null, false, false, true);
assertNotEquals(suggestion, suggestion1);
}
@@ -587,57 +577,18 @@ public class WifiNetworkSuggestionTest {
configuration.SSID = TEST_SSID;
configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
WifiNetworkSuggestion suggestion =
- new WifiNetworkSuggestion(configuration, null, false, false, true, TEST_UID,
- TEST_PACKAGE_NAME);
+ new WifiNetworkSuggestion(configuration, null, false, false, true);
WifiConfiguration configuration1 = new WifiConfiguration();
configuration1.SSID = TEST_SSID;
configuration1.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
WifiNetworkSuggestion suggestion1 =
- new WifiNetworkSuggestion(configuration1, null, false, false, true, TEST_UID,
- TEST_PACKAGE_NAME);
+ new WifiNetworkSuggestion(configuration1, null, false, false, true);
assertNotEquals(suggestion, suggestion1);
}
/**
- * Check NetworkSuggestion equals returns {@code false} for 2 network suggestions with the same
- * SSID, BSSID and key mgmt, but different UID.
- */
- @Test
- public void testWifiNetworkSuggestionEqualsFailsWhenUidIsDifferent() {
- WifiConfiguration configuration = new WifiConfiguration();
- configuration.SSID = TEST_SSID;
- configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
- WifiNetworkSuggestion suggestion =
- new WifiNetworkSuggestion(configuration, null, false, false, true, TEST_UID,
- TEST_PACKAGE_NAME);
-
- WifiNetworkSuggestion suggestion1 =
- new WifiNetworkSuggestion(configuration, null, false, false, true, TEST_UID_OTHER,
- TEST_PACKAGE_NAME);
-
- assertNotEquals(suggestion, suggestion1);
- }
-
- /**
- * Check NetworkSuggestion equals returns {@code false} for 2 network suggestions with the same
- * SSID, BSSID and key mgmt, but different package name.
- */
- @Test
- public void testWifiNetworkSuggestionEqualsFailsWhenPackageNameIsDifferent() {
- WifiConfiguration configuration = new WifiConfiguration();
- configuration.SSID = TEST_SSID;
- configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
- WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion(
- configuration, null, false, false, true, TEST_UID, TEST_PACKAGE_NAME);
-
- WifiNetworkSuggestion suggestion1 = new WifiNetworkSuggestion(
- configuration, null, false, false, true, TEST_UID, TEST_PACKAGE_NAME_OTHER);
-
- assertNotEquals(suggestion, suggestion1);
- }
- /**
* Check NetworkSuggestion equals returns {@code true} for 2 Passpoint network suggestions with
* same FQDN.
*/
diff --git a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
index 3483ff8a4664..200c0e31cb22 100644
--- a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
@@ -36,6 +36,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.net.MacAddress;
import android.net.wifi.RttManager;
+import android.net.wifi.util.HexEncoding;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
@@ -44,8 +45,6 @@ import android.os.test.TestLooper;
import androidx.test.filters.SmallTest;
-import libcore.util.HexEncoding;
-
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
diff --git a/wifi/tests/src/android/net/wifi/util/HexEncodingTest.java b/wifi/tests/src/android/net/wifi/util/HexEncodingTest.java
new file mode 100644
index 000000000000..0d751389e244
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/util/HexEncodingTest.java
@@ -0,0 +1,130 @@
+/*
+ * 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.net.wifi.util;
+
+import static android.net.wifi.util.HexEncoding.decode;
+import static android.net.wifi.util.HexEncoding.encode;
+import static android.net.wifi.util.HexEncoding.encodeToString;
+
+import junit.framework.TestCase;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.Locale;
+
+/** Copied from {@link libcore.libcore.util.HexEncodingTest}. */
+public class HexEncodingTest extends TestCase {
+
+ public void testEncodeByte() {
+ Object[][] testCases = new Object[][]{
+ {0x01, "01"},
+ {0x09, "09"},
+ {0x0A, "0A"},
+ {0x0F, "0F"},
+ {0x10, "10"},
+ {0x1F, "1F"},
+ {0x20, "20"},
+ {0x7F, "7F"},
+ {0x80, "80"},
+ {0xFF, "FF"},
+ };
+ for (Object[] testCase : testCases) {
+ Number toEncode = (Number) testCase[0];
+ String expected = (String) testCase[1];
+
+ String actualUpper = encodeToString(toEncode.byteValue(), true /* upperCase */);
+ assertEquals(upper(expected), actualUpper);
+
+ String actualLower = encodeToString(toEncode.byteValue(), false /* upperCase */);
+ assertEquals(lower(expected), actualLower);
+ }
+ }
+
+ public void testEncodeBytes() {
+ Object[][] testCases = new Object[][]{
+ {"avocados".getBytes(StandardCharsets.UTF_8), "61766F6361646F73"},
+ };
+
+ for (Object[] testCase : testCases) {
+ byte[] bytes = (byte[]) testCase[0];
+ String encodedLower = lower((String) testCase[1]);
+ String encodedUpper = upper((String) testCase[1]);
+
+ assertArraysEqual(encodedUpper.toCharArray(), encode(bytes));
+ assertArraysEqual(encodedUpper.toCharArray(), encode(bytes, true /* upperCase */));
+ assertArraysEqual(encodedLower.toCharArray(), encode(bytes, false /* upperCase */));
+
+ assertArraysEqual(bytes, decode(encode(bytes), false /* allowSingleChar */));
+
+ // Make sure we can handle lower case hex encodings as well.
+ assertArraysEqual(bytes,
+ decode(encodedLower.toCharArray(), false /* allowSingleChar */));
+ }
+ }
+
+ public void testDecode_allow4Bit() {
+ assertArraysEqual(new byte[]{6}, decode("6".toCharArray(), true));
+ assertArraysEqual(new byte[]{6, 0x76}, decode("676".toCharArray(), true));
+ }
+
+ public void testDecode_disallow4Bit() {
+ try {
+ decode("676".toCharArray(), false /* allowSingleChar */);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testDecode_invalid() {
+ try {
+ decode("DEADBARD".toCharArray(), false /* allowSingleChar */);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+
+ // This demonstrates a difference in behaviour from apache commons : apache
+ // commons uses Character.isDigit and would successfully decode a string with
+ // arabic and devanagari characters.
+ try {
+ decode("६१٧٥٥F6361646F73".toCharArray(), false /* allowSingleChar */);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+
+ try {
+ decode("#%6361646F73".toCharArray(), false /* allowSingleChar */);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ private static void assertArraysEqual(char[] lhs, char[] rhs) {
+ assertEquals(new String(lhs), new String(rhs));
+ }
+
+ private static void assertArraysEqual(byte[] lhs, byte[] rhs) {
+ assertEquals(Arrays.toString(lhs), Arrays.toString(rhs));
+ }
+
+ private static String lower(String string) {
+ return string.toLowerCase(Locale.ROOT);
+ }
+
+ private static String upper(String string) {
+ return string.toUpperCase(Locale.ROOT);
+ }
+}