summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp2
-rw-r--r--apex/appsearch/framework/Android.bp29
-rw-r--r--apex/appsearch/service/Android.bp1
-rw-r--r--apex/jobscheduler/service/java/com/android/server/TEST_MAPPING22
-rw-r--r--apex/jobscheduler/service/java/com/android/server/deviceidle/TEST_MAPPING19
-rw-r--r--apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java4
-rw-r--r--apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java26
-rw-r--r--apex/jobscheduler/service/java/com/android/server/usage/TEST_MAPPING19
-rw-r--r--apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java214
-rw-r--r--api/current.txt4
-rw-r--r--api/module-lib-current.txt80
-rwxr-xr-xapi/system-current.txt97
-rw-r--r--api/test-current.txt2
-rw-r--r--cmds/statsd/src/atoms.proto37
-rw-r--r--cmds/statsd/src/external/StatsPullerManager.cpp29
-rw-r--r--core/java/android/accounts/AccountManager.java76
-rw-r--r--core/java/android/accounts/IAccountManager.aidl3
-rw-r--r--core/java/android/app/ActivityManager.java23
-rw-r--r--core/java/android/app/IActivityManager.aidl10
-rw-r--r--core/java/android/app/SystemServiceRegistry.java8
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java12
-rw-r--r--core/java/android/app/timedetector/PhoneTimeSuggestion.java44
-rw-r--r--core/java/android/app/timedetector/TimeDetector.java11
-rw-r--r--core/java/android/app/timezonedetector/PhoneTimeZoneSuggestion.java66
-rw-r--r--core/java/android/app/timezonedetector/TimeZoneDetector.java11
-rw-r--r--core/java/android/app/usage/UsageStatsManager.java22
-rw-r--r--core/java/android/content/Context.java4
-rw-r--r--core/java/android/net/ConnectivityManager.java10
-rw-r--r--core/java/android/net/IConnectivityManager.aidl2
-rw-r--r--core/java/android/net/NattKeepalivePacketData.java16
-rw-r--r--core/java/android/net/NetworkAgent.java9
-rw-r--r--core/java/android/net/NetworkAgentConfig.java104
-rw-r--r--core/java/android/net/NetworkScoreManager.java31
-rw-r--r--core/java/android/os/TimestampedValue.java13
-rw-r--r--core/java/android/provider/Settings.java36
-rw-r--r--core/java/android/util/FeatureFlagUtils.java3
-rw-r--r--core/java/android/view/ViewRootImpl.java6
-rw-r--r--core/java/android/view/inputmethod/InlineSuggestionsRequest.java82
-rw-r--r--core/java/android/widget/Editor.java2
-rw-r--r--core/jni/Android.bp2
-rw-r--r--core/jni/android/graphics/apex/android_bitmap.cpp92
-rw-r--r--core/jni/android/graphics/apex/include/android/graphics/bitmap.h5
-rw-r--r--core/jni/com_android_internal_os_Zygote.cpp104
-rw-r--r--core/res/AndroidManifest.xml2
-rw-r--r--core/tests/coretests/src/android/widget/EditorCursorDragTest.java18
-rw-r--r--core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java10
-rw-r--r--core/tests/coretests/src/android/widget/espresso/MouseUiController.java2
-rw-r--r--media/java/android/media/IMediaRoute2ProviderClient.aidl10
-rw-r--r--media/java/android/media/MediaRoute2ProviderService.java200
-rw-r--r--media/java/android/media/MediaTranscodeManager.java403
-rw-r--r--media/java/android/media/audiopolicy/AudioPolicy.java20
-rw-r--r--media/java/android/media/tv/tuner/Tuner.java50
-rw-r--r--media/java/android/media/tv/tuner/TunerConstants.java23
-rw-r--r--media/java/android/media/tv/tuner/filter/FilterConfiguration.java4
-rw-r--r--media/java/android/media/tv/tuner/filter/PesSettings.java30
-rw-r--r--media/java/android/media/tv/tuner/filter/Settings.java3
-rw-r--r--media/java/android/media/tv/tuner/filter/TsFilterConfiguration.java29
-rw-r--r--media/java/android/media/tv/tuner/frontend/FrontendCallback.java6
-rw-r--r--media/java/android/media/tv/tuner/frontend/ScanCallback.java80
-rw-r--r--media/java/android/media/tv/tuner/frontend/ScanMessage.java172
-rw-r--r--media/jni/Android.bp1
-rw-r--r--media/jni/android_media_MediaPlayer.cpp6
-rw-r--r--media/jni/android_media_MediaTranscodeManager.cpp102
-rw-r--r--media/tests/MediaFrameworkTest/Android.bp1
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/mediatranscodemanager/MediaTranscodeManagerTest.java74
-rw-r--r--media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java23
-rw-r--r--native/graphics/jni/bitmap.cpp10
-rw-r--r--native/graphics/jni/libjnigraphics.map.txt1
-rw-r--r--packages/CarSystemUI/res/layout/sysui_primary_window.xml7
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java2
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/car/SystemUIPrimaryWindowController.java22
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java68
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarKeyguardViewManager.java18
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java15
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java35
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java17
-rw-r--r--packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java16
-rw-r--r--packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/CarrierDefaultReceiverTest.java7
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java19
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/wifi/TestAccessPointBuilder.java7
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java2
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java2
-rw-r--r--packages/SettingsLib/tests/integ/Android.bp5
-rw-r--r--packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java17
-rw-r--r--packages/SystemUI/res/layout/global_actions_grid_item_v2.xml68
-rw-r--r--packages/SystemUI/res/layout/global_actions_grid_v2.xml130
-rw-r--r--packages/SystemUI/res/layout/global_screenshot_action_chip.xml33
-rw-r--r--packages/SystemUI/res/values/dimens.xml14
-rw-r--r--packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayout.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java27
-rw-r--r--packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsFlatLayout.java186
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionChip.java73
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java39
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifInflaterImpl.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifPipeline.java191
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java (renamed from packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifListBuilderImpl.java)39
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/CoalescedEvent.kt (renamed from packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/CoalescedEvent.kt)4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/EventBatch.java (renamed from packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/EventBatch.java)4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescer.java (renamed from packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/GroupCoalescer.java)4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/Coordinator.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinator.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinator.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifInflater.java (renamed from packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifInflater.java)3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinder.java (renamed from packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinder.java)5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java (renamed from packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java)5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/FakePipelineConsumer.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NotifPipelineInitializer.java (renamed from packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NewNotifPipeline.java)28
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/NotifListBuilder.java127
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeRenderListListener.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeSortListener.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeTransformGroupsListener.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/PipelineState.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifComparator.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifFilter.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifPromoter.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/Pluggable.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/CollectionReadyForBuildListener.java (renamed from packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/CollectionReadyForBuildListener.java)6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/DismissedByUserStats.java (renamed from packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/DismissedByUserStats.java)4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionListener.java (renamed from packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollectionListener.java)10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifLifetimeExtender.java (renamed from packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifLifetimeExtender.java)6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotifEvent.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarModule.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/TestableNotificationEntryManager.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java32
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java (renamed from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifListBuilderImplTest.java)9
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescerTest.java (renamed from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/notifcollection/GroupCoalescerTest.java)4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinatorTest.java8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinatorTest.java14
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java2
-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/StatusBarTest.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java4
-rw-r--r--packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java14
-rw-r--r--services/autofill/java/com/android/server/autofill/Session.java6
-rw-r--r--services/backup/java/com/android/server/backup/internal/BackupHandler.java18
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java10
-rw-r--r--services/core/java/com/android/server/NetworkScoreService.java8
-rw-r--r--services/core/java/com/android/server/TestNetworkService.java4
-rw-r--r--services/core/java/com/android/server/accounts/AccountManagerService.java16
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java16
-rw-r--r--services/core/java/com/android/server/compat/CompatConfig.java2
-rw-r--r--services/core/java/com/android/server/connectivity/Vpn.java2
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java10
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodManagerService.java62
-rw-r--r--services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java5
-rw-r--r--services/core/java/com/android/server/media/MediaRoute2Provider.java33
-rw-r--r--services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java157
-rw-r--r--services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java45
-rw-r--r--services/core/java/com/android/server/media/SystemMediaRoute2Provider.java4
-rw-r--r--services/core/java/com/android/server/pm/InstantAppRegistry.java3
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java3
-rw-r--r--services/core/java/com/android/server/policy/LegacyGlobalActions.java4
-rw-r--r--services/core/java/com/android/server/stats/StatsPullAtomService.java273
-rw-r--r--services/core/jni/com_android_server_net_NetworkStatsService.cpp1
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java87
-rw-r--r--services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java22
-rw-r--r--services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java20
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java253
-rw-r--r--services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java17
-rw-r--r--telecomm/TEST_MAPPING29
-rw-r--r--telephony/TEST_MAPPING29
-rw-r--r--telephony/java/android/telephony/PreciseDataConnectionState.java14
-rw-r--r--telephony/java/android/telephony/SmsManager.java105
-rw-r--r--telephony/java/android/telephony/SubscriptionManager.java273
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java295
-rw-r--r--telephony/java/com/android/internal/telephony/PhoneConstants.java3
-rw-r--r--tests/net/integration/util/com/android/server/NetworkAgentWrapper.java2
-rw-r--r--tests/net/java/com/android/server/ConnectivityServiceTest.java2
-rw-r--r--tests/net/java/com/android/server/connectivity/LingerMonitorTest.java4
-rw-r--r--tests/net/java/com/android/server/connectivity/Nat464XlatTest.java2
-rw-r--r--wifi/Android.bp2
-rw-r--r--wifi/java/android/net/wifi/ScanResult.java17
-rw-r--r--wifi/java/android/net/wifi/WifiConfiguration.java90
-rw-r--r--wifi/java/android/net/wifi/WifiEnterpriseConfig.java4
-rw-r--r--wifi/java/android/net/wifi/WifiInfo.java69
-rw-r--r--wifi/tests/Android.bp50
-rw-r--r--wifi/tests/Android.mk66
194 files changed, 4458 insertions, 1953 deletions
diff --git a/Android.bp b/Android.bp
index a61b5472e6fc..4e2b156afbbf 100644
--- a/Android.bp
+++ b/Android.bp
@@ -487,7 +487,7 @@ java_library {
"framework-minus-apex",
"updatable_media_stubs",
"framework_mediaprovider_stubs",
- "framework-appsearch-stubs",
+ "framework-appsearch", // TODO(b/146218515): should be framework-appsearch-stubs
"framework-sdkextensions-stubs-systemapi",
// TODO(b/146167933): Use framework-statsd-stubs instead.
"framework-statsd",
diff --git a/apex/appsearch/framework/Android.bp b/apex/appsearch/framework/Android.bp
index 60cc3bec0a9d..1f30dda21ef7 100644
--- a/apex/appsearch/framework/Android.bp
+++ b/apex/appsearch/framework/Android.bp
@@ -30,10 +30,29 @@ java_library {
libs: [
"framework-minus-apex", // TODO(b/146218515) should be framework-system-stubs
],
- visibility: ["//frameworks/base/apex/appsearch:__subpackages__"],
+ visibility: [
+ "//frameworks/base/apex/appsearch:__subpackages__",
+ // TODO(b/146218515) remove this when framework is built with the stub of appsearch
+ "//frameworks/base",
+ ],
apex_available: ["com.android.appsearch"],
}
+metalava_appsearch_docs_args =
+ "--hide-package com.android.server " +
+ "--error UnhiddenSystemApi " +
+ "--hide RequiresPermission " +
+ "--hide MissingPermission " +
+ "--hide BroadcastBehavior " +
+ "--hide HiddenSuperclass " +
+ "--hide DeprecationMismatch " +
+ "--hide UnavailableSymbol " +
+ "--hide SdkConstant " +
+ "--hide HiddenTypeParameter " +
+ "--hide Todo --hide Typo " +
+ "--hide HiddenTypedefConstant " +
+ "--show-annotation android.annotation.SystemApi "
+
droidstubs {
name: "framework-appsearch-stubs-srcs",
srcs: [
@@ -43,8 +62,9 @@ droidstubs {
aidl: {
include_dirs: ["frameworks/base/core/java"],
},
- defaults: ["framework-module-stubs-defaults-systemapi"],
- sdk_version: "system_current",
+ args: metalava_appsearch_docs_args,
+ sdk_version: "core_current",
+ libs: ["android_system_stubs_current"],
}
java_library {
@@ -55,6 +75,7 @@ java_library {
"java",
],
},
- sdk_version: "system_current",
+ sdk_version: "core_current",
+ libs: ["android_system_stubs_current"],
installable: false,
}
diff --git a/apex/appsearch/service/Android.bp b/apex/appsearch/service/Android.bp
index e7abcd9a645a..8aed5d04a32b 100644
--- a/apex/appsearch/service/Android.bp
+++ b/apex/appsearch/service/Android.bp
@@ -20,7 +20,6 @@ java_library {
libs: [
"framework",
"services.core",
- "framework-appsearch",
],
static_libs: [
"icing-java-proto-lite",
diff --git a/apex/jobscheduler/service/java/com/android/server/TEST_MAPPING b/apex/jobscheduler/service/java/com/android/server/TEST_MAPPING
new file mode 100644
index 000000000000..8fbfb1daaf6f
--- /dev/null
+++ b/apex/jobscheduler/service/java/com/android/server/TEST_MAPPING
@@ -0,0 +1,22 @@
+{
+ "presubmit": [
+ {
+ "name": "FrameworksMockingServicesTests",
+ "file_patterns": [
+ "DeviceIdleController\\.java"
+ ],
+ "options": [
+ {"include-filter": "com.android.server.DeviceIdleControllerTest"},
+ {"exclude-annotation": "androidx.test.filters.FlakyTest"}
+ ]
+ }
+ ],
+ "postsubmit": [
+ {
+ "name": "FrameworksMockingServicesTests",
+ "options": [
+ {"include-filter": "com.android.server"}
+ ]
+ }
+ ]
+} \ No newline at end of file
diff --git a/apex/jobscheduler/service/java/com/android/server/deviceidle/TEST_MAPPING b/apex/jobscheduler/service/java/com/android/server/deviceidle/TEST_MAPPING
new file mode 100644
index 000000000000..bc7a7d3bef7d
--- /dev/null
+++ b/apex/jobscheduler/service/java/com/android/server/deviceidle/TEST_MAPPING
@@ -0,0 +1,19 @@
+{
+ "presubmit": [
+ {
+ "name": "FrameworksMockingServicesTests",
+ "options": [
+ {"include-filter": "com.android.server.DeviceIdleControllerTest"},
+ {"exclude-annotation": "androidx.test.filters.FlakyTest"}
+ ]
+ }
+ ],
+ "postsubmit": [
+ {
+ "name": "FrameworksMockingServicesTests",
+ "options": [
+ {"include-filter": "com.android.server"}
+ ]
+ }
+ ]
+} \ No newline at end of file
diff --git a/apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java b/apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java
index 82292cfeea09..b9df30aa4d95 100644
--- a/apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java
+++ b/apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java
@@ -17,7 +17,7 @@
package com.android.server.usage;
import static android.app.usage.UsageStatsManager.REASON_MAIN_DEFAULT;
-import static android.app.usage.UsageStatsManager.REASON_MAIN_FORCED;
+import static android.app.usage.UsageStatsManager.REASON_MAIN_FORCED_BY_USER;
import static android.app.usage.UsageStatsManager.REASON_MAIN_MASK;
import static android.app.usage.UsageStatsManager.REASON_MAIN_PREDICTED;
import static android.app.usage.UsageStatsManager.REASON_MAIN_USAGE;
@@ -441,7 +441,7 @@ public class AppIdleHistory {
elapsedRealtime, true);
if (idle) {
appUsageHistory.currentBucket = STANDBY_BUCKET_RARE;
- appUsageHistory.bucketingReason = REASON_MAIN_FORCED;
+ appUsageHistory.bucketingReason = REASON_MAIN_FORCED_BY_USER;
} else {
appUsageHistory.currentBucket = STANDBY_BUCKET_ACTIVE;
// This is to pretend that the app was just used, don't freeze the state anymore.
diff --git a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
index 58eb58961ac4..eb0b54b1d9fc 100644
--- a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
+++ b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
@@ -17,7 +17,8 @@
package com.android.server.usage;
import static android.app.usage.UsageStatsManager.REASON_MAIN_DEFAULT;
-import static android.app.usage.UsageStatsManager.REASON_MAIN_FORCED;
+import static android.app.usage.UsageStatsManager.REASON_MAIN_FORCED_BY_SYSTEM;
+import static android.app.usage.UsageStatsManager.REASON_MAIN_FORCED_BY_USER;
import static android.app.usage.UsageStatsManager.REASON_MAIN_MASK;
import static android.app.usage.UsageStatsManager.REASON_MAIN_PREDICTED;
import static android.app.usage.UsageStatsManager.REASON_MAIN_TIMEOUT;
@@ -565,7 +566,7 @@ public class AppStandbyController implements AppStandbyInternal {
// If the bucket was forced by the user/developer, leave it alone.
// A usage event will be the only way to bring it out of this forced state
- if (oldMainReason == REASON_MAIN_FORCED) {
+ if (oldMainReason == REASON_MAIN_FORCED_BY_USER) {
return;
}
final int oldBucket = app.currentBucket;
@@ -783,7 +784,7 @@ public class AppStandbyController implements AppStandbyInternal {
// Inform listeners if necessary
if (previouslyIdle != stillIdle) {
maybeInformListeners(packageName, userId, elapsedRealtime, standbyBucket,
- REASON_MAIN_FORCED, false);
+ REASON_MAIN_FORCED_BY_USER, false);
if (!stillIdle) {
notifyBatteryStats(packageName, userId, idle);
}
@@ -1030,8 +1031,17 @@ public class AppStandbyController implements AppStandbyInternal {
callingPid, callingUid, userId, false, true, "setAppStandbyBucket", null);
final boolean shellCaller = callingUid == Process.ROOT_UID
|| callingUid == Process.SHELL_UID;
- final boolean systemCaller = UserHandle.isCore(callingUid);
- final int reason = systemCaller ? REASON_MAIN_FORCED : REASON_MAIN_PREDICTED;
+ final int reason;
+ // The Settings app runs in the system UID but in a separate process. Assume
+ // things coming from other processes are due to the user.
+ if ((UserHandle.isSameApp(callingUid, Process.SYSTEM_UID) && callingPid != Process.myPid())
+ || shellCaller) {
+ reason = REASON_MAIN_FORCED_BY_USER;
+ } else if (UserHandle.isCore(callingUid)) {
+ reason = REASON_MAIN_FORCED_BY_SYSTEM;
+ } else {
+ reason = REASON_MAIN_PREDICTED;
+ }
final int packageFlags = PackageManager.MATCH_ANY_USER
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE
| PackageManager.MATCH_DIRECT_BOOT_AWARE;
@@ -1087,7 +1097,11 @@ public class AppStandbyController implements AppStandbyInternal {
}
// If the bucket was forced, don't allow prediction to override
- if ((app.bucketingReason & REASON_MAIN_MASK) == REASON_MAIN_FORCED && predicted) return;
+ if (predicted
+ && ((app.bucketingReason & REASON_MAIN_MASK) == REASON_MAIN_FORCED_BY_USER
+ || (app.bucketingReason & REASON_MAIN_MASK) == REASON_MAIN_FORCED_BY_SYSTEM)) {
+ return;
+ }
// If the bucket is required to stay in a higher state for a specified duration, don't
// override unless the duration has passed
diff --git a/apex/jobscheduler/service/java/com/android/server/usage/TEST_MAPPING b/apex/jobscheduler/service/java/com/android/server/usage/TEST_MAPPING
new file mode 100644
index 000000000000..cf70878b8899
--- /dev/null
+++ b/apex/jobscheduler/service/java/com/android/server/usage/TEST_MAPPING
@@ -0,0 +1,19 @@
+{
+ "presubmit": [
+ {
+ "name": "FrameworksServicesTests",
+ "options": [
+ {"include-filter": "com.android.server.usage"},
+ {"exclude-annotation": "androidx.test.filters.FlakyTest"}
+ ]
+ }
+ ],
+ "postsubmit": [
+ {
+ "name": "FrameworksServicesTests",
+ "options": [
+ {"include-filter": "com.android.server.usage"}
+ ]
+ }
+ ]
+} \ No newline at end of file
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 0f981e25b37a..bbb87ab6ce7c 100644
--- a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
+++ b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
@@ -714,60 +714,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
}
}
- private void addNetworkStats(
- int tag, List<StatsLogEventWrapper> ret, NetworkStats stats, boolean withFGBG) {
- int size = stats.size();
- long elapsedNanos = SystemClock.elapsedRealtimeNanos();
- long wallClockNanos = SystemClock.currentTimeMicro() * 1000L;
- NetworkStats.Entry entry = new NetworkStats.Entry(); // For recycling
- for (int j = 0; j < size; j++) {
- stats.getValues(j, entry);
- StatsLogEventWrapper e = new StatsLogEventWrapper(tag, elapsedNanos, wallClockNanos);
- e.writeInt(entry.uid);
- if (withFGBG) {
- e.writeInt(entry.set);
- }
- e.writeLong(entry.rxBytes);
- e.writeLong(entry.rxPackets);
- e.writeLong(entry.txBytes);
- e.writeLong(entry.txPackets);
- ret.add(e);
- }
- }
-
- /**
- * Allows rollups per UID but keeping the set (foreground/background) slicing.
- * Adapted from groupedByUid in frameworks/base/core/java/android/net/NetworkStats.java
- */
- private NetworkStats rollupNetworkStatsByFGBG(NetworkStats stats) {
- final NetworkStats ret = new NetworkStats(stats.getElapsedRealtime(), 1);
-
- final NetworkStats.Entry entry = new NetworkStats.Entry();
- entry.iface = NetworkStats.IFACE_ALL;
- entry.tag = NetworkStats.TAG_NONE;
- entry.metered = NetworkStats.METERED_ALL;
- entry.roaming = NetworkStats.ROAMING_ALL;
-
- int size = stats.size();
- NetworkStats.Entry recycle = new NetworkStats.Entry(); // Used for retrieving values
- for (int i = 0; i < size; i++) {
- stats.getValues(i, recycle);
-
- // Skip specific tags, since already counted in TAG_NONE
- if (recycle.tag != NetworkStats.TAG_NONE) continue;
-
- entry.set = recycle.set; // Allows slicing by background/foreground
- entry.uid = recycle.uid;
- entry.rxBytes = recycle.rxBytes;
- entry.rxPackets = recycle.rxPackets;
- entry.txBytes = recycle.txBytes;
- entry.txPackets = recycle.txPackets;
- // Operations purposefully omitted since we don't use them for statsd.
- ret.combineValues(entry);
- }
- return ret;
- }
-
/**
* Helper method to extract the Parcelable controller info from a
* SynchronousResultReceiver.
@@ -815,94 +761,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
}
}
- private void pullWifiBytesTransferByFgBg(
- int tagId, long elapsedNanos, long wallClockNanos,
- List<StatsLogEventWrapper> pulledData) {
- long token = Binder.clearCallingIdentity();
- try {
- BatteryStatsInternal bs = LocalServices.getService(BatteryStatsInternal.class);
- String[] ifaces = bs.getWifiIfaces();
- if (ifaces.length == 0) {
- return;
- }
- if (mNetworkStatsService == null) {
- Slog.e(TAG, "NetworkStats Service is not available!");
- return;
- }
- NetworkStats stats = rollupNetworkStatsByFGBG(
- mNetworkStatsService.getDetailedUidStats(ifaces));
- addNetworkStats(tagId, pulledData, stats, true);
- } catch (RemoteException e) {
- Slog.e(TAG, "Pulling netstats for wifi bytes w/ fg/bg has error", e);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- private void pullMobileBytesTransfer(
- int tagId, long elapsedNanos, long wallClockNanos,
- List<StatsLogEventWrapper> pulledData) {
- long token = Binder.clearCallingIdentity();
- try {
- BatteryStatsInternal bs = LocalServices.getService(BatteryStatsInternal.class);
- String[] ifaces = bs.getMobileIfaces();
- if (ifaces.length == 0) {
- return;
- }
- if (mNetworkStatsService == null) {
- Slog.e(TAG, "NetworkStats Service is not available!");
- return;
- }
- // Combine all the metrics per Uid into one record.
- NetworkStats stats = mNetworkStatsService.getDetailedUidStats(ifaces).groupedByUid();
- addNetworkStats(tagId, pulledData, stats, false);
- } catch (RemoteException e) {
- Slog.e(TAG, "Pulling netstats for mobile bytes has error", e);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- private void pullBluetoothBytesTransfer(
- int tagId, long elapsedNanos, long wallClockNanos,
- List<StatsLogEventWrapper> pulledData) {
- BluetoothActivityEnergyInfo info = fetchBluetoothData();
- if (info.getUidTraffic() != null) {
- for (UidTraffic traffic : info.getUidTraffic()) {
- StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos,
- wallClockNanos);
- e.writeInt(traffic.getUid());
- e.writeLong(traffic.getRxBytes());
- e.writeLong(traffic.getTxBytes());
- pulledData.add(e);
- }
- }
- }
-
- private void pullMobileBytesTransferByFgBg(
- int tagId, long elapsedNanos, long wallClockNanos,
- List<StatsLogEventWrapper> pulledData) {
- long token = Binder.clearCallingIdentity();
- try {
- BatteryStatsInternal bs = LocalServices.getService(BatteryStatsInternal.class);
- String[] ifaces = bs.getMobileIfaces();
- if (ifaces.length == 0) {
- return;
- }
- if (mNetworkStatsService == null) {
- Slog.e(TAG, "NetworkStats Service is not available!");
- return;
- }
- NetworkStats stats = rollupNetworkStatsByFGBG(
- mNetworkStatsService.getDetailedUidStats(ifaces));
- addNetworkStats(tagId, pulledData, stats, true);
- } catch (RemoteException e) {
- Slog.e(TAG, "Pulling netstats for mobile bytes w/ fg/bg has error", e);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
private void pullCpuTimePerFreq(
int tagId, long elapsedNanos, long wallClockNanos,
List<StatsLogEventWrapper> pulledData) {
@@ -1052,33 +910,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
}
}
- private void pullBluetoothActivityInfo(
- int tagId, long elapsedNanos, long wallClockNanos,
- List<StatsLogEventWrapper> pulledData) {
- BluetoothActivityEnergyInfo info = fetchBluetoothData();
- StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
- e.writeLong(info.getTimeStamp());
- e.writeInt(info.getBluetoothStackState());
- e.writeLong(info.getControllerTxTimeMillis());
- e.writeLong(info.getControllerRxTimeMillis());
- e.writeLong(info.getControllerIdleTimeMillis());
- e.writeLong(info.getControllerEnergyUsed());
- pulledData.add(e);
- }
-
- private synchronized BluetoothActivityEnergyInfo fetchBluetoothData() {
- final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
- if (adapter != null) {
- SynchronousResultReceiver bluetoothReceiver = new SynchronousResultReceiver(
- "bluetooth");
- adapter.requestControllerActivityEnergyInfo(bluetoothReceiver);
- return awaitControllerInfo(bluetoothReceiver);
- } else {
- Slog.e(TAG, "Failed to get bluetooth adapter!");
- return null;
- }
- }
-
private void pullSystemElapsedRealtime(
int tagId, long elapsedNanos, long wallClockNanos,
List<StatsLogEventWrapper> pulledData) {
@@ -1671,21 +1502,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
}
}
- private void pullPowerProfile(
- int tagId, long elapsedNanos, long wallClockNanos,
- List<StatsLogEventWrapper> pulledData) {
- PowerProfile powerProfile = new PowerProfile(mContext);
- Objects.requireNonNull(powerProfile);
-
- StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos,
- wallClockNanos);
- ProtoOutputStream proto = new ProtoOutputStream();
- powerProfile.dumpDebug(proto);
- proto.flush();
- e.writeStorage(proto.getBytes());
- pulledData.add(e);
- }
-
private void pullBuildInformation(int tagId,
long elapsedNanos, long wallClockNanos, List<StatsLogEventWrapper> pulledData) {
StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
@@ -2291,26 +2107,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
long elapsedNanos = SystemClock.elapsedRealtimeNanos();
long wallClockNanos = SystemClock.currentTimeMicro() * 1000L;
switch (tagId) {
-
- case StatsLog.MOBILE_BYTES_TRANSFER: {
- pullMobileBytesTransfer(tagId, elapsedNanos, wallClockNanos, ret);
- break;
- }
-
- case StatsLog.WIFI_BYTES_TRANSFER_BY_FG_BG: {
- pullWifiBytesTransferByFgBg(tagId, elapsedNanos, wallClockNanos, ret);
- break;
- }
-
- case StatsLog.MOBILE_BYTES_TRANSFER_BY_FG_BG: {
- pullMobileBytesTransferByFgBg(tagId, elapsedNanos, wallClockNanos, ret);
- break;
- }
-
- case StatsLog.BLUETOOTH_BYTES_TRANSFER: {
- pullBluetoothBytesTransfer(tagId, elapsedNanos, wallClockNanos, ret);
- break;
- }
case StatsLog.KERNEL_WAKELOCK: {
pullKernelWakelock(tagId, elapsedNanos, wallClockNanos, ret);
@@ -2352,11 +2148,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
break;
}
- case StatsLog.BLUETOOTH_ACTIVITY_INFO: {
- pullBluetoothActivityInfo(tagId, elapsedNanos, wallClockNanos, ret);
- break;
- }
-
case StatsLog.SYSTEM_UPTIME: {
pullSystemUpTime(tagId, elapsedNanos, wallClockNanos, ret);
break;
@@ -2455,11 +2246,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
break;
}
- case StatsLog.POWER_PROFILE: {
- pullPowerProfile(tagId, elapsedNanos, wallClockNanos, ret);
- break;
- }
-
case StatsLog.BUILD_INFORMATION: {
pullBuildInformation(tagId, elapsedNanos, wallClockNanos, ret);
break;
diff --git a/api/current.txt b/api/current.txt
index 16a9e49da032..afbb427ed288 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -30507,6 +30507,7 @@ package android.net.wifi {
method @Nullable public java.security.cert.X509Certificate[] getCaCertificates();
method public java.security.cert.X509Certificate getClientCertificate();
method @Nullable public java.security.cert.X509Certificate[] getClientCertificateChain();
+ method @Nullable public java.security.PrivateKey getClientPrivateKey();
method public String getDomainSuffixMatch();
method public int getEapMethod();
method public String getIdentity();
@@ -39205,6 +39206,7 @@ package android.provider {
method @NonNull public static android.app.PendingIntent createWriteRequest(@NonNull android.content.ContentResolver, @NonNull java.util.Collection<android.net.Uri>);
method @Nullable public static android.net.Uri getDocumentUri(@NonNull android.content.Context, @NonNull android.net.Uri);
method @NonNull public static java.util.Set<java.lang.String> getExternalVolumeNames(@NonNull android.content.Context);
+ method public static long getGeneration(@NonNull android.content.Context, @NonNull String);
method public static android.net.Uri getMediaScannerUri();
method @Nullable public static android.net.Uri getMediaUri(@NonNull android.content.Context, @NonNull android.net.Uri);
method @NonNull public static java.util.Set<java.lang.String> getRecentExternalVolumeNames(@NonNull android.content.Context);
@@ -39515,6 +39517,7 @@ package android.provider {
field public static final String DISPLAY_NAME = "_display_name";
field public static final String DOCUMENT_ID = "document_id";
field public static final String DURATION = "duration";
+ field public static final String GENERATION = "generation";
field public static final String GENRE = "genre";
field public static final String HEIGHT = "height";
field public static final String INSTANCE_ID = "instance_id";
@@ -54822,6 +54825,7 @@ package android.view.inputmethod {
public final class InlineSuggestionsRequest implements android.os.Parcelable {
method public int describeContents();
+ method @NonNull public String getHostPackageName();
method public int getMaxSuggestionCount();
method @NonNull public java.util.List<android.view.inline.InlinePresentationSpec> getPresentationSpecs();
method public void writeToParcel(@NonNull android.os.Parcel, int);
diff --git a/api/module-lib-current.txt b/api/module-lib-current.txt
index d802177e249b..0a6706550074 100644
--- a/api/module-lib-current.txt
+++ b/api/module-lib-current.txt
@@ -1 +1,81 @@
// Signature format: 2.0
+package android.app.timedetector {
+
+ public final class PhoneTimeSuggestion implements android.os.Parcelable {
+ method public void addDebugInfo(@NonNull String);
+ method public void addDebugInfo(@NonNull java.util.List<java.lang.String>);
+ method public int describeContents();
+ method @NonNull public java.util.List<java.lang.String> getDebugInfo();
+ method public int getPhoneId();
+ method @Nullable public android.os.TimestampedValue<java.lang.Long> getUtcTime();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.app.timedetector.PhoneTimeSuggestion> CREATOR;
+ }
+
+ public static final class PhoneTimeSuggestion.Builder {
+ ctor public PhoneTimeSuggestion.Builder(int);
+ method @NonNull public android.app.timedetector.PhoneTimeSuggestion.Builder addDebugInfo(@NonNull String);
+ method @NonNull public android.app.timedetector.PhoneTimeSuggestion build();
+ method @NonNull public android.app.timedetector.PhoneTimeSuggestion.Builder setUtcTime(@Nullable android.os.TimestampedValue<java.lang.Long>);
+ }
+
+ public class TimeDetector {
+ method @RequiresPermission("android.permission.SUGGEST_PHONE_TIME_AND_ZONE") public void suggestPhoneTime(@NonNull android.app.timedetector.PhoneTimeSuggestion);
+ }
+
+}
+
+package android.app.timezonedetector {
+
+ public final class PhoneTimeZoneSuggestion implements android.os.Parcelable {
+ method public void addDebugInfo(@NonNull String);
+ method public void addDebugInfo(@NonNull java.util.List<java.lang.String>);
+ method @NonNull public static android.app.timezonedetector.PhoneTimeZoneSuggestion createEmptySuggestion(int, @NonNull String);
+ method public int describeContents();
+ method @NonNull public java.util.List<java.lang.String> getDebugInfo();
+ method public int getMatchType();
+ method public int getPhoneId();
+ method public int getQuality();
+ method @Nullable public String getZoneId();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.app.timezonedetector.PhoneTimeZoneSuggestion> CREATOR;
+ field public static final int MATCH_TYPE_EMULATOR_ZONE_ID = 4; // 0x4
+ field public static final int MATCH_TYPE_NA = 0; // 0x0
+ field public static final int MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET = 3; // 0x3
+ field public static final int MATCH_TYPE_NETWORK_COUNTRY_ONLY = 2; // 0x2
+ field public static final int MATCH_TYPE_TEST_NETWORK_OFFSET_ONLY = 5; // 0x5
+ field public static final int QUALITY_MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS = 3; // 0x3
+ field public static final int QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET = 2; // 0x2
+ field public static final int QUALITY_NA = 0; // 0x0
+ field public static final int QUALITY_SINGLE_ZONE = 1; // 0x1
+ }
+
+ public static final class PhoneTimeZoneSuggestion.Builder {
+ ctor public PhoneTimeZoneSuggestion.Builder(int);
+ method @NonNull public android.app.timezonedetector.PhoneTimeZoneSuggestion.Builder addDebugInfo(@NonNull String);
+ method @NonNull public android.app.timezonedetector.PhoneTimeZoneSuggestion build();
+ method @NonNull public android.app.timezonedetector.PhoneTimeZoneSuggestion.Builder setMatchType(int);
+ method @NonNull public android.app.timezonedetector.PhoneTimeZoneSuggestion.Builder setQuality(int);
+ method @NonNull public android.app.timezonedetector.PhoneTimeZoneSuggestion.Builder setZoneId(@Nullable String);
+ }
+
+ public class TimeZoneDetector {
+ method @RequiresPermission("android.permission.SUGGEST_PHONE_TIME_AND_ZONE") public void suggestPhoneTimeZone(@NonNull android.app.timezonedetector.PhoneTimeZoneSuggestion);
+ }
+
+}
+
+package android.os {
+
+ public final class TimestampedValue<T> implements android.os.Parcelable {
+ ctor public TimestampedValue(long, @Nullable T);
+ method public int describeContents();
+ method public long getReferenceTimeMillis();
+ method @Nullable public T getValue();
+ method public static long referenceTimeDifference(@NonNull android.os.TimestampedValue<?>, @NonNull android.os.TimestampedValue<?>);
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.os.TimestampedValue<?>> CREATOR;
+ }
+
+}
+
diff --git a/api/system-current.txt b/api/system-current.txt
index ee2e10072034..71d1a381ec31 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -208,6 +208,7 @@ package android {
field public static final String STOP_APP_SWITCHES = "android.permission.STOP_APP_SWITCHES";
field public static final String SUBSTITUTE_NOTIFICATION_APP_NAME = "android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME";
field public static final String SUBSTITUTE_SHARE_TARGET_APP_NAME_AND_ICON = "android.permission.SUBSTITUTE_SHARE_TARGET_APP_NAME_AND_ICON";
+ field public static final String SUGGEST_PHONE_TIME_AND_ZONE = "android.permission.SUGGEST_PHONE_TIME_AND_ZONE";
field public static final String SUSPEND_APPS = "android.permission.SUSPEND_APPS";
field public static final String SYSTEM_CAMERA = "android.permission.SYSTEM_CAMERA";
field public static final String TETHER_PRIVILEGED = "android.permission.TETHER_PRIVILEGED";
@@ -327,6 +328,7 @@ package android.app {
method public void setDeviceLocales(@NonNull android.os.LocaleList);
method @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS) public static void setPersistentVrThread(int);
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean switchUser(@NonNull android.os.UserHandle);
+ method @RequiresPermission(android.Manifest.permission.CHANGE_CONFIGURATION) public boolean updateMccMncConfiguration(@NonNull String, @NonNull String);
}
public static interface ActivityManager.OnUidImportanceListener {
@@ -1714,6 +1716,7 @@ package android.content {
field public static final String NETD_SERVICE = "netd";
field public static final String NETWORK_POLICY_SERVICE = "netpolicy";
field public static final String NETWORK_SCORE_SERVICE = "network_score";
+ field public static final String NETWORK_STACK_SERVICE = "network_stack";
field public static final String OEM_LOCK_SERVICE = "oem_lock";
field public static final String PERMISSION_SERVICE = "permission";
field public static final String PERSISTENT_DATA_BLOCK_SERVICE = "persistent_data_block";
@@ -4686,10 +4689,30 @@ package android.media.tv.tuner {
package android.media.tv.tuner.filter {
+ public abstract class FilterConfiguration {
+ field public static final int FILTER_TYPE_ALP = 16; // 0x10
+ field public static final int FILTER_TYPE_IP = 4; // 0x4
+ field public static final int FILTER_TYPE_MMTP = 2; // 0x2
+ field public static final int FILTER_TYPE_TLV = 8; // 0x8
+ field public static final int FILTER_TYPE_TS = 1; // 0x1
+ }
+
public abstract class FilterEvent {
ctor public FilterEvent();
}
+ public class PesSettings extends android.media.tv.tuner.filter.Settings {
+ method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public static android.media.tv.tuner.filter.PesSettings.Builder builder(@NonNull android.content.Context, int);
+ method public int getStreamId();
+ method public boolean isRaw();
+ }
+
+ public static class PesSettings.Builder {
+ method @NonNull public android.media.tv.tuner.filter.PesSettings build();
+ method @NonNull public android.media.tv.tuner.filter.PesSettings.Builder setRaw(boolean);
+ method @NonNull public android.media.tv.tuner.filter.PesSettings.Builder setStreamId(int);
+ }
+
public class SectionEvent extends android.media.tv.tuner.filter.FilterEvent {
method public int getDataLength();
method public int getSectionNumber();
@@ -4697,6 +4720,22 @@ package android.media.tv.tuner.filter {
method public int getVersion();
}
+ public abstract class Settings {
+ }
+
+ public class TsFilterConfiguration extends android.media.tv.tuner.filter.FilterConfiguration {
+ method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public static android.media.tv.tuner.filter.TsFilterConfiguration.Builder builder(@NonNull android.content.Context);
+ method @Nullable public android.media.tv.tuner.filter.Settings getSettings();
+ method public int getTpid();
+ method public int getType();
+ }
+
+ public static class TsFilterConfiguration.Builder {
+ method @NonNull public android.media.tv.tuner.filter.TsFilterConfiguration build();
+ method @NonNull public android.media.tv.tuner.filter.TsFilterConfiguration.Builder setSettings(@NonNull android.media.tv.tuner.filter.Settings);
+ method @NonNull public android.media.tv.tuner.filter.TsFilterConfiguration.Builder setTpid(int);
+ }
+
}
package android.metrics {
@@ -4779,6 +4818,7 @@ package android.net {
field public static final int TETHER_ERROR_ENTITLEMENT_UNKONWN = 13; // 0xd
field public static final int TETHER_ERROR_NO_ERROR = 0; // 0x0
field public static final int TETHER_ERROR_PROVISION_FAILED = 11; // 0xb
+ field public static final int TYPE_NONE = -1; // 0xffffffff
}
public abstract static class ConnectivityManager.OnStartTetheringCallback {
@@ -4914,12 +4954,36 @@ package android.net {
field @NonNull public static final android.os.Parcelable.Creator<android.net.MatchAllNetworkSpecifier> CREATOR;
}
+ public final class NattKeepalivePacketData extends android.net.KeepalivePacketData implements android.os.Parcelable {
+ ctor public NattKeepalivePacketData(@NonNull java.net.InetAddress, int, @NonNull java.net.InetAddress, int, @NonNull byte[]) throws android.net.InvalidPacketException;
+ method public int describeContents();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.NattKeepalivePacketData> CREATOR;
+ }
+
public class Network implements android.os.Parcelable {
ctor public Network(@NonNull android.net.Network);
method @NonNull public android.net.Network getPrivateDnsBypassingCopy();
field public final int netId;
}
+ public final class NetworkAgentConfig implements android.os.Parcelable {
+ method public int describeContents();
+ method @Nullable public String getSubscriberId();
+ method public boolean isNat64DetectionEnabled();
+ method public boolean isProvisioningNotificationEnabled();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkAgentConfig> CREATOR;
+ }
+
+ public static class NetworkAgentConfig.Builder {
+ ctor public NetworkAgentConfig.Builder();
+ method @NonNull public android.net.NetworkAgentConfig build();
+ method @NonNull public android.net.NetworkAgentConfig.Builder disableNat64Detection();
+ method @NonNull public android.net.NetworkAgentConfig.Builder disableProvisioningNotification();
+ method @NonNull public android.net.NetworkAgentConfig.Builder setSubscriberId(@Nullable String);
+ }
+
public final class NetworkCapabilities implements android.os.Parcelable {
method public boolean deduceRestrictedCapability();
method @NonNull public int[] getTransportTypes();
@@ -4978,6 +5042,9 @@ package android.net {
field @Deprecated public static final String EXTRA_NETWORKS_TO_SCORE = "networksToScore";
field public static final String EXTRA_NEW_SCORER = "newScorer";
field @Deprecated public static final String EXTRA_PACKAGE_NAME = "packageName";
+ field public static final int SCORE_FILTER_CURRENT_NETWORK = 1; // 0x1
+ field public static final int SCORE_FILTER_NONE = 0; // 0x0
+ field public static final int SCORE_FILTER_SCAN_RESULTS = 2; // 0x2
}
public static interface NetworkScoreManager.NetworkScoreCallback {
@@ -5855,6 +5922,7 @@ package android.net.wifi {
}
public class ScanResult implements android.os.Parcelable {
+ ctor public ScanResult();
field public static final int CIPHER_CCMP = 3; // 0x3
field public static final int CIPHER_GCMP_256 = 4; // 0x4
field public static final int CIPHER_NONE = 0; // 0x0
@@ -5971,6 +6039,7 @@ package android.net.wifi {
method @Deprecated public static boolean isMetered(@Nullable android.net.wifi.WifiConfiguration, @Nullable android.net.wifi.WifiInfo);
method @Deprecated public boolean isNoInternetAccessExpected();
method @Deprecated public void setIpConfiguration(@Nullable android.net.IpConfiguration);
+ method @Deprecated public void setNetworkSelectionStatus(@NonNull android.net.wifi.WifiConfiguration.NetworkSelectionStatus);
method @Deprecated public void setProxy(@NonNull android.net.IpConfiguration.ProxySettings, @NonNull android.net.ProxyInfo);
field @Deprecated public static final int AP_BAND_2GHZ = 0; // 0x0
field @Deprecated public static final int AP_BAND_5GHZ = 1; // 0x1
@@ -6015,6 +6084,7 @@ package android.net.wifi {
method @Deprecated public boolean getHasEverConnected();
method @Deprecated @Nullable public static String getNetworkDisableReasonString(int);
method @Deprecated public int getNetworkSelectionDisableReason();
+ method @Deprecated public int getNetworkSelectionStatus();
method @Deprecated @NonNull public String getNetworkStatusString();
method @Deprecated public boolean isNetworkEnabled();
method @Deprecated public boolean isNetworkPermanentlyDisabled();
@@ -6029,6 +6099,16 @@ package android.net.wifi {
field @Deprecated public static final int DISABLED_NO_INTERNET_TEMPORARY = 4; // 0x4
field @Deprecated public static final int NETWORK_SELECTION_DISABLED_MAX = 10; // 0xa
field @Deprecated public static final int NETWORK_SELECTION_ENABLE = 0; // 0x0
+ field @Deprecated public static final int NETWORK_SELECTION_ENABLED = 0; // 0x0
+ field @Deprecated public static final int NETWORK_SELECTION_PERMANENTLY_DISABLED = 2; // 0x2
+ field @Deprecated public static final int NETWORK_SELECTION_TEMPORARY_DISABLED = 1; // 0x1
+ }
+
+ @Deprecated public static final class WifiConfiguration.NetworkSelectionStatus.Builder {
+ ctor @Deprecated public WifiConfiguration.NetworkSelectionStatus.Builder();
+ method @Deprecated @NonNull public android.net.wifi.WifiConfiguration.NetworkSelectionStatus build();
+ method @Deprecated @NonNull public android.net.wifi.WifiConfiguration.NetworkSelectionStatus.Builder setNetworkSelectionDisableReason(int);
+ method @Deprecated @NonNull public android.net.wifi.WifiConfiguration.NetworkSelectionStatus.Builder setNetworkSelectionStatus(int);
}
@Deprecated public static class WifiConfiguration.RecentFailure {
@@ -6073,6 +6153,15 @@ package android.net.wifi {
field public static final int INVALID_RSSI = -127; // 0xffffff81
}
+ public static final class WifiInfo.Builder {
+ ctor public WifiInfo.Builder();
+ method @NonNull public android.net.wifi.WifiInfo build();
+ method @NonNull public android.net.wifi.WifiInfo.Builder setBssid(@NonNull String);
+ method @NonNull public android.net.wifi.WifiInfo.Builder setNetworkId(int);
+ method @NonNull public android.net.wifi.WifiInfo.Builder setRssi(int);
+ method @NonNull public android.net.wifi.WifiInfo.Builder setSsid(@NonNull byte[]);
+ }
+
public class WifiManager {
method @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE) public void addOnWifiUsabilityStatsListener(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.OnWifiUsabilityStatsListener);
method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void allowAutojoin(int, boolean);
@@ -10368,9 +10457,15 @@ package android.telephony {
method public boolean disableCellBroadcastRange(int, int, int);
method public boolean enableCellBroadcastRange(int, int, int);
method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_MESSAGES_ON_ICC) public java.util.List<android.telephony.SmsMessage> getMessagesFromIcc();
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getPremiumSmsConsent(@NonNull String);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSmsCapacityOnIcc();
method public void sendMultipartTextMessage(@NonNull String, @NonNull String, @NonNull java.util.List<java.lang.String>, @Nullable java.util.List<android.app.PendingIntent>, @Nullable java.util.List<android.app.PendingIntent>, @NonNull String);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void sendMultipartTextMessageWithoutPersisting(String, String, java.util.List<java.lang.String>, java.util.List<android.app.PendingIntent>, java.util.List<android.app.PendingIntent>);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setPremiumSmsConsent(@NonNull String, int);
+ field public static final int PREMIUM_SMS_CONSENT_ALWAYS_ALLOW = 3; // 0x3
+ field public static final int PREMIUM_SMS_CONSENT_ASK_USER = 1; // 0x1
+ field public static final int PREMIUM_SMS_CONSENT_NEVER_ALLOW = 2; // 0x2
+ field public static final int PREMIUM_SMS_CONSENT_UNKNOWN = 0; // 0x0
}
public class SmsMessage {
@@ -10598,6 +10693,8 @@ package android.telephony {
field public static final String EXTRA_ERROR_CODE = "errorCode";
field public static final String EXTRA_PCO_ID = "pcoId";
field public static final String EXTRA_PCO_VALUE = "pcoValue";
+ field public static final String EXTRA_PHONE_IN_ECM_STATE = "android.telephony.extra.PHONE_IN_ECM_STATE";
+ field public static final String EXTRA_PHONE_IN_EMERGENCY_CALL = "android.telephony.extra.PHONE_IN_EMERGENCY_CALL";
field public static final String EXTRA_REDIRECTION_URL = "redirectionUrl";
field public static final String EXTRA_SIM_STATE = "android.telephony.extra.SIM_STATE";
field public static final String EXTRA_VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL = "android.telephony.extra.VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL";
diff --git a/api/test-current.txt b/api/test-current.txt
index 491d1eb19b86..1db4c9b82343 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -757,6 +757,7 @@ package android.content {
field public static final String BUGREPORT_SERVICE = "bugreport";
field public static final String CONTENT_CAPTURE_MANAGER_SERVICE = "content_capture";
field public static final String DEVICE_IDLE_CONTROLLER = "deviceidle";
+ field public static final String NETWORK_STACK_SERVICE = "network_stack";
field public static final String PERMISSION_SERVICE = "permission";
field public static final String POWER_WHITELIST_MANAGER = "power_whitelist";
field public static final String ROLLBACK_SERVICE = "rollback";
@@ -4278,6 +4279,7 @@ package android.util {
field public static final String FFLAG_OVERRIDE_PREFIX = "sys.fflag.override.";
field public static final String FFLAG_PREFIX = "sys.fflag.";
field public static final String HEARING_AID_SETTINGS = "settings_bluetooth_hearing_aid";
+ field public static final String NOTIF_CONVO_BYPASS_SHORTCUT_REQ = "settings_notif_convo_bypass_shortcut_req";
field public static final String PERSIST_PREFIX = "persist.sys.fflag.override.";
field public static final String SCREENRECORD_LONG_PRESS = "settings_screenrecord_long_press";
field public static final String SEAMLESS_TRANSFER = "settings_seamless_transfer";
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 8d5b5b4f3596..1441d48771d6 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -341,7 +341,7 @@ message Atom {
}
// Pulled events will start at field 10000.
- // Next: 10069
+ // Next: 10070
oneof pulled {
WifiBytesTransfer wifi_bytes_transfer = 10000;
WifiBytesTransferByFgBg wifi_bytes_transfer_by_fg_bg = 10001;
@@ -411,6 +411,7 @@ message Atom {
NotificationRemoteViews notification_remote_views = 10066;
DangerousPermissionStateSampled dangerous_permission_state_sampled = 10067;
GraphicsStats graphics_stats = 10068;
+ RuntimeAppOpsAccess runtime_app_ops_access = 10069;
}
// DO NOT USE field numbers above 100,000 in AOSP.
@@ -7086,7 +7087,7 @@ message AppOps {
// Uid of the package requesting the op
optional int32 uid = 1 [(is_uid) = true];
- // Nmae of the package performing the op
+ // Name of the package performing the op
optional string package_name = 2;
// operation id; maps to the OP_* constants in AppOpsManager.java
@@ -7872,3 +7873,35 @@ message GraphicsStats {
// more apps are running / rendering.
optional bool is_today = 16;
}
+
+/**
+ * Message related to dangerous (runtime) app ops access
+ */
+message RuntimeAppOpsAccess {
+ // Uid of the package accessing app op
+ optional int32 uid = 1 [(is_uid) = true];
+
+ // Name of the package accessing app op
+ optional string package_name = 2;
+
+ // operation id; maps to the OP_* constants in AppOpsManager.java
+ optional int32 op_id = 3;
+
+ // feature id; provided by developer when accessing related API, limited at 50 chars by API.
+ // Features must be provided through manifest using <feature> tag available in R and above.
+ optional string feature_id = 4;
+
+ // message related to app op access, limited to 600 chars by API
+ optional string message = 5;
+
+ enum SamplingStrategy {
+ DEFAULT = 0;
+ UNIFORM = 1;
+ RARELY_USED = 2;
+ }
+
+ // sampling strategy used to collect this message
+ optional SamplingStrategy sampling_strategy = 6;
+}
+
+
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index b5680331f63e..731afe8c0859 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -60,27 +60,6 @@ const int64_t NO_ALARM_UPDATE = INT64_MAX;
std::map<PullerKey, PullAtomInfo> StatsPullerManager::kAllPullAtomInfo = {
- // wifi_bytes_transfer_by_fg_bg
- {{.atomTag = android::util::WIFI_BYTES_TRANSFER_BY_FG_BG},
- {.additiveFields = {3, 4, 5, 6},
- .puller = new StatsCompanionServicePuller(android::util::WIFI_BYTES_TRANSFER_BY_FG_BG)}},
-
- // mobile_bytes_transfer
- {{.atomTag = android::util::MOBILE_BYTES_TRANSFER},
- {.additiveFields = {2, 3, 4, 5},
- .puller = new StatsCompanionServicePuller(android::util::MOBILE_BYTES_TRANSFER)}},
-
- // mobile_bytes_transfer_by_fg_bg
- {{.atomTag = android::util::MOBILE_BYTES_TRANSFER_BY_FG_BG},
- {.additiveFields = {3, 4, 5, 6},
- .puller =
- new StatsCompanionServicePuller(android::util::MOBILE_BYTES_TRANSFER_BY_FG_BG)}},
-
- // bluetooth_bytes_transfer
- {{.atomTag = android::util::BLUETOOTH_BYTES_TRANSFER},
- {.additiveFields = {2, 3},
- .puller = new StatsCompanionServicePuller(android::util::BLUETOOTH_BYTES_TRANSFER)}},
-
// kernel_wakelock
{{.atomTag = android::util::KERNEL_WAKELOCK},
{.puller = new StatsCompanionServicePuller(android::util::KERNEL_WAKELOCK)}},
@@ -132,10 +111,6 @@ std::map<PullerKey, PullAtomInfo> StatsPullerManager::kAllPullAtomInfo = {
{{.atomTag = android::util::MODEM_ACTIVITY_INFO},
{.puller = new StatsCompanionServicePuller(android::util::MODEM_ACTIVITY_INFO)}},
- // bluetooth_activity_info
- {{.atomTag = android::util::BLUETOOTH_ACTIVITY_INFO},
- {.puller = new StatsCompanionServicePuller(android::util::BLUETOOTH_ACTIVITY_INFO)}},
-
// system_elapsed_realtime
{{.atomTag = android::util::SYSTEM_ELAPSED_REALTIME},
{.coolDownNs = NS_PER_SEC,
@@ -249,10 +224,6 @@ std::map<PullerKey, PullAtomInfo> StatsPullerManager::kAllPullAtomInfo = {
.coolDownNs = 3 * NS_PER_SEC,
.puller = new StatsCompanionServicePuller(android::util::DISK_IO)}},
- // PowerProfile constants for power model calculations.
- {{.atomTag = android::util::POWER_PROFILE},
- {.puller = new StatsCompanionServicePuller(android::util::POWER_PROFILE)}},
-
// Process cpu stats. Min cool-down is 5 sec, inline with what AcitivityManagerService uses.
{{.atomTag = android::util::PROCESS_CPU_TIME},
{.coolDownNs = 5 * NS_PER_SEC /* min cool-down in seconds*/,
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index 8fe2f12a1023..f2702a864c2f 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -25,6 +25,7 @@ import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.Size;
import android.annotation.SystemApi;
import android.annotation.SystemService;
+import android.annotation.UserHandleAware;
import android.app.Activity;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
@@ -40,6 +41,7 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Parcelable;
+import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
import android.text.TextUtils;
@@ -528,12 +530,9 @@ public class AccountManager {
* authenticator known to the AccountManager service. Empty (never
* null) if no authenticators are known.
*/
+ @UserHandleAware
public AuthenticatorDescription[] getAuthenticatorTypes() {
- try {
- return mService.getAuthenticatorTypes(UserHandle.getCallingUserId());
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return getAuthenticatorTypesAsUser(mContext.getUserId());
}
/**
@@ -584,13 +583,10 @@ public class AccountManager {
* @return An array of {@link Account}, one for each account. Empty (never null) if no accounts
* have been added.
*/
+ @UserHandleAware
@NonNull
public Account[] getAccounts() {
- try {
- return mService.getAccounts(null, mContext.getOpPackageName());
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return getAccountsAsUser(mContext.getUserId());
}
/**
@@ -708,6 +704,7 @@ public class AccountManager {
* @return An array of {@link Account}, one per matching account. Empty (never null) if no
* accounts of the specified type have been added.
*/
+ @UserHandleAware
@NonNull
public Account[] getAccountsByType(String type) {
return getAccountsByTypeAsUser(type, mContext.getUser());
@@ -1183,23 +1180,11 @@ public class AccountManager {
* {@link #removeAccount(Account, Activity, AccountManagerCallback, Handler)}
* instead
*/
+ @UserHandleAware
@Deprecated
public AccountManagerFuture<Boolean> removeAccount(final Account account,
AccountManagerCallback<Boolean> callback, Handler handler) {
- if (account == null) throw new IllegalArgumentException("account is null");
- return new Future2Task<Boolean>(handler, callback) {
- @Override
- public void doWork() throws RemoteException {
- mService.removeAccount(mResponse, account, false);
- }
- @Override
- public Boolean bundleToResult(Bundle bundle) throws AuthenticatorException {
- if (!bundle.containsKey(KEY_BOOLEAN_RESULT)) {
- throw new AuthenticatorException("no result in response");
- }
- return bundle.getBoolean(KEY_BOOLEAN_RESULT);
- }
- }.start();
+ return removeAccountAsUser(account, callback, handler, mContext.getUser());
}
/**
@@ -1243,15 +1228,10 @@ public class AccountManager {
* adding accounts (of this type) has been disabled by policy
* </ul>
*/
+ @UserHandleAware
public AccountManagerFuture<Bundle> removeAccount(final Account account,
final Activity activity, AccountManagerCallback<Bundle> callback, Handler handler) {
- if (account == null) throw new IllegalArgumentException("account is null");
- return new AmsTask(activity, handler, callback) {
- @Override
- public void doWork() throws RemoteException {
- mService.removeAccount(mResponse, account, activity != null);
- }
- }.start();
+ return removeAccountAsUser(account, activity, callback, handler, mContext.getUser());
}
/**
@@ -1841,24 +1821,30 @@ public class AccountManager {
* creating a new account, usually because of network trouble
* </ul>
*/
+ @UserHandleAware
public AccountManagerFuture<Bundle> addAccount(final String accountType,
final String authTokenType, final String[] requiredFeatures,
final Bundle addAccountOptions,
final Activity activity, AccountManagerCallback<Bundle> callback, Handler handler) {
- if (accountType == null) throw new IllegalArgumentException("accountType is null");
- final Bundle optionsIn = new Bundle();
- if (addAccountOptions != null) {
- optionsIn.putAll(addAccountOptions);
- }
- optionsIn.putString(KEY_ANDROID_PACKAGE_NAME, mContext.getPackageName());
-
- return new AmsTask(activity, handler, callback) {
- @Override
- public void doWork() throws RemoteException {
- mService.addAccount(mResponse, accountType, authTokenType,
- requiredFeatures, activity != null, optionsIn);
+ if (Process.myUserHandle().equals(mContext.getUser())) {
+ if (accountType == null) throw new IllegalArgumentException("accountType is null");
+ final Bundle optionsIn = new Bundle();
+ if (addAccountOptions != null) {
+ optionsIn.putAll(addAccountOptions);
}
- }.start();
+ optionsIn.putString(KEY_ANDROID_PACKAGE_NAME, mContext.getPackageName());
+
+ return new AmsTask(activity, handler, callback) {
+ @Override
+ public void doWork() throws RemoteException {
+ mService.addAccount(mResponse, accountType, authTokenType,
+ requiredFeatures, activity != null, optionsIn);
+ }
+ }.start();
+ } else {
+ return addAccountAsUser(accountType, authTokenType, requiredFeatures, addAccountOptions,
+ activity, callback, handler, mContext.getUser());
+ }
}
/**
@@ -2002,6 +1988,7 @@ public class AccountManager {
* verifying the password, usually because of network trouble
* </ul>
*/
+ @UserHandleAware
public AccountManagerFuture<Bundle> confirmCredentials(final Account account,
final Bundle options,
final Activity activity,
@@ -3209,6 +3196,7 @@ public class AccountManager {
* </ul>
* @see #startAddAccountSession and #startUpdateCredentialsSession
*/
+ @UserHandleAware
public AccountManagerFuture<Bundle> finishSession(
final Bundle sessionBundle,
final Activity activity,
diff --git a/core/java/android/accounts/IAccountManager.aidl b/core/java/android/accounts/IAccountManager.aidl
index 012713891d11..ce68e082cf4f 100644
--- a/core/java/android/accounts/IAccountManager.aidl
+++ b/core/java/android/accounts/IAccountManager.aidl
@@ -34,7 +34,6 @@ interface IAccountManager {
String getPassword(in Account account);
String getUserData(in Account account, String key);
AuthenticatorDescription[] getAuthenticatorTypes(int userId);
- Account[] getAccounts(String accountType, String opPackageName);
Account[] getAccountsForPackage(String packageName, int uid, String opPackageName);
Account[] getAccountsByTypeForPackage(String type, String packageName, String opPackageName);
Account[] getAccountsAsUser(String accountType, int userId, String opPackageName);
@@ -45,8 +44,6 @@ interface IAccountManager {
void getAccountsByFeatures(in IAccountManagerResponse response, String accountType,
in String[] features, String opPackageName);
boolean addAccountExplicitly(in Account account, String password, in Bundle extras);
- void removeAccount(in IAccountManagerResponse response, in Account account,
- boolean expectActivityLaunch);
void removeAccountAsUser(in IAccountManagerResponse response, in Account account,
boolean expectActivityLaunch, int userId);
boolean removeAccountExplicitly(in Account account);
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 9aef20b29490..c3b07c8644da 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -4073,6 +4073,29 @@ public class ActivityManager {
}
/**
+ * Updates mcc mnc configuration and applies changes to the entire system.
+ *
+ * @param mcc mcc configuration to update.
+ * @param mnc mnc configuration to update.
+ * @throws RemoteException; IllegalArgumentException if mcc or mnc is null;
+ * @return Returns {@code true} if the configuration was updated successfully;
+ * {@code false} otherwise.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.CHANGE_CONFIGURATION)
+ public boolean updateMccMncConfiguration(@NonNull String mcc, @NonNull String mnc) {
+ if (mcc == null || mnc == null) {
+ throw new IllegalArgumentException("mcc or mnc cannot be null.");
+ }
+ try {
+ return getService().updateMccMncConfiguration(mcc, mnc);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Logs out current current foreground user by switching to the system user and stopping the
* user being switched from.
* @hide
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index e8494c4c5893..bd6baec30be0 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -188,6 +188,16 @@ interface IActivityManager {
*/
@UnsupportedAppUsage
boolean updateConfiguration(in Configuration values);
+ /**
+ * Updates mcc mnc configuration and applies changes to the entire system.
+ *
+ * @param mcc mcc configuration to update.
+ * @param mnc mnc configuration to update.
+ * @throws RemoteException; IllegalArgumentException if mcc or mnc is null.
+ * @return Returns {@code true} if the configuration was updated;
+ * {@code false} otherwise.
+ */
+ boolean updateMccMncConfiguration(in String mcc, in String mnc);
boolean stopServiceToken(in ComponentName className, in IBinder token, int startId);
@UnsupportedAppUsage
void setProcessLimit(int max);
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 96664ebd87bd..a9be9ea33089 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -346,6 +346,14 @@ public final class SystemServiceRegistry {
}
});
+ registerService(Context.NETWORK_STACK_SERVICE, IBinder.class,
+ new StaticServiceFetcher<IBinder>() {
+ @Override
+ public IBinder createService() {
+ return ServiceManager.getService(Context.NETWORK_STACK_SERVICE);
+ }
+ });
+
registerService(Context.TETHERING_SERVICE, TetheringManager.class,
new CachedServiceFetcher<TetheringManager>() {
@Override
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 69640b8321d1..caaa686ecf08 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -1992,16 +1992,6 @@ public class DevicePolicyManager {
public static final int CODE_SPLIT_SYSTEM_USER_DEVICE_SYSTEM_USER = 14;
/**
- * Result code for {@link #checkProvisioningPreCondition}.
- *
- * <p>Returned for {@link #ACTION_PROVISION_MANAGED_PROFILE} when adding a managed profile is
- * disallowed by {@link UserManager#DISALLOW_ADD_MANAGED_PROFILE}.
- *
- * @hide
- */
- public static final int CODE_ADD_MANAGED_PROFILE_DISALLOWED = 15;
-
- /**
* Result codes for {@link #checkProvisioningPreCondition} indicating all the provisioning pre
* conditions.
*
@@ -2013,7 +2003,7 @@ public class DevicePolicyManager {
CODE_USER_SETUP_COMPLETED, CODE_NOT_SYSTEM_USER, CODE_HAS_PAIRED,
CODE_MANAGED_USERS_NOT_SUPPORTED, CODE_SYSTEM_USER, CODE_CANNOT_ADD_MANAGED_PROFILE,
CODE_NOT_SYSTEM_USER_SPLIT, CODE_DEVICE_ADMIN_NOT_SUPPORTED,
- CODE_SPLIT_SYSTEM_USER_DEVICE_SYSTEM_USER, CODE_ADD_MANAGED_PROFILE_DISALLOWED
+ CODE_SPLIT_SYSTEM_USER_DEVICE_SYSTEM_USER
})
public @interface ProvisioningPreCondition {}
diff --git a/core/java/android/app/timedetector/PhoneTimeSuggestion.java b/core/java/android/app/timedetector/PhoneTimeSuggestion.java
index 479e4b4efb4c..bd649f88f40a 100644
--- a/core/java/android/app/timedetector/PhoneTimeSuggestion.java
+++ b/core/java/android/app/timedetector/PhoneTimeSuggestion.java
@@ -18,6 +18,7 @@ package android.app.timedetector;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.TimestampedValue;
@@ -28,17 +29,23 @@ import java.util.List;
import java.util.Objects;
/**
- * A time signal from a telephony source. The value can be {@code null} to indicate that the
- * telephony source has entered an "un-opinionated" state and any previously sent suggestions are
- * being withdrawn. When not {@code null}, the value consists of the number of milliseconds elapsed
- * since 1/1/1970 00:00:00 UTC and the time according to the elapsed realtime clock when that number
- * was established. The elapsed realtime clock is considered accurate but volatile, so time signals
- * must not be persisted across device resets.
+ * A time suggestion from an identified telephony source. e.g. from NITZ information from a specific
+ * radio.
+ *
+ * <p>The time value can be {@code null} to indicate that the telephony source has entered an
+ * "un-opinionated" state and any previous suggestions from the source are being withdrawn. When not
+ * {@code null}, the value consists of the number of milliseconds elapsed since 1/1/1970 00:00:00
+ * UTC and the time according to the elapsed realtime clock when that number was established. The
+ * elapsed realtime clock is considered accurate but volatile, so time suggestions must not be
+ * persisted across device resets.
*
* @hide
*/
+@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public final class PhoneTimeSuggestion implements Parcelable {
+ /** @hide */
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public static final @NonNull Parcelable.Creator<PhoneTimeSuggestion> CREATOR =
new Parcelable.Creator<PhoneTimeSuggestion>() {
public PhoneTimeSuggestion createFromParcel(Parcel in) {
@@ -85,15 +92,27 @@ public final class PhoneTimeSuggestion implements Parcelable {
dest.writeList(mDebugInfo);
}
+ /**
+ * Returns an identifier for the source of this suggestion. When a device has several "phones",
+ * i.e. sim slots or equivalent, it is used to identify which one.
+ */
public int getPhoneId() {
return mPhoneId;
}
+ /**
+ * Returns the suggestion. {@code null} means that the caller is no longer sure what time it
+ * is.
+ */
@Nullable
public TimestampedValue<Long> getUtcTime() {
return mUtcTime;
}
+ /**
+ * Returns debug metadata for the suggestion. The information is present in {@link #toString()}
+ * but is not considered for {@link #equals(Object)} and {@link #hashCode()}.
+ */
@NonNull
public List<String> getDebugInfo() {
return mDebugInfo == null
@@ -105,7 +124,7 @@ public final class PhoneTimeSuggestion implements Parcelable {
* information is present in {@link #toString()} but is not considered for
* {@link #equals(Object)} and {@link #hashCode()}.
*/
- public void addDebugInfo(String debugInfo) {
+ public void addDebugInfo(@NonNull String debugInfo) {
if (mDebugInfo == null) {
mDebugInfo = new ArrayList<>();
}
@@ -156,16 +175,19 @@ public final class PhoneTimeSuggestion implements Parcelable {
*
* @hide
*/
- public static class Builder {
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ public static final class Builder {
private final int mPhoneId;
- private TimestampedValue<Long> mUtcTime;
- private List<String> mDebugInfo;
+ @Nullable private TimestampedValue<Long> mUtcTime;
+ @Nullable private List<String> mDebugInfo;
+ /** Creates a builder with the specified {@code phoneId}. */
public Builder(int phoneId) {
mPhoneId = phoneId;
}
/** Returns the builder for call chaining. */
+ @NonNull
public Builder setUtcTime(@Nullable TimestampedValue<Long> utcTime) {
if (utcTime != null) {
// utcTime can be null, but the value it holds cannot.
@@ -177,6 +199,7 @@ public final class PhoneTimeSuggestion implements Parcelable {
}
/** Returns the builder for call chaining. */
+ @NonNull
public Builder addDebugInfo(@NonNull String debugInfo) {
if (mDebugInfo == null) {
mDebugInfo = new ArrayList<>();
@@ -186,6 +209,7 @@ public final class PhoneTimeSuggestion implements Parcelable {
}
/** Returns the {@link PhoneTimeSuggestion}. */
+ @NonNull
public PhoneTimeSuggestion build() {
return new PhoneTimeSuggestion(this);
}
diff --git a/core/java/android/app/timedetector/TimeDetector.java b/core/java/android/app/timedetector/TimeDetector.java
index 54dd1bed5361..7c29f017c02b 100644
--- a/core/java/android/app/timedetector/TimeDetector.java
+++ b/core/java/android/app/timedetector/TimeDetector.java
@@ -18,6 +18,7 @@ package android.app.timedetector;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.content.Context;
import android.os.RemoteException;
@@ -29,8 +30,11 @@ import android.util.Log;
/**
* The interface through which system components can send signals to the TimeDetectorService.
+ *
+ * <p>This class is marked non-final for mockito.
* @hide
*/
+@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
@SystemService(Context.TIME_DETECTOR_SERVICE)
public class TimeDetector {
private static final String TAG = "timedetector.TimeDetector";
@@ -38,6 +42,7 @@ public class TimeDetector {
private final ITimeDetectorService mITimeDetectorService;
+ /** @hide */
public TimeDetector() throws ServiceNotFoundException {
mITimeDetectorService = ITimeDetectorService.Stub.asInterface(
ServiceManager.getServiceOrThrow(Context.TIME_DETECTOR_SERVICE));
@@ -62,6 +67,8 @@ public class TimeDetector {
/**
* Suggests the user's manually entered current time to the detector.
+ *
+ * @hide
*/
@RequiresPermission(android.Manifest.permission.SUGGEST_MANUAL_TIME_AND_ZONE)
public void suggestManualTime(@NonNull ManualTimeSuggestion timeSuggestion) {
@@ -77,6 +84,8 @@ public class TimeDetector {
/**
* A shared utility method to create a {@link ManualTimeSuggestion}.
+ *
+ * @hide
*/
public static ManualTimeSuggestion createManualTimeSuggestion(long when, String why) {
TimestampedValue<Long> utcTime =
@@ -88,6 +97,8 @@ public class TimeDetector {
/**
* Suggests the time according to a network time source like NTP.
+ *
+ * @hide
*/
@RequiresPermission(android.Manifest.permission.SET_TIME)
public void suggestNetworkTime(NetworkTimeSuggestion timeSuggestion) {
diff --git a/core/java/android/app/timezonedetector/PhoneTimeZoneSuggestion.java b/core/java/android/app/timezonedetector/PhoneTimeZoneSuggestion.java
index e8162488394c..d71ffcb9f772 100644
--- a/core/java/android/app/timezonedetector/PhoneTimeZoneSuggestion.java
+++ b/core/java/android/app/timezonedetector/PhoneTimeZoneSuggestion.java
@@ -19,6 +19,7 @@ package android.app.timezonedetector;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -30,12 +31,27 @@ import java.util.List;
import java.util.Objects;
/**
- * A suggested time zone from a Phone-based signal, e.g. from MCC and NITZ information.
+ * A time zone suggestion from an identified telephony source, e.g. from MCC and NITZ information
+ * associated with a specific radio.
+ *
+ * <p>The time zone ID can be {@code null} to indicate that the telephony source has entered an
+ * "un-opinionated" state and any previous suggestions from that source are being withdrawn.
+ * When not {@code null}, the value consists of a suggested time zone ID and metadata that can be
+ * used to judge quality / certainty of the suggestion.
+ *
+ * <p>{@code matchType} must be set to {@link #MATCH_TYPE_NA} when {@code zoneId} is {@code null},
+ * and one of the other {@code MATCH_TYPE_} values when it is not {@code null}.
+ *
+ * <p>{@code quality} must be set to {@link #QUALITY_NA} when {@code zoneId} is {@code null},
+ * and one of the other {@code QUALITY_} values when it is not {@code null}.
*
* @hide
*/
+@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public final class PhoneTimeZoneSuggestion implements Parcelable {
+ /** @hide */
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
@NonNull
public static final Creator<PhoneTimeZoneSuggestion> CREATOR =
new Creator<PhoneTimeZoneSuggestion>() {
@@ -58,6 +74,7 @@ public final class PhoneTimeZoneSuggestion implements Parcelable {
return new Builder(phoneId).addDebugInfo(debugInfo).build();
}
+ /** @hide */
@IntDef({ MATCH_TYPE_NA, MATCH_TYPE_NETWORK_COUNTRY_ONLY, MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET,
MATCH_TYPE_EMULATOR_ZONE_ID, MATCH_TYPE_TEST_NETWORK_OFFSET_ONLY })
@Retention(RetentionPolicy.SOURCE)
@@ -90,6 +107,7 @@ public final class PhoneTimeZoneSuggestion implements Parcelable {
*/
public static final int MATCH_TYPE_TEST_NETWORK_OFFSET_ONLY = 5;
+ /** @hide */
@IntDef({ QUALITY_NA, QUALITY_SINGLE_ZONE, QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET,
QUALITY_MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS })
@Retention(RetentionPolicy.SOURCE)
@@ -115,7 +133,7 @@ public final class PhoneTimeZoneSuggestion implements Parcelable {
/**
* The ID of the phone this suggestion is associated with. For multiple-sim devices this
- * helps to establish origin so filtering / stickiness can be implemented.
+ * helps to establish source so filtering / stickiness can be implemented.
*/
private final int mPhoneId;
@@ -123,6 +141,7 @@ public final class PhoneTimeZoneSuggestion implements Parcelable {
* The suggestion. {@code null} means there is no current suggestion and any previous suggestion
* should be forgotten.
*/
+ @Nullable
private final String mZoneId;
/**
@@ -139,9 +158,10 @@ public final class PhoneTimeZoneSuggestion implements Parcelable {
private final int mQuality;
/**
- * Free-form debug information about how the signal was derived. Used for debug only,
+ * Free-form debug information about how the suggestion was derived. Used for debug only,
* intentionally not used in equals(), etc.
*/
+ @Nullable
private List<String> mDebugInfo;
private PhoneTimeZoneSuggestion(Builder builder) {
@@ -182,25 +202,47 @@ public final class PhoneTimeZoneSuggestion implements Parcelable {
return 0;
}
+ /**
+ * Returns an identifier for the source of this suggestion. When a device has several "phones",
+ * i.e. sim slots or equivalent, it is used to identify which one.
+ */
public int getPhoneId() {
return mPhoneId;
}
+ /**
+ * Returns the suggested time zone Olson ID, e.g. "America/Los_Angeles". {@code null} means that
+ * the caller is no longer sure what the current time zone is. See
+ * {@link PhoneTimeZoneSuggestion} for the associated {@code matchType} / {@code quality} rules.
+ */
@Nullable
public String getZoneId() {
return mZoneId;
}
+ /**
+ * Returns information about how the suggestion was determined which could be used to rank
+ * suggestions when several are available from different sources. See
+ * {@link PhoneTimeZoneSuggestion} for the associated rules.
+ */
@MatchType
public int getMatchType() {
return mMatchType;
}
+ /**
+ * Returns information about the likelihood of the suggested zone being correct. See
+ * {@link PhoneTimeZoneSuggestion} for the associated rules.
+ */
@Quality
public int getQuality() {
return mQuality;
}
+ /**
+ * Returns debug metadata for the suggestion. The information is present in {@link #toString()}
+ * but is not considered for {@link #equals(Object)} and {@link #hashCode()}.
+ */
@NonNull
public List<String> getDebugInfo() {
return mDebugInfo == null
@@ -267,36 +309,43 @@ public final class PhoneTimeZoneSuggestion implements Parcelable {
*
* @hide
*/
- public static class Builder {
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ public static final class Builder {
private final int mPhoneId;
- private String mZoneId;
+ @Nullable private String mZoneId;
@MatchType private int mMatchType;
@Quality private int mQuality;
- private List<String> mDebugInfo;
+ @Nullable private List<String> mDebugInfo;
public Builder(int phoneId) {
mPhoneId = phoneId;
}
- /** Returns the builder for call chaining. */
- public Builder setZoneId(String zoneId) {
+ /**
+ * Returns the builder for call chaining.
+ */
+ @NonNull
+ public Builder setZoneId(@Nullable String zoneId) {
mZoneId = zoneId;
return this;
}
/** Returns the builder for call chaining. */
+ @NonNull
public Builder setMatchType(@MatchType int matchType) {
mMatchType = matchType;
return this;
}
/** Returns the builder for call chaining. */
+ @NonNull
public Builder setQuality(@Quality int quality) {
mQuality = quality;
return this;
}
/** Returns the builder for call chaining. */
+ @NonNull
public Builder addDebugInfo(@NonNull String debugInfo) {
if (mDebugInfo == null) {
mDebugInfo = new ArrayList<>();
@@ -333,6 +382,7 @@ public final class PhoneTimeZoneSuggestion implements Parcelable {
}
/** Returns the {@link PhoneTimeZoneSuggestion}. */
+ @NonNull
public PhoneTimeZoneSuggestion build() {
validate();
return new PhoneTimeZoneSuggestion(this);
diff --git a/core/java/android/app/timezonedetector/TimeZoneDetector.java b/core/java/android/app/timezonedetector/TimeZoneDetector.java
index e165d8a76caa..5b5f311264e3 100644
--- a/core/java/android/app/timezonedetector/TimeZoneDetector.java
+++ b/core/java/android/app/timezonedetector/TimeZoneDetector.java
@@ -18,6 +18,7 @@ package android.app.timezonedetector;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.content.Context;
import android.os.RemoteException;
@@ -28,8 +29,10 @@ import android.util.Log;
/**
* The interface through which system components can send signals to the TimeZoneDetectorService.
*
+ * <p>This class is non-final for mockito.
* @hide
*/
+@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
@SystemService(Context.TIME_ZONE_DETECTOR_SERVICE)
public class TimeZoneDetector {
private static final String TAG = "timezonedetector.TimeZoneDetector";
@@ -37,6 +40,7 @@ public class TimeZoneDetector {
private final ITimeZoneDetectorService mITimeZoneDetectorService;
+ /** @hide */
public TimeZoneDetector() throws ServiceNotFoundException {
mITimeZoneDetectorService = ITimeZoneDetectorService.Stub.asInterface(
ServiceManager.getServiceOrThrow(Context.TIME_ZONE_DETECTOR_SERVICE));
@@ -46,7 +50,10 @@ public class TimeZoneDetector {
* Suggests the current time zone, determined using telephony signals, to the detector. The
* detector may ignore the signal based on system settings, whether better information is
* available, and so on.
+ *
+ * @hide
*/
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
@RequiresPermission(android.Manifest.permission.SUGGEST_PHONE_TIME_AND_ZONE)
public void suggestPhoneTimeZone(@NonNull PhoneTimeZoneSuggestion timeZoneSuggestion) {
if (DEBUG) {
@@ -62,6 +69,8 @@ public class TimeZoneDetector {
/**
* Suggests the current time zone, determined for the user's manually information, to the
* detector. The detector may ignore the signal based on system settings.
+ *
+ * @hide
*/
@RequiresPermission(android.Manifest.permission.SUGGEST_MANUAL_TIME_AND_ZONE)
public void suggestManualTimeZone(@NonNull ManualTimeZoneSuggestion timeZoneSuggestion) {
@@ -77,6 +86,8 @@ public class TimeZoneDetector {
/**
* A shared utility method to create a {@link ManualTimeZoneSuggestion}.
+ *
+ * @hide
*/
public static ManualTimeZoneSuggestion createManualTimeZoneSuggestion(String tzId, String why) {
ManualTimeZoneSuggestion suggestion = new ManualTimeZoneSuggestion(tzId);
diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java
index 176a181965ed..a60e591dd0e6 100644
--- a/core/java/android/app/usage/UsageStatsManager.java
+++ b/core/java/android/app/usage/UsageStatsManager.java
@@ -163,7 +163,6 @@ public final class UsageStatsManager {
/**
* The app spent sufficient time in the old bucket without any substantial event so it reached
* the timeout threshold to have its bucket lowered.
- *
* @hide
*/
public static final int REASON_MAIN_TIMEOUT = 0x0200;
@@ -173,15 +172,25 @@ public final class UsageStatsManager {
*/
public static final int REASON_MAIN_USAGE = 0x0300;
/**
- * Forced by a core UID.
+ * Forced by the user/developer, either explicitly or implicitly through some action. If user
+ * action was not involved and this is purely due to the system,
+ * {@link #REASON_MAIN_FORCED_BY_SYSTEM} should be used instead.
* @hide
*/
- public static final int REASON_MAIN_FORCED = 0x0400;
+ public static final int REASON_MAIN_FORCED_BY_USER = 0x0400;
/**
- * Set by a privileged system app.
+ * Set by a privileged system app. This may be overridden by
+ * {@link #REASON_MAIN_FORCED_BY_SYSTEM} or user action.
* @hide
*/
public static final int REASON_MAIN_PREDICTED = 0x0500;
+ /**
+ * Forced by the system, independent of user action. If user action is involved,
+ * {@link #REASON_MAIN_FORCED_BY_USER} should be used instead. When this is used, only
+ * {@link #REASON_MAIN_FORCED_BY_SYSTEM} or user action can change the bucket.
+ * @hide
+ */
+ public static final int REASON_MAIN_FORCED_BY_SYSTEM = 0x0600;
/** @hide */
public static final int REASON_SUB_MASK = 0x00FF;
@@ -1016,7 +1025,10 @@ public final class UsageStatsManager {
case REASON_MAIN_DEFAULT:
sb.append("d");
break;
- case REASON_MAIN_FORCED:
+ case REASON_MAIN_FORCED_BY_SYSTEM:
+ sb.append("s");
+ break;
+ case REASON_MAIN_FORCED_BY_USER:
sb.append("f");
break;
case REASON_MAIN_PREDICTED:
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 1b40a184c52b..9ef95743b0c9 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3953,10 +3953,12 @@ public abstract class Context {
/**
* Use with {@link android.os.ServiceManager.getService()} to retrieve a
- * {@link NetworkStackClient} IBinder for communicating with the network stack
+ * {@link INetworkStackConnector} IBinder for communicating with the network stack
* @hide
* @see NetworkStackClient
*/
+ @SystemApi
+ @TestApi
public static final String NETWORK_STACK_SERVICE = "network_stack";
/**
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 4bf3e905697d..c523f6514c54 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -517,7 +517,7 @@ public class ConnectivityManager {
* The absence of a connection type.
* @hide
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562)
+ @SystemApi
public static final int TYPE_NONE = -1;
/**
@@ -3169,10 +3169,10 @@ public class ConnectivityManager {
/**
* @hide
* Register a NetworkAgent with ConnectivityService.
- * @return NetID corresponding to NetworkAgent.
+ * @return Network corresponding to NetworkAgent.
*/
@RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
- public int registerNetworkAgent(Messenger messenger, NetworkInfo ni, LinkProperties lp,
+ public Network registerNetworkAgent(Messenger messenger, NetworkInfo ni, LinkProperties lp,
NetworkCapabilities nc, int score, NetworkAgentConfig config) {
return registerNetworkAgent(messenger, ni, lp, nc, score, config, NetworkProvider.ID_NONE);
}
@@ -3180,10 +3180,10 @@ public class ConnectivityManager {
/**
* @hide
* Register a NetworkAgent with ConnectivityService.
- * @return NetID corresponding to NetworkAgent.
+ * @return Network corresponding to NetworkAgent.
*/
@RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
- public int registerNetworkAgent(Messenger messenger, NetworkInfo ni, LinkProperties lp,
+ public Network registerNetworkAgent(Messenger messenger, NetworkInfo ni, LinkProperties lp,
NetworkCapabilities nc, int score, NetworkAgentConfig config, int providerId) {
try {
return mService.registerNetworkAgent(messenger, ni, lp, nc, score, config, providerId);
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 7691beba3208..186196bd31c7 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -152,7 +152,7 @@ interface IConnectivityManager
void declareNetworkRequestUnfulfillable(in NetworkRequest request);
- int registerNetworkAgent(in Messenger messenger, in NetworkInfo ni, in LinkProperties lp,
+ Network registerNetworkAgent(in Messenger messenger, in NetworkInfo ni, in LinkProperties lp,
in NetworkCapabilities nc, int score, in NetworkAgentConfig config,
in int factorySerialNumber);
diff --git a/core/java/android/net/NattKeepalivePacketData.java b/core/java/android/net/NattKeepalivePacketData.java
index 3fb52f12a88d..bd39c13ba092 100644
--- a/core/java/android/net/NattKeepalivePacketData.java
+++ b/core/java/android/net/NattKeepalivePacketData.java
@@ -16,9 +16,11 @@
package android.net;
-import static android.net.SocketKeepalive.ERROR_INVALID_IP_ADDRESS;
-import static android.net.SocketKeepalive.ERROR_INVALID_PORT;
+import static android.net.InvalidPacketException.ERROR_INVALID_IP_ADDRESS;
+import static android.net.InvalidPacketException.ERROR_INVALID_PORT;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.net.util.IpUtils;
import android.os.Parcel;
import android.os.Parcelable;
@@ -30,20 +32,22 @@ import java.nio.ByteBuffer;
import java.nio.ByteOrder;
/** @hide */
+@SystemApi
public final class NattKeepalivePacketData extends KeepalivePacketData implements Parcelable {
private static final int IPV4_HEADER_LENGTH = 20;
private static final int UDP_HEADER_LENGTH = 8;
// This should only be constructed via static factory methods, such as
// nattKeepalivePacket
- private NattKeepalivePacketData(InetAddress srcAddress, int srcPort,
- InetAddress dstAddress, int dstPort, byte[] data) throws
+ public NattKeepalivePacketData(@NonNull InetAddress srcAddress, int srcPort,
+ @NonNull InetAddress dstAddress, int dstPort, @NonNull byte[] data) throws
InvalidPacketException {
super(srcAddress, srcPort, dstAddress, dstPort, data);
}
/**
* Factory method to create Nat-T keepalive packet structure.
+ * @hide
*/
public static NattKeepalivePacketData nattKeepalivePacket(
InetAddress srcAddress, int srcPort, InetAddress dstAddress, int dstPort)
@@ -87,7 +91,7 @@ public final class NattKeepalivePacketData extends KeepalivePacketData implement
}
/** Write to parcel */
- public void writeToParcel(Parcel out, int flags) {
+ public void writeToParcel(@NonNull Parcel out, int flags) {
out.writeString(srcAddress.getHostAddress());
out.writeString(dstAddress.getHostAddress());
out.writeInt(srcPort);
@@ -95,7 +99,7 @@ public final class NattKeepalivePacketData extends KeepalivePacketData implement
}
/** Parcelable Creator */
- public static final Parcelable.Creator<NattKeepalivePacketData> CREATOR =
+ public static final @NonNull Parcelable.Creator<NattKeepalivePacketData> CREATOR =
new Parcelable.Creator<NattKeepalivePacketData>() {
public NattKeepalivePacketData createFromParcel(Parcel in) {
final InetAddress srcAddress =
diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java
index fc72eecd4145..d28620433c21 100644
--- a/core/java/android/net/NetworkAgent.java
+++ b/core/java/android/net/NetworkAgent.java
@@ -44,9 +44,10 @@ import java.util.concurrent.atomic.AtomicBoolean;
* @hide
*/
public abstract class NetworkAgent {
- // Guaranteed to be valid (not NETID_UNSET), otherwise registerNetworkAgent() would have thrown
- // an exception.
- public final int netId;
+ // Guaranteed to be non-null, otherwise registerNetworkAgent() would have thrown
+ // an exception. Be careful in tests when mocking though.
+ @NonNull
+ public final Network network;
private final Handler mHandler;
private volatile AsyncChannel mAsyncChannel;
@@ -246,7 +247,7 @@ public abstract class NetworkAgent {
if (VDBG) log("Registering NetworkAgent");
ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService(
Context.CONNECTIVITY_SERVICE);
- netId = cm.registerNetworkAgent(new Messenger(mHandler), new NetworkInfo(ni),
+ network = cm.registerNetworkAgent(new Messenger(mHandler), new NetworkInfo(ni),
new LinkProperties(lp), new NetworkCapabilities(nc), score, config,
providerId);
}
diff --git a/core/java/android/net/NetworkAgentConfig.java b/core/java/android/net/NetworkAgentConfig.java
index 3a383a44cdc3..abc6b67efb11 100644
--- a/core/java/android/net/NetworkAgentConfig.java
+++ b/core/java/android/net/NetworkAgentConfig.java
@@ -18,22 +18,27 @@ package android.net;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
+import android.text.TextUtils;
/**
- * A grab-bag of information (metadata, policies, properties, etc) about a
- * {@link Network}. Since this contains PII, it should not be sent outside the
- * system.
+ * Allows a network transport to provide the system with policy and configuration information about
+ * a particular network when registering a {@link NetworkAgent}. This information cannot change once
+ * the agent is registered.
*
* @hide
*/
-public class NetworkAgentConfig implements Parcelable {
+@SystemApi
+public final class NetworkAgentConfig implements Parcelable {
/**
* If the {@link Network} is a VPN, whether apps are allowed to bypass the
* VPN. This is set by a {@link VpnService} and used by
* {@link ConnectivityManager} when creating a VPN.
+ *
+ * @hide
*/
public boolean allowBypass;
@@ -43,6 +48,8 @@ public class NetworkAgentConfig implements Parcelable {
* ap in the wifi settings to trigger a connection is explicit. A 3rd party app asking to
* connect to a particular access point is also explicit, though this may change in the future
* as we want apps to use the multinetwork apis.
+ *
+ * @hide
*/
public boolean explicitlySelected;
@@ -50,12 +57,16 @@ public class NetworkAgentConfig implements Parcelable {
* Set if the user desires to use this network even if it is unvalidated. This field has meaning
* only if {@link explicitlySelected} is true. If it is, this field must also be set to the
* appropriate value based on previous user choice.
+ *
+ * @hide
*/
public boolean acceptUnvalidated;
/**
* Whether the user explicitly set that this network should be validated even if presence of
* only partial internet connectivity.
+ *
+ * @hide
*/
public boolean acceptPartialConnectivity;
@@ -65,29 +76,62 @@ public class NetworkAgentConfig implements Parcelable {
* procedure, a carrier specific provisioning notification will be placed.
* only one notification should be displayed. This field is set based on
* which notification should be used for provisioning.
+ *
+ * @hide
*/
public boolean provisioningNotificationDisabled;
/**
+ *
+ * @return whether the sign in to network notification is enabled by this configuration.
+ */
+ public boolean isProvisioningNotificationEnabled() {
+ return !provisioningNotificationDisabled;
+ }
+
+ /**
* For mobile networks, this is the subscriber ID (such as IMSI).
+ *
+ * @hide
*/
public String subscriberId;
/**
+ * @return the subscriber ID, or null if none.
+ */
+ @Nullable
+ public String getSubscriberId() {
+ return subscriberId;
+ }
+
+ /**
* Set to skip 464xlat. This means the device will treat the network as IPv6-only and
* will not attempt to detect a NAT64 via RFC 7050 DNS lookups.
+ *
+ * @hide
*/
public boolean skip464xlat;
/**
+ * @return whether NAT64 prefix detection is enabled.
+ */
+ public boolean isNat64DetectionEnabled() {
+ return !skip464xlat;
+ }
+
+ /**
* Set to true if the PRIVATE_DNS_BROKEN notification has shown for this network.
* Reset this bit when private DNS mode is changed from strict mode to opportunistic/off mode.
+ *
+ * @hide
*/
public boolean hasShownBroken;
+ /** @hide */
public NetworkAgentConfig() {
}
+ /** @hide */
public NetworkAgentConfig(@Nullable NetworkAgentConfig nac) {
if (nac != null) {
allowBypass = nac.allowBypass;
@@ -99,13 +143,63 @@ public class NetworkAgentConfig implements Parcelable {
}
}
+ /**
+ * Builder class to facilitate constructing {@link NetworkAgentConfig} objects.
+ */
+ public static class Builder {
+ private final NetworkAgentConfig mConfig = new NetworkAgentConfig();
+
+ /**
+ * Sets the subscriber ID for this network.
+ *
+ * @return this builder, to facilitate chaining.
+ */
+ @NonNull
+ public Builder setSubscriberId(@Nullable String subscriberId) {
+ mConfig.subscriberId = subscriberId;
+ return this;
+ }
+
+ /**
+ * Disables active detection of NAT64 (e.g., via RFC 7050 DNS lookups). Used to save power
+ * and reduce idle traffic on networks that are known to be IPv6-only without a NAT64.
+ *
+ * @return this builder, to facilitate chaining.
+ */
+ @NonNull
+ public Builder disableNat64Detection() {
+ mConfig.skip464xlat = true;
+ return this;
+ }
+
+ /**
+ * Disables the "Sign in to network" notification. Used if the network transport will
+ * perform its own carrier-specific provisioning procedure.
+ *
+ * @return this builder, to facilitate chaining.
+ */
+ @NonNull
+ public Builder disableProvisioningNotification() {
+ mConfig.provisioningNotificationDisabled = true;
+ return this;
+ }
+
+ /**
+ * Returns the constructed {@link NetworkAgentConfig} object.
+ */
+ @NonNull
+ public NetworkAgentConfig build() {
+ return mConfig;
+ }
+ }
+
@Override
public int describeContents() {
return 0;
}
@Override
- public void writeToParcel(Parcel out, int flags) {
+ public void writeToParcel(@NonNull Parcel out, int flags) {
out.writeInt(allowBypass ? 1 : 0);
out.writeInt(explicitlySelected ? 1 : 0);
out.writeInt(acceptUnvalidated ? 1 : 0);
diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java
index f6dc52522cb2..428a4ea32b28 100644
--- a/core/java/android/net/NetworkScoreManager.java
+++ b/core/java/android/net/NetworkScoreManager.java
@@ -163,27 +163,26 @@ public class NetworkScoreManager {
public static final String EXTRA_NEW_SCORER = "newScorer";
/** @hide */
- @IntDef({CACHE_FILTER_NONE, CACHE_FILTER_CURRENT_NETWORK, CACHE_FILTER_SCAN_RESULTS})
+ @IntDef({SCORE_FILTER_NONE, SCORE_FILTER_CURRENT_NETWORK, SCORE_FILTER_SCAN_RESULTS})
@Retention(RetentionPolicy.SOURCE)
- public @interface CacheUpdateFilter {}
+ public @interface ScoreUpdateFilter {}
/**
- * Do not filter updates sent to the cache.
- * @hide
+ * Do not filter updates sent to the {@link NetworkScoreCallback}].
*/
- public static final int CACHE_FILTER_NONE = 0;
+ public static final int SCORE_FILTER_NONE = 0;
/**
- * Only send cache updates when the network matches the connected network.
- * @hide
+ * Only send updates to the {@link NetworkScoreCallback} when the network matches the connected
+ * network.
*/
- public static final int CACHE_FILTER_CURRENT_NETWORK = 1;
+ public static final int SCORE_FILTER_CURRENT_NETWORK = 1;
/**
- * Only send cache updates when the network is part of the current scan result set.
- * @hide
+ * Only send updates to the {@link NetworkScoreCallback} when the network is part of the
+ * current scan result set.
*/
- public static final int CACHE_FILTER_SCAN_RESULTS = 2;
+ public static final int SCORE_FILTER_SCAN_RESULTS = 2;
/** @hide */
@IntDef({RECOMMENDATIONS_ENABLED_FORCED_OFF, RECOMMENDATIONS_ENABLED_OFF,
@@ -410,7 +409,7 @@ public class NetworkScoreManager {
@RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES)
@Deprecated // migrate to registerNetworkScoreCache(int, INetworkScoreCache, int)
public void registerNetworkScoreCache(int networkType, INetworkScoreCache scoreCache) {
- registerNetworkScoreCache(networkType, scoreCache, CACHE_FILTER_NONE);
+ registerNetworkScoreCache(networkType, scoreCache, SCORE_FILTER_NONE);
}
/**
@@ -418,7 +417,7 @@ public class NetworkScoreManager {
*
* @param networkType the type of network this cache can handle. See {@link NetworkKey#type}
* @param scoreCache implementation of {@link INetworkScoreCache} to store the scores
- * @param filterType the {@link CacheUpdateFilter} to apply
+ * @param filterType the {@link ScoreUpdateFilter} to apply
* @throws SecurityException if the caller does not hold the
* {@link permission#REQUEST_NETWORK_SCORES} permission.
* @throws IllegalArgumentException if a score cache is already registered for this type.
@@ -426,7 +425,7 @@ public class NetworkScoreManager {
*/
@RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES)
public void registerNetworkScoreCache(int networkType, INetworkScoreCache scoreCache,
- @CacheUpdateFilter int filterType) {
+ @ScoreUpdateFilter int filterType) {
try {
mService.registerNetworkScoreCache(networkType, scoreCache, filterType);
} catch (RemoteException e) {
@@ -510,7 +509,7 @@ public class NetworkScoreManager {
* Register a network score callback.
*
* @param networkType the type of network this cache can handle. See {@link NetworkKey#type}
- * @param filterType the {@link CacheUpdateFilter} to apply
+ * @param filterType the {@link ScoreUpdateFilter} to apply
* @param callback implementation of {@link NetworkScoreCallback} that will be invoked when the
* scores change.
* @param executor The executor on which to execute the callbacks.
@@ -522,7 +521,7 @@ public class NetworkScoreManager {
@SystemApi
@RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES)
public void registerNetworkScoreCallback(@NetworkKey.NetworkType int networkType,
- @CacheUpdateFilter int filterType,
+ @ScoreUpdateFilter int filterType,
@NonNull @CallbackExecutor Executor executor,
@NonNull NetworkScoreCallback callback) throws SecurityException {
if (callback == null || executor == null) {
diff --git a/core/java/android/os/TimestampedValue.java b/core/java/android/os/TimestampedValue.java
index 348574ed43c7..f4c87ac9dfc9 100644
--- a/core/java/android/os/TimestampedValue.java
+++ b/core/java/android/os/TimestampedValue.java
@@ -18,6 +18,7 @@ package android.os;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
import java.util.Objects;
@@ -35,19 +36,27 @@ import java.util.Objects;
* @param <T> the type of the value with an associated timestamp
* @hide
*/
+@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public final class TimestampedValue<T> implements Parcelable {
private final long mReferenceTimeMillis;
+ @Nullable
private final T mValue;
- public TimestampedValue(long referenceTimeMillis, T value) {
+ public TimestampedValue(long referenceTimeMillis, @Nullable T value) {
mReferenceTimeMillis = referenceTimeMillis;
mValue = value;
}
+ /** Returns the reference time value. See {@link TimestampedValue} for more information. */
public long getReferenceTimeMillis() {
return mReferenceTimeMillis;
}
+ /**
+ * Returns the value associated with the timestamp. See {@link TimestampedValue} for more
+ * information.
+ */
+ @Nullable
public T getValue() {
return mValue;
}
@@ -86,6 +95,8 @@ public final class TimestampedValue<T> implements Parcelable {
return one.mReferenceTimeMillis - two.mReferenceTimeMillis;
}
+ /** @hide */
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public static final @NonNull Parcelable.Creator<TimestampedValue<?>> CREATOR =
new Parcelable.ClassLoaderCreator<TimestampedValue<?>>() {
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 548b1230d6e2..089122ddb023 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -523,7 +523,9 @@ public final class Settings {
* Input: The Intent's data URI specifies bootstrapping information for authenticating and
* provisioning the peer, and uses a "DPP" scheme. The URI should be attached to the intent
* using {@link Intent#setData(Uri)}. The calling app can obtain a DPP URI in any
- * way, e.g. by scanning a QR code or other out-of-band methods.
+ * way, e.g. by scanning a QR code or other out-of-band methods. The calling app may also
+ * attach the {@link #EXTRA_EASY_CONNECT_BAND_LIST} extra to provide information
+ * about the bands supported by the enrollee device.
* <p>
* Output: After calling {@link android.app.Activity#startActivityForResult}, the callback
* {@code onActivityResult} will have resultCode {@link android.app.Activity#RESULT_OK} if
@@ -595,17 +597,29 @@ public final class Settings {
/**
* Activity Extra: The Band List that the Enrollee supports.
* <p>
- * An extra returned on the result intent received when using the {@link
- * #ACTION_PROCESS_WIFI_EASY_CONNECT_URI} intent to launch the Easy Connect Operation. This
- * extra contains the bands the Enrollee supports, expressed as the Global Operating Class,
- * see Table E-4 in IEEE Std 802.11-2016 Global operating classes. This value is populated only
- * by remote R2 devices, and only for the following error codes: {@link
- * android.net.wifi.EasyConnectStatusCallback#EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK}
- * {@link android.net.wifi.EasyConnectStatusCallback#EASY_CONNECT_EVENT_FAILURE_ENROLLEE_AUTHENTICATION}
+ * This extra contains the bands the Enrollee supports, expressed as the Global Operating
+ * Class, see Table E-4 in IEEE Std 802.11-2016 Global operating classes. It is used both as
+ * input, to configure the Easy Connect operation and as output of the operation.
+ * <p>
+ * As input: an optional extra to be attached to the
+ * {@link #ACTION_PROCESS_WIFI_EASY_CONNECT_URI}. If attached, it indicates the bands which
+ * the remote device (enrollee, device-to-be-configured) supports. The Settings operation
+ * may take this into account when presenting the user with list of networks configurations
+ * to be used. The calling app may obtain this information in any out-of-band method. The
+ * information should be attached as an array of raw integers - using the
+ * {@link Intent#putExtra(String, int[])}.
+ * <p>
+ * As output: an extra returned on the result intent received when using the
+ * {@link #ACTION_PROCESS_WIFI_EASY_CONNECT_URI} intent to launch the Easy Connect Operation
+ * . This value is populated only by remote R2 devices, and only for the following error
+ * codes:
+ * {@link android.net.wifi.EasyConnectStatusCallback#EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK},
+ * {@link android.net.wifi.EasyConnectStatusCallback#EASY_CONNECT_EVENT_FAILURE_ENROLLEE_AUTHENTICATION},
+ * or
* {@link android.net.wifi.EasyConnectStatusCallback#EASY_CONNECT_EVENT_FAILURE_ENROLLEE_REJECTED_CONFIGURATION}.
- * Therefore, always check if this extra is available using {@link Intent#hasExtra(String)}. If
- * there is no error, i.e. if the operation returns {@link android.app.Activity#RESULT_OK}, then
- * this extra is not attached to the result intent.
+ * Therefore, always check if this extra is available using {@link Intent#hasExtra(String)}.
+ * If there is no error, i.e. if the operation returns {@link android.app.Activity#RESULT_OK}
+ * , then this extra is not attached to the result intent.
* <p>
* Use the {@link Intent#getIntArrayExtra(String)} to obtain the list.
*/
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index 1b2db36c1335..9d22d304ad00 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -42,6 +42,8 @@ public class FeatureFlagUtils {
public static final String DYNAMIC_SYSTEM = "settings_dynamic_system";
public static final String SETTINGS_WIFITRACKER2 = "settings_wifitracker2";
public static final String SETTINGS_FUSE_FLAG = "settings_fuse";
+ public static final String NOTIF_CONVO_BYPASS_SHORTCUT_REQ =
+ "settings_notif_convo_bypass_shortcut_req";
private static final Map<String, String> DEFAULT_FLAGS;
@@ -60,6 +62,7 @@ public class FeatureFlagUtils {
DEFAULT_FLAGS.put("settings_work_profile", "true");
DEFAULT_FLAGS.put("settings_controller_loading_enhancement", "false");
DEFAULT_FLAGS.put("settings_conditionals", "false");
+ DEFAULT_FLAGS.put(NOTIF_CONVO_BYPASS_SHORTCUT_REQ, "false");
}
/**
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index ca8ba4ca1b8a..e0f6e0668f8b 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -826,6 +826,10 @@ public final class ViewRootImpl implements ViewParent,
if (mWindowAttributes.packageName == null) {
mWindowAttributes.packageName = mBasePackageName;
}
+ if (WindowManagerGlobal.USE_BLAST_ADAPTER) {
+ mWindowAttributes.privateFlags |=
+ WindowManager.LayoutParams.PRIVATE_FLAG_USE_BLAST;
+ }
attrs = mWindowAttributes;
setTag();
@@ -1308,7 +1312,7 @@ public final class ViewRootImpl implements ViewParent,
mWindowAttributes.privateFlags |= compatibleWindowFlag;
if (WindowManagerGlobal.USE_BLAST_ADAPTER) {
- mWindowAttributes.privateFlags =
+ mWindowAttributes.privateFlags |=
WindowManager.LayoutParams.PRIVATE_FLAG_USE_BLAST;
}
diff --git a/core/java/android/view/inputmethod/InlineSuggestionsRequest.java b/core/java/android/view/inputmethod/InlineSuggestionsRequest.java
index 386c9cb9d14f..860ce90d5fc0 100644
--- a/core/java/android/view/inputmethod/InlineSuggestionsRequest.java
+++ b/core/java/android/view/inputmethod/InlineSuggestionsRequest.java
@@ -17,6 +17,8 @@
package android.view.inputmethod;
import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.ActivityThread;
import android.os.Parcelable;
import android.view.inline.InlinePresentationSpec;
@@ -49,6 +51,21 @@ public final class InlineSuggestionsRequest implements Parcelable {
*/
private final @NonNull List<InlinePresentationSpec> mPresentationSpecs;
+ /**
+ * The package name of the app that requests for the inline suggestions and will host the
+ * embedded suggestion views. The app does not have to set the value for the field because
+ * it'll be set by the system for safety reasons.
+ */
+ private @NonNull String mHostPackageName;
+
+ /**
+ * @hide
+ * @see {@link #mHostPackageName}.
+ */
+ public void setHostPackageName(@NonNull String hostPackageName) {
+ mHostPackageName = hostPackageName;
+ }
+
private void onConstructed() {
Preconditions.checkState(mMaxSuggestionCount >= mPresentationSpecs.size());
}
@@ -57,9 +74,15 @@ public final class InlineSuggestionsRequest implements Parcelable {
return SUGGESTION_COUNT_UNLIMITED;
}
+ private static String defaultHostPackageName() {
+ return ActivityThread.currentPackageName();
+ }
+
/** @hide */
abstract static class BaseBuilder {
abstract Builder setPresentationSpecs(@NonNull List<InlinePresentationSpec> value);
+
+ abstract Builder setHostPackageName(@Nullable String value);
}
@@ -80,11 +103,15 @@ public final class InlineSuggestionsRequest implements Parcelable {
@DataClass.Generated.Member
/* package-private */ InlineSuggestionsRequest(
int maxSuggestionCount,
- @NonNull List<InlinePresentationSpec> presentationSpecs) {
+ @NonNull List<InlinePresentationSpec> presentationSpecs,
+ @NonNull String hostPackageName) {
this.mMaxSuggestionCount = maxSuggestionCount;
this.mPresentationSpecs = presentationSpecs;
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, mPresentationSpecs);
+ this.mHostPackageName = hostPackageName;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mHostPackageName);
onConstructed();
}
@@ -108,6 +135,16 @@ public final class InlineSuggestionsRequest implements Parcelable {
return mPresentationSpecs;
}
+ /**
+ * The package name of the app that requests for the inline suggestions and will host the
+ * embedded suggestion views. The app does not have to set the value for the field because
+ * it'll be set by the system for safety reasons.
+ */
+ @DataClass.Generated.Member
+ public @NonNull String getHostPackageName() {
+ return mHostPackageName;
+ }
+
@Override
@DataClass.Generated.Member
public String toString() {
@@ -116,13 +153,14 @@ public final class InlineSuggestionsRequest implements Parcelable {
return "InlineSuggestionsRequest { " +
"maxSuggestionCount = " + mMaxSuggestionCount + ", " +
- "presentationSpecs = " + mPresentationSpecs +
+ "presentationSpecs = " + mPresentationSpecs + ", " +
+ "hostPackageName = " + mHostPackageName +
" }";
}
@Override
@DataClass.Generated.Member
- public boolean equals(@android.annotation.Nullable Object o) {
+ public boolean equals(@Nullable Object o) {
// You can override field equality logic by defining either of the methods like:
// boolean fieldNameEquals(InlineSuggestionsRequest other) { ... }
// boolean fieldNameEquals(FieldType otherValue) { ... }
@@ -134,7 +172,8 @@ public final class InlineSuggestionsRequest implements Parcelable {
//noinspection PointlessBooleanExpression
return true
&& mMaxSuggestionCount == that.mMaxSuggestionCount
- && java.util.Objects.equals(mPresentationSpecs, that.mPresentationSpecs);
+ && java.util.Objects.equals(mPresentationSpecs, that.mPresentationSpecs)
+ && java.util.Objects.equals(mHostPackageName, that.mHostPackageName);
}
@Override
@@ -146,6 +185,7 @@ public final class InlineSuggestionsRequest implements Parcelable {
int _hash = 1;
_hash = 31 * _hash + mMaxSuggestionCount;
_hash = 31 * _hash + java.util.Objects.hashCode(mPresentationSpecs);
+ _hash = 31 * _hash + java.util.Objects.hashCode(mHostPackageName);
return _hash;
}
@@ -157,6 +197,7 @@ public final class InlineSuggestionsRequest implements Parcelable {
dest.writeInt(mMaxSuggestionCount);
dest.writeParcelableList(mPresentationSpecs, flags);
+ dest.writeString(mHostPackageName);
}
@Override
@@ -173,11 +214,15 @@ public final class InlineSuggestionsRequest implements Parcelable {
int maxSuggestionCount = in.readInt();
List<InlinePresentationSpec> presentationSpecs = new ArrayList<>();
in.readParcelableList(presentationSpecs, InlinePresentationSpec.class.getClassLoader());
+ String hostPackageName = in.readString();
this.mMaxSuggestionCount = maxSuggestionCount;
this.mPresentationSpecs = presentationSpecs;
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, mPresentationSpecs);
+ this.mHostPackageName = hostPackageName;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mHostPackageName);
onConstructed();
}
@@ -205,6 +250,7 @@ public final class InlineSuggestionsRequest implements Parcelable {
private int mMaxSuggestionCount;
private @NonNull List<InlinePresentationSpec> mPresentationSpecs;
+ private @NonNull String mHostPackageName;
private long mBuilderFieldsSet = 0L;
@@ -260,22 +306,40 @@ public final class InlineSuggestionsRequest implements Parcelable {
return this;
}
+ /**
+ * The package name of the app that requests for the inline suggestions and will host the
+ * embedded suggestion views. The app does not have to set the value for the field because
+ * it'll be set by the system for safety reasons.
+ */
+ @DataClass.Generated.Member
+ @Override
+ @NonNull Builder setHostPackageName(@NonNull String value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x4;
+ mHostPackageName = value;
+ return this;
+ }
+
/** Builds the instance. This builder should not be touched after calling this! */
public @NonNull InlineSuggestionsRequest build() {
checkNotUsed();
- mBuilderFieldsSet |= 0x4; // Mark builder used
+ mBuilderFieldsSet |= 0x8; // Mark builder used
if ((mBuilderFieldsSet & 0x1) == 0) {
mMaxSuggestionCount = defaultMaxSuggestionCount();
}
+ if ((mBuilderFieldsSet & 0x4) == 0) {
+ mHostPackageName = defaultHostPackageName();
+ }
InlineSuggestionsRequest o = new InlineSuggestionsRequest(
mMaxSuggestionCount,
- mPresentationSpecs);
+ mPresentationSpecs,
+ mHostPackageName);
return o;
}
private void checkNotUsed() {
- if ((mBuilderFieldsSet & 0x4) != 0) {
+ if ((mBuilderFieldsSet & 0x8) != 0) {
throw new IllegalStateException(
"This Builder should not be reused. Use a new Builder instance instead");
}
@@ -283,10 +347,10 @@ public final class InlineSuggestionsRequest implements Parcelable {
}
@DataClass.Generated(
- time = 1576637222199L,
+ time = 1578948035951L,
codegenVersion = "1.0.14",
sourceFile = "frameworks/base/core/java/android/view/inputmethod/InlineSuggestionsRequest.java",
- inputSignatures = "public static final int SUGGESTION_COUNT_UNLIMITED\nprivate final int mMaxSuggestionCount\nprivate final @android.annotation.NonNull java.util.List<android.view.inline.InlinePresentationSpec> mPresentationSpecs\nprivate void onConstructed()\nprivate static int defaultMaxSuggestionCount()\nclass InlineSuggestionsRequest extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genBuilder=true)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setPresentationSpecs(java.util.List<android.view.inline.InlinePresentationSpec>)\nclass BaseBuilder extends java.lang.Object implements []")
+ inputSignatures = "public static final int SUGGESTION_COUNT_UNLIMITED\nprivate final int mMaxSuggestionCount\nprivate final @android.annotation.NonNull java.util.List<android.view.inline.InlinePresentationSpec> mPresentationSpecs\nprivate @android.annotation.NonNull java.lang.String mHostPackageName\npublic void setHostPackageName(java.lang.String)\nprivate void onConstructed()\nprivate static int defaultMaxSuggestionCount()\nprivate static java.lang.String defaultHostPackageName()\nclass InlineSuggestionsRequest extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genBuilder=true)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setPresentationSpecs(java.util.List<android.view.inline.InlinePresentationSpec>)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostPackageName(java.lang.String)\nclass BaseBuilder extends java.lang.Object implements []")
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 20af76b0d5ca..f851e10fa4f6 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -5737,7 +5737,7 @@ public class Editor {
private boolean mIsDraggingCursor;
public void onTouchEvent(MotionEvent event) {
- if (getSelectionController().isCursorBeingModified()) {
+ if (hasSelectionController() && getSelectionController().isCursorBeingModified()) {
return;
}
switch (event.getActionMasked()) {
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 6e6746f16748..a2f514a85ff8 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -344,7 +344,6 @@ cc_library_static {
cppflags: ["-Wno-conversion-null"],
srcs: [
- "android/graphics/apex/android_bitmap.cpp",
"android/graphics/apex/android_matrix.cpp",
"android/graphics/apex/android_paint.cpp",
"android/graphics/apex/android_region.cpp",
@@ -430,6 +429,7 @@ cc_library_static {
android: {
srcs: [ // sources that depend on android only libraries
"android/graphics/apex/android_canvas.cpp",
+ "android/graphics/apex/android_bitmap.cpp",
"android/graphics/apex/renderthread.cpp",
"android/graphics/apex/jni_runtime.cpp",
diff --git a/core/jni/android/graphics/apex/android_bitmap.cpp b/core/jni/android/graphics/apex/android_bitmap.cpp
index 90cc98699827..6a3c01efe98c 100644
--- a/core/jni/android/graphics/apex/android_bitmap.cpp
+++ b/core/jni/android/graphics/apex/android_bitmap.cpp
@@ -122,6 +122,98 @@ AndroidBitmapInfo ABitmap_getInfo(ABitmap* bitmapHandle) {
return getInfo(bitmap->info(), bitmap->rowBytes());
}
+static bool nearlyEqual(float a, float b) {
+ // By trial and error, this is close enough to match for the ADataSpaces we
+ // compare for.
+ return ::fabs(a - b) < .002f;
+}
+
+static bool nearlyEqual(const skcms_TransferFunction& x, const skcms_TransferFunction& y) {
+ return nearlyEqual(x.g, y.g)
+ && nearlyEqual(x.a, y.a)
+ && nearlyEqual(x.b, y.b)
+ && nearlyEqual(x.c, y.c)
+ && nearlyEqual(x.d, y.d)
+ && nearlyEqual(x.e, y.e)
+ && nearlyEqual(x.f, y.f);
+}
+
+static bool nearlyEqual(const skcms_Matrix3x3& x, const skcms_Matrix3x3& y) {
+ for (int i = 0; i < 3; i++) {
+ for (int j = 0; j < 3; j++) {
+ if (!nearlyEqual(x.vals[i][j], y.vals[i][j])) return false;
+ }
+ }
+ return true;
+}
+
+static constexpr skcms_TransferFunction k2Dot6 = {2.6f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
+
+// Skia's SkNamedGamut::kDCIP3 is based on a white point of D65. This gamut
+// matches the white point used by ColorSpace.Named.DCIP3.
+static constexpr skcms_Matrix3x3 kDCIP3 = {{
+ {0.486143, 0.323835, 0.154234},
+ {0.226676, 0.710327, 0.0629966},
+ {0.000800549, 0.0432385, 0.78275},
+}};
+
+ADataSpace ABitmap_getDataSpace(ABitmap* bitmapHandle) {
+ Bitmap* bitmap = TypeCast::toBitmap(bitmapHandle);
+ const SkImageInfo& info = bitmap->info();
+ SkColorSpace* colorSpace = info.colorSpace();
+ if (!colorSpace) {
+ return ADATASPACE_UNKNOWN;
+ }
+
+ if (colorSpace->isSRGB()) {
+ if (info.colorType() == kRGBA_F16_SkColorType) {
+ return ADATASPACE_SCRGB;
+ }
+ return ADATASPACE_SRGB;
+ }
+
+ skcms_TransferFunction fn;
+ LOG_ALWAYS_FATAL_IF(!colorSpace->isNumericalTransferFn(&fn));
+
+ skcms_Matrix3x3 gamut;
+ LOG_ALWAYS_FATAL_IF(!colorSpace->toXYZD50(&gamut));
+
+ if (nearlyEqual(gamut, SkNamedGamut::kSRGB)) {
+ if (nearlyEqual(fn, SkNamedTransferFn::kLinear)) {
+ // Skia doesn't differentiate amongst the RANGES. In Java, we associate
+ // LINEAR_EXTENDED_SRGB with F16, and LINEAR_SRGB with other Configs.
+ // Make the same association here.
+ if (info.colorType() == kRGBA_F16_SkColorType) {
+ return ADATASPACE_SCRGB_LINEAR;
+ }
+ return ADATASPACE_SRGB_LINEAR;
+ }
+
+ if (nearlyEqual(fn, SkNamedTransferFn::kRec2020)) {
+ return ADATASPACE_BT709;
+ }
+ }
+
+ if (nearlyEqual(fn, SkNamedTransferFn::kSRGB) && nearlyEqual(gamut, SkNamedGamut::kDCIP3)) {
+ return ADATASPACE_DISPLAY_P3;
+ }
+
+ if (nearlyEqual(fn, SkNamedTransferFn::k2Dot2) && nearlyEqual(gamut, SkNamedGamut::kAdobeRGB)) {
+ return ADATASPACE_ADOBE_RGB;
+ }
+
+ if (nearlyEqual(fn, SkNamedTransferFn::kRec2020) &&
+ nearlyEqual(gamut, SkNamedGamut::kRec2020)) {
+ return ADATASPACE_BT2020;
+ }
+
+ if (nearlyEqual(fn, k2Dot6) && nearlyEqual(gamut, kDCIP3)) {
+ return ADATASPACE_DCI_P3;
+ }
+
+ return ADATASPACE_UNKNOWN;
+}
+
AndroidBitmapInfo ABitmap_getInfoFromJava(JNIEnv* env, jobject bitmapObj) {
uint32_t rowBytes = 0;
SkImageInfo imageInfo = GraphicsJNI::getBitmapInfo(env, bitmapObj, &rowBytes);
diff --git a/core/jni/android/graphics/apex/include/android/graphics/bitmap.h b/core/jni/android/graphics/apex/include/android/graphics/bitmap.h
index f231eeddb7e2..32b8a450e147 100644
--- a/core/jni/android/graphics/apex/include/android/graphics/bitmap.h
+++ b/core/jni/android/graphics/apex/include/android/graphics/bitmap.h
@@ -17,6 +17,7 @@
#define ANDROID_GRAPHICS_BITMAP_H
#include <android/bitmap.h>
+#include <android/data_space.h>
#include <jni.h>
#include <sys/cdefs.h>
@@ -49,6 +50,7 @@ void ABitmap_acquireRef(ABitmap* bitmap);
void ABitmap_releaseRef(ABitmap* bitmap);
AndroidBitmapInfo ABitmap_getInfo(ABitmap* bitmap);
+ADataSpace ABitmap_getDataSpace(ABitmap* bitmap);
void* ABitmap_getPixels(ABitmap* bitmap);
void ABitmap_notifyPixelsChanged(ABitmap* bitmap);
@@ -106,6 +108,7 @@ namespace graphics {
ABitmap* get() const { return mBitmap; }
AndroidBitmapInfo getInfo() const { return ABitmap_getInfo(mBitmap); }
+ ADataSpace getDataSpace() const { return ABitmap_getDataSpace(mBitmap); }
void* getPixels() const { return ABitmap_getPixels(mBitmap); }
void notifyPixelsChanged() const { ABitmap_notifyPixelsChanged(mBitmap); }
@@ -119,4 +122,4 @@ namespace graphics {
}; // namespace android
#endif // __cplusplus
-#endif // ANDROID_GRAPHICS_BITMAP_H \ No newline at end of file
+#endif // ANDROID_GRAPHICS_BITMAP_H
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 466544c1448e..673772a52212 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -1156,6 +1156,36 @@ static void isolateAppDataPerPackage(int userId, std::string_view package_name,
createAndMountAppData(package_name, ce_data_path, mirrorCePath, actualCePath, fail_fn);
}
+// Relabel directory
+static void relabelDir(const char* path, security_context_t context, fail_fn_t fail_fn) {
+ if (setfilecon(path, context) != 0) {
+ fail_fn(CREATE_ERROR("Failed to setfilecon %s %s", path, strerror(errno)));
+ }
+}
+
+// Relabel all directories under a path non-recursively.
+static void relabelAllDirs(const char* path, security_context_t context, fail_fn_t fail_fn) {
+ DIR* dir = opendir(path);
+ if (dir == nullptr) {
+ fail_fn(CREATE_ERROR("Failed to opendir %s", path));
+ }
+ struct dirent* ent;
+ while ((ent = readdir(dir))) {
+ if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) continue;
+ auto filePath = StringPrintf("%s/%s", path, ent->d_name);
+ if (ent->d_type == DT_DIR) {
+ relabelDir(filePath.c_str(), context, fail_fn);
+ } else if (ent->d_type == DT_LNK) {
+ if (lsetfilecon(filePath.c_str(), context) != 0) {
+ fail_fn(CREATE_ERROR("Failed to lsetfilecon %s %s", filePath.c_str(), strerror(errno)));
+ }
+ } else {
+ fail_fn(CREATE_ERROR("Unexpected type: %d %s", ent->d_type, filePath.c_str()));
+ }
+ }
+ closedir(dir);
+}
+
/**
* Make other apps data directory not visible in CE, DE storage.
*
@@ -1215,10 +1245,36 @@ static void isolateAppData(JNIEnv* env, jobjectArray pkg_data_info_list,
snprintf(internalDePath, PATH_MAX, "/data/user_de");
snprintf(externalPrivateMountPath, PATH_MAX, "/mnt/expand");
+ security_context_t dataDataContext = nullptr;
+ if (getfilecon(internalDePath, &dataDataContext) < 0) {
+ fail_fn(CREATE_ERROR("Unable to getfilecon on %s %s", internalDePath,
+ strerror(errno)));
+ }
+
MountAppDataTmpFs(internalLegacyCePath, fail_fn);
MountAppDataTmpFs(internalCePath, fail_fn);
MountAppDataTmpFs(internalDePath, fail_fn);
- MountAppDataTmpFs(externalPrivateMountPath, fail_fn);
+
+ // Mount tmpfs on all external vols DE and CE storage
+ DIR* dir = opendir(externalPrivateMountPath);
+ if (dir == nullptr) {
+ fail_fn(CREATE_ERROR("Failed to opendir %s", externalPrivateMountPath));
+ }
+ struct dirent* ent;
+ while ((ent = readdir(dir))) {
+ if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) continue;
+ if (ent->d_type != DT_DIR) {
+ fail_fn(CREATE_ERROR("Unexpected type: %d %s", ent->d_type, ent->d_name));
+ }
+ auto volPath = StringPrintf("%s/%s", externalPrivateMountPath, ent->d_name);
+ auto cePath = StringPrintf("%s/user", volPath.c_str());
+ auto dePath = StringPrintf("%s/user_de", volPath.c_str());
+ MountAppDataTmpFs(cePath.c_str(), fail_fn);
+ MountAppDataTmpFs(dePath.c_str(), fail_fn);
+ }
+ closedir(dir);
+
+ bool legacySymlinkCreated = false;
for (int i = 0; i < size; i += 3) {
jstring package_str = (jstring) (env->GetObjectArrayElement(pkg_data_info_list, i));
@@ -1266,7 +1322,14 @@ static void isolateAppData(JNIEnv* env, jobjectArray pkg_data_info_list,
// If it's user 0, create a symlink /data/user/0 -> /data/data,
// otherwise create /data/user/$USER
if (userId == 0) {
- symlink(internalLegacyCePath, internalCeUserPath);
+ if (!legacySymlinkCreated) {
+ legacySymlinkCreated = true;
+ int result = symlink(internalLegacyCePath, internalCeUserPath);
+ if (result != 0) {
+ fail_fn(CREATE_ERROR("Failed to create symlink %s %s", internalCeUserPath,
+ strerror(errno)));
+ }
+ }
actualCePath = internalLegacyCePath;
} else {
PrepareDirIfNotPresent(internalCeUserPath, DEFAULT_DATA_DIR_PERMISSION,
@@ -1280,6 +1343,43 @@ static void isolateAppData(JNIEnv* env, jobjectArray pkg_data_info_list,
isolateAppDataPerPackage(userId, packageName, volUuid, ceDataInode,
actualCePath, actualDePath, fail_fn);
}
+ // We set the label AFTER everything is done, as we are applying
+ // the file operations on tmpfs. If we set the label when we mount
+ // tmpfs, SELinux will not happy as we are changing system_data_files.
+ // Relabel dir under /data/user, including /data/user/0
+ relabelAllDirs(internalCePath, dataDataContext, fail_fn);
+
+ // Relabel /data/user
+ relabelDir(internalCePath, dataDataContext, fail_fn);
+
+ // Relabel /data/data
+ relabelDir(internalLegacyCePath, dataDataContext, fail_fn);
+
+ // Relabel dir under /data/user_de
+ relabelAllDirs(internalDePath, dataDataContext, fail_fn);
+
+ // Relabel /data/user_de
+ relabelDir(internalDePath, dataDataContext, fail_fn);
+
+ // Relabel CE and DE dirs under /mnt/expand
+ dir = opendir(externalPrivateMountPath);
+ if (dir == nullptr) {
+ fail_fn(CREATE_ERROR("Failed to opendir %s", externalPrivateMountPath));
+ }
+ while ((ent = readdir(dir))) {
+ if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) continue;
+ auto volPath = StringPrintf("%s/%s", externalPrivateMountPath, ent->d_name);
+ auto cePath = StringPrintf("%s/user", volPath.c_str());
+ auto dePath = StringPrintf("%s/user_de", volPath.c_str());
+
+ relabelAllDirs(cePath.c_str(), dataDataContext, fail_fn);
+ relabelDir(cePath.c_str(), dataDataContext, fail_fn);
+ relabelAllDirs(dePath.c_str(), dataDataContext, fail_fn);
+ relabelDir(dePath.c_str(), dataDataContext, fail_fn);
+ }
+ closedir(dir);
+
+ freecon(dataDataContext);
}
// Utility routine to specialize a zygote child process.
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index b78b18192f45..7ecd9b702e53 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2568,7 +2568,7 @@
<!-- Allows telephony to suggest the time / time zone.
<p>Not for use by third-party applications.
- @hide
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) @hide
-->
<permission android:name="android.permission.SUGGEST_PHONE_TIME_AND_ZONE"
android:protectionLevel="signature|telephony" />
diff --git a/core/tests/coretests/src/android/widget/EditorCursorDragTest.java b/core/tests/coretests/src/android/widget/EditorCursorDragTest.java
index 89c237498e5c..8c9b4d071c2d 100644
--- a/core/tests/coretests/src/android/widget/EditorCursorDragTest.java
+++ b/core/tests/coretests/src/android/widget/EditorCursorDragTest.java
@@ -67,6 +67,7 @@ public class EditorCursorDragTest {
mOriginalFlagValue = Editor.FLAG_ENABLE_CURSOR_DRAG;
Editor.FLAG_ENABLE_CURSOR_DRAG = true;
}
+
@After
public void after() throws Throwable {
Editor.FLAG_ENABLE_CURSOR_DRAG = mOriginalFlagValue;
@@ -356,6 +357,23 @@ public class EditorCursorDragTest {
assertFalse(editor.getSelectionController().isCursorBeingModified());
}
+ @Test // Reproduces b/147366705
+ public void testCursorDrag_nonSelectableTextView() throws Throwable {
+ String text = "Hello world!";
+ TextView tv = mActivity.findViewById(R.id.nonselectable_textview);
+ tv.setText(text);
+ Editor editor = tv.getEditorForTesting();
+
+ // Simulate a tap. No error should be thrown.
+ long event1Time = 1001;
+ MotionEvent event1 = downEvent(event1Time, event1Time, 20f, 30f);
+ mInstrumentation.runOnMainSync(() -> editor.onTouchEvent(event1));
+
+ // Swipe left to right. No error should be thrown.
+ onView(withId(R.id.nonselectable_textview)).perform(
+ dragOnText(text.indexOf("llo"), text.indexOf("!")));
+ }
+
private static MotionEvent downEvent(long downTime, long eventTime, float x, float y) {
return MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_DOWN, x, y, 0);
}
diff --git a/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java b/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java
index b4116681e723..aa55e08dbcdc 100644
--- a/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java
@@ -19,7 +19,6 @@ package android.widget;
import static android.widget.espresso.ContextMenuUtils.assertContextMenuContainsItemDisabled;
import static android.widget.espresso.ContextMenuUtils.assertContextMenuContainsItemEnabled;
import static android.widget.espresso.ContextMenuUtils.assertContextMenuIsNotDisplayed;
-import static android.widget.espresso.DragHandleUtils.assertNoSelectionHandles;
import static android.widget.espresso.DragHandleUtils.onHandleView;
import static android.widget.espresso.TextViewActions.mouseClick;
import static android.widget.espresso.TextViewActions.mouseClickOnTextAtIndex;
@@ -64,7 +63,6 @@ import org.junit.runner.RunWith;
*/
@RunWith(AndroidJUnit4.class)
@MediumTest
-@Suppress // Consistently failing. b/29591177
public class TextViewActivityMouseTest {
@Rule
@@ -86,11 +84,8 @@ public class TextViewActivityMouseTest {
onView(withId(R.id.textview)).perform(mouseClick());
onView(withId(R.id.textview)).perform(replaceText(helloWorld));
- assertNoSelectionHandles();
-
onView(withId(R.id.textview)).perform(
mouseDragOnText(helloWorld.indexOf("llo"), helloWorld.indexOf("ld!")));
-
onView(withId(R.id.textview)).check(hasSelection("llo wor"));
onHandleView(com.android.internal.R.id.selection_start_handle)
@@ -100,8 +95,6 @@ public class TextViewActivityMouseTest {
onView(withId(R.id.textview)).perform(mouseClickOnTextAtIndex(helloWorld.indexOf("w")));
onView(withId(R.id.textview)).check(hasSelection(""));
-
- assertNoSelectionHandles();
}
@Test
@@ -196,11 +189,11 @@ public class TextViewActivityMouseTest {
onView(withId(R.id.textview)).check(matches(withText("abc ghi.def")));
onView(withId(R.id.textview)).check(hasSelection(""));
- assertNoSelectionHandles();
onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex("abc ghi.def".length()));
}
@Test
+ @Suppress // Consistently failing. b/29591177
public void testDragAndDrop_longClick() {
final String text = "abc def ghi.";
onView(withId(R.id.textview)).perform(mouseClick());
@@ -213,7 +206,6 @@ public class TextViewActivityMouseTest {
onView(withId(R.id.textview)).check(matches(withText("abc ghi.def")));
onView(withId(R.id.textview)).check(hasSelection(""));
- assertNoSelectionHandles();
onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex("abc ghi.def".length()));
}
diff --git a/core/tests/coretests/src/android/widget/espresso/MouseUiController.java b/core/tests/coretests/src/android/widget/espresso/MouseUiController.java
index abee7369414b..1928d2587f70 100644
--- a/core/tests/coretests/src/android/widget/espresso/MouseUiController.java
+++ b/core/tests/coretests/src/android/widget/espresso/MouseUiController.java
@@ -70,6 +70,8 @@ public final class MouseUiController implements UiController {
event.setSource(InputDevice.SOURCE_MOUSE);
if (event.getActionMasked() != MotionEvent.ACTION_UP) {
event.setButtonState(mButton);
+ } else {
+ event.setButtonState(0);
}
return mUiController.injectMotionEvent(event);
}
diff --git a/media/java/android/media/IMediaRoute2ProviderClient.aidl b/media/java/android/media/IMediaRoute2ProviderClient.aidl
index e8abfdca89b7..0fccb3a9aeac 100644
--- a/media/java/android/media/IMediaRoute2ProviderClient.aidl
+++ b/media/java/android/media/IMediaRoute2ProviderClient.aidl
@@ -25,8 +25,10 @@ import android.os.Bundle;
* @hide
*/
oneway interface IMediaRoute2ProviderClient {
- void updateState(in MediaRoute2ProviderInfo providerInfo,
- in List<RoutingSessionInfo> sessionInfos);
- void notifySessionCreated(in @nullable RoutingSessionInfo sessionInfo, long requestId);
- void notifySessionInfoChanged(in RoutingSessionInfo sessionInfo);
+ // TODO: Change it to updateRoutes?
+ void updateState(in MediaRoute2ProviderInfo providerInfo);
+ void notifySessionCreated(in RoutingSessionInfo sessionInfo, long requestId);
+ void notifySessionCreationFailed(long requestId);
+ void notifySessionUpdated(in RoutingSessionInfo sessionInfo);
+ void notifySessionReleased(in RoutingSessionInfo sessionInfo);
}
diff --git a/media/java/android/media/MediaRoute2ProviderService.java b/media/java/android/media/MediaRoute2ProviderService.java
index 1cd5dfa087fa..6d9aea512f01 100644
--- a/media/java/android/media/MediaRoute2ProviderService.java
+++ b/media/java/android/media/MediaRoute2ProviderService.java
@@ -58,6 +58,16 @@ public abstract class MediaRoute2ProviderService extends Service {
public static final String SERVICE_INTERFACE = "android.media.MediaRoute2ProviderService";
+ /**
+ * The request ID to pass {@link #notifySessionCreated(RoutingSessionInfo, long)}
+ * when {@link MediaRoute2ProviderService} created a session although there was no creation
+ * request.
+ *
+ * @see #notifySessionCreated(RoutingSessionInfo, long)
+ * @hide
+ */
+ public static final long REQUEST_ID_UNKNOWN = 0;
+
private final Handler mHandler;
private final Object mSessionLock = new Object();
private final AtomicBoolean mStatePublishScheduled = new AtomicBoolean(false);
@@ -118,7 +128,7 @@ public abstract class MediaRoute2ProviderService extends Service {
*
* @param sessionId id of the session
* @return information of the session with the given id.
- * null if the session is destroyed or id is not valid.
+ * null if the session is released or ID is not valid.
* @hide
*/
@Nullable
@@ -143,161 +153,178 @@ public abstract class MediaRoute2ProviderService extends Service {
}
/**
- * Updates the information of a session.
- * If the session is destroyed or not created before, it will be ignored.
- * Call {@link #updateProviderInfo(MediaRoute2ProviderInfo)} to notify clients of
- * session info changes.
+ * Notifies clients of that the session is created and ready for use.
+ * <p>
+ * If this session is created without any creation request, use {@link #REQUEST_ID_UNKNOWN}
+ * as the request ID.
*
- * @param sessionInfo new session information
- * @see #notifySessionCreated(RoutingSessionInfo, long)
+ * @param sessionInfo information of the new session.
+ * The {@link RoutingSessionInfo#getId() id} of the session must be unique.
+ * @param requestId id of the previous request to create this session provided in
+ * {@link #onCreateSession(String, String, String, long)}
+ * @see #onCreateSession(String, String, String, long)
* @hide
*/
- public final void updateSessionInfo(@NonNull RoutingSessionInfo sessionInfo) {
+ public final void notifySessionCreated(@NonNull RoutingSessionInfo sessionInfo,
+ long requestId) {
Objects.requireNonNull(sessionInfo, "sessionInfo must not be null");
- String sessionId = sessionInfo.getId();
+ String sessionId = sessionInfo.getId();
synchronized (mSessionLock) {
if (mSessionInfo.containsKey(sessionId)) {
- mSessionInfo.put(sessionId, sessionInfo);
- schedulePublishState();
- } else {
- Log.w(TAG, "Ignoring unknown session info.");
+ Log.w(TAG, "Ignoring duplicate session id.");
return;
}
+ mSessionInfo.put(sessionInfo.getId(), sessionInfo);
+ }
+ schedulePublishState();
+
+ if (mClient == null) {
+ return;
+ }
+ try {
+ // TODO: Calling binder calls in multiple thread may cause timing issue.
+ // Consider to change implementations to avoid the problems.
+ // For example, post binder calls, always send all sessions at once, etc.
+ mClient.notifySessionCreated(sessionInfo, requestId);
+ } catch (RemoteException ex) {
+ Log.w(TAG, "Failed to notify session created.");
}
}
/**
- * Notifies the session is changed.
+ * Notifies clients of that the session could not be created.
*
- * TODO: This method is temporary, only created for tests. Remove when the alternative is ready.
+ * @param requestId id of the previous request to create the session provided in
+ * {@link #onCreateSession(String, String, String, long)}.
+ * @see #onCreateSession(String, String, String, long)
* @hide
*/
- public final void notifySessionInfoChanged(@NonNull RoutingSessionInfo sessionInfo) {
- Objects.requireNonNull(sessionInfo, "sessionInfo must not be null");
-
- String sessionId = sessionInfo.getId();
- synchronized (mSessionLock) {
- if (mSessionInfo.containsKey(sessionId)) {
- mSessionInfo.put(sessionId, sessionInfo);
- } else {
- Log.w(TAG, "Ignoring unknown session info.");
- return;
- }
- }
-
+ public final void notifySessionCreationFailed(long requestId) {
if (mClient == null) {
return;
}
try {
- mClient.notifySessionInfoChanged(sessionInfo);
+ mClient.notifySessionCreationFailed(requestId);
} catch (RemoteException ex) {
- Log.w(TAG, "Failed to notify session info changed.");
+ Log.w(TAG, "Failed to notify session creation failed.");
}
}
/**
- * Notifies clients of that the session is created and ready for use. If the session can be
- * controlled, pass a {@link Bundle} that contains how to control it.
+ * Notifies the existing session is updated. For example, when
+ * {@link RoutingSessionInfo#getSelectedRoutes() selected routes} are changed.
*
- * @param sessionInfo information of the new session.
- * The {@link RoutingSessionInfo#getId() id} of the session must be
- * unique. Pass {@code null} to reject the request or inform clients that
- * session creation is failed.
- * @param requestId id of the previous request to create this session
* @hide
*/
- // TODO: fail reason?
- // TODO: Maybe better to create notifySessionCreationFailed?
- public final void notifySessionCreated(@Nullable RoutingSessionInfo sessionInfo,
- long requestId) {
- if (sessionInfo != null) {
- String sessionId = sessionInfo.getId();
- synchronized (mSessionLock) {
- if (mSessionInfo.containsKey(sessionId)) {
- Log.w(TAG, "Ignoring duplicate session id.");
- return;
- }
- mSessionInfo.put(sessionInfo.getId(), sessionInfo);
+ public final void notifySessionUpdated(@NonNull RoutingSessionInfo sessionInfo) {
+ Objects.requireNonNull(sessionInfo, "sessionInfo must not be null");
+
+ String sessionId = sessionInfo.getId();
+ synchronized (mSessionLock) {
+ if (mSessionInfo.containsKey(sessionId)) {
+ mSessionInfo.put(sessionId, sessionInfo);
+ } else {
+ Log.w(TAG, "Ignoring unknown session info.");
+ return;
}
- schedulePublishState();
}
if (mClient == null) {
return;
}
try {
- mClient.notifySessionCreated(sessionInfo, requestId);
+ mClient.notifySessionUpdated(sessionInfo);
} catch (RemoteException ex) {
- Log.w(TAG, "Failed to notify session created.");
+ Log.w(TAG, "Failed to notify session info changed.");
}
}
/**
- * Releases a session with the given id.
- * {@link #onDestroySession} is called if the session is released.
+ * Notifies that the session is released.
*
- * @param sessionId id of the session to be released
- * @see #onDestroySession(String, RoutingSessionInfo)
+ * @param sessionId id of the released session.
+ * @see #onReleaseSession(String)
* @hide
*/
- public final void releaseSession(@NonNull String sessionId) {
+ public final void notifySessionReleased(@NonNull String sessionId) {
if (TextUtils.isEmpty(sessionId)) {
throw new IllegalArgumentException("sessionId must not be empty");
}
- //TODO: notify media router service of release.
RoutingSessionInfo sessionInfo;
synchronized (mSessionLock) {
sessionInfo = mSessionInfo.remove(sessionId);
}
- if (sessionInfo != null) {
- mHandler.sendMessage(obtainMessage(
- MediaRoute2ProviderService::onDestroySession, this, sessionId, sessionInfo));
- schedulePublishState();
+
+ if (sessionInfo == null) {
+ Log.w(TAG, "Ignoring unknown session info.");
+ return;
+ }
+
+ if (mClient == null) {
+ return;
+ }
+ try {
+ mClient.notifySessionReleased(sessionInfo);
+ } catch (RemoteException ex) {
+ Log.w(TAG, "Failed to notify session info changed.");
}
}
/**
- * Called when a session should be created.
+ * Called when the service receives a request to create a session.
+ * <p>
* You should create and maintain your own session and notifies the client of
* session info. Call {@link #notifySessionCreated(RoutingSessionInfo, long)}
* with the given {@code requestId} to notify the information of a new session.
- * If you can't create the session or want to reject the request, pass {@code null}
- * as session info in {@link #notifySessionCreated(RoutingSessionInfo, long)}
- * with the given {@code requestId}.
+ * The created session must have the same route feature and must include the given route
+ * specified by {@code routeId}.
+ * <p>
+ * If the session can be controlled, you can optionally pass the control hints to
+ * {@link RoutingSessionInfo.Builder#setControlHints(Bundle)}. Control hints is a
+ * {@link Bundle} which contains how to control the session.
+ * <p>
+ * If you can't create the session or want to reject the request, call
+ * {@link #notifySessionCreationFailed(long)} with the given {@code requestId}.
*
* @param packageName the package name of the application that selected the route
* @param routeId the id of the route initially being connected
* @param routeFeature the route feature of the new session
* @param requestId the id of this session creation request
+ *
+ * @see RoutingSessionInfo.Builder#Builder(String, String, String)
+ * @see RoutingSessionInfo.Builder#addSelectedRoute(String)
+ * @see RoutingSessionInfo.Builder#setControlHints(Bundle)
* @hide
*/
public abstract void onCreateSession(@NonNull String packageName, @NonNull String routeId,
@NonNull String routeFeature, long requestId);
/**
- * Called when a session is about to be destroyed.
- * You can clean up your session here. This can happen by the
- * client or provider itself.
+ * Called when the session should be released. A client of the session or system can request
+ * a session to be released.
+ * <p>
+ * After releasing the session, call {@link #notifySessionReleased(String)}
+ * with the ID of the released session.
+ *
+ * Note: Calling {@link #notifySessionReleased(String)} will <em>NOT</em> trigger
+ * this method to be called.
*
- * @param sessionId id of the session being destroyed.
- * @param lastSessionInfo information of the session being destroyed.
- * @see #releaseSession(String)
+ * @param sessionId id of the session being released.
+ * @see #notifySessionReleased(String)
+ * @see #getSessionInfo(String)
* @hide
*/
- public abstract void onDestroySession(@NonNull String sessionId,
- @NonNull RoutingSessionInfo lastSessionInfo);
+ public abstract void onReleaseSession(@NonNull String sessionId);
//TODO: make a way to reject the request
/**
* Called when a client requests selecting a route for the session.
- * After the route is selected, call {@link #updateSessionInfo(RoutingSessionInfo)} to update
- * session info and call {@link #updateProviderInfo(MediaRoute2ProviderInfo)} to notify
- * clients of updated session info.
+ * After the route is selected, call {@link #notifySessionUpdated(RoutingSessionInfo)}
+ * to update session info.
*
* @param sessionId id of the session
* @param routeId id of the route
- * @see #updateSessionInfo(RoutingSessionInfo)
* @hide
*/
public abstract void onSelectRoute(@NonNull String sessionId, @NonNull String routeId);
@@ -305,9 +332,8 @@ public abstract class MediaRoute2ProviderService extends Service {
//TODO: make a way to reject the request
/**
* Called when a client requests deselecting a route from the session.
- * After the route is deselected, call {@link #updateSessionInfo(RoutingSessionInfo)} to update
- * session info and call {@link #updateProviderInfo(MediaRoute2ProviderInfo)} to notify
- * clients of updated session info.
+ * After the route is deselected, call {@link #notifySessionUpdated(RoutingSessionInfo)}
+ * to update session info.
*
* @param sessionId id of the session
* @param routeId id of the route
@@ -318,9 +344,8 @@ public abstract class MediaRoute2ProviderService extends Service {
//TODO: make a way to reject the request
/**
* Called when a client requests transferring a session to a route.
- * After the transfer is finished, call {@link #updateSessionInfo(RoutingSessionInfo)} to update
- * session info and call {@link #updateProviderInfo(MediaRoute2ProviderInfo)} to notify
- * clients of updated session info.
+ * After the transfer is finished, call {@link #notifySessionUpdated(RoutingSessionInfo)}
+ * to update session info.
*
* @param sessionId id of the session
* @param routeId id of the route
@@ -344,6 +369,8 @@ public abstract class MediaRoute2ProviderService extends Service {
* </p>
*
* @param preference the new discovery preference
+ *
+ * TODO: This method needs tests.
*/
public void onDiscoveryPreferenceChanged(@NonNull RouteDiscoveryPreference preference) {}
@@ -383,7 +410,7 @@ public abstract class MediaRoute2ProviderService extends Service {
sessionInfos = new ArrayList<>(mSessionInfo.values());
}
try {
- mClient.updateState(mProviderInfo, sessionInfos);
+ mClient.updateState(mProviderInfo);
} catch (RemoteException ex) {
Log.w(TAG, "Failed to send onProviderInfoUpdated");
}
@@ -415,6 +442,7 @@ public abstract class MediaRoute2ProviderService extends Service {
MediaRoute2ProviderService.this, packageName, routeId, routeFeature,
requestId));
}
+
@Override
public void releaseSession(@NonNull String sessionId) {
if (!checkCallerisSystem()) {
@@ -424,7 +452,7 @@ public abstract class MediaRoute2ProviderService extends Service {
Log.w(TAG, "releaseSession: Ignoring empty sessionId from system service.");
return;
}
- mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::releaseSession,
+ mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onReleaseSession,
MediaRoute2ProviderService.this, sessionId));
}
diff --git a/media/java/android/media/MediaTranscodeManager.java b/media/java/android/media/MediaTranscodeManager.java
new file mode 100644
index 000000000000..2c431b98fc7a
--- /dev/null
+++ b/media/java/android/media/MediaTranscodeManager.java
@@ -0,0 +1,403 @@
+/*
+ * 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.media;
+
+import android.annotation.CallbackExecutor;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.net.Uri;
+import android.util.Log;
+
+import com.android.internal.util.Preconditions;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.Executor;
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * MediaTranscodeManager provides an interface to the system's media transcode service.
+ * Transcode requests are put in a queue and processed in order. When a transcode operation is
+ * completed the caller is notified via its OnTranscodingFinishedListener. In the meantime the
+ * caller may use the returned TranscodingJob object to cancel or check the status of a specific
+ * transcode operation.
+ * The currently supported media types are video and still images.
+ *
+ * TODO(lnilsson): Add sample code when API is settled.
+ *
+ * @hide
+ */
+public final class MediaTranscodeManager {
+ private static final String TAG = "MediaTranscodeManager";
+
+ // Invalid ID passed from native means the request was never enqueued.
+ private static final long ID_INVALID = -1;
+
+ // Events passed from native.
+ private static final int EVENT_JOB_STARTED = 1;
+ private static final int EVENT_JOB_PROGRESSED = 2;
+ private static final int EVENT_JOB_FINISHED = 3;
+
+ @IntDef(prefix = { "EVENT_" }, value = {
+ EVENT_JOB_STARTED,
+ EVENT_JOB_PROGRESSED,
+ EVENT_JOB_FINISHED,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Event {}
+
+ private static MediaTranscodeManager sMediaTranscodeManager;
+ private final ConcurrentMap<Long, TranscodingJob> mPendingTranscodingJobs =
+ new ConcurrentHashMap<>();
+ private final Context mContext;
+
+ /**
+ * Listener that gets notified when a transcoding operation has finished.
+ * This listener gets notified regardless of how the operation finished. It is up to the
+ * listener implementation to check the result and take appropriate action.
+ */
+ @FunctionalInterface
+ public interface OnTranscodingFinishedListener {
+ /**
+ * Called when the transcoding operation has finished. The receiver may use the
+ * TranscodingJob to check the result, i.e. whether the operation succeeded, was canceled or
+ * if an error occurred.
+ * @param transcodingJob The TranscodingJob instance for the finished transcoding operation.
+ */
+ void onTranscodingFinished(@NonNull TranscodingJob transcodingJob);
+ }
+
+ /**
+ * Class describing a transcode operation to be performed. The caller uses this class to
+ * configure a transcoding operation that can then be enqueued using MediaTranscodeManager.
+ */
+ public static final class TranscodingRequest {
+ private Uri mSrcUri;
+ private Uri mDstUri;
+ private MediaFormat mDstFormat;
+
+ private TranscodingRequest(Builder b) {
+ mSrcUri = b.mSrcUri;
+ mDstUri = b.mDstUri;
+ mDstFormat = b.mDstFormat;
+ }
+
+ /** TranscodingRequest builder class. */
+ public static class Builder {
+ private Uri mSrcUri;
+ private Uri mDstUri;
+ private MediaFormat mDstFormat;
+
+ /**
+ * Specifies the source media file.
+ * @param uri Content uri for the source media file.
+ * @return The builder instance.
+ */
+ public Builder setSourceUri(Uri uri) {
+ mSrcUri = uri;
+ return this;
+ }
+
+ /**
+ * Specifies the destination media file.
+ * @param uri Content uri for the destination media file.
+ * @return The builder instance.
+ */
+ public Builder setDestinationUri(Uri uri) {
+ mDstUri = uri;
+ return this;
+ }
+
+ /**
+ * Specifies the media format of the transcoded media file.
+ * @param dstFormat MediaFormat containing the desired destination format.
+ * @return The builder instance.
+ */
+ public Builder setDestinationFormat(MediaFormat dstFormat) {
+ mDstFormat = dstFormat;
+ return this;
+ }
+
+ /**
+ * Builds a new TranscodingRequest with the configuration set on this builder.
+ * @return A new TranscodingRequest.
+ */
+ public TranscodingRequest build() {
+ return new TranscodingRequest(this);
+ }
+ }
+ }
+
+ /**
+ * Handle to an enqueued transcoding operation. An instance of this class represents a single
+ * enqueued transcoding operation. The caller can use that instance to query the status or
+ * progress, and to get the result once the operation has completed.
+ */
+ public static final class TranscodingJob {
+ /** The job is enqueued but not yet running. */
+ public static final int STATUS_PENDING = 1;
+ /** The job is currently running. */
+ public static final int STATUS_RUNNING = 2;
+ /** The job is finished. */
+ public static final int STATUS_FINISHED = 3;
+
+ @IntDef(prefix = { "STATUS_" }, value = {
+ STATUS_PENDING,
+ STATUS_RUNNING,
+ STATUS_FINISHED,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Status {}
+
+ /** The job does not have a result yet. */
+ public static final int RESULT_NONE = 1;
+ /** The job completed successfully. */
+ public static final int RESULT_SUCCESS = 2;
+ /** The job encountered an error while running. */
+ public static final int RESULT_ERROR = 3;
+ /** The job was canceled by the caller. */
+ public static final int RESULT_CANCELED = 4;
+
+ @IntDef(prefix = { "RESULT_" }, value = {
+ RESULT_NONE,
+ RESULT_SUCCESS,
+ RESULT_ERROR,
+ RESULT_CANCELED,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Result {}
+
+ /** Listener that gets notified when the progress changes. */
+ @FunctionalInterface
+ public interface OnProgressChangedListener {
+
+ /**
+ * Called when the progress changes. The progress is between 0 and 1, where 0 means
+ * that the job has not yet started and 1 means that it has finished.
+ * @param progress The new progress.
+ */
+ void onProgressChanged(float progress);
+ }
+
+ private final Executor mExecutor;
+ private final OnTranscodingFinishedListener mListener;
+ private final ReentrantLock mStatusChangeLock = new ReentrantLock();
+ private Executor mProgressChangedExecutor;
+ private OnProgressChangedListener mProgressChangedListener;
+ private long mID;
+ private float mProgress = 0.0f;
+ private @Status int mStatus = STATUS_PENDING;
+ private @Result int mResult = RESULT_NONE;
+
+ private TranscodingJob(long id, @NonNull @CallbackExecutor Executor executor,
+ @NonNull OnTranscodingFinishedListener listener) {
+ mID = id;
+ mExecutor = executor;
+ mListener = listener;
+ }
+
+ /**
+ * Set a progress listener.
+ * @param listener The progress listener.
+ */
+ public void setOnProgressChangedListener(@NonNull @CallbackExecutor Executor executor,
+ @Nullable OnProgressChangedListener listener) {
+ mProgressChangedExecutor = executor;
+ mProgressChangedListener = listener;
+ }
+
+ /**
+ * Cancels the transcoding job and notify the listener. If the job happened to finish before
+ * being canceled this call is effectively a no-op and will not update the result in that
+ * case.
+ */
+ public void cancel() {
+ setJobFinished(RESULT_CANCELED);
+ sMediaTranscodeManager.native_cancelTranscodingRequest(mID);
+ }
+
+ /**
+ * Gets the progress of the transcoding job. The progress is between 0 and 1, where 0 means
+ * that the job has not yet started and 1 means that it is finished.
+ * @return The progress.
+ */
+ public float getProgress() {
+ return mProgress;
+ }
+
+ /**
+ * Gets the status of the transcoding job.
+ * @return The status.
+ */
+ public @Status int getStatus() {
+ return mStatus;
+ }
+
+ /**
+ * Gets the result of the transcoding job.
+ * @return The result.
+ */
+ public @Result int getResult() {
+ return mResult;
+ }
+
+ private void setJobStarted() {
+ mStatus = STATUS_RUNNING;
+ }
+
+ private void setJobProgress(float newProgress) {
+ mProgress = newProgress;
+
+ // Notify listener.
+ OnProgressChangedListener onProgressChangedListener = mProgressChangedListener;
+ if (onProgressChangedListener != null) {
+ mProgressChangedExecutor.execute(
+ () -> onProgressChangedListener.onProgressChanged(mProgress));
+ }
+ }
+
+ private void setJobFinished(int result) {
+ boolean doNotifyListener = false;
+
+ // Prevent conflicting simultaneous status updates from native (finished) and from the
+ // caller (cancel).
+ try {
+ mStatusChangeLock.lock();
+ if (mStatus != STATUS_FINISHED) {
+ mStatus = STATUS_FINISHED;
+ mResult = result;
+ doNotifyListener = true;
+ }
+ } finally {
+ mStatusChangeLock.unlock();
+ }
+
+ if (doNotifyListener) {
+ mExecutor.execute(() -> mListener.onTranscodingFinished(this));
+ }
+ }
+
+ private void processJobEvent(@Event int event, int arg) {
+ switch (event) {
+ case EVENT_JOB_STARTED:
+ setJobStarted();
+ break;
+ case EVENT_JOB_PROGRESSED:
+ setJobProgress((float) arg / 100);
+ break;
+ case EVENT_JOB_FINISHED:
+ setJobFinished(arg);
+ break;
+ default:
+ Log.e(TAG, "Unsupported event: " + event);
+ break;
+ }
+ }
+ }
+
+ // Initializes the native library.
+ private static native void native_init();
+ // Requests a new job ID from the native service.
+ private native long native_requestUniqueJobID();
+ // Enqueues a transcoding request to the native service.
+ private native boolean native_enqueueTranscodingRequest(
+ long id, @NonNull TranscodingRequest transcodingRequest, @NonNull Context context);
+ // Cancels an enqueued transcoding request.
+ private native void native_cancelTranscodingRequest(long id);
+
+ // Private constructor.
+ private MediaTranscodeManager(@NonNull Context context) {
+ mContext = context;
+ }
+
+ // Events posted from the native service.
+ @SuppressWarnings("unused")
+ private void postEventFromNative(@Event int event, long id, int arg) {
+ Log.d(TAG, String.format("postEventFromNative. Event %d, ID %d, arg %d", event, id, arg));
+
+ TranscodingJob transcodingJob = mPendingTranscodingJobs.get(id);
+
+ // Job IDs are added to the tracking set before the job is enqueued so it should never
+ // be null unless the service misbehaves.
+ if (transcodingJob == null) {
+ Log.e(TAG, "No matching transcode job found for id " + id);
+ return;
+ }
+
+ transcodingJob.processJobEvent(event, arg);
+ }
+
+ /**
+ * Gets the MediaTranscodeManager singleton instance.
+ * @param context The application context.
+ * @return the {@link MediaTranscodeManager} singleton instance.
+ */
+ public static MediaTranscodeManager getInstance(@NonNull Context context) {
+ Preconditions.checkNotNull(context);
+ synchronized (MediaTranscodeManager.class) {
+ if (sMediaTranscodeManager == null) {
+ sMediaTranscodeManager = new MediaTranscodeManager(context.getApplicationContext());
+ }
+ return sMediaTranscodeManager;
+ }
+ }
+
+ /**
+ * Enqueues a TranscodingRequest for execution.
+ * @param transcodingRequest The TranscodingRequest to enqueue.
+ * @param listenerExecutor Executor on which the listener is notified.
+ * @param listener Listener to get notified when the transcoding job is finished.
+ * @return A TranscodingJob for this operation.
+ */
+ public @Nullable TranscodingJob enqueueTranscodingRequest(
+ @NonNull TranscodingRequest transcodingRequest,
+ @NonNull @CallbackExecutor Executor listenerExecutor,
+ @NonNull OnTranscodingFinishedListener listener) {
+ Log.i(TAG, "enqueueTranscodingRequest called.");
+ Preconditions.checkNotNull(transcodingRequest);
+ Preconditions.checkNotNull(listenerExecutor);
+ Preconditions.checkNotNull(listener);
+
+ // Reserve a job ID.
+ long jobID = native_requestUniqueJobID();
+ if (jobID == ID_INVALID) {
+ return null;
+ }
+
+ // Add the job to the tracking set.
+ TranscodingJob transcodingJob = new TranscodingJob(jobID, listenerExecutor, listener);
+ mPendingTranscodingJobs.put(jobID, transcodingJob);
+
+ // Enqueue the request with the native service.
+ boolean enqueued = native_enqueueTranscodingRequest(jobID, transcodingRequest, mContext);
+ if (!enqueued) {
+ mPendingTranscodingJobs.remove(jobID);
+ return null;
+ }
+
+ return transcodingJob;
+ }
+
+ static {
+ System.loadLibrary("media_jni");
+ native_init();
+ }
+}
diff --git a/media/java/android/media/audiopolicy/AudioPolicy.java b/media/java/android/media/audiopolicy/AudioPolicy.java
index 01f12500b77b..27f02fe528f3 100644
--- a/media/java/android/media/audiopolicy/AudioPolicy.java
+++ b/media/java/android/media/audiopolicy/AudioPolicy.java
@@ -719,9 +719,14 @@ public class AudioPolicy {
if (track == null) {
break;
}
- // TODO: add synchronous versions
- track.stop();
- track.flush();
+ try {
+ // TODO: add synchronous versions
+ track.stop();
+ track.flush();
+ } catch (IllegalStateException e) {
+ // ignore exception, AudioTrack could have already been stopped or
+ // released by the user of the AudioPolicy
+ }
}
}
if (mCaptors != null) {
@@ -730,8 +735,13 @@ public class AudioPolicy {
if (record == null) {
break;
}
- // TODO: if needed: implement an invalidate method
- record.stop();
+ try {
+ // TODO: if needed: implement an invalidate method
+ record.stop();
+ } catch (IllegalStateException e) {
+ // ignore exception, AudioRecord could have already been stopped or
+ // released by the user of the AudioPolicy
+ }
}
}
}
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index 862489f4ed8d..e3dfaeb10948 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -16,6 +16,7 @@
package android.media.tv.tuner;
+import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -32,11 +33,13 @@ import android.media.tv.tuner.filter.TimeFilter;
import android.media.tv.tuner.frontend.FrontendCallback;
import android.media.tv.tuner.frontend.FrontendInfo;
import android.media.tv.tuner.frontend.FrontendStatus;
+import android.media.tv.tuner.frontend.ScanCallback;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import java.util.List;
+import java.util.concurrent.Executor;
/**
* This class is used to interact with hardware tuners devices.
@@ -70,6 +73,10 @@ public final class Tuner implements AutoCloseable {
private List<Integer> mLnbIds;
private Lnb mLnb;
+ @Nullable
+ private ScanCallback mScanCallback;
+ @Nullable
+ private Executor mScanCallbackExecutor;
/**
* Constructs a Tuner instance.
@@ -231,29 +238,6 @@ public final class Tuner implements AutoCloseable {
private Frontend(int id) {
mId = id;
}
-
- public void setCallback(@Nullable FrontendCallback callback, @Nullable Handler handler) {
- mCallback = callback;
-
- if (mCallback == null) {
- return;
- }
-
- if (handler == null) {
- // use default looper if handler is null
- if (mHandler == null) {
- mHandler = createEventHandler();
- }
- return;
- }
-
- Looper looper = handler.getLooper();
- if (mHandler != null && mHandler.getLooper() == looper) {
- // the same looper. reuse mHandler
- return;
- }
- mHandler = new EventHandler(looper);
- }
}
/**
@@ -286,18 +270,32 @@ public final class Tuner implements AutoCloseable {
* Scan channels.
* @hide
*/
- public int scan(@NonNull FrontendSettings settings, @FrontendScanType int scanType) {
+ @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
+ public int scan(@NonNull FrontendSettings settings, @FrontendScanType int scanType,
+ @NonNull @CallbackExecutor Executor executor, @NonNull ScanCallback scanCallback) {
+ mScanCallback = scanCallback;
+ mScanCallbackExecutor = executor;
return nativeScan(settings.getType(), settings, scanType);
}
/**
* Stops a previous scanning.
*
- * If the method completes successfully, the frontend stop previous scanning.
+ * <p>
+ * The {@link ScanCallback} and it's {@link Executor} will be removed.
+ *
+ * <p>
+ * If the method completes successfully, the frontend stopped previous scanning.
+ *
* @hide
*/
+ @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
public int stopScan() {
- return nativeStopScan();
+ TunerUtils.checkTunerPermission(mContext);
+ int retVal = nativeStopScan();
+ mScanCallback = null;
+ mScanCallbackExecutor = null;
+ return retVal;
}
/**
diff --git a/media/java/android/media/tv/tuner/TunerConstants.java b/media/java/android/media/tv/tuner/TunerConstants.java
index c2d6c58c6558..4532122034ed 100644
--- a/media/java/android/media/tv/tuner/TunerConstants.java
+++ b/media/java/android/media/tv/tuner/TunerConstants.java
@@ -1015,10 +1015,13 @@ public final class TunerConstants {
Constants.FrontendAtsc3DemodOutputFormat.BASEBAND_PACKET;
/** @hide */
- @IntDef({FRONTEND_DVBS_STANDARD_AUTO, FRONTEND_DVBS_STANDARD_S, FRONTEND_DVBS_STANDARD_S2,
- FRONTEND_DVBS_STANDARD_S2X})
+ @IntDef(prefix = "FRONTEND_DVBS_STANDARD",
+ value = {FRONTEND_DVBS_STANDARD_AUTO, FRONTEND_DVBS_STANDARD_S,
+ FRONTEND_DVBS_STANDARD_S2,
+ FRONTEND_DVBS_STANDARD_S2X})
@Retention(RetentionPolicy.SOURCE)
- public @interface FrontendDvbsStandard {}
+ public @interface FrontendDvbsStandard {
+ }
/** @hide */
public static final int FRONTEND_DVBS_STANDARD_AUTO = Constants.FrontendDvbsStandard.AUTO;
/** @hide */
@@ -1210,6 +1213,20 @@ public final class TunerConstants {
Constants.FrontendDvbtGuardInterval.INTERVAL_19_256;
/** @hide */
+ @IntDef(prefix = "FRONTEND_DVBT_STANDARD",
+ value = {FRONTEND_DVBT_STANDARD_AUTO, FRONTEND_DVBT_STANDARD_T,
+ FRONTEND_DVBT_STANDARD_T2}
+ )
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface FrontendDvbtStandard {}
+ /** @hide */
+ public static final int FRONTEND_DVBT_STANDARD_AUTO = Constants.FrontendDvbtStandard.AUTO;
+ /** @hide */
+ public static final int FRONTEND_DVBT_STANDARD_T = Constants.FrontendDvbtStandard.T;
+ /** @hide */
+ public static final int FRONTEND_DVBT_STANDARD_T2 = Constants.FrontendDvbtStandard.T2;
+
+ /** @hide */
@IntDef({FRONTEND_ISDBS_CODERATE_UNDEFINED, FRONTEND_ISDBS_CODERATE_AUTO,
FRONTEND_ISDBS_CODERATE_1_2, FRONTEND_ISDBS_CODERATE_2_3, FRONTEND_ISDBS_CODERATE_3_4,
FRONTEND_ISDBS_CODERATE_5_6, FRONTEND_ISDBS_CODERATE_7_8})
diff --git a/media/java/android/media/tv/tuner/filter/FilterConfiguration.java b/media/java/android/media/tv/tuner/filter/FilterConfiguration.java
index 99b10cde34f9..6496627cd1d4 100644
--- a/media/java/android/media/tv/tuner/filter/FilterConfiguration.java
+++ b/media/java/android/media/tv/tuner/filter/FilterConfiguration.java
@@ -18,6 +18,7 @@ package android.media.tv.tuner.filter;
import android.annotation.IntDef;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.hardware.tv.tuner.V1_0.Constants;
import java.lang.annotation.Retention;
@@ -28,6 +29,7 @@ import java.lang.annotation.RetentionPolicy;
*
* @hide
*/
+@SystemApi
public abstract class FilterConfiguration {
/** @hide */
@@ -57,7 +59,7 @@ public abstract class FilterConfiguration {
public static final int FILTER_TYPE_ALP = Constants.DemuxFilterMainType.ALP;
@Nullable
- private final Settings mSettings;
+ /* package */ final Settings mSettings;
/* package */ FilterConfiguration(Settings settings) {
mSettings = settings;
diff --git a/media/java/android/media/tv/tuner/filter/PesSettings.java b/media/java/android/media/tv/tuner/filter/PesSettings.java
index f38abf12e120..bfa1f8c67d97 100644
--- a/media/java/android/media/tv/tuner/filter/PesSettings.java
+++ b/media/java/android/media/tv/tuner/filter/PesSettings.java
@@ -17,6 +17,9 @@
package android.media.tv.tuner.filter;
import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
+import android.content.Context;
import android.media.tv.tuner.TunerConstants;
import android.media.tv.tuner.TunerUtils;
import android.media.tv.tuner.filter.FilterConfiguration.FilterType;
@@ -26,6 +29,7 @@ import android.media.tv.tuner.filter.FilterConfiguration.FilterType;
*
* @hide
*/
+@SystemApi
public class PesSettings extends Settings {
private final int mStreamId;
private final boolean mIsRaw;
@@ -37,12 +41,32 @@ public class PesSettings extends Settings {
}
/**
+ * Gets stream ID.
+ */
+ public int getStreamId() {
+ return mStreamId;
+ }
+
+ /**
+ * Returns whether the data is raw.
+ *
+ * @return {@code true} if the data is raw. Filter sends onFilterStatus callback
+ * instead of onFilterEvent for raw data. {@code false} otherwise.
+ */
+ public boolean isRaw() {
+ return mIsRaw;
+ }
+
+ /**
* Creates a builder for {@link PesSettings}.
*
* @param mainType the filter main type of the settings.
+ * @param context the context of the caller.
*/
+ @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
@NonNull
- public static Builder newBuilder(@FilterType int mainType) {
+ public static Builder builder(@NonNull Context context, @FilterType int mainType) {
+ TunerUtils.checkTunerPermission(context);
return new Builder(mainType);
}
@@ -70,13 +94,13 @@ public class PesSettings extends Settings {
}
/**
- * Sets whether it's raw.
+ * Sets whether the data is raw.
*
* @param isRaw {@code true} if the data is raw. Filter sends onFilterStatus callback
* instead of onFilterEvent for raw data. {@code false} otherwise.
*/
@NonNull
- public Builder setIsRaw(boolean isRaw) {
+ public Builder setRaw(boolean isRaw) {
mIsRaw = isRaw;
return this;
}
diff --git a/media/java/android/media/tv/tuner/filter/Settings.java b/media/java/android/media/tv/tuner/filter/Settings.java
index 146aca74ce0e..91559260031c 100644
--- a/media/java/android/media/tv/tuner/filter/Settings.java
+++ b/media/java/android/media/tv/tuner/filter/Settings.java
@@ -16,11 +16,14 @@
package android.media.tv.tuner.filter;
+import android.annotation.SystemApi;
+
/**
* Settings for filters of different subtypes.
*
* @hide
*/
+@SystemApi
public abstract class Settings {
private final int mType;
diff --git a/media/java/android/media/tv/tuner/filter/TsFilterConfiguration.java b/media/java/android/media/tv/tuner/filter/TsFilterConfiguration.java
index d0241b6aba09..5c38cfa70eb3 100644
--- a/media/java/android/media/tv/tuner/filter/TsFilterConfiguration.java
+++ b/media/java/android/media/tv/tuner/filter/TsFilterConfiguration.java
@@ -17,12 +17,18 @@
package android.media.tv.tuner.filter;
import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
+import android.content.Context;
+import android.media.tv.tuner.TunerUtils;
/**
* Filter configuration for a TS filter.
*
* @hide
*/
+@SystemApi
public class TsFilterConfiguration extends FilterConfiguration {
private final int mTpid;
@@ -37,10 +43,28 @@ public class TsFilterConfiguration extends FilterConfiguration {
}
/**
+ * Gets the {@link Settings} object of this filter configuration.
+ */
+ @Nullable
+ public Settings getSettings() {
+ return mSettings;
+ }
+ /**
+ * Gets Tag Protocol ID.
+ */
+ public int getTpid() {
+ return mTpid;
+ }
+
+ /**
* Creates a builder for {@link TsFilterConfiguration}.
+ *
+ * @param context the context of the caller.
*/
+ @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
@NonNull
- public static Builder newBuilder() {
+ public static Builder builder(@NonNull Context context) {
+ TunerUtils.checkTunerPermission(context);
return new Builder();
}
@@ -51,6 +75,9 @@ public class TsFilterConfiguration extends FilterConfiguration {
private Settings mSettings;
private int mTpid;
+ private Builder() {
+ }
+
/**
* Sets filter settings.
*
diff --git a/media/java/android/media/tv/tuner/frontend/FrontendCallback.java b/media/java/android/media/tv/tuner/frontend/FrontendCallback.java
index 0992eb665330..9c4f4606a9bc 100644
--- a/media/java/android/media/tv/tuner/frontend/FrontendCallback.java
+++ b/media/java/android/media/tv/tuner/frontend/FrontendCallback.java
@@ -27,10 +27,4 @@ public interface FrontendCallback {
* Invoked when there is a frontend event.
*/
void onEvent(int frontendEventType);
-
- /**
- * Invoked when there is a scan message.
- * @param msg
- */
- void onScanMessage(ScanMessage msg);
}
diff --git a/media/java/android/media/tv/tuner/frontend/ScanCallback.java b/media/java/android/media/tv/tuner/frontend/ScanCallback.java
new file mode 100644
index 000000000000..8118fcc0e900
--- /dev/null
+++ b/media/java/android/media/tv/tuner/frontend/ScanCallback.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2020 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.frontend;
+
+import android.media.tv.tuner.TunerConstants;
+
+/**
+ * Scan callback.
+ *
+ * @hide
+ */
+public interface ScanCallback {
+ /** Scan locked the signal. */
+ void onLocked(boolean isLocked);
+
+ /** Scan stopped. */
+ void onEnd(boolean isEnd);
+
+ /** scan progress percent (0..100) */
+ void onProgress(int percent);
+
+ /** Signal frequency in Hertz */
+ void onFrequencyReport(int frequency);
+
+ /** Symbols per second */
+ void onSymbolRate(int rate);
+
+ /** Locked Plp Ids for DVBT2 frontend. */
+ void onPlpIds(int[] plpIds);
+
+ /** Locked group Ids for DVBT2 frontend. */
+ void onGroupIds(int[] groupIds);
+
+ /** Stream Ids. */
+ void onInputStreamIds(int[] inputStreamIds);
+
+ /** Locked signal standard. */
+ void onDvbsStandard(@TunerConstants.FrontendDvbsStandard int dvbsStandandard);
+
+ /** Locked signal standard. */
+ void onDvbtStandard(@TunerConstants.FrontendDvbtStandard int dvbtStandard);
+
+ /** PLP status in a tuned frequency band for ATSC3 frontend. */
+ void onAtsc3PlpInfos(Atsc3PlpInfo[] atsc3PlpInfos);
+
+ /** PLP information for ATSC3. */
+ class Atsc3PlpInfo {
+ private final int mPlpId;
+ private final boolean mLlsFlag;
+
+ private Atsc3PlpInfo(int plpId, boolean llsFlag) {
+ mPlpId = plpId;
+ mLlsFlag = llsFlag;
+ }
+
+ /** Gets PLP IDs. */
+ public int getPlpId() {
+ return mPlpId;
+ }
+
+ /** Gets LLS flag. */
+ public boolean getLlsFlag() {
+ return mLlsFlag;
+ }
+ }
+}
diff --git a/media/java/android/media/tv/tuner/frontend/ScanMessage.java b/media/java/android/media/tv/tuner/frontend/ScanMessage.java
deleted file mode 100644
index dd687dd2959c..000000000000
--- a/media/java/android/media/tv/tuner/frontend/ScanMessage.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright (C) 2020 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.frontend;
-
-import android.annotation.IntDef;
-import android.hardware.tv.tuner.V1_0.Constants;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Message from frontend during scan operations.
- *
- * @hide
- */
-public class ScanMessage {
-
- /** @hide */
- @IntDef({
- LOCKED,
- END,
- PROGRESS_PERCENT,
- FREQUENCY,
- SYMBOL_RATE,
- PLP_IDS,
- GROUP_IDS,
- INPUT_STREAM_IDS,
- STANDARD,
- ATSC3_PLP_INFO
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface Type {}
- /** @hide */
- public static final int LOCKED = Constants.FrontendScanMessageType.LOCKED;
- /** @hide */
- public static final int END = Constants.FrontendScanMessageType.END;
- /** @hide */
- public static final int PROGRESS_PERCENT = Constants.FrontendScanMessageType.PROGRESS_PERCENT;
- /** @hide */
- public static final int FREQUENCY = Constants.FrontendScanMessageType.FREQUENCY;
- /** @hide */
- public static final int SYMBOL_RATE = Constants.FrontendScanMessageType.SYMBOL_RATE;
- /** @hide */
- public static final int PLP_IDS = Constants.FrontendScanMessageType.PLP_IDS;
- /** @hide */
- public static final int GROUP_IDS = Constants.FrontendScanMessageType.GROUP_IDS;
- /** @hide */
- public static final int INPUT_STREAM_IDS = Constants.FrontendScanMessageType.INPUT_STREAM_IDS;
- /** @hide */
- public static final int STANDARD = Constants.FrontendScanMessageType.STANDARD;
- /** @hide */
- public static final int ATSC3_PLP_INFO = Constants.FrontendScanMessageType.ATSC3_PLP_INFO;
-
- private final int mType;
- private final Object mValue;
-
- private ScanMessage(int type, Object value) {
- mType = type;
- mValue = value;
- }
-
- /** Gets scan message type. */
- @Type
- public int getMessageType() {
- return mType;
- }
- /** Message indicates whether frontend is locked or not. */
- public boolean getIsLocked() {
- if (mType != LOCKED) {
- throw new IllegalStateException();
- }
- return (Boolean) mValue;
- }
- /** Message indicates whether the scan has reached the end or not. */
- public boolean getIsEnd() {
- if (mType != END) {
- throw new IllegalStateException();
- }
- return (Boolean) mValue;
- }
- /** Progress message in percent. */
- public int getProgressPercent() {
- if (mType != PROGRESS_PERCENT) {
- throw new IllegalStateException();
- }
- return (Integer) mValue;
- }
- /** Gets frequency. */
- public int getFrequency() {
- if (mType != FREQUENCY) {
- throw new IllegalStateException();
- }
- return (Integer) mValue;
- }
- /** Gets symbol rate. */
- public int getSymbolRate() {
- if (mType != SYMBOL_RATE) {
- throw new IllegalStateException();
- }
- return (Integer) mValue;
- }
- /** Gets PLP IDs. */
- public int[] getPlpIds() {
- if (mType != PLP_IDS) {
- throw new IllegalStateException();
- }
- return (int[]) mValue;
- }
- /** Gets group IDs. */
- public int[] getGroupIds() {
- if (mType != GROUP_IDS) {
- throw new IllegalStateException();
- }
- return (int[]) mValue;
- }
- /** Gets Input stream IDs. */
- public int[] getInputStreamIds() {
- if (mType != INPUT_STREAM_IDS) {
- throw new IllegalStateException();
- }
- return (int[]) mValue;
- }
- /** Gets the DVB-T or DVB-S standard. */
- public int getStandard() {
- if (mType != STANDARD) {
- throw new IllegalStateException();
- }
- return (int) mValue;
- }
-
- /** Gets PLP information for ATSC3. */
- public Atsc3PlpInfo[] getAtsc3PlpInfos() {
- if (mType != ATSC3_PLP_INFO) {
- throw new IllegalStateException();
- }
- return (Atsc3PlpInfo[]) mValue;
- }
-
- /** PLP information for ATSC3. */
- public static class Atsc3PlpInfo {
- private final int mPlpId;
- private final boolean mLlsFlag;
-
- private Atsc3PlpInfo(int plpId, boolean llsFlag) {
- mPlpId = plpId;
- mLlsFlag = llsFlag;
- }
-
- /** Gets PLP IDs. */
- public int getPlpId() {
- return mPlpId;
- }
- /** Gets LLS flag. */
- public boolean getLlsFlag() {
- return mLlsFlag;
- }
- }
-}
diff --git a/media/jni/Android.bp b/media/jni/Android.bp
index 536a061190d7..aeacd8f63cb0 100644
--- a/media/jni/Android.bp
+++ b/media/jni/Android.bp
@@ -19,6 +19,7 @@ cc_library_shared {
"android_media_MediaProfiles.cpp",
"android_media_MediaRecorder.cpp",
"android_media_MediaSync.cpp",
+ "android_media_MediaTranscodeManager.cpp",
"android_media_ResampleInputStream.cpp",
"android_media_Streams.cpp",
"android_media_SyncParams.cpp",
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index 963b650292e4..5cb42a9a96cc 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -1453,6 +1453,7 @@ extern int register_android_media_MediaProfiles(JNIEnv *env);
extern int register_android_mtp_MtpDatabase(JNIEnv *env);
extern int register_android_mtp_MtpDevice(JNIEnv *env);
extern int register_android_mtp_MtpServer(JNIEnv *env);
+extern int register_android_media_MediaTranscodeManager(JNIEnv *env);
jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
{
@@ -1565,6 +1566,11 @@ jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
goto bail;
}
+ if (register_android_media_MediaTranscodeManager(env) < 0) {
+ ALOGE("ERROR: MediaTranscodeManager native registration failed");
+ goto bail;
+ }
+
/* success -- return valid version number */
result = JNI_VERSION_1_4;
diff --git a/media/jni/android_media_MediaTranscodeManager.cpp b/media/jni/android_media_MediaTranscodeManager.cpp
new file mode 100644
index 000000000000..0b4048c1170c
--- /dev/null
+++ b/media/jni/android_media_MediaTranscodeManager.cpp
@@ -0,0 +1,102 @@
+/*
+ * 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.
+ */
+//#define LOG_NDEBUG 0
+#define LOG_TAG "MediaTranscodeManager_JNI"
+
+#include "android_runtime/AndroidRuntime.h"
+#include "jni.h"
+
+#include <nativehelper/JNIHelp.h>
+#include <utils/Log.h>
+
+namespace {
+
+// NOTE: Keep these enums in sync with their equivalents in MediaTranscodeManager.java.
+enum {
+ ID_INVALID = -1
+};
+
+enum {
+ EVENT_JOB_STARTED = 1,
+ EVENT_JOB_PROGRESSED = 2,
+ EVENT_JOB_FINISHED = 3,
+};
+
+enum {
+ RESULT_NONE = 1,
+ RESULT_SUCCESS = 2,
+ RESULT_ERROR = 3,
+ RESULT_CANCELED = 4,
+};
+
+struct {
+ jmethodID postEventFromNative;
+} gMediaTranscodeManagerClassInfo;
+
+using namespace android;
+
+void android_media_MediaTranscodeManager_native_init(JNIEnv *env, jclass clazz) {
+ ALOGV("android_media_MediaTranscodeManager_native_init");
+
+ gMediaTranscodeManagerClassInfo.postEventFromNative = env->GetMethodID(
+ clazz, "postEventFromNative", "(IJI)V");
+ LOG_ALWAYS_FATAL_IF(gMediaTranscodeManagerClassInfo.postEventFromNative == NULL,
+ "can't find android/media/MediaTranscodeManager.postEventFromNative");
+}
+
+jlong android_media_MediaTranscodeManager_requestUniqueJobID(
+ JNIEnv *env __unused, jobject thiz __unused) {
+ ALOGV("android_media_MediaTranscodeManager_reserveUniqueJobID");
+ static std::atomic_int32_t sJobIDCounter{0};
+ jlong id = (jlong)++sJobIDCounter;
+ return id;
+}
+
+jboolean android_media_MediaTranscodeManager_enqueueTranscodingRequest(
+ JNIEnv *env, jobject thiz, jlong id, jobject request, jobject context __unused) {
+ ALOGV("android_media_MediaTranscodeManager_enqueueTranscodingRequest");
+ if (!request) {
+ return ID_INVALID;
+ }
+
+ env->CallVoidMethod(thiz, gMediaTranscodeManagerClassInfo.postEventFromNative,
+ EVENT_JOB_FINISHED, id, RESULT_ERROR);
+ return true;
+}
+
+void android_media_MediaTranscodeManager_cancelTranscodingRequest(
+ JNIEnv *env __unused, jobject thiz __unused, jlong jobID __unused) {
+ ALOGV("android_media_MediaTranscodeManager_cancelTranscodingRequest");
+}
+
+const JNINativeMethod gMethods[] = {
+ { "native_init", "()V",
+ (void *)android_media_MediaTranscodeManager_native_init },
+ { "native_requestUniqueJobID", "()J",
+ (void *)android_media_MediaTranscodeManager_requestUniqueJobID },
+ { "native_enqueueTranscodingRequest",
+ "(JLandroid/media/MediaTranscodeManager$TranscodingRequest;Landroid/content/Context;)Z",
+ (void *)android_media_MediaTranscodeManager_enqueueTranscodingRequest },
+ { "native_cancelTranscodingRequest", "(J)V",
+ (void *)android_media_MediaTranscodeManager_cancelTranscodingRequest },
+};
+
+} // namespace anonymous
+
+int register_android_media_MediaTranscodeManager(JNIEnv *env) {
+ return AndroidRuntime::registerNativeMethods(env,
+ "android/media/MediaTranscodeManager", gMethods, NELEM(gMethods));
+}
diff --git a/media/tests/MediaFrameworkTest/Android.bp b/media/tests/MediaFrameworkTest/Android.bp
index f0fbc509cc9d..ecbe2b3eb8b7 100644
--- a/media/tests/MediaFrameworkTest/Android.bp
+++ b/media/tests/MediaFrameworkTest/Android.bp
@@ -7,6 +7,7 @@ android_test {
],
static_libs: [
"mockito-target-minus-junit4",
+ "androidx.test.ext.junit",
"androidx.test.rules",
"android-ex-camera2",
],
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/mediatranscodemanager/MediaTranscodeManagerTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/mediatranscodemanager/MediaTranscodeManagerTest.java
new file mode 100644
index 000000000000..eeda50e5c095
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/mediatranscodemanager/MediaTranscodeManagerTest.java
@@ -0,0 +1,74 @@
+/*
+ * 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.mediaframeworktest.functional.mediatranscodemanager;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import android.media.MediaTranscodeManager;
+import android.util.Log;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+@RunWith(AndroidJUnit4.class)
+public class MediaTranscodeManagerTest {
+ private static final String TAG = "MediaTranscodeManagerTest";
+
+ /** The time to wait for the transcode operation to complete before failing the test. */
+ private static final int TRANSCODE_TIMEOUT_SECONDS = 2;
+
+ @Test
+ public void testMediaTranscodeManager() throws InterruptedException {
+ Log.d(TAG, "Starting: testMediaTranscodeManager");
+
+ Semaphore transcodeCompleteSemaphore = new Semaphore(0);
+ MediaTranscodeManager.TranscodingRequest request =
+ new MediaTranscodeManager.TranscodingRequest.Builder().build();
+ Executor listenerExecutor = Executors.newSingleThreadExecutor();
+
+ MediaTranscodeManager mediaTranscodeManager =
+ MediaTranscodeManager.getInstance(ApplicationProvider.getApplicationContext());
+ assertNotNull(mediaTranscodeManager);
+
+ MediaTranscodeManager.TranscodingJob job;
+ job = mediaTranscodeManager.enqueueTranscodingRequest(request, listenerExecutor,
+ transcodingJob -> {
+ Log.d(TAG, "Transcoding completed with result: " + transcodingJob.getResult());
+ transcodeCompleteSemaphore.release();
+ });
+ assertNotNull(job);
+
+ job.setOnProgressChangedListener(
+ listenerExecutor, progress -> Log.d(TAG, "Progress: " + progress));
+
+ if (job != null) {
+ Log.d(TAG, "testMediaTranscodeManager - Waiting for transcode to complete.");
+ boolean finishedOnTime = transcodeCompleteSemaphore.tryAcquire(
+ TRANSCODE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+ assertTrue("Transcode failed to complete in time.", finishedOnTime);
+ }
+ }
+}
diff --git a/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java b/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java
index 221783b1c97d..ed93112d5288 100644
--- a/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java
+++ b/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java
@@ -172,7 +172,7 @@ public class SampleMediaRoute2ProviderService extends MediaRoute2ProviderService
MediaRoute2Info route = mRoutes.get(routeId);
if (route == null || TextUtils.equals(ROUTE_ID3_SESSION_CREATION_FAILED, routeId)) {
// Tell the router that session cannot be created by passing null as sessionInfo.
- notifySessionCreated(/* sessionInfo= */ null, requestId);
+ notifySessionCreationFailed(requestId);
return;
}
maybeDeselectRoute(routeId);
@@ -196,8 +196,13 @@ public class SampleMediaRoute2ProviderService extends MediaRoute2ProviderService
}
@Override
- public void onDestroySession(String sessionId, RoutingSessionInfo lastSessionInfo) {
- for (String routeId : lastSessionInfo.getSelectedRoutes()) {
+ public void onReleaseSession(String sessionId) {
+ RoutingSessionInfo sessionInfo = getSessionInfo(sessionId);
+ if (sessionInfo == null) {
+ return;
+ }
+
+ for (String routeId : sessionInfo.getSelectedRoutes()) {
mRouteIdToSessionId.remove(routeId);
MediaRoute2Info route = mRoutes.get(routeId);
if (route != null) {
@@ -206,6 +211,7 @@ public class SampleMediaRoute2ProviderService extends MediaRoute2ProviderService
.build());
}
}
+ notifySessionReleased(sessionId);
}
@Override
@@ -227,8 +233,7 @@ public class SampleMediaRoute2ProviderService extends MediaRoute2ProviderService
.removeSelectableRoute(routeId)
.addDeselectableRoute(routeId)
.build();
- updateSessionInfo(newSessionInfo);
- notifySessionInfoChanged(newSessionInfo);
+ notifySessionUpdated(newSessionInfo);
}
@Override
@@ -247,7 +252,7 @@ public class SampleMediaRoute2ProviderService extends MediaRoute2ProviderService
.build());
if (sessionInfo.getSelectedRoutes().size() == 1) {
- releaseSession(sessionId);
+ notifySessionReleased(sessionId);
return;
}
@@ -256,8 +261,7 @@ public class SampleMediaRoute2ProviderService extends MediaRoute2ProviderService
.addSelectableRoute(routeId)
.removeDeselectableRoute(routeId)
.build();
- updateSessionInfo(newSessionInfo);
- notifySessionInfoChanged(newSessionInfo);
+ notifySessionUpdated(newSessionInfo);
}
@Override
@@ -269,8 +273,7 @@ public class SampleMediaRoute2ProviderService extends MediaRoute2ProviderService
.removeDeselectableRoute(routeId)
.removeTransferrableRoute(routeId)
.build();
- updateSessionInfo(newSessionInfo);
- notifySessionInfoChanged(newSessionInfo);
+ notifySessionUpdated(newSessionInfo);
}
void maybeDeselectRoute(String routeId) {
diff --git a/native/graphics/jni/bitmap.cpp b/native/graphics/jni/bitmap.cpp
index 1aebeaf1e7e8..26c7f8d709e7 100644
--- a/native/graphics/jni/bitmap.cpp
+++ b/native/graphics/jni/bitmap.cpp
@@ -16,6 +16,7 @@
#include <android/bitmap.h>
#include <android/graphics/bitmap.h>
+#include <android/data_space.h>
int AndroidBitmap_getInfo(JNIEnv* env, jobject jbitmap,
AndroidBitmapInfo* info) {
@@ -29,6 +30,15 @@ int AndroidBitmap_getInfo(JNIEnv* env, jobject jbitmap,
return ANDROID_BITMAP_RESULT_SUCCESS;
}
+int32_t AndroidBitmap_getDataSpace(JNIEnv* env, jobject jbitmap) {
+ if (NULL == env || NULL == jbitmap) {
+ return ADATASPACE_UNKNOWN; // Or return a real error?
+ }
+
+ android::graphics::Bitmap bitmap(env, jbitmap);
+ return bitmap.getDataSpace();
+}
+
int AndroidBitmap_lockPixels(JNIEnv* env, jobject jbitmap, void** addrPtr) {
if (NULL == env || NULL == jbitmap) {
return ANDROID_BITMAP_RESULT_BAD_PARAMETER;
diff --git a/native/graphics/jni/libjnigraphics.map.txt b/native/graphics/jni/libjnigraphics.map.txt
index bdd7f63b2d78..832770ffb97e 100644
--- a/native/graphics/jni/libjnigraphics.map.txt
+++ b/native/graphics/jni/libjnigraphics.map.txt
@@ -18,6 +18,7 @@ LIBJNIGRAPHICS {
AImageDecoderHeaderInfo_isAnimated;
AImageDecoderHeaderInfo_getAndroidBitmapFormat;
AndroidBitmap_getInfo;
+ AndroidBitmap_getDataSpace;
AndroidBitmap_lockPixels;
AndroidBitmap_unlockPixels;
local:
diff --git a/packages/CarSystemUI/res/layout/sysui_primary_window.xml b/packages/CarSystemUI/res/layout/sysui_primary_window.xml
index 309d9ef3ccfd..cc36e87eb480 100644
--- a/packages/CarSystemUI/res/layout/sysui_primary_window.xml
+++ b/packages/CarSystemUI/res/layout/sysui_primary_window.xml
@@ -15,9 +15,16 @@
~ limitations under the License.
-->
+<!-- Fullscreen views in sysui should be listed here in increasing Z order. -->
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:background="@android:color/transparent"
android:layout_width="match_parent"
android:layout_height="match_parent">
+
+ <ViewStub android:id="@+id/fullscreen_user_switcher_stub"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout="@layout/car_fullscreen_user_switcher"/>
+
</FrameLayout> \ No newline at end of file
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java b/packages/CarSystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java
index 6ec385438e23..cfe1c702663e 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java
@@ -22,7 +22,7 @@ import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationRankingManager;
-import com.android.systemui.statusbar.notification.collection.NotificationRowBinder;
+import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder;
import com.android.systemui.statusbar.notification.logging.NotifLog;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.util.leak.LeakDetector;
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/SystemUIPrimaryWindowController.java b/packages/CarSystemUI/src/com/android/systemui/car/SystemUIPrimaryWindowController.java
index e3e9ab75e3a2..c7e14d677b04 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/SystemUIPrimaryWindowController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/SystemUIPrimaryWindowController.java
@@ -54,6 +54,7 @@ public class SystemUIPrimaryWindowController implements
private ViewGroup mBaseLayout;
private WindowManager.LayoutParams mLp;
private WindowManager.LayoutParams mLpChanged;
+ private boolean mIsAttached = false;
@Inject
public SystemUIPrimaryWindowController(
@@ -86,8 +87,17 @@ public class SystemUIPrimaryWindowController implements
return mBaseLayout;
}
+ /** Returns {@code true} if the window is already attached. */
+ public boolean isAttached() {
+ return mIsAttached;
+ }
+
/** Attaches the window to the window manager. */
public void attach() {
+ if (mIsAttached) {
+ return;
+ }
+ mIsAttached = true;
// Now that the status bar window encompasses the sliding panel and its
// translucent backdrop, the entire thing is made TRANSLUCENT and is
// hardware-accelerated.
@@ -98,13 +108,14 @@ public class SystemUIPrimaryWindowController implements
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
- | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
+ | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+ | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
PixelFormat.TRANSLUCENT);
mLp.token = new Binder();
mLp.gravity = Gravity.TOP;
mLp.setFitWindowInsetsTypes(/* types= */ 0);
mLp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
- mLp.setTitle("NotificationShade");
+ mLp.setTitle("SystemUIPrimaryWindow");
mLp.packageName = mContext.getPackageName();
mLp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
@@ -118,8 +129,11 @@ public class SystemUIPrimaryWindowController implements
// TODO: Update this so that the windowing type gets the full height of the display
// when we use MATCH_PARENT.
mLpChanged.height = mDisplayHeight + mNavBarHeight;
+ mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
} else {
mLpChanged.height = mStatusBarHeight;
+ // TODO: Allow touches to go through to the status bar to handle notification panel.
+ mLpChanged.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
}
updateWindow();
}
@@ -131,7 +145,9 @@ public class SystemUIPrimaryWindowController implements
private void updateWindow() {
if (mLp != null && mLp.copyFrom(mLpChanged) != 0) {
- mWindowManager.updateViewLayout(mBaseLayout, mLp);
+ if (isAttached()) {
+ mWindowManager.updateViewLayout(mBaseLayout, mLp);
+ }
}
}
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index 4521f5fb470e..18485dc283f0 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -67,6 +67,7 @@ import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.car.CarDeviceProvisionedController;
import com.android.systemui.car.CarDeviceProvisionedListener;
import com.android.systemui.car.CarServiceProvider;
+import com.android.systemui.car.SystemUIPrimaryWindowController;
import com.android.systemui.classifier.FalsingLog;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.dagger.qualifiers.UiBackground;
@@ -106,8 +107,8 @@ import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
-import com.android.systemui.statusbar.notification.collection.NotificationRowBinderImpl;
-import com.android.systemui.statusbar.notification.collection.init.NewNotifPipeline;
+import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
+import com.android.systemui.statusbar.notification.collection.init.NotifPipelineInitializer;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.phone.AutoHideController;
@@ -168,6 +169,7 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
// acceleration rate for the fling animation
private static final float FLING_SPEED_UP_FACTOR = 0.6f;
+ private final UserSwitcherController mUserSwitcherController;
private final ScrimController mScrimController;
private final LockscreenLockIconController mLockscreenLockIconController;
@@ -177,17 +179,16 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
private float mBackgroundAlphaDiff;
private float mInitialBackgroundAlpha;
- private final Lazy<FullscreenUserSwitcher> mFullscreenUserSwitcherLazy;
- private FullscreenUserSwitcher mFullscreenUserSwitcher;
-
private CarBatteryController mCarBatteryController;
private BatteryMeterView mBatteryMeterView;
private Drawable mNotificationPanelBackground;
private final Object mQueueLock = new Object();
+ private final SystemUIPrimaryWindowController mSystemUIPrimaryWindowController;
private final CarNavigationBarController mCarNavigationBarController;
private final FlingAnimationUtils.Builder mFlingAnimationUtilsBuilder;
private final Lazy<PowerManagerHelper> mPowerManagerHelperLazy;
+ private final FullscreenUserSwitcher mFullscreenUserSwitcher;
private final ShadeController mShadeController;
private final CarServiceProvider mCarServiceProvider;
private final CarDeviceProvisionedController mCarDeviceProvisionedController;
@@ -268,7 +269,7 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
HeadsUpManagerPhone headsUpManagerPhone,
DynamicPrivacyController dynamicPrivacyController,
BypassHeadsUpNotifier bypassHeadsUpNotifier,
- Lazy<NewNotifPipeline> newNotifPipeline,
+ Lazy<NotifPipelineInitializer> notifPipelineInitializer,
FalsingManager falsingManager,
BroadcastDispatcher broadcastDispatcher,
RemoteInputQuickSettingsDisabler remoteInputQuickSettingsDisabler,
@@ -338,7 +339,8 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
/* Car Settings injected components. */
CarServiceProvider carServiceProvider,
Lazy<PowerManagerHelper> powerManagerHelperLazy,
- Lazy<FullscreenUserSwitcher> fullscreenUserSwitcherLazy,
+ FullscreenUserSwitcher fullscreenUserSwitcher,
+ SystemUIPrimaryWindowController systemUIPrimaryWindowController,
CarNavigationBarController carNavigationBarController,
FlingAnimationUtils.Builder flingAnimationUtilsBuilder) {
super(
@@ -355,7 +357,7 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
headsUpManagerPhone,
dynamicPrivacyController,
bypassHeadsUpNotifier,
- newNotifPipeline,
+ notifPipelineInitializer,
falsingManager,
broadcastDispatcher,
remoteInputQuickSettingsDisabler,
@@ -422,6 +424,7 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
userInfoControllerImpl,
notificationRowBinder,
dismissCallbackRegistry);
+ mUserSwitcherController = userSwitcherController;
mScrimController = scrimController;
mLockscreenLockIconController = lockscreenLockIconController;
mCarDeviceProvisionedController =
@@ -429,7 +432,8 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
mShadeController = shadeController;
mCarServiceProvider = carServiceProvider;
mPowerManagerHelperLazy = powerManagerHelperLazy;
- mFullscreenUserSwitcherLazy = fullscreenUserSwitcherLazy;
+ mFullscreenUserSwitcher = fullscreenUserSwitcher;
+ mSystemUIPrimaryWindowController = systemUIPrimaryWindowController;
mCarNavigationBarController = carNavigationBarController;
mFlingAnimationUtilsBuilder = flingAnimationUtilsBuilder;
}
@@ -444,6 +448,13 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
mScreenLifecycle = Dependency.get(ScreenLifecycle.class);
mScreenLifecycle.addObserver(mScreenObserver);
+ // TODO: Remove the setup of user switcher from Car Status Bar.
+ mSystemUIPrimaryWindowController.attach();
+ mFullscreenUserSwitcher.setStatusBar(this);
+ mFullscreenUserSwitcher.setContainer(
+ mSystemUIPrimaryWindowController.getBaseLayout().findViewById(
+ R.id.fullscreen_user_switcher_stub));
+
// Notification bar related setup.
mInitialBackgroundAlpha = (float) mContext.getResources().getInteger(
R.integer.config_initialNotificationBackgroundAlpha) / 100;
@@ -510,16 +521,6 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
});
}
- /**
- * Allows for showing or hiding just the navigation bars. This is indented to be used when
- * the full screen user selector is shown.
- */
- void setNavBarVisibility(@View.Visibility int visibility) {
- mCarNavigationBarController.setBottomWindowVisibility(visibility);
- mCarNavigationBarController.setLeftWindowVisibility(visibility);
- mCarNavigationBarController.setRightWindowVisibility(visibility);
- }
-
@Override
public boolean hideKeyguard() {
boolean result = super.hideKeyguard();
@@ -924,9 +925,6 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
+ " scroll " + mStackScroller.getScrollX()
+ "," + mStackScroller.getScrollY());
}
-
- pw.print(" mFullscreenUserSwitcher=");
- pw.println(mFullscreenUserSwitcher);
pw.print(" mCarBatteryController=");
pw.println(mCarBatteryController);
pw.print(" mBatteryMeterView=");
@@ -972,14 +970,7 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
@Override
protected void createUserSwitcher() {
- UserSwitcherController userSwitcherController =
- Dependency.get(UserSwitcherController.class);
- if (userSwitcherController.useFullscreenUserSwitcher()) {
- mFullscreenUserSwitcher = mFullscreenUserSwitcherLazy.get();
- mFullscreenUserSwitcher.setStatusBar(this);
- mFullscreenUserSwitcher.setContainer(
- mStatusBarWindow.findViewById(R.id.fullscreen_user_switcher_stub));
- } else {
+ if (!mUserSwitcherController.useFullscreenUserSwitcher()) {
super.createUserSwitcher();
}
}
@@ -996,25 +987,12 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
super.onStateChanged(newState);
if (newState != StatusBarState.FULLSCREEN_USER_SWITCHER) {
- hideUserSwitcher();
+ mFullscreenUserSwitcher.hide();
} else {
dismissKeyguardWhenUserSwitcherNotDisplayed();
}
}
- /** Makes the full screen user switcher visible, if applicable. */
- public void showUserSwitcher() {
- if (mFullscreenUserSwitcher != null && mState == StatusBarState.FULLSCREEN_USER_SWITCHER) {
- mFullscreenUserSwitcher.show(); // Makes the switcher visible.
- }
- }
-
- private void hideUserSwitcher() {
- if (mFullscreenUserSwitcher != null) {
- mFullscreenUserSwitcher.hide();
- }
- }
-
final ScreenLifecycle.Observer mScreenObserver = new ScreenLifecycle.Observer() {
@Override
public void onScreenTurnedOn() {
@@ -1024,7 +1002,7 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
// We automatically dismiss keyguard unless user switcher is being shown on the keyguard.
private void dismissKeyguardWhenUserSwitcherNotDisplayed() {
- if (mFullscreenUserSwitcher == null) {
+ if (!mUserSwitcherController.useFullscreenUserSwitcher()) {
return; // Not using the full screen user switcher.
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarKeyguardViewManager.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarKeyguardViewManager.java
index 0ad0992b68a4..2a2eb6976653 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarKeyguardViewManager.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarKeyguardViewManager.java
@@ -24,6 +24,7 @@ import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.R;
import com.android.systemui.dock.DockManager;
+import com.android.systemui.navigationbar.car.CarNavigationBarController;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.phone.NavigationModeController;
@@ -40,6 +41,8 @@ import javax.inject.Singleton;
public class CarStatusBarKeyguardViewManager extends StatusBarKeyguardViewManager {
protected boolean mShouldHideNavBar;
+ private final CarNavigationBarController mCarNavigationBarController;
+ private final FullscreenUserSwitcher mFullscreenUserSwitcher;
@Inject
public CarStatusBarKeyguardViewManager(Context context,
@@ -52,13 +55,17 @@ public class CarStatusBarKeyguardViewManager extends StatusBarKeyguardViewManage
DockManager dockManager,
StatusBarWindowController statusBarWindowController,
KeyguardStateController keyguardStateController,
- NotificationMediaManager notificationMediaManager) {
+ NotificationMediaManager notificationMediaManager,
+ CarNavigationBarController carNavigationBarController,
+ FullscreenUserSwitcher fullscreenUserSwitcher) {
super(context, callback, lockPatternUtils, sysuiStatusBarStateController,
configurationController, keyguardUpdateMonitor, navigationModeController,
dockManager, statusBarWindowController, keyguardStateController,
notificationMediaManager);
mShouldHideNavBar = context.getResources()
.getBoolean(R.bool.config_hideNavWhenKeyguardBouncerShown);
+ mCarNavigationBarController = carNavigationBarController;
+ mFullscreenUserSwitcher = fullscreenUserSwitcher;
}
@Override
@@ -66,8 +73,10 @@ public class CarStatusBarKeyguardViewManager extends StatusBarKeyguardViewManage
if (!mShouldHideNavBar) {
return;
}
- CarStatusBar statusBar = (CarStatusBar) mStatusBar;
- statusBar.setNavBarVisibility(navBarVisible ? View.VISIBLE : View.GONE);
+ int visibility = navBarVisible ? View.VISIBLE : View.GONE;
+ mCarNavigationBarController.setBottomWindowVisibility(visibility);
+ mCarNavigationBarController.setLeftWindowVisibility(visibility);
+ mCarNavigationBarController.setRightWindowVisibility(visibility);
}
/**
@@ -86,8 +95,7 @@ public class CarStatusBarKeyguardViewManager extends StatusBarKeyguardViewManage
*/
@Override
public void onCancelClicked() {
- CarStatusBar statusBar = (CarStatusBar) mStatusBar;
- statusBar.showUserSwitcher();
+ mFullscreenUserSwitcher.show();
}
/**
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java
index e5a091f94077..3abbe32df2da 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java
@@ -31,6 +31,7 @@ import com.android.systemui.assist.AssistManager;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.car.CarServiceProvider;
+import com.android.systemui.car.SystemUIPrimaryWindowController;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.keyguard.DismissCallbackRegistry;
@@ -66,8 +67,8 @@ import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
-import com.android.systemui.statusbar.notification.collection.NotificationRowBinderImpl;
-import com.android.systemui.statusbar.notification.collection.init.NewNotifPipeline;
+import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
+import com.android.systemui.statusbar.notification.collection.init.NotifPipelineInitializer;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.phone.AutoHideController;
@@ -138,7 +139,7 @@ public class CarStatusBarModule {
HeadsUpManagerPhone headsUpManagerPhone,
DynamicPrivacyController dynamicPrivacyController,
BypassHeadsUpNotifier bypassHeadsUpNotifier,
- Lazy<NewNotifPipeline> newNotifPipeline,
+ Lazy<NotifPipelineInitializer> notifPipelineInitializer,
FalsingManager falsingManager,
BroadcastDispatcher broadcastDispatcher,
RemoteInputQuickSettingsDisabler remoteInputQuickSettingsDisabler,
@@ -207,7 +208,8 @@ public class CarStatusBarModule {
DismissCallbackRegistry dismissCallbackRegistry,
CarServiceProvider carServiceProvider,
Lazy<PowerManagerHelper> powerManagerHelperLazy,
- Lazy<FullscreenUserSwitcher> fullscreenUserSwitcherLazy,
+ FullscreenUserSwitcher fullscreenUserSwitcher,
+ SystemUIPrimaryWindowController systemUIPrimaryWindowController,
CarNavigationBarController carNavigationBarController,
FlingAnimationUtils.Builder flingAnimationUtilsBuilder) {
return new CarStatusBar(
@@ -224,7 +226,7 @@ public class CarStatusBarModule {
headsUpManagerPhone,
dynamicPrivacyController,
bypassHeadsUpNotifier,
- newNotifPipeline,
+ notifPipelineInitializer,
falsingManager,
broadcastDispatcher,
remoteInputQuickSettingsDisabler,
@@ -292,7 +294,8 @@ public class CarStatusBarModule {
dismissCallbackRegistry,
carServiceProvider,
powerManagerHelperLazy,
- fullscreenUserSwitcherLazy,
+ fullscreenUserSwitcher,
+ systemUIPrimaryWindowController,
carNavigationBarController,
flingAnimationUtilsBuilder);
}
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 f8fc3bbefb01..3cd66c232717 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
@@ -38,6 +38,7 @@ 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.car.SystemUIPrimaryWindowController;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.statusbar.car.CarTrustAgentUnlockDialogHelper.OnHideListener;
import com.android.systemui.statusbar.car.UserGridRecyclerView.UserRecord;
@@ -56,9 +57,10 @@ public class FullscreenUserSwitcher {
private final UserManager mUserManager;
private final CarServiceProvider mCarServiceProvider;
private final CarTrustAgentUnlockDialogHelper mUnlockDialogHelper;
+ private final SystemUIPrimaryWindowController mSystemUIPrimaryWindowController;
+ private CarStatusBar mCarStatusBar;
private final int mShortAnimDuration;
- private CarStatusBar mStatusBar;
private View mParent;
private UserGridRecyclerView mUserGridView;
private CarTrustAgentEnrollmentManager mEnrollmentManager;
@@ -81,23 +83,35 @@ public class FullscreenUserSwitcher {
@Main Resources resources,
UserManager userManager,
CarServiceProvider carServiceProvider,
- CarTrustAgentUnlockDialogHelper carTrustAgentUnlockDialogHelper) {
+ CarTrustAgentUnlockDialogHelper carTrustAgentUnlockDialogHelper,
+ SystemUIPrimaryWindowController systemUIPrimaryWindowController) {
mContext = context;
mResources = resources;
mUserManager = userManager;
mCarServiceProvider = carServiceProvider;
mUnlockDialogHelper = carTrustAgentUnlockDialogHelper;
+ mSystemUIPrimaryWindowController = systemUIPrimaryWindowController;
mShortAnimDuration = mResources.getInteger(android.R.integer.config_shortAnimTime);
}
- /** Sets the status bar which controls the keyguard. */
+ /** Sets the status bar which gives an entry point to dismiss the keyguard. */
+ // TODO: Remove this in favor of a keyguard controller.
public void setStatusBar(CarStatusBar statusBar) {
- mStatusBar = statusBar;
+ mCarStatusBar = statusBar;
+ }
+
+ /** Returns {@code true} if the user switcher already has a parent view. */
+ public boolean isAttached() {
+ return mParent != null;
}
/** Sets the {@link ViewStub} to show the user switcher. */
public void setContainer(ViewStub containerStub) {
+ if (isAttached()) {
+ return;
+ }
+
mParent = containerStub.inflate();
View container = mParent.findViewById(R.id.container);
@@ -148,20 +162,31 @@ public class FullscreenUserSwitcher {
* Makes user grid visible.
*/
public void show() {
+ if (!isAttached()) {
+ return;
+ }
mParent.setVisibility(View.VISIBLE);
+ mSystemUIPrimaryWindowController.setWindowExpanded(true);
}
/**
* Hides the user grid.
*/
public void hide() {
+ if (!isAttached()) {
+ return;
+ }
mParent.setVisibility(View.INVISIBLE);
+ mSystemUIPrimaryWindowController.setWindowExpanded(false);
}
/**
* @return {@code true} if user grid is visible, {@code false} otherwise.
*/
public boolean isVisible() {
+ if (!isAttached()) {
+ return false;
+ }
return mParent.getVisibility() == View.VISIBLE;
}
@@ -196,7 +221,7 @@ public class FullscreenUserSwitcher {
}
if (mSelectedUser.mType == UserRecord.FOREGROUND_USER) {
hide();
- mStatusBar.dismissKeyguard();
+ mCarStatusBar.dismissKeyguard();
return;
}
// Switching is about to happen, since it takes time, fade out the switcher gradually.
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
index cdabeebe2819..8c756ecbaefc 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
@@ -43,6 +43,9 @@ import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.view.Window;
+import android.view.WindowInsets;
+import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.TextView;
@@ -53,7 +56,6 @@ import androidx.recyclerview.widget.RecyclerView;
import com.android.internal.util.UserIcons;
import com.android.systemui.R;
-import com.android.systemui.statusbar.phone.SystemUIDialog;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -337,7 +339,7 @@ public class UserGridRecyclerView extends RecyclerView {
.setPositiveButton(android.R.string.ok, null)
.create();
// Sets window flags for the SysUI dialog
- SystemUIDialog.applyFlags(maxUsersDialog);
+ applyCarSysUIDialogFlags(maxUsersDialog);
maxUsersDialog.show();
}
@@ -356,10 +358,19 @@ public class UserGridRecyclerView extends RecyclerView {
.setOnCancelListener(this)
.create();
// Sets window flags for the SysUI dialog
- SystemUIDialog.applyFlags(addUserDialog);
+ applyCarSysUIDialogFlags(addUserDialog);
addUserDialog.show();
}
+ private void applyCarSysUIDialogFlags(AlertDialog dialog) {
+ final Window window = dialog.getWindow();
+ window.setType(WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL);
+ window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
+ | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
+ window.setFitWindowInsetsTypes(
+ window.getFitWindowInsetsTypes() & ~WindowInsets.Type.statusBars());
+ }
+
private void notifyUserSelected(UserRecord userRecord) {
// Notify the listener which user was selected
if (mUserSelectionListener != null) {
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java
index 2697a1066ed2..cb062a63541e 100644
--- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java
@@ -30,8 +30,6 @@ import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
-import com.android.internal.telephony.PhoneConstants;
-
/**
* This util class provides common logic for carrier actions
*/
@@ -103,7 +101,7 @@ public class CarrierActionUtils {
}
private static void onDisableAllMeteredApns(Intent intent, Context context) {
- int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
+ int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX,
SubscriptionManager.getDefaultVoiceSubscriptionId());
logd("onDisableAllMeteredApns subId: " + subId);
final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class);
@@ -111,7 +109,7 @@ public class CarrierActionUtils {
}
private static void onEnableAllMeteredApns(Intent intent, Context context) {
- int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
+ int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX,
SubscriptionManager.getDefaultVoiceSubscriptionId());
logd("onEnableAllMeteredApns subId: " + subId);
final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class);
@@ -135,7 +133,7 @@ public class CarrierActionUtils {
}
private static void onRegisterDefaultNetworkAvail(Intent intent, Context context) {
- int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
+ int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX,
SubscriptionManager.getDefaultVoiceSubscriptionId());
logd("onRegisterDefaultNetworkAvail subId: " + subId);
final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class);
@@ -143,7 +141,7 @@ public class CarrierActionUtils {
}
private static void onDeregisterDefaultNetworkAvail(Intent intent, Context context) {
- int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
+ int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX,
SubscriptionManager.getDefaultVoiceSubscriptionId());
logd("onDeregisterDefaultNetworkAvail subId: " + subId);
final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class);
@@ -151,7 +149,7 @@ public class CarrierActionUtils {
}
private static void onDisableRadio(Intent intent, Context context) {
- int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
+ int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX,
SubscriptionManager.getDefaultVoiceSubscriptionId());
logd("onDisableRadio subId: " + subId);
final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class);
@@ -159,7 +157,7 @@ public class CarrierActionUtils {
}
private static void onEnableRadio(Intent intent, Context context) {
- int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
+ int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX,
SubscriptionManager.getDefaultVoiceSubscriptionId());
logd("onEnableRadio subId: " + subId);
final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class);
@@ -202,7 +200,7 @@ public class CarrierActionUtils {
}
private static void onResetAllCarrierActions(Intent intent, Context context) {
- int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
+ int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX,
SubscriptionManager.getDefaultVoiceSubscriptionId());
logd("onResetAllCarrierActions subId: " + subId);
final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class);
diff --git a/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/CarrierDefaultReceiverTest.java b/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/CarrierDefaultReceiverTest.java
index 086a287fd243..6229434d1d86 100644
--- a/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/CarrierDefaultReceiverTest.java
+++ b/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/CarrierDefaultReceiverTest.java
@@ -15,6 +15,7 @@
*/
package com.android.carrierdefaultapp;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.times;
@@ -26,11 +27,10 @@ import android.app.PendingIntent;
import android.content.Intent;
import android.os.PersistableBundle;
import android.telephony.CarrierConfigManager;
+import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.test.InstrumentationTestCase;
-import com.android.internal.telephony.PhoneConstants;
-
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -69,6 +69,7 @@ public class CarrierDefaultReceiverTest extends InstrumentationTestCase {
mContext.injectSystemService(NotificationManager.class, mNotificationMgr);
mContext.injectSystemService(TelephonyManager.class, mTelephonyMgr);
mContext.injectSystemService(CarrierConfigManager.class, mCarrierConfigMgr);
+ doReturn(mTelephonyMgr).when(mTelephonyMgr).createForSubscriptionId(anyInt());
mReceiver = new CarrierDefaultBroadcastReceiver();
}
@@ -88,7 +89,7 @@ public class CarrierDefaultReceiverTest extends InstrumentationTestCase {
doReturn(b).when(mCarrierConfigMgr).getConfig();
Intent intent = new Intent(TelephonyManager.ACTION_CARRIER_SIGNAL_REDIRECTED);
- intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
+ intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId);
mReceiver.onReceive(mContext, intent);
mContext.waitForMs(100);
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index 81739e069e28..9d4c24e8faa4 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -211,13 +211,6 @@ public class AccessPoint implements Comparable<AccessPoint> {
private static final int EAP_WPA = 1; // WPA-EAP
private static final int EAP_WPA2_WPA3 = 2; // RSN-EAP
- /**
- * The number of distinct wifi levels.
- *
- * <p>Must keep in sync with {@link R.array.wifi_signal} and {@link WifiManager#RSSI_LEVELS}.
- */
- public static final int SIGNAL_LEVELS = 5;
-
public static final int UNREACHABLE_RSSI = Integer.MIN_VALUE;
public static final String KEY_PREFIX_AP = "AP:";
@@ -453,9 +446,10 @@ public class AccessPoint implements Comparable<AccessPoint> {
return other.getSpeed() - getSpeed();
}
+ WifiManager wifiManager = getWifiManager();
// Sort by signal strength, bucketed by level
- int difference = WifiManager.calculateSignalLevel(other.mRssi, SIGNAL_LEVELS)
- - WifiManager.calculateSignalLevel(mRssi, SIGNAL_LEVELS);
+ int difference = wifiManager.calculateSignalLevel(other.mRssi)
+ - wifiManager.calculateSignalLevel(mRssi);
if (difference != 0) {
return difference;
}
@@ -869,13 +863,14 @@ public class AccessPoint implements Comparable<AccessPoint> {
}
/**
- * Returns the number of levels to show for a Wifi icon, from 0 to {@link #SIGNAL_LEVELS}-1.
+ * Returns the number of levels to show for a Wifi icon, from 0 to
+ * {@link WifiManager#getMaxSignalLevel()}.
*
- * <p>Use {@#isReachable()} to determine if an AccessPoint is in range, as this method will
+ * <p>Use {@link #isReachable()} to determine if an AccessPoint is in range, as this method will
* always return at least 0.
*/
public int getLevel() {
- return WifiManager.calculateSignalLevel(mRssi, SIGNAL_LEVELS);
+ return getWifiManager().calculateSignalLevel(mRssi);
}
public int getRssi() {
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/TestAccessPointBuilder.java b/packages/SettingsLib/src/com/android/settingslib/wifi/TestAccessPointBuilder.java
index 4a4f0e66cfe8..f21e466dd8ab 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/TestAccessPointBuilder.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/TestAccessPointBuilder.java
@@ -22,6 +22,7 @@ import android.net.NetworkInfo;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.Parcelable;
@@ -126,13 +127,15 @@ public class TestAccessPointBuilder {
@Keep
public TestAccessPointBuilder setLevel(int level) {
// Reversal of WifiManager.calculateSignalLevels
+ WifiManager wifiManager = mContext.getSystemService(WifiManager.class);
+ int maxSignalLevel = wifiManager.getMaxSignalLevel();
if (level == 0) {
mRssi = MIN_RSSI;
- } else if (level >= AccessPoint.SIGNAL_LEVELS) {
+ } else if (level > maxSignalLevel) {
mRssi = MAX_RSSI;
} else {
float inputRange = MAX_RSSI - MIN_RSSI;
- float outputRange = AccessPoint.SIGNAL_LEVELS - 1;
+ float outputRange = maxSignalLevel;
mRssi = (int) (level * inputRange / outputRange + MIN_RSSI);
}
return this;
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
index 8591116fce0f..3f55ceaad29a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
@@ -89,7 +89,7 @@ public class WifiStatusTracker extends ConnectivityManager.NetworkCallback {
public void setListening(boolean listening) {
if (listening) {
mNetworkScoreManager.registerNetworkScoreCache(NetworkKey.TYPE_WIFI,
- mWifiNetworkScoreCache, NetworkScoreManager.CACHE_FILTER_CURRENT_NETWORK);
+ mWifiNetworkScoreCache, NetworkScoreManager.SCORE_FILTER_CURRENT_NETWORK);
mWifiNetworkScoreCache.registerListener(mCacheListener);
mConnectivityManager.registerNetworkCallback(
mNetworkRequest, mNetworkCallback, mHandler);
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index ba6a8ea31987..ed4ff085aeac 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -361,7 +361,7 @@ public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestro
mNetworkScoreManager.registerNetworkScoreCache(
NetworkKey.TYPE_WIFI,
mScoreCache,
- NetworkScoreManager.CACHE_FILTER_SCAN_RESULTS);
+ NetworkScoreManager.SCORE_FILTER_SCAN_RESULTS);
}
private void requestScoresForNetworkKeys(Collection<NetworkKey> keys) {
diff --git a/packages/SettingsLib/tests/integ/Android.bp b/packages/SettingsLib/tests/integ/Android.bp
index 4600793729a2..2ccff1ecaf6c 100644
--- a/packages/SettingsLib/tests/integ/Android.bp
+++ b/packages/SettingsLib/tests/integ/Android.bp
@@ -14,7 +14,10 @@
android_test {
name: "SettingsLibTests",
- defaults: ["SettingsLibDefaults"],
+ defaults: [
+ "SettingsLibDefaults",
+ "framework-wifi-test-defaults"
+ ],
certificate: "platform",
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
index 61cbbd3eb0a4..03201ae6d5ba 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
@@ -83,7 +83,6 @@ import java.util.concurrent.CountDownLatch;
@SmallTest
@RunWith(AndroidJUnit4.class)
public class AccessPointTest {
-
private static final String TEST_SSID = "\"test_ssid\"";
private static final String ROAMING_SSID = "\"roaming_ssid\"";
private static final String OSU_FRIENDLY_NAME = "osu_friendly_name";
@@ -98,6 +97,7 @@ public class AccessPointTest {
20 * DateUtils.MINUTE_IN_MILLIS;
private Context mContext;
+ private int mMaxSignalLevel;
private WifiInfo mWifiInfo;
@Mock private Context mMockContext;
@Mock private WifiManager mMockWifiManager;
@@ -128,6 +128,7 @@ public class AccessPointTest {
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = InstrumentationRegistry.getTargetContext();
+ mMaxSignalLevel = mContext.getSystemService(WifiManager.class).getMaxSignalLevel();
mWifiInfo = new WifiInfo();
mWifiInfo.setSSID(WifiSsid.createFromAsciiEncoded(TEST_SSID));
mWifiInfo.setBSSID(TEST_BSSID);
@@ -180,7 +181,7 @@ public class AccessPointTest {
@Test
public void testCompareTo_GivesHighLevelBeforeLowLevel() {
- final int highLevel = AccessPoint.SIGNAL_LEVELS - 1;
+ final int highLevel = mMaxSignalLevel;
final int lowLevel = 1;
assertThat(highLevel).isGreaterThan(lowLevel);
@@ -226,7 +227,7 @@ public class AccessPointTest {
.setReachable(true).build();
AccessPoint saved = new TestAccessPointBuilder(mContext).setSaved(true).build();
AccessPoint highLevelAndReachable = new TestAccessPointBuilder(mContext)
- .setLevel(AccessPoint.SIGNAL_LEVELS - 1).build();
+ .setLevel(mMaxSignalLevel).build();
AccessPoint firstName = new TestAccessPointBuilder(mContext).setSsid("a").build();
AccessPoint lastname = new TestAccessPointBuilder(mContext).setSsid("z").build();
@@ -520,6 +521,8 @@ public class AccessPointTest {
when(packageManager.getApplicationInfoAsUser(eq(appPackageName), anyInt(), anyInt()))
.thenReturn(applicationInfo);
when(applicationInfo.loadLabel(packageManager)).thenReturn(appLabel);
+ when(context.getSystemService(Context.WIFI_SERVICE)).thenReturn(mMockWifiManager);
+ when(mMockWifiManager.calculateSignalLevel(rssi)).thenReturn(4);
NetworkInfo networkInfo =
new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0 /* subtype */, "WIFI", "");
@@ -636,14 +639,14 @@ public class AccessPointTest {
public void testBuilder_setLevel() {
AccessPoint testAp;
- for (int i = 0; i < AccessPoint.SIGNAL_LEVELS; i++) {
+ for (int i = 0; i <= mMaxSignalLevel; i++) {
testAp = new TestAccessPointBuilder(mContext).setLevel(i).build();
assertThat(testAp.getLevel()).isEqualTo(i);
}
// numbers larger than the max level should be set to max
- testAp = new TestAccessPointBuilder(mContext).setLevel(AccessPoint.SIGNAL_LEVELS).build();
- assertThat(testAp.getLevel()).isEqualTo(AccessPoint.SIGNAL_LEVELS - 1);
+ testAp = new TestAccessPointBuilder(mContext).setLevel(mMaxSignalLevel + 1).build();
+ assertThat(testAp.getLevel()).isEqualTo(mMaxSignalLevel);
// numbers less than 0 should give level 0
testAp = new TestAccessPointBuilder(mContext).setLevel(-100).build();
@@ -653,7 +656,7 @@ public class AccessPointTest {
@Test
public void testBuilder_settingReachableAfterLevelDoesNotAffectLevel() {
int level = 1;
- assertThat(level).isLessThan(AccessPoint.SIGNAL_LEVELS - 1);
+ assertThat(level).isLessThan(mMaxSignalLevel);
AccessPoint testAp =
new TestAccessPointBuilder(mContext).setLevel(level).setReachable(true).build();
diff --git a/packages/SystemUI/res/layout/global_actions_grid_item_v2.xml b/packages/SystemUI/res/layout/global_actions_grid_item_v2.xml
new file mode 100644
index 000000000000..50aa212c94a6
--- /dev/null
+++ b/packages/SystemUI/res/layout/global_actions_grid_item_v2.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<!-- RelativeLayouts have an issue enforcing minimum heights, so just
+ work around this for now with LinearLayouts. -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:paddingTop="@dimen/global_actions_grid_item_vertical_margin"
+ android:paddingBottom="@dimen/global_actions_grid_item_vertical_margin"
+ android:paddingLeft="@dimen/global_actions_grid_item_side_margin"
+ android:paddingRight="@dimen/global_actions_grid_item_side_margin"
+ android:layout_marginRight="3dp"
+ android:layout_marginLeft="3dp"
+ android:background="@drawable/rounded_bg_full">
+ <LinearLayout
+ android:layout_width="@dimen/global_actions_grid_item_width"
+ android:layout_height="@dimen/global_actions_grid_item_height"
+ android:gravity="top|center_horizontal"
+ android:orientation="vertical">
+ <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" />
+
+ <TextView
+ android:id="@*android:id/message"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:ellipsize="marquee"
+ android:marqueeRepeatLimit="marquee_forever"
+ android:singleLine="true"
+ android:gravity="center"
+ android:textSize="12dp"
+ android:textColor="@color/global_actions_text"
+ android:textAppearance="?android:attr/textAppearanceSmall" />
+
+ <TextView
+ android:visibility="gone"
+ android:id="@*android:id/status"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:textColor="@color/global_actions_text"
+ android:textAppearance="?android:attr/textAppearanceSmall" />
+ </LinearLayout>
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/global_actions_grid_v2.xml b/packages/SystemUI/res/layout/global_actions_grid_v2.xml
new file mode 100644
index 000000000000..4cfb47e3c642
--- /dev/null
+++ b/packages/SystemUI/res/layout/global_actions_grid_v2.xml
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ScrollView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <androidx.constraintlayout.widget.ConstraintLayout
+ android:id="@+id/global_actions_grid_root"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:layout_marginBottom="@dimen/global_actions_grid_container_negative_shadow_offset">
+
+ <com.android.systemui.globalactions.GlobalActionsFlatLayout
+ android:id="@id/global_actions_view"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:theme="@style/qs_theme"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintLeft_toLeftOf="parent"
+ app:layout_constraintRight_toRightOf="parent"
+ android:gravity="top | center_horizontal"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:paddingBottom="@dimen/global_actions_grid_container_shadow_offset"
+ android:layout_marginTop="@dimen/global_actions_top_margin"
+ android:layout_marginBottom="@dimen/global_actions_grid_container_negative_shadow_offset">
+ <LinearLayout
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layoutDirection="ltr"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:layout_marginBottom="@dimen/global_actions_grid_container_bottom_margin">
+ <!-- For separated items-->
+ <LinearLayout
+ android:id="@+id/separated_button"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_marginLeft="@dimen/global_actions_grid_side_margin"
+ android:layout_marginRight="@dimen/global_actions_grid_side_margin"
+ android:paddingLeft="@dimen/global_actions_grid_horizontal_padding"
+ android:paddingRight="@dimen/global_actions_grid_horizontal_padding"
+ android:paddingTop="@dimen/global_actions_grid_vertical_padding"
+ android:paddingBottom="@dimen/global_actions_grid_vertical_padding"
+ android:orientation="vertical"
+ android:gravity="center"
+ android:translationZ="@dimen/global_actions_translate"
+ />
+ <!-- Grid of action items -->
+ <com.android.systemui.globalactions.ListGridLayout
+ android:id="@android:id/list"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:gravity="right"
+ android:layout_marginRight="@dimen/global_actions_grid_side_margin"
+ android:translationZ="@dimen/global_actions_translate"
+ android:paddingLeft="@dimen/global_actions_grid_horizontal_padding"
+ android:paddingRight="@dimen/global_actions_grid_horizontal_padding"
+ android:paddingTop="@dimen/global_actions_grid_vertical_padding"
+ android:paddingBottom="@dimen/global_actions_grid_vertical_padding"
+ >
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:visibility="gone"
+ android:layoutDirection="locale"
+ />
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:visibility="gone"
+ android:layoutDirection="locale"
+ />
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:visibility="gone"
+ android:layoutDirection="locale"
+ />
+ </com.android.systemui.globalactions.ListGridLayout>
+ </LinearLayout>
+ </com.android.systemui.globalactions.GlobalActionsFlatLayout>
+
+ <LinearLayout
+ android:id="@+id/global_actions_panel"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ app:layout_constraintLeft_toLeftOf="parent"
+ app:layout_constraintRight_toRightOf="parent"
+ app:layout_constraintTop_toBottomOf="@id/global_actions_view">
+
+ <FrameLayout
+ android:translationY="@dimen/global_actions_plugin_offset"
+ android:id="@+id/global_actions_panel_container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+ </LinearLayout>
+
+ <LinearLayout
+ android:translationY="@dimen/global_actions_plugin_offset"
+ android:id="@+id/global_actions_controls"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ app:layout_constraintLeft_toLeftOf="parent"
+ app:layout_constraintRight_toRightOf="parent"
+ app:layout_constraintTop_toBottomOf="@id/global_actions_panel">
+ <TextView
+ android:text="Home"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:gravity="center"
+ android:textSize="25dp"
+ android:textColor="?android:attr/textColorPrimary"
+ android:fontFamily="@*android:string/config_headlineFontFamily" />
+ <LinearLayout
+ android:id="@+id/global_actions_controls_list"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical" />
+ </LinearLayout>
+ </androidx.constraintlayout.widget.ConstraintLayout>
+</ScrollView>
diff --git a/packages/SystemUI/res/layout/global_screenshot_action_chip.xml b/packages/SystemUI/res/layout/global_screenshot_action_chip.xml
index 6b424002d7ff..366abaa1366d 100644
--- a/packages/SystemUI/res/layout/global_screenshot_action_chip.xml
+++ b/packages/SystemUI/res/layout/global_screenshot_action_chip.xml
@@ -14,12 +14,27 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<TextView xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/global_screenshot_action_chip"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginHorizontal="@dimen/screenshot_action_chip_margin_horizontal"
- android:paddingVertical="@dimen/screenshot_action_chip_padding_vertical"
- android:paddingHorizontal="@dimen/screenshot_action_chip_padding_horizontal"
- android:background="@drawable/action_chip_background"
- android:textColor="@color/global_screenshot_button_text"/>
+<com.android.systemui.screenshot.ScreenshotActionChip
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/global_screenshot_action_chip"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginHorizontal="@dimen/screenshot_action_chip_margin_horizontal"
+ android:layout_gravity="center"
+ android:paddingVertical="@dimen/screenshot_action_chip_padding_vertical"
+ android:background="@drawable/action_chip_background"
+ android:gravity="center">
+ <ImageView
+ android:id="@+id/screenshot_action_chip_icon"
+ android:layout_width="@dimen/screenshot_action_chip_icon_size"
+ android:layout_height="@dimen/screenshot_action_chip_icon_size"
+ android:layout_marginStart="@dimen/screenshot_action_chip_padding_start"
+ android:layout_marginEnd="@dimen/screenshot_action_chip_padding_middle"/>
+ <TextView
+ android:id="@+id/screenshot_action_chip_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="@dimen/screenshot_action_chip_padding_end"
+ android:textSize="@dimen/screenshot_action_chip_text_size"
+ android:textColor="@color/global_screenshot_button_text"/>
+</com.android.systemui.screenshot.ScreenshotActionChip>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 5a1151eb9f6e..c26cb9a18dd4 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -291,12 +291,17 @@
<dimen name="global_screenshot_legacy_bg_padding">20dp</dimen>
<dimen name="global_screenshot_bg_padding">20dp</dimen>
<dimen name="screenshot_action_container_corner_radius">10dp</dimen>
- <dimen name="screenshot_action_container_padding">20dp</dimen>
+ <dimen name="screenshot_action_container_padding">10dp</dimen>
<!-- Radius of the chip background on global screenshot actions -->
<dimen name="screenshot_button_corner_radius">20dp</dimen>
- <dimen name="screenshot_action_chip_margin_horizontal">10dp</dimen>
+ <dimen name="screenshot_action_chip_margin_horizontal">4dp</dimen>
<dimen name="screenshot_action_chip_padding_vertical">10dp</dimen>
- <dimen name="screenshot_action_chip_padding_horizontal">15dp</dimen>
+ <dimen name="screenshot_action_chip_icon_size">20dp</dimen>
+ <dimen name="screenshot_action_chip_padding_start">4dp</dimen>
+ <!-- Padding between icon and text -->
+ <dimen name="screenshot_action_chip_padding_middle">8dp</dimen>
+ <dimen name="screenshot_action_chip_padding_end">12dp</dimen>
+ <dimen name="screenshot_action_chip_text_size">14sp</dimen>
<!-- The width of the view containing navigation buttons -->
@@ -951,6 +956,9 @@
<dimen name="cell_overlay_padding">18dp</dimen>
<!-- Global actions power menu -->
+ <dimen name="global_actions_top_margin">12dp</dimen>
+ <dimen name="global_actions_plugin_offset">-145dp</dimen>
+
<dimen name="global_actions_panel_width">120dp</dimen>
<dimen name="global_actions_padding">12dp</dimen>
<dimen name="global_actions_translate">9dp</dimen>
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java
index 8105faa23e89..eab970626bf1 100644
--- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java
@@ -27,9 +27,9 @@ import android.util.Log;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.collection.NotifCollection;
-import com.android.systemui.statusbar.notification.collection.NotifCollectionListener;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -49,7 +49,7 @@ public class ForegroundServiceNotificationListener {
public ForegroundServiceNotificationListener(Context context,
ForegroundServiceController foregroundServiceController,
NotificationEntryManager notificationEntryManager,
- NotifCollection notifCollection) {
+ NotifPipeline notifPipeline) {
mContext = context;
mForegroundServiceController = foregroundServiceController;
@@ -77,7 +77,7 @@ public class ForegroundServiceNotificationListener {
});
mEntryManager.addNotificationLifetimeExtender(new ForegroundServiceLifetimeExtender());
- notifCollection.addCollectionListener(new NotifCollectionListener() {
+ notifPipeline.addCollectionListener(new NotifCollectionListener() {
@Override
public void onEntryAdded(NotificationEntry entry) {
addNotification(entry, entry.getImportance());
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayout.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayout.java
index 563a0a7e43e1..31656a00c3ed 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayout.java
@@ -961,6 +961,13 @@ public class PhysicsAnimationLayout extends FrameLayout {
if (view != null) {
final SpringAnimation animation =
(SpringAnimation) view.getTag(getTagIdForProperty(property));
+
+ // If the animation is null, the view was probably removed from the layout before
+ // the animation started.
+ if (animation == null) {
+ return;
+ }
+
if (afterCallbacks != null) {
animation.addEndListener(new OneTimeEndListener() {
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index b19523866814..a6fa4146300d 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -30,10 +30,8 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.recents.Recents;
import com.android.systemui.stackdivider.Divider;
import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.notification.collection.NotifListBuilderImpl;
-import com.android.systemui.statusbar.notification.collection.NotificationRowBinder;
-import com.android.systemui.statusbar.notification.collection.NotificationRowBinderImpl;
-import com.android.systemui.statusbar.notification.collection.listbuilder.NotifListBuilder;
+import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder;
+import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
import com.android.systemui.statusbar.notification.people.PeopleHubModule;
import com.android.systemui.statusbar.phone.KeyguardLiftController;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -113,9 +111,4 @@ public abstract class SystemUIModule {
@Singleton
@Binds
abstract SystemClock bindSystemClock(SystemClockImpl systemClock);
-
- @Singleton
- @Binds
- abstract NotifListBuilder bindNotifListBuilder(NotifListBuilderImpl impl);
-
}
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 91bb80c60e3f..c138462d06c4 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -59,7 +59,6 @@ import android.telecom.TelecomManager;
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
-import android.text.TextUtils;
import android.util.ArraySet;
import android.util.FeatureFlagUtils;
import android.util.Log;
@@ -444,7 +443,8 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
mKeyguardManager.isDeviceLocked())
: null;
- ActionsDialog dialog = new ActionsDialog(mContext, mAdapter, panelViewController);
+ ActionsDialog dialog = new ActionsDialog(
+ mContext, mAdapter, panelViewController, isControlsEnabled(mContext));
dialog.setCanceledOnTouchOutside(false); // Handled by the custom class.
dialog.setKeyguardShowing(mKeyguardShowing);
@@ -518,7 +518,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
@Override
public boolean shouldBeSeparated() {
- return shouldUseSeparatedView();
+ return !isControlsEnabled(mContext);
}
@Override
@@ -1154,6 +1154,9 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
}
protected int getActionLayoutId(Context context) {
+ if (isControlsEnabled(context)) {
+ return com.android.systemui.R.layout.global_actions_grid_item_v2;
+ }
return com.android.systemui.R.layout.global_actions_grid_item;
}
@@ -1415,8 +1418,8 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
} else if (TelephonyManager.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED.equals(action)) {
// Airplane mode can be changed after ECM exits if airplane toggle button
// is pressed during ECM mode
- if (!(intent.getBooleanExtra("PHONE_IN_ECM_STATE", false)) &&
- mIsWaitingForEcmExit) {
+ if (!(intent.getBooleanExtra(TelephonyManager.EXTRA_PHONE_IN_ECM_STATE, false))
+ && mIsWaitingForEcmExit) {
mIsWaitingForEcmExit = false;
changeAirplaneModeSystemSetting(true);
}
@@ -1526,15 +1529,18 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
private ResetOrientationData mResetOrientationData;
private boolean mHadTopUi;
private final StatusBarWindowController mStatusBarWindowController;
+ private boolean mControlsEnabled;
ActionsDialog(Context context, MyAdapter adapter,
- GlobalActionsPanelPlugin.PanelViewController plugin) {
+ GlobalActionsPanelPlugin.PanelViewController plugin,
+ boolean controlsEnabled) {
super(context, com.android.systemui.R.style.Theme_SystemUI_Dialog_GlobalActions);
mContext = context;
mAdapter = adapter;
mColorExtractor = Dependency.get(SysuiColorExtractor.class);
mStatusBarService = Dependency.get(IStatusBarService.class);
mStatusBarWindowController = Dependency.get(StatusBarWindowController.class);
+ mControlsEnabled = controlsEnabled;
// Window initialization
Window window = getWindow();
@@ -1651,6 +1657,10 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
}
private int getGlobalActionsLayoutId(Context context) {
+ if (mControlsEnabled) {
+ return com.android.systemui.R.layout.global_actions_grid_v2;
+ }
+
int rotation = RotationUtils.getRotation(context);
boolean useGridLayout = isForceGridEnabled(context)
|| (shouldUsePanel() && rotation == RotationUtils.ROTATION_NONE);
@@ -1854,4 +1864,9 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
private static boolean shouldUseSeparatedView() {
return true;
}
+
+ private static boolean isControlsEnabled(Context context) {
+ return Settings.Secure.getInt(
+ context.getContentResolver(), "systemui.controls_available", 0) == 1;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsFlatLayout.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsFlatLayout.java
new file mode 100644
index 000000000000..6749f1d663eb
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsFlatLayout.java
@@ -0,0 +1,186 @@
+/*
+ * 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.globalactions;
+
+import static com.android.systemui.util.leak.RotationUtils.ROTATION_LANDSCAPE;
+import static com.android.systemui.util.leak.RotationUtils.ROTATION_NONE;
+import static com.android.systemui.util.leak.RotationUtils.ROTATION_SEASCAPE;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * Single row implementation of the button layout created by the global actions dialog.
+ */
+public class GlobalActionsFlatLayout extends GlobalActionsLayout {
+ public GlobalActionsFlatLayout(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ mBackgroundsSet = true;
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+ // backgrounds set only once, the first time onMeasure is called after inflation
+ // if (getListView() != null && !mBackgroundsSet) {
+ // setBackgrounds();
+ // mBackgroundsSet = true;
+ // }
+ }
+
+ @VisibleForTesting
+ protected void setupListView() {
+ ListGridLayout listView = getListView();
+ listView.setExpectedCount(Math.min(2, mAdapter.countListItems()));
+ listView.setReverseSublists(shouldReverseSublists());
+ listView.setReverseItems(shouldReverseListItems());
+ listView.setSwapRowsAndColumns(shouldSwapRowsAndColumns());
+ }
+
+ @Override
+ public void onUpdateList() {
+ setupListView();
+ super.onUpdateList();
+ updateSeparatedItemSize();
+ }
+
+ /**
+ * If the separated view contains only one item, expand the bounds of that item to take up the
+ * entire view, so that the whole thing is touch-able.
+ */
+ @VisibleForTesting
+ protected void updateSeparatedItemSize() {
+ ViewGroup separated = getSeparatedView();
+ if (separated.getChildCount() == 0) {
+ return;
+ }
+ View firstChild = separated.getChildAt(0);
+ ViewGroup.LayoutParams childParams = firstChild.getLayoutParams();
+
+ if (separated.getChildCount() == 1) {
+ childParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
+ childParams.height = ViewGroup.LayoutParams.MATCH_PARENT;
+ } else {
+ childParams.width = ViewGroup.LayoutParams.WRAP_CONTENT;
+ childParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
+ }
+ }
+
+ @Override
+ protected ListGridLayout getListView() {
+ return (ListGridLayout) super.getListView();
+ }
+
+ @Override
+ protected void removeAllListViews() {
+ ListGridLayout list = getListView();
+ if (list != null) {
+ list.removeAllItems();
+ }
+ }
+
+ @Override
+ protected void addToListView(View v, boolean reverse) {
+ ListGridLayout list = getListView();
+ if (list != null) {
+ list.addItem(v);
+ }
+ }
+
+ @Override
+ public void removeAllItems() {
+ ViewGroup separatedList = getSeparatedView();
+ ListGridLayout list = getListView();
+ if (separatedList != null) {
+ separatedList.removeAllViews();
+ }
+ if (list != null) {
+ list.removeAllItems();
+ }
+ }
+
+ /**
+ * Determines whether the ListGridLayout should fill sublists in the reverse order.
+ * Used to account for sublist ordering changing between landscape and seascape views.
+ */
+ @VisibleForTesting
+ protected boolean shouldReverseSublists() {
+ if (getCurrentRotation() == ROTATION_SEASCAPE) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Determines whether the ListGridLayout should fill rows first instead of columns.
+ * Used to account for vertical/horizontal changes due to landscape or seascape rotations.
+ */
+ @VisibleForTesting
+ protected boolean shouldSwapRowsAndColumns() {
+ if (getCurrentRotation() == ROTATION_NONE) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ protected boolean shouldReverseListItems() {
+ int rotation = getCurrentRotation();
+ boolean reverse = false; // should we add items to parents in the reverse order?
+ if (rotation == ROTATION_NONE
+ || rotation == ROTATION_SEASCAPE) {
+ reverse = !reverse; // if we're in portrait or seascape, reverse items
+ }
+ if (getCurrentLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
+ reverse = !reverse; // if we're in an RTL language, reverse items (again)
+ }
+ return reverse;
+ }
+
+ @VisibleForTesting
+ protected float getAnimationDistance() {
+ int rows = getListView().getRowCount();
+ float gridItemSize = getContext().getResources().getDimension(
+ com.android.systemui.R.dimen.global_actions_grid_item_height);
+ return rows * gridItemSize / 2;
+ }
+
+ @Override
+ public float getAnimationOffsetX() {
+ switch (getCurrentRotation()) {
+ case ROTATION_LANDSCAPE:
+ return getAnimationDistance();
+ case ROTATION_SEASCAPE:
+ return -getAnimationDistance();
+ default: // Portrait
+ return 0;
+ }
+ }
+
+ @Override
+ public float getAnimationOffsetY() {
+ if (getCurrentRotation() == ROTATION_NONE) {
+ return getAnimationDistance();
+ }
+ return 0;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 9f2bbc680897..27c95552c1d1 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -64,7 +64,6 @@ import android.view.WindowManager;
import android.view.animation.Interpolator;
import android.widget.ImageView;
import android.widget.LinearLayout;
-import android.widget.TextView;
import android.widget.Toast;
import com.android.systemui.R;
@@ -529,9 +528,10 @@ public class GlobalScreenshot {
mActionsView.removeAllViews();
for (Notification.Action action : actions) {
- TextView actionChip = (TextView) inflater.inflate(
+ ScreenshotActionChip actionChip = (ScreenshotActionChip) inflater.inflate(
R.layout.global_screenshot_action_chip, mActionsView, false);
actionChip.setText(action.title);
+ actionChip.setIcon(action.getIcon(), true);
actionChip.setOnClickListener(v -> {
try {
action.actionIntent.send();
@@ -545,11 +545,11 @@ public class GlobalScreenshot {
}
if (DeviceConfig.getBoolean(NAMESPACE_SYSTEMUI, SCREENSHOT_SCROLLING_ENABLED, false)) {
- TextView scrollChip = (TextView) inflater.inflate(
+ ScreenshotActionChip scrollChip = (ScreenshotActionChip) inflater.inflate(
R.layout.global_screenshot_action_chip, mActionsView, false);
Toast scrollNotImplemented = Toast.makeText(
mContext, "Not implemented", Toast.LENGTH_SHORT);
- scrollChip.setText("Scroll"); // TODO (mkephart): add resource and translate
+ scrollChip.setText("Extend"); // TODO (mkephart): add resource and translate
scrollChip.setOnClickListener(v -> scrollNotImplemented.show());
mActionsView.addView(scrollChip);
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionChip.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionChip.java
new file mode 100644
index 000000000000..6edacd12a9d1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionChip.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2020 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.screenshot;
+
+import android.annotation.ColorInt;
+import android.content.Context;
+import android.graphics.drawable.Icon;
+import android.util.AttributeSet;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.systemui.R;
+
+/**
+ * View for a chip with an icon and text.
+ */
+public class ScreenshotActionChip extends LinearLayout {
+
+ private ImageView mIcon;
+ private TextView mText;
+ private @ColorInt int mIconColor;
+
+ public ScreenshotActionChip(Context context) {
+ this(context, null);
+ }
+
+ public ScreenshotActionChip(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public ScreenshotActionChip(Context context, AttributeSet attrs, int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public ScreenshotActionChip(Context context, AttributeSet attrs, int defStyleAttr,
+ int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+
+ mIconColor = context.getColor(R.color.global_screenshot_button_text);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ mIcon = findViewById(R.id.screenshot_action_chip_icon);
+ mText = findViewById(R.id.screenshot_action_chip_text);
+ }
+
+ void setIcon(Icon icon, boolean tint) {
+ if (tint) {
+ icon.setTint(mIconColor);
+ }
+ mIcon.setImageIcon(icon);
+ }
+
+ void setText(CharSequence text) {
+ mText.setText(text);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
index 36dcaac15a5f..4a2283171694 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
@@ -43,7 +43,7 @@ import com.android.systemui.statusbar.NotificationRemoveInterceptor;
import com.android.systemui.statusbar.NotificationUiAdjustment;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationRankingManager;
-import com.android.systemui.statusbar.notification.collection.NotificationRowBinder;
+import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder;
import com.android.systemui.statusbar.notification.logging.NotifEvent;
import com.android.systemui.statusbar.notification.logging.NotifLog;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java
index e1268f6d60ef..73bfe2536830 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java
@@ -16,13 +16,11 @@
package com.android.systemui.statusbar.notification.collection;
-import com.android.systemui.statusbar.notification.collection.listbuilder.NotifListBuilder;
-
import java.util.List;
/**
- * Utility class for dumping the results of a {@link NotifListBuilder} to a debug string.
+ * Utility class for dumping the results of a {@link ShadeListBuilder} to a debug string.
*/
public class ListDumper {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
index 856b75b7e36c..4b15b7fbce5d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
@@ -47,9 +47,13 @@ import android.util.ArrayMap;
import android.util.Log;
import com.android.internal.statusbar.IStatusBarService;
-import com.android.systemui.statusbar.notification.collection.notifcollection.CoalescedEvent;
-import com.android.systemui.statusbar.notification.collection.notifcollection.GroupCoalescer;
-import com.android.systemui.statusbar.notification.collection.notifcollection.GroupCoalescer.BatchableNotificationHandler;
+import com.android.systemui.statusbar.notification.collection.coalescer.CoalescedEvent;
+import com.android.systemui.statusbar.notification.collection.coalescer.GroupCoalescer;
+import com.android.systemui.statusbar.notification.collection.coalescer.GroupCoalescer.BatchableNotificationHandler;
+import com.android.systemui.statusbar.notification.collection.notifcollection.CollectionReadyForBuildListener;
+import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats;
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender;
import com.android.systemui.util.Assert;
import java.lang.annotation.Retention;
@@ -123,36 +127,25 @@ public class NotifCollection {
* Sets the class responsible for converting the collection into the list of currently-visible
* notifications.
*/
- public void setBuildListener(CollectionReadyForBuildListener buildListener) {
+ void setBuildListener(CollectionReadyForBuildListener buildListener) {
Assert.isMainThread();
mBuildListener = buildListener;
}
- /**
- * Returns the list of "active" notifications, i.e. the notifications that are currently posted
- * to the phone. In general, this tracks closely to the list maintained by NotificationManager,
- * but it can diverge slightly due to lifetime extenders.
- *
- * The returned list is read-only, unsorted, unfiltered, and ungrouped.
- */
- public Collection<NotificationEntry> getNotifs() {
+ /** @see NotifPipeline#getActiveNotifs() */
+ Collection<NotificationEntry> getActiveNotifs() {
Assert.isMainThread();
return mReadOnlyNotificationSet;
}
- /**
- * Registers a listener to be informed when notifications are added, removed or updated.
- */
- public void addCollectionListener(NotifCollectionListener listener) {
+ /** @see NotifPipeline#addCollectionListener(NotifCollectionListener) */
+ void addCollectionListener(NotifCollectionListener listener) {
Assert.isMainThread();
mNotifCollectionListeners.add(listener);
}
- /**
- * Registers a lifetime extender. Lifetime extenders can cause notifications that have been
- * dismissed or retracted to be temporarily retained in the collection.
- */
- public void addNotificationLifetimeExtender(NotifLifetimeExtender extender) {
+ /** @see NotifPipeline#addNotificationLifetimeExtender(NotifLifetimeExtender) */
+ void addNotificationLifetimeExtender(NotifLifetimeExtender extender) {
Assert.isMainThread();
checkForReentrantCall();
if (mLifetimeExtenders.contains(extender)) {
@@ -165,7 +158,7 @@ public class NotifCollection {
/**
* Dismiss a notification on behalf of the user.
*/
- public void dismissNotification(
+ void dismissNotification(
NotificationEntry entry,
@CancellationReason int reason,
@NonNull DismissedByUserStats stats) {
@@ -446,7 +439,7 @@ public class NotifCollection {
REASON_TIMEOUT,
})
@Retention(RetentionPolicy.SOURCE)
- @interface CancellationReason {}
+ public @interface CancellationReason {}
public static final int REASON_UNKNOWN = 0;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifInflaterImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifInflaterImpl.java
index 0d175574f16b..e7b772f1c7b2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifInflaterImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifInflaterImpl.java
@@ -25,6 +25,9 @@ import android.service.notification.StatusBarNotification;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.statusbar.notification.InflationException;
+import com.android.systemui.statusbar.notification.collection.inflation.NotifInflater;
+import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
+import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.NotificationContentInflater;
@@ -107,7 +110,7 @@ public class NotifInflaterImpl implements NotifInflater {
DISMISS_SENTIMENT_NEUTRAL,
NotificationVisibility.obtain(entry.getKey(),
entry.getRanking().getRank(),
- mNotifCollection.getNotifs().size(),
+ mNotifCollection.getActiveNotifs().size(),
true,
NotificationLogger.getNotificationLocation(entry))
));
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifPipeline.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifPipeline.java
new file mode 100644
index 000000000000..71245178a876
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifPipeline.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2020 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.statusbar.notification.collection;
+
+import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener;
+import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeSortListener;
+import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeTransformGroupsListener;
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifComparator;
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter;
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.SectionsProvider;
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender;
+
+import java.util.Collection;
+import java.util.List;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * The system that constructs the "shade list", the filtered, grouped, and sorted list of
+ * notifications that are currently being displayed to the user in the notification shade.
+ *
+ * The pipeline proceeds through a series of stages in order to produce the final list (see below).
+ * Each stage exposes hooks and listeners to allow other code to participate.
+ *
+ * This list differs from the canonical one we receive from system server in a few ways:
+ * - Filtered: Some notifications are filtered out. For example, we filter out notifications whose
+ * views haven't been inflated yet. We also filter out some notifications if we're on the lock
+ * screen and notifications for other users. So participate, see
+ * {@link #addPreGroupFilter} and similar methods.
+ * - Grouped: Notifications that are part of the same group are clustered together into a single
+ * GroupEntry. These groups are then transformed in order to remove children or completely split
+ * them apart. To participate, see {@link #addPromoter}.
+ * - Sorted: All top-level notifications are sorted. To participate, see
+ * {@link #setSectionsProvider} and {@link #setComparators}
+ *
+ * The exact order of all hooks is as follows:
+ * 0. Collection listeners are fired ({@link #addCollectionListener}).
+ * 1. Pre-group filters are fired on each notification ({@link #addPreGroupFilter}).
+ * 2. Initial grouping is performed (NotificationEntries will have their parents set
+ * appropriately).
+ * 3. OnBeforeTransformGroupListeners are fired ({@link #addOnBeforeTransformGroupsListener})
+ * 4. NotifPromoters are called on each notification with a parent ({@link #addPromoter})
+ * 5. OnBeforeSortListeners are fired ({@link #addOnBeforeSortListener})
+ * 6. SectionsProvider is called on each top-level entry in the list ({@link #setSectionsProvider})
+ * 7. Top-level entries within the same section are sorted by NotifComparators
+ * ({@link #setComparators})
+ * 8. Pre-render filters are fired on each notification ({@link #addPreRenderFilter})
+ * 9. OnBeforeRenderListListeners are fired ({@link #addOnBeforeRenderListListener})
+ * 9. The list is handed off to the view layer to be rendered
+ */
+@Singleton
+public class NotifPipeline {
+ private final NotifCollection mNotifCollection;
+ private final ShadeListBuilder mShadeListBuilder;
+
+ @Inject
+ public NotifPipeline(
+ NotifCollection notifCollection,
+ ShadeListBuilder shadeListBuilder) {
+ mNotifCollection = notifCollection;
+ mShadeListBuilder = shadeListBuilder;
+ }
+
+ /**
+ * Returns the list of "active" notifications, i.e. the notifications that are currently posted
+ * to the phone. In general, this tracks closely to the list maintained by NotificationManager,
+ * but it can diverge slightly due to lifetime extenders.
+ *
+ * The returned collection is read-only, unsorted, unfiltered, and ungrouped.
+ */
+ public Collection<NotificationEntry> getActiveNotifs() {
+ return mNotifCollection.getActiveNotifs();
+ }
+
+ /**
+ * Registers a listener to be informed when notifications are added, removed or updated.
+ */
+ public void addCollectionListener(NotifCollectionListener listener) {
+ mNotifCollection.addCollectionListener(listener);
+ }
+
+ /**
+ * Registers a lifetime extender. Lifetime extenders can cause notifications that have been
+ * dismissed or retracted to be temporarily retained in the collection.
+ */
+ public void addNotificationLifetimeExtender(NotifLifetimeExtender extender) {
+ mNotifCollection.addNotificationLifetimeExtender(extender);
+ }
+
+ /**
+ * Registers a filter with the pipeline before grouping, promoting and sorting occurs. Filters
+ * are called on each notification in the order that they were registered. If any filter
+ * returns true, the notification is removed from the pipeline (and no other filters are
+ * called on that notif).
+ */
+ public void addPreGroupFilter(NotifFilter filter) {
+ mShadeListBuilder.addPreGroupFilter(filter);
+ }
+
+ /**
+ * Called after notifications have been filtered and after the initial grouping has been
+ * performed but before NotifPromoters have had a chance to promote children out of groups.
+ */
+ public void addOnBeforeTransformGroupsListener(OnBeforeTransformGroupsListener listener) {
+ mShadeListBuilder.addOnBeforeTransformGroupsListener(listener);
+ }
+
+ /**
+ * Registers a promoter with the pipeline. Promoters are able to promote child notifications to
+ * top-level, i.e. move a notification that would be a child of a group and make it appear
+ * ungrouped. Promoters are called on each child notification in the order that they are
+ * registered. If any promoter returns true, the notification is removed from the group (and no
+ * other promoters are called on it).
+ */
+ public void addPromoter(NotifPromoter promoter) {
+ mShadeListBuilder.addPromoter(promoter);
+ }
+
+ /**
+ * Called after notifs have been filtered and groups have been determined but before sections
+ * have been determined or the notifs have been sorted.
+ */
+ public void addOnBeforeSortListener(OnBeforeSortListener listener) {
+ mShadeListBuilder.addOnBeforeSortListener(listener);
+ }
+
+ /**
+ * Assigns sections to each top-level entry, where a section is simply an integer. Sections are
+ * the primary metric by which top-level entries are sorted; NotifComparators are only consulted
+ * when two entries are in the same section. The pipeline doesn't assign any particular meaning
+ * to section IDs -- from it's perspective they're just numbers and it sorts them by a simple
+ * numerical comparison.
+ */
+ public void setSectionsProvider(SectionsProvider provider) {
+ mShadeListBuilder.setSectionsProvider(provider);
+ }
+
+ /**
+ * Comparators that are used to sort top-level entries that share the same section. The
+ * comparators are executed in order until one of them returns a non-zero result. If all return
+ * zero, the pipeline falls back to sorting by rank (and, failing that, Notification.when).
+ */
+ public void setComparators(List<NotifComparator> comparators) {
+ mShadeListBuilder.setComparators(comparators);
+ }
+
+ /**
+ * Registers a filter with the pipeline to filter right before rendering the list (after
+ * pre-group filtering, grouping, promoting and sorting occurs). Filters are
+ * called on each notification in the order that they were registered. If any filter returns
+ * true, the notification is removed from the pipeline (and no other filters are called on that
+ * notif).
+ */
+ public void addPreRenderFilter(NotifFilter filter) {
+ mShadeListBuilder.addPreRenderFilter(filter);
+ }
+
+ /**
+ * Called at the end of the pipeline after the notif list has been finalized but before it has
+ * been handed off to the view layer.
+ */
+ public void addOnBeforeRenderListListener(OnBeforeRenderListListener listener) {
+ mShadeListBuilder.addOnBeforeRenderListListener(listener);
+ }
+
+ /**
+ * Returns a read-only view in to the current shade list, i.e. the list of notifications that
+ * are currently present in the shade. If this method is called during pipeline execution it
+ * will return the current state of the list, which will likely be only partially-generated.
+ */
+ public List<ListEntry> getShadeList() {
+ return mShadeListBuilder.getShadeList();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
index 7301fe1df398..2fcfb8c811aa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
@@ -59,6 +59,7 @@ import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.notification.InflationException;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter;
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationGuts;
import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifListBuilderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
index 19d90f083592..76c524be1b8f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifListBuilderImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
@@ -32,7 +32,6 @@ import android.annotation.MainThread;
import android.annotation.Nullable;
import android.util.ArrayMap;
-import com.android.systemui.statusbar.notification.collection.listbuilder.NotifListBuilder;
import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener;
import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeSortListener;
import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeTransformGroupsListener;
@@ -41,6 +40,7 @@ import com.android.systemui.statusbar.notification.collection.listbuilder.plugga
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.SectionsProvider;
+import com.android.systemui.statusbar.notification.collection.notifcollection.CollectionReadyForBuildListener;
import com.android.systemui.statusbar.notification.logging.NotifEvent;
import com.android.systemui.statusbar.notification.logging.NotifLog;
import com.android.systemui.util.Assert;
@@ -57,11 +57,13 @@ import javax.inject.Inject;
import javax.inject.Singleton;
/**
- * The implementation of {@link NotifListBuilder}.
+ * The second half of {@link NotifPipeline}. Sits downstream of the NotifCollection and transforms
+ * its "notification set" into the "shade list", the filtered, grouped, and sorted list of
+ * notifications that are currently present in the notification shade.
*/
@MainThread
@Singleton
-public class NotifListBuilderImpl implements NotifListBuilder {
+public class ShadeListBuilder {
private final SystemClock mSystemClock;
private final NotifLog mNotifLog;
@@ -90,7 +92,7 @@ public class NotifListBuilderImpl implements NotifListBuilder {
private final List<ListEntry> mReadOnlyNotifList = Collections.unmodifiableList(mNotifList);
@Inject
- public NotifListBuilderImpl(SystemClock systemClock, NotifLog notifLog) {
+ public ShadeListBuilder(SystemClock systemClock, NotifLog notifLog) {
Assert.isMainThread();
mSystemClock = systemClock;
mNotifLog = notifLog;
@@ -116,32 +118,28 @@ public class NotifListBuilderImpl implements NotifListBuilder {
mOnRenderListListener = onRenderListListener;
}
- @Override
- public void addOnBeforeTransformGroupsListener(OnBeforeTransformGroupsListener listener) {
+ void addOnBeforeTransformGroupsListener(OnBeforeTransformGroupsListener listener) {
Assert.isMainThread();
mPipelineState.requireState(STATE_IDLE);
mOnBeforeTransformGroupsListeners.add(listener);
}
- @Override
- public void addOnBeforeSortListener(OnBeforeSortListener listener) {
+ void addOnBeforeSortListener(OnBeforeSortListener listener) {
Assert.isMainThread();
mPipelineState.requireState(STATE_IDLE);
mOnBeforeSortListeners.add(listener);
}
- @Override
- public void addOnBeforeRenderListListener(OnBeforeRenderListListener listener) {
+ void addOnBeforeRenderListListener(OnBeforeRenderListListener listener) {
Assert.isMainThread();
mPipelineState.requireState(STATE_IDLE);
mOnBeforeRenderListListeners.add(listener);
}
- @Override
- public void addPreGroupFilter(NotifFilter filter) {
+ void addPreGroupFilter(NotifFilter filter) {
Assert.isMainThread();
mPipelineState.requireState(STATE_IDLE);
@@ -149,8 +147,7 @@ public class NotifListBuilderImpl implements NotifListBuilder {
filter.setInvalidationListener(this::onPreGroupFilterInvalidated);
}
- @Override
- public void addPreRenderFilter(NotifFilter filter) {
+ void addPreRenderFilter(NotifFilter filter) {
Assert.isMainThread();
mPipelineState.requireState(STATE_IDLE);
@@ -158,8 +155,7 @@ public class NotifListBuilderImpl implements NotifListBuilder {
filter.setInvalidationListener(this::onPreRenderFilterInvalidated);
}
- @Override
- public void addPromoter(NotifPromoter promoter) {
+ void addPromoter(NotifPromoter promoter) {
Assert.isMainThread();
mPipelineState.requireState(STATE_IDLE);
@@ -167,8 +163,7 @@ public class NotifListBuilderImpl implements NotifListBuilder {
promoter.setInvalidationListener(this::onPromoterInvalidated);
}
- @Override
- public void setSectionsProvider(SectionsProvider provider) {
+ void setSectionsProvider(SectionsProvider provider) {
Assert.isMainThread();
mPipelineState.requireState(STATE_IDLE);
@@ -176,8 +171,7 @@ public class NotifListBuilderImpl implements NotifListBuilder {
provider.setInvalidationListener(this::onSectionsProviderInvalidated);
}
- @Override
- public void setComparators(List<NotifComparator> comparators) {
+ void setComparators(List<NotifComparator> comparators) {
Assert.isMainThread();
mPipelineState.requireState(STATE_IDLE);
@@ -188,8 +182,7 @@ public class NotifListBuilderImpl implements NotifListBuilder {
}
}
- @Override
- public List<ListEntry> getActiveNotifs() {
+ List<ListEntry> getShadeList() {
Assert.isMainThread();
return mReadOnlyNotifList;
}
@@ -275,7 +268,7 @@ public class NotifListBuilderImpl implements NotifListBuilder {
}
/**
- * The core algorithm of the pipeline. See the top comment in {@link NotifListBuilder} for
+ * The core algorithm of the pipeline. See the top comment in {@link NotifPipeline} for
* details on our contracts with other code.
*
* Once the build starts we are very careful to protect against reentrant code. Anything that
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/CoalescedEvent.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/CoalescedEvent.kt
index b6218b4a9c47..143de8a27816 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/CoalescedEvent.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/CoalescedEvent.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.statusbar.notification.collection.notifcollection
+package com.android.systemui.statusbar.notification.collection.coalescer
import android.service.notification.NotificationListenerService.Ranking
import android.service.notification.StatusBarNotification
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/EventBatch.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/EventBatch.java
index ac51178e26d7..2c6a165cc550 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/EventBatch.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/EventBatch.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.statusbar.notification.collection.notifcollection;
+package com.android.systemui.statusbar.notification.collection.coalescer;
import java.util.ArrayList;
import java.util.List;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/GroupCoalescer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescer.java
index c3e3c5373b7b..8076616de05e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/GroupCoalescer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.statusbar.notification.collection.notifcollection;
+package com.android.systemui.statusbar.notification.collection.coalescer;
import static com.android.systemui.statusbar.notification.logging.NotifEvent.COALESCED_EVENT;
import static com.android.systemui.statusbar.notification.logging.NotifEvent.EARLY_BATCH_EMIT;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/Coordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/Coordinator.java
index 898918eb076d..c1a11b2f64c8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/Coordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/Coordinator.java
@@ -16,27 +16,16 @@
package com.android.systemui.statusbar.notification.collection.coordinator;
-import com.android.systemui.statusbar.notification.collection.NotifCollection;
-import com.android.systemui.statusbar.notification.collection.NotifCollectionListener;
-import com.android.systemui.statusbar.notification.collection.NotifLifetimeExtender;
-import com.android.systemui.statusbar.notification.collection.init.NewNotifPipeline;
-import com.android.systemui.statusbar.notification.collection.listbuilder.NotifListBuilder;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Pluggable;
/**
- * Interface for registering callbacks to the {@link NewNotifPipeline}.
- *
- * This includes registering:
- * {@link Pluggable}s to the {@link NotifListBuilder}
- * {@link NotifCollectionListener}s and {@link NotifLifetimeExtender}s to {@link NotifCollection}
+ * Interface for registering callbacks to the {@link NotifPipeline}.
*/
public interface Coordinator {
-
/**
* Called after the NewNotifPipeline is initialized.
- * Coordinators should register their {@link Pluggable}s to the notifListBuilder
- * and their {@link NotifCollectionListener}s and {@link NotifLifetimeExtender}s
- * to the notifCollection in this method.
+ * Coordinators should register their listeners and {@link Pluggable}s to the pipeline.
*/
- void attach(NotifCollection notifCollection, NotifListBuilder notifListBuilder);
+ void attach(NotifPipeline pipeline);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinator.java
index 5e7dd98fa9da..625d1b9686e9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinator.java
@@ -23,9 +23,8 @@ import android.content.pm.PackageManager;
import android.os.RemoteException;
import android.service.notification.StatusBarNotification;
-import com.android.systemui.statusbar.notification.collection.NotifCollection;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.collection.listbuilder.NotifListBuilder;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
@@ -52,10 +51,10 @@ public class DeviceProvisionedCoordinator implements Coordinator {
}
@Override
- public void attach(NotifCollection notifCollection, NotifListBuilder notifListBuilder) {
+ public void attach(NotifPipeline pipeline) {
mDeviceProvisionedController.addCallback(mDeviceProvisionedListener);
- notifListBuilder.addPreGroupFilter(mNotifFilter);
+ pipeline.addPreGroupFilter(mNotifFilter);
}
private final NotifFilter mNotifFilter = new NotifFilter(TAG) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinator.java
index 62342b13f9cf..da119c1502c6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinator.java
@@ -25,12 +25,11 @@ import android.util.ArraySet;
import com.android.systemui.ForegroundServiceController;
import com.android.systemui.appops.AppOpsController;
import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.statusbar.notification.collection.NotifCollection;
-import com.android.systemui.statusbar.notification.collection.NotifCollectionListener;
-import com.android.systemui.statusbar.notification.collection.NotifLifetimeExtender;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.collection.listbuilder.NotifListBuilder;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender;
import java.util.HashMap;
import java.util.Map;
@@ -57,7 +56,7 @@ public class ForegroundCoordinator implements Coordinator {
private final AppOpsController mAppOpsController;
private final Handler mMainHandler;
- private NotifCollection mNotifCollection;
+ private NotifPipeline mNotifPipeline;
@Inject
public ForegroundCoordinator(
@@ -70,20 +69,20 @@ public class ForegroundCoordinator implements Coordinator {
}
@Override
- public void attach(NotifCollection notifCollection, NotifListBuilder notifListBuilder) {
- mNotifCollection = notifCollection;
+ public void attach(NotifPipeline pipeline) {
+ mNotifPipeline = pipeline;
// extend the lifetime of foreground notification services to show for at least 5 seconds
- mNotifCollection.addNotificationLifetimeExtender(mForegroundLifetimeExtender);
+ mNotifPipeline.addNotificationLifetimeExtender(mForegroundLifetimeExtender);
// listen for new notifications to add appOps
- mNotifCollection.addCollectionListener(mNotifCollectionListener);
+ mNotifPipeline.addCollectionListener(mNotifCollectionListener);
// when appOps change, update any relevant notifications to update appOps for
mAppOpsController.addCallback(ForegroundServiceController.APP_OPS, this::onAppOpsChanged);
// filter out foreground service notifications that aren't necessary anymore
- notifListBuilder.addPreGroupFilter(mNotifFilter);
+ mNotifPipeline.addPreGroupFilter(mNotifFilter);
}
/**
@@ -230,7 +229,7 @@ public class ForegroundCoordinator implements Coordinator {
}
private NotificationEntry findNotificationEntryWithKey(String key) {
- for (NotificationEntry entry : mNotifCollection.getNotifs()) {
+ for (NotificationEntry entry : mNotifPipeline.getActiveNotifs()) {
if (entry.getKey().equals(key)) {
return entry;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java
index db107f531e9e..a26ee5450d60 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java
@@ -39,9 +39,8 @@ import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.notification.collection.GroupEntry;
import com.android.systemui.statusbar.notification.collection.ListEntry;
-import com.android.systemui.statusbar.notification.collection.NotifCollection;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.collection.listbuilder.NotifListBuilder;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -86,9 +85,9 @@ public class KeyguardCoordinator implements Coordinator {
}
@Override
- public void attach(NotifCollection notifCollection, NotifListBuilder notifListBuilder) {
+ public void attach(NotifPipeline pipeline) {
setupInvalidateNotifListCallbacks();
- notifListBuilder.addPreRenderFilter(mNotifFilter);
+ pipeline.addPreRenderFilter(mNotifFilter);
}
private final NotifFilter mNotifFilter = new NotifFilter(TAG) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.java
index 2436bb9f82f0..562a618126de 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.java
@@ -18,11 +18,10 @@ package com.android.systemui.statusbar.notification.collection.coordinator;
import com.android.systemui.Dumpable;
import com.android.systemui.statusbar.FeatureFlags;
-import com.android.systemui.statusbar.notification.collection.NotifCollection;
-import com.android.systemui.statusbar.notification.collection.NotifCollectionListener;
-import com.android.systemui.statusbar.notification.collection.NotifLifetimeExtender;
-import com.android.systemui.statusbar.notification.collection.listbuilder.NotifListBuilder;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Pluggable;
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -33,8 +32,8 @@ import javax.inject.Inject;
import javax.inject.Singleton;
/**
- * Handles the attachment of the {@link NotifListBuilder} and {@link NotifCollection} to the
- * {@link Coordinator}s, so that the Coordinators can register their respective callbacks.
+ * Handles the attachment of {@link Coordinator}s to the {@link NotifPipeline} so that the
+ * Coordinators can register their respective callbacks.
*/
@Singleton
public class NotifCoordinators implements Dumpable {
@@ -63,14 +62,12 @@ public class NotifCoordinators implements Dumpable {
}
/**
- * Sends the initialized notifListBuilder and notifCollection to each
- * coordinator to indicate the notifListBuilder is ready to accept {@link Pluggable}s
- * and the notifCollection is ready to accept {@link NotifCollectionListener}s and
- * {@link NotifLifetimeExtender}s.
+ * Sends the pipeline to each coordinator when the pipeline is ready to accept
+ * {@link Pluggable}s, {@link NotifCollectionListener}s and {@link NotifLifetimeExtender}s.
*/
- public void attach(NotifCollection notifCollection, NotifListBuilder notifListBuilder) {
+ public void attach(NotifPipeline pipeline) {
for (Coordinator c : mCoordinators) {
- c.attach(notifCollection, notifListBuilder);
+ c.attach(pipeline);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java
index a14f0e1cf631..20c9cbc8790d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java
@@ -16,13 +16,12 @@
package com.android.systemui.statusbar.notification.collection.coordinator;
-import com.android.systemui.statusbar.notification.collection.NotifCollection;
-import com.android.systemui.statusbar.notification.collection.NotifCollectionListener;
-import com.android.systemui.statusbar.notification.collection.NotifInflater;
import com.android.systemui.statusbar.notification.collection.NotifInflaterImpl;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.collection.listbuilder.NotifListBuilder;
+import com.android.systemui.statusbar.notification.collection.inflation.NotifInflater;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
import com.android.systemui.statusbar.notification.logging.NotifEvent;
import com.android.systemui.statusbar.notification.logging.NotifLog;
@@ -55,10 +54,10 @@ public class PreparationCoordinator implements Coordinator {
}
@Override
- public void attach(NotifCollection notifCollection, NotifListBuilder notifListBuilder) {
- notifCollection.addCollectionListener(mNotifCollectionListener);
- notifListBuilder.addPreRenderFilter(mNotifInflationErrorFilter);
- notifListBuilder.addPreRenderFilter(mNotifInflatingFilter);
+ public void attach(NotifPipeline pipeline) {
+ pipeline.addCollectionListener(mNotifCollectionListener);
+ pipeline.addPreRenderFilter(mNotifInflationErrorFilter);
+ pipeline.addPreRenderFilter(mNotifInflatingFilter);
}
private final NotifCollectionListener mNotifCollectionListener = new NotifCollectionListener() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java
index 0751aa814215..7e9e76096873 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java
@@ -17,9 +17,8 @@
package com.android.systemui.statusbar.notification.collection.coordinator;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.notification.collection.NotifCollection;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.collection.listbuilder.NotifListBuilder;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
import javax.inject.Inject;
@@ -43,10 +42,10 @@ public class RankingCoordinator implements Coordinator {
}
@Override
- public void attach(NotifCollection notifCollection, NotifListBuilder notifListBuilder) {
+ public void attach(NotifPipeline pipeline) {
mStatusBarStateController.addCallback(mStatusBarStateCallback);
- notifListBuilder.addPreGroupFilter(mNotifFilter);
+ pipeline.addPreGroupFilter(mNotifFilter);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifInflater.java
index fc04827a9d6a..ea0ece444a67 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifInflater.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifInflater.java
@@ -14,7 +14,8 @@
* limitations under the License.
*/
-package com.android.systemui.statusbar.notification.collection;
+package com.android.systemui.statusbar.notification.collection.inflation;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.coordinator.PreparationCoordinator;
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinder.java
index 7504e863ca73..3f500644b184 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinder.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -14,13 +14,14 @@
* limitations under the License.
*/
-package com.android.systemui.statusbar.notification.collection;
+package com.android.systemui.statusbar.notification.collection.inflation;
import android.annotation.Nullable;
import com.android.systemui.statusbar.NotificationUiAdjustment;
import com.android.systemui.statusbar.notification.InflationException;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
/**
* Used by the {@link NotificationEntryManager}. When notifications are added or updated, the binder
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
index 80b5b8af28ac..1ab20a95ca6c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.statusbar.notification.collection;
+package com.android.systemui.statusbar.notification.collection.inflation;
import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
import static com.android.systemui.statusbar.NotificationRemoteInputManager.ENABLE_REMOTE_INPUT;
@@ -39,6 +39,7 @@ import com.android.systemui.statusbar.NotificationUiAdjustment;
import com.android.systemui.statusbar.notification.InflationException;
import com.android.systemui.statusbar.notification.NotificationClicker;
import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/FakePipelineConsumer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/FakePipelineConsumer.java
index 986ee17cc906..15f312dbdc00 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/FakePipelineConsumer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/FakePipelineConsumer.java
@@ -19,8 +19,8 @@ package com.android.systemui.statusbar.notification.collection.init;
import com.android.systemui.Dumpable;
import com.android.systemui.statusbar.notification.collection.GroupEntry;
import com.android.systemui.statusbar.notification.collection.ListEntry;
-import com.android.systemui.statusbar.notification.collection.NotifListBuilderImpl;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.ShadeListBuilder;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -36,7 +36,7 @@ public class FakePipelineConsumer implements Dumpable {
private List<ListEntry> mEntries = Collections.emptyList();
/** Attach the consumer to the pipeline. */
- public void attach(NotifListBuilderImpl listBuilder) {
+ public void attach(ShadeListBuilder listBuilder) {
listBuilder.setOnRenderListListener(this::onBuildComplete);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NewNotifPipeline.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NotifPipelineInitializer.java
index 8d3d0ff43deb..959b00211c63 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NewNotifPipeline.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NotifPipelineInitializer.java
@@ -24,10 +24,11 @@ import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifInflaterImpl;
-import com.android.systemui.statusbar.notification.collection.NotifListBuilderImpl;
-import com.android.systemui.statusbar.notification.collection.NotificationRowBinderImpl;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
+import com.android.systemui.statusbar.notification.collection.ShadeListBuilder;
+import com.android.systemui.statusbar.notification.collection.coalescer.GroupCoalescer;
import com.android.systemui.statusbar.notification.collection.coordinator.NotifCoordinators;
-import com.android.systemui.statusbar.notification.collection.notifcollection.GroupCoalescer;
+import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -39,10 +40,11 @@ import javax.inject.Singleton;
* Initialization code for the new notification pipeline.
*/
@Singleton
-public class NewNotifPipeline implements Dumpable {
+public class NotifPipelineInitializer implements Dumpable {
+ private final NotifPipeline mPipelineWrapper;
private final GroupCoalescer mGroupCoalescer;
private final NotifCollection mNotifCollection;
- private final NotifListBuilderImpl mNotifPipeline;
+ private final ShadeListBuilder mListBuilder;
private final NotifCoordinators mNotifPluggableCoordinators;
private final NotifInflaterImpl mNotifInflater;
private final DumpController mDumpController;
@@ -51,17 +53,19 @@ public class NewNotifPipeline implements Dumpable {
private final FakePipelineConsumer mFakePipelineConsumer = new FakePipelineConsumer();
@Inject
- public NewNotifPipeline(
+ public NotifPipelineInitializer(
+ NotifPipeline pipelineWrapper,
GroupCoalescer groupCoalescer,
NotifCollection notifCollection,
- NotifListBuilderImpl notifPipeline,
+ ShadeListBuilder listBuilder,
NotifCoordinators notifCoordinators,
NotifInflaterImpl notifInflater,
DumpController dumpController,
FeatureFlags featureFlags) {
+ mPipelineWrapper = pipelineWrapper;
mGroupCoalescer = groupCoalescer;
mNotifCollection = notifCollection;
- mNotifPipeline = notifPipeline;
+ mListBuilder = listBuilder;
mNotifPluggableCoordinators = notifCoordinators;
mDumpController = dumpController;
mNotifInflater = notifInflater;
@@ -81,11 +85,11 @@ public class NewNotifPipeline implements Dumpable {
}
// Wire up coordinators
- mFakePipelineConsumer.attach(mNotifPipeline);
- mNotifPluggableCoordinators.attach(mNotifCollection, mNotifPipeline);
+ mNotifPluggableCoordinators.attach(mPipelineWrapper);
// Wire up pipeline
- mNotifPipeline.attach(mNotifCollection);
+ mFakePipelineConsumer.attach(mListBuilder);
+ mListBuilder.attach(mNotifCollection);
mNotifCollection.attach(mGroupCoalescer);
mGroupCoalescer.attach(notificationService);
@@ -99,5 +103,5 @@ public class NewNotifPipeline implements Dumpable {
mGroupCoalescer.dump(fd, pw, args);
}
- private static final String TAG = "NewNotifPipeline";
+ private static final String TAG = "NotifPipeline";
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/NotifListBuilder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/NotifListBuilder.java
deleted file mode 100644
index 758092417ae0..000000000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/NotifListBuilder.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.notification.collection.listbuilder;
-
-import com.android.systemui.statusbar.notification.collection.ListEntry;
-import com.android.systemui.statusbar.notification.collection.NotifCollection;
-import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifComparator;
-import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
-import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter;
-import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.SectionsProvider;
-
-import java.util.List;
-
-/**
- * The system that constructs the current "notification list", the list of notifications that are
- * currently being displayed to the user.
- *
- * The pipeline proceeds through a series of stages in order to produce the final list (see below).
- * Each stage exposes hooks and listeners for other code to participate.
- *
- * This list differs from the canonical one we receive from system server in a few ways:
- * - Filtered: Some notifications are filtered out. For example, we filter out notifications whose
- * views haven't been inflated yet. We also filter out some notifications if we're on the lock
- * screen. To participate, see {@link #addFilter(NotifFilter)}.
- * - Grouped: Notifications that are part of the same group are clustered together into a single
- * GroupEntry. These groups are then transformed in order to remove children or completely split
- * them apart. To participate, see {@link #addPromoter(NotifPromoter)}.
- * - Sorted: All top-level notifications are sorted. To participate, see
- * {@link #setSectionsProvider(SectionsProvider)} and {@link #setComparators(List)}
- *
- * The exact order of all hooks is as follows:
- * 0. Collection listeners are fired (see {@link NotifCollection}).
- * 1. NotifFilters are called on each notification currently in NotifCollection.
- * 2. Initial grouping is performed (NotificationEntries will have their parents set
- * appropriately).
- * 3. OnBeforeTransformGroupListeners are fired
- * 4. NotifPromoters are called on each notification with a parent
- * 5. OnBeforeSortListeners are fired
- * 6. SectionsProvider is called on each top-level entry in the list
- * 7. The top-level entries are sorted using the provided NotifComparators (plus some additional
- * built-in logic).
- * 8. OnBeforeRenderListListeners are fired
- * 9. The list is handed off to the view layer to be rendered.
- */
-public interface NotifListBuilder {
-
- /**
- * Registers a filter with the pipeline before grouping, promoting and sorting occurs. Filters
- * are called on each notification in the order that they were registered. If any filter
- * returns true, the notification is removed from the pipeline (and no other filters are
- * called on that notif).
- */
- void addPreGroupFilter(NotifFilter filter);
-
- /**
- * Registers a promoter with the pipeline. Promoters are able to promote child notifications to
- * top-level, i.e. move a notification that would be a child of a group and make it appear
- * ungrouped. Promoters are called on each child notification in the order that they are
- * registered. If any promoter returns true, the notification is removed from the group (and no
- * other promoters are called on it).
- */
- void addPromoter(NotifPromoter promoter);
-
- /**
- * Assigns sections to each top-level entry, where a section is simply an integer. Sections are
- * the primary metric by which top-level entries are sorted; NotifComparators are only consulted
- * when two entries are in the same section. The pipeline doesn't assign any particular meaning
- * to section IDs -- from it's perspective they're just numbers and it sorts them by a simple
- * numerical comparison.
- */
- void setSectionsProvider(SectionsProvider provider);
-
- /**
- * Comparators that are used to sort top-level entries that share the same section. The
- * comparators are executed in order until one of them returns a non-zero result. If all return
- * zero, the pipeline falls back to sorting by rank (and, failing that, Notification.when).
- */
- void setComparators(List<NotifComparator> comparators);
-
- /**
- * Registers a filter with the pipeline to filter right before rendering the list (after
- * pre-group filtering, grouping, promoting and sorting occurs). Filters are
- * called on each notification in the order that they were registered. If any filter returns
- * true, the notification is removed from the pipeline (and no other filters are called on that
- * notif).
- */
- void addPreRenderFilter(NotifFilter filter);
-
- /**
- * Called after notifications have been filtered and after the initial grouping has been
- * performed but before NotifPromoters have had a chance to promote children out of groups.
- */
- void addOnBeforeTransformGroupsListener(OnBeforeTransformGroupsListener listener);
-
- /**
- * Called after notifs have been filtered and groups have been determined but before sections
- * have been determined or the notifs have been sorted.
- */
- void addOnBeforeSortListener(OnBeforeSortListener listener);
-
- /**
- * Called at the end of the pipeline after the notif list has been finalized but before it has
- * been handed off to the view layer.
- */
- void addOnBeforeRenderListListener(OnBeforeRenderListListener listener);
-
- /**
- * Returns a read-only view in to the current notification list. If this method is called
- * during pipeline execution it will return the current state of the list, which will likely
- * be only partially-generated.
- */
- List<ListEntry> getActiveNotifs();
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeRenderListListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeRenderListListener.java
index f6ca12d83fdd..44a27a4b546a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeRenderListListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeRenderListListener.java
@@ -17,10 +17,11 @@
package com.android.systemui.statusbar.notification.collection.listbuilder;
import com.android.systemui.statusbar.notification.collection.ListEntry;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import java.util.List;
-/** See {@link NotifListBuilder#addOnBeforeRenderListListener(OnBeforeRenderListListener)} */
+/** See {@link NotifPipeline#addOnBeforeRenderListListener(OnBeforeRenderListListener)} */
public interface OnBeforeRenderListListener {
/**
* Called at the end of the pipeline after the notif list has been finalized but before it has
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeSortListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeSortListener.java
index 7be7ac03e1f1..56cfe5cb3716 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeSortListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeSortListener.java
@@ -17,10 +17,11 @@
package com.android.systemui.statusbar.notification.collection.listbuilder;
import com.android.systemui.statusbar.notification.collection.ListEntry;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import java.util.List;
-/** See {@link NotifListBuilder#addOnBeforeSortListener(OnBeforeSortListener)} */
+/** See {@link NotifPipeline#addOnBeforeSortListener(OnBeforeSortListener)} */
public interface OnBeforeSortListener {
/**
* Called after the notif list has been filtered and grouped but before sections have been
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeTransformGroupsListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeTransformGroupsListener.java
index d7a081510655..0dc4df0da066 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeTransformGroupsListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeTransformGroupsListener.java
@@ -17,13 +17,14 @@
package com.android.systemui.statusbar.notification.collection.listbuilder;
import com.android.systemui.statusbar.notification.collection.ListEntry;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter;
import java.util.List;
/**
* See
- * {@link NotifListBuilder#addOnBeforeTransformGroupsListener(OnBeforeTransformGroupsListener)}
+ * {@link NotifPipeline#addOnBeforeTransformGroupsListener(OnBeforeTransformGroupsListener)}
*/
public interface OnBeforeTransformGroupsListener {
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/PipelineState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/PipelineState.java
index 084d03810ad9..1897ba2319ac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/PipelineState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/PipelineState.java
@@ -18,13 +18,13 @@ package com.android.systemui.statusbar.notification.collection.listbuilder;
import android.annotation.IntDef;
-import com.android.systemui.statusbar.notification.collection.NotifListBuilderImpl;
+import com.android.systemui.statusbar.notification.collection.ShadeListBuilder;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
- * Used by {@link NotifListBuilderImpl} to track its internal state machine.
+ * Used by {@link ShadeListBuilder} to track its internal state machine.
*/
public class PipelineState {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifComparator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifComparator.java
index a191c830537d..0d150edee128 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifComparator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifComparator.java
@@ -17,13 +17,13 @@
package com.android.systemui.statusbar.notification.collection.listbuilder.pluggable;
import com.android.systemui.statusbar.notification.collection.ListEntry;
-import com.android.systemui.statusbar.notification.collection.listbuilder.NotifListBuilder;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import java.util.Comparator;
import java.util.List;
/**
- * Pluggable for participating in notif sorting. See {@link NotifListBuilder#setComparators(List)}.
+ * Pluggable for participating in notif sorting. See {@link NotifPipeline#setComparators(List)}.
*/
public abstract class NotifComparator
extends Pluggable<NotifComparator>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifFilter.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifFilter.java
index e6189edc2f3b..8f575cdd8918 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifFilter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifFilter.java
@@ -16,12 +16,12 @@
package com.android.systemui.statusbar.notification.collection.listbuilder.pluggable;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.collection.listbuilder.NotifListBuilder;
/**
* Pluggable for participating in notif filtering.
- * See {@link NotifListBuilder#addPreGroupFilter} and {@link NotifListBuilder#addPreRenderFilter}.
+ * See {@link NotifPipeline#addPreGroupFilter} and {@link NotifPipeline#addPreRenderFilter}.
*/
public abstract class NotifFilter extends Pluggable<NotifFilter> {
protected NotifFilter(String name) {
@@ -35,9 +35,9 @@ public abstract class NotifFilter extends Pluggable<NotifFilter> {
* however. If another filter returns true before yours, we'll skip straight to the next notif.
*
* @param entry The entry in question.
- * If this filter is registered via {@link NotifListBuilder#addPreGroupFilter},
+ * If this filter is registered via {@link NotifPipeline#addPreGroupFilter},
* this entry will not have any grouping nor sorting information.
- * If this filter is registered via {@link NotifListBuilder#addPreRenderFilter},
+ * If this filter is registered via {@link NotifPipeline#addPreRenderFilter},
* this entry will have grouping and sorting information.
* @param now A timestamp in SystemClock.uptimeMillis that represents "now" for the purposes of
* pipeline execution. This value will be the same for all pluggable calls made
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifPromoter.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifPromoter.java
index 84e16f432740..5fce4462aede 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifPromoter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifPromoter.java
@@ -16,13 +16,13 @@
package com.android.systemui.statusbar.notification.collection.listbuilder.pluggable;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.collection.listbuilder.NotifListBuilder;
/**
* Pluggable for participating in notif promotion. Notif promoters can upgrade notifications
* from being children of a group to top-level notifications. See
- * {@link NotifListBuilder#addPromoter(NotifPromoter)}.
+ * {@link NotifPipeline#addPromoter}.
*/
public abstract class NotifPromoter extends Pluggable<NotifPromoter> {
protected NotifPromoter(String name) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/Pluggable.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/Pluggable.java
index f9ce197c6547..4270408d0c66 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/Pluggable.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/Pluggable.java
@@ -18,10 +18,10 @@ package com.android.systemui.statusbar.notification.collection.listbuilder.plugg
import android.annotation.Nullable;
-import com.android.systemui.statusbar.notification.collection.listbuilder.NotifListBuilder;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
/**
- * Generic superclass for chunks of code that can plug into the {@link NotifListBuilder}.
+ * Generic superclass for chunks of code that can plug into the {@link NotifPipeline}.
*
* A pluggable is fundamentally three things:
* 1. A name (for debugging purposes)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/CollectionReadyForBuildListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/CollectionReadyForBuildListener.java
index 87aaea007e65..4023474bf6a7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/CollectionReadyForBuildListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/CollectionReadyForBuildListener.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -14,7 +14,9 @@
* limitations under the License.
*/
-package com.android.systemui.statusbar.notification.collection;
+package com.android.systemui.statusbar.notification.collection.notifcollection;
+
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import java.util.Collection;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/DismissedByUserStats.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/DismissedByUserStats.java
index ecce6ea1b211..b2686864cc43 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/DismissedByUserStats.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/DismissedByUserStats.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.statusbar.notification.collection;
+package com.android.systemui.statusbar.notification.collection.notifcollection;
import android.service.notification.NotificationStats.DismissalSentiment;
import android.service.notification.NotificationStats.DismissalSurface;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollectionListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionListener.java
index 032620e14336..9cbc7d7efa66 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollectionListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionListener.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -14,9 +14,11 @@
* limitations under the License.
*/
-package com.android.systemui.statusbar.notification.collection;
+package com.android.systemui.statusbar.notification.collection.notifcollection;
+import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifCollection.CancellationReason;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
/**
* Listener interface for {@link NotifCollection}.
@@ -36,7 +38,9 @@ public interface NotifCollectionListener {
}
/**
- * Called immediately after a notification has been removed from the collection.
+ * Called whenever a notification is retracted by system server. This method is not called
+ * immediately after a user dismisses a notification: we wait until we receive confirmation from
+ * system server before considering the notification removed.
*/
default void onEntryRemoved(
NotificationEntry entry,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifLifetimeExtender.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifLifetimeExtender.java
index 2c7b13866c10..05f5ea85bd4d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifLifetimeExtender.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifLifetimeExtender.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -14,9 +14,11 @@
* limitations under the License.
*/
-package com.android.systemui.statusbar.notification.collection;
+package com.android.systemui.statusbar.notification.collection.notifcollection;
+import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifCollection.CancellationReason;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
/**
* A way for other code to temporarily extend the lifetime of a notification after it has been
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotifEvent.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotifEvent.java
index c6c36ee17873..02acc8149cc4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotifEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotifEvent.java
@@ -22,8 +22,8 @@ import android.service.notification.StatusBarNotification;
import com.android.systemui.log.RichEvent;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.collection.listbuilder.NotifListBuilder;
-import com.android.systemui.statusbar.notification.collection.notifcollection.GroupCoalescer;
+import com.android.systemui.statusbar.notification.collection.ShadeListBuilder;
+import com.android.systemui.statusbar.notification.collection.coalescer.GroupCoalescer;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -67,7 +67,7 @@ public class NotifEvent extends RichEvent {
}
/**
- * @return if this event occurred in {@link NotifListBuilder}
+ * @return if this event occurred in {@link ShadeListBuilder}
*/
static boolean isListBuilderEvent(@EventType int type) {
return isBetweenInclusive(type, 0, TOTAL_LIST_BUILDER_EVENT_TYPES);
@@ -161,7 +161,7 @@ public class NotifEvent extends RichEvent {
private static final int TOTAL_EVENT_LABELS = EVENT_LABELS.length;
/**
- * Events related to {@link NotifListBuilder}
+ * Events related to {@link ShadeListBuilder}
*/
public static final int WARN = 0;
public static final int ON_BUILD_LIST = 1;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt
index 78eaf3ee10a4..452d1eb95aab 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt
@@ -17,7 +17,9 @@
package com.android.systemui.statusbar.notification.people
import android.app.Notification
+import android.content.Context
import android.service.notification.StatusBarNotification
+import android.util.FeatureFlagUtils
import javax.inject.Inject
import javax.inject.Singleton
@@ -27,10 +29,16 @@ interface PeopleNotificationIdentifier {
@Singleton
class PeopleNotificationIdentifierImpl @Inject constructor(
- private val personExtractor: NotificationPersonExtractor
+ private val personExtractor: NotificationPersonExtractor,
+ private val context: Context
) : PeopleNotificationIdentifier {
override fun isPeopleNotification(sbn: StatusBarNotification) =
- sbn.notification.notificationStyle == Notification.MessagingStyle::class.java ||
+ (sbn.notification.notificationStyle == Notification.MessagingStyle::class.java &&
+ (sbn.notification.shortcutId != null ||
+ FeatureFlagUtils.isEnabled(
+ context,
+ FeatureFlagUtils.NOTIF_CONVO_BYPASS_SHORTCUT_REQ
+ ))) ||
personExtractor.isPersonNotification(sbn)
} \ No newline at end of file
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 189d3b6f530b..ba70cf4a39f4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -199,8 +199,8 @@ import com.android.systemui.statusbar.notification.NotificationListController;
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.collection.NotificationRowBinderImpl;
-import com.android.systemui.statusbar.notification.collection.init.NewNotifPipeline;
+import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
+import com.android.systemui.statusbar.notification.collection.init.NotifPipelineInitializer;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
@@ -364,7 +364,7 @@ public class StatusBar extends SystemUI implements DemoMode,
private final HeadsUpManagerPhone mHeadsUpManager;
private final DynamicPrivacyController mDynamicPrivacyController;
private final BypassHeadsUpNotifier mBypassHeadsUpNotifier;
- private final Lazy<NewNotifPipeline> mNewNotifPipeline;
+ private final Lazy<NotifPipelineInitializer> mNewNotifPipeline;
private final FalsingManager mFalsingManager;
private final BroadcastDispatcher mBroadcastDispatcher;
private final ConfigurationController mConfigurationController;
@@ -625,7 +625,7 @@ public class StatusBar extends SystemUI implements DemoMode,
HeadsUpManagerPhone headsUpManagerPhone,
DynamicPrivacyController dynamicPrivacyController,
BypassHeadsUpNotifier bypassHeadsUpNotifier,
- Lazy<NewNotifPipeline> newNotifPipeline,
+ Lazy<NotifPipelineInitializer> newNotifPipeline,
FalsingManager falsingManager,
BroadcastDispatcher broadcastDispatcher,
RemoteInputQuickSettingsDisabler remoteInputQuickSettingsDisabler,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarModule.java
index be7f0a0c36f2..b4d5dadda5b8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarModule.java
@@ -65,8 +65,8 @@ import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
-import com.android.systemui.statusbar.notification.collection.NotificationRowBinderImpl;
-import com.android.systemui.statusbar.notification.collection.init.NewNotifPipeline;
+import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
+import com.android.systemui.statusbar.notification.collection.init.NotifPipelineInitializer;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.phone.dagger.StatusBarComponent;
@@ -117,7 +117,7 @@ public class StatusBarModule {
HeadsUpManagerPhone headsUpManagerPhone,
DynamicPrivacyController dynamicPrivacyController,
BypassHeadsUpNotifier bypassHeadsUpNotifier,
- Lazy<NewNotifPipeline> newNotifPipeline,
+ Lazy<NotifPipelineInitializer> newNotifPipeline,
FalsingManager falsingManager,
BroadcastDispatcher broadcastDispatcher,
RemoteInputQuickSettingsDisabler remoteInputQuickSettingsDisabler,
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 12a65169e1df..720f22964915 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
@@ -66,7 +66,7 @@ import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.collection.NotificationRowBinderImpl;
+import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
index 9c9a627fa6e0..8d11b54dacb2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
@@ -48,7 +48,7 @@ import com.android.internal.messages.nano.SystemMessageProto;
import com.android.systemui.appops.AppOpsController;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.collection.NotifCollection;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
@@ -71,7 +71,7 @@ public class ForegroundServiceControllerTest extends SysuiTestCase {
@Mock private NotificationEntryManager mEntryManager;
@Mock private AppOpsController mAppOpsController;
@Mock private Handler mMainHandler;
- @Mock private NotifCollection mNotifCollection;
+ @Mock private NotifPipeline mNotifPipeline;
@Before
public void setUp() throws Exception {
@@ -81,7 +81,7 @@ public class ForegroundServiceControllerTest extends SysuiTestCase {
MockitoAnnotations.initMocks(this);
mFsc = new ForegroundServiceController(mEntryManager, mAppOpsController, mMainHandler);
mListener = new ForegroundServiceNotificationListener(
- mContext, mFsc, mEntryManager, mNotifCollection);
+ mContext, mFsc, mEntryManager, mNotifPipeline);
ArgumentCaptor<NotificationEntryListener> entryListenerCaptor =
ArgumentCaptor.forClass(NotificationEntryListener.class);
verify(mEntryManager).addNotificationEntryListener(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
index 1e0179dc92f1..cc5514f1ff68 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
@@ -78,7 +78,7 @@ import com.android.systemui.statusbar.notification.NotificationEntryManager.Keyg
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.NotificationRankingManager;
-import com.android.systemui.statusbar.notification.collection.NotificationRowBinderImpl;
+import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
import com.android.systemui.statusbar.notification.logging.NotifLog;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/TestableNotificationEntryManager.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/TestableNotificationEntryManager.kt
index bf84f2bc599c..29ce92074027 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/TestableNotificationEntryManager.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/TestableNotificationEntryManager.kt
@@ -21,7 +21,7 @@ import com.android.systemui.statusbar.NotificationPresenter
import com.android.systemui.statusbar.NotificationRemoteInputManager
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.NotificationRankingManager
-import com.android.systemui.statusbar.notification.collection.NotificationRowBinder
+import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder
import com.android.systemui.statusbar.notification.logging.NotifLog
import com.android.systemui.statusbar.notification.stack.NotificationListContainer
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
index 28feacac8c44..09cc5ba204f8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
@@ -52,9 +52,13 @@ import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.RankingBuilder;
import com.android.systemui.statusbar.notification.collection.NoManSimulator.NotifEvent;
import com.android.systemui.statusbar.notification.collection.NotifCollection.CancellationReason;
-import com.android.systemui.statusbar.notification.collection.notifcollection.CoalescedEvent;
-import com.android.systemui.statusbar.notification.collection.notifcollection.GroupCoalescer;
-import com.android.systemui.statusbar.notification.collection.notifcollection.GroupCoalescer.BatchableNotificationHandler;
+import com.android.systemui.statusbar.notification.collection.coalescer.CoalescedEvent;
+import com.android.systemui.statusbar.notification.collection.coalescer.GroupCoalescer;
+import com.android.systemui.statusbar.notification.collection.coalescer.GroupCoalescer.BatchableNotificationHandler;
+import com.android.systemui.statusbar.notification.collection.notifcollection.CollectionReadyForBuildListener;
+import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats;
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender;
import com.android.systemui.util.Assert;
import org.junit.Before;
@@ -377,7 +381,7 @@ public class NotifCollectionTest extends SysuiTestCase {
verify(mExtender3).shouldExtendLifetime(entry2, REASON_UNKNOWN);
// THEN the entry is not removed
- assertTrue(mCollection.getNotifs().contains(entry2));
+ assertTrue(mCollection.getActiveNotifs().contains(entry2));
// THEN the entry properly records all extenders that returned true
assertEquals(Arrays.asList(mExtender1, mExtender2), entry2.mLifetimeExtenders);
@@ -398,7 +402,7 @@ public class NotifCollectionTest extends SysuiTestCase {
// GIVEN a notification gets lifetime-extended by one of them
mNoMan.retractNotif(notif2.sbn, REASON_APP_CANCEL);
- assertTrue(mCollection.getNotifs().contains(entry2));
+ assertTrue(mCollection.getActiveNotifs().contains(entry2));
clearInvocations(mExtender1, mExtender2, mExtender3);
// WHEN the last active extender expires (but new ones become active)
@@ -413,7 +417,7 @@ public class NotifCollectionTest extends SysuiTestCase {
verify(mExtender3).shouldExtendLifetime(entry2, REASON_UNKNOWN);
// THEN the entry is not removed
- assertTrue(mCollection.getNotifs().contains(entry2));
+ assertTrue(mCollection.getActiveNotifs().contains(entry2));
// THEN the entry properly records all extenders that returned true
assertEquals(Arrays.asList(mExtender1, mExtender3), entry2.mLifetimeExtenders);
@@ -435,7 +439,7 @@ public class NotifCollectionTest extends SysuiTestCase {
// GIVEN a notification gets lifetime-extended by a couple of them
mNoMan.retractNotif(notif2.sbn, REASON_APP_CANCEL);
- assertTrue(mCollection.getNotifs().contains(entry2));
+ assertTrue(mCollection.getActiveNotifs().contains(entry2));
clearInvocations(mExtender1, mExtender2, mExtender3);
// WHEN one (but not all) of the extenders expires
@@ -443,7 +447,7 @@ public class NotifCollectionTest extends SysuiTestCase {
mExtender2.callback.onEndLifetimeExtension(mExtender2, entry2);
// THEN the entry is not removed
- assertTrue(mCollection.getNotifs().contains(entry2));
+ assertTrue(mCollection.getActiveNotifs().contains(entry2));
// THEN we don't re-query the extenders
verify(mExtender1, never()).shouldExtendLifetime(eq(entry2), anyInt());
@@ -470,7 +474,7 @@ public class NotifCollectionTest extends SysuiTestCase {
// GIVEN a notification gets lifetime-extended by a couple of them
mNoMan.retractNotif(notif2.sbn, REASON_UNKNOWN);
- assertTrue(mCollection.getNotifs().contains(entry2));
+ assertTrue(mCollection.getActiveNotifs().contains(entry2));
clearInvocations(mExtender1, mExtender2, mExtender3);
// WHEN all of the active extenders expire
@@ -480,7 +484,7 @@ public class NotifCollectionTest extends SysuiTestCase {
mExtender1.callback.onEndLifetimeExtension(mExtender1, entry2);
// THEN the entry removed
- assertFalse(mCollection.getNotifs().contains(entry2));
+ assertFalse(mCollection.getActiveNotifs().contains(entry2));
verify(mCollectionListener).onEntryRemoved(entry2, REASON_UNKNOWN, false);
}
@@ -500,7 +504,7 @@ public class NotifCollectionTest extends SysuiTestCase {
// GIVEN a notification gets lifetime-extended by a couple of them
mNoMan.retractNotif(notif2.sbn, REASON_UNKNOWN);
- assertTrue(mCollection.getNotifs().contains(entry2));
+ assertTrue(mCollection.getActiveNotifs().contains(entry2));
clearInvocations(mExtender1, mExtender2, mExtender3);
// WHEN the notification is reposted
@@ -511,7 +515,7 @@ public class NotifCollectionTest extends SysuiTestCase {
verify(mExtender2).cancelLifetimeExtension(entry2);
// THEN the notification is still present
- assertTrue(mCollection.getNotifs().contains(entry2));
+ assertTrue(mCollection.getActiveNotifs().contains(entry2));
}
@Test(expected = IllegalStateException.class)
@@ -530,7 +534,7 @@ public class NotifCollectionTest extends SysuiTestCase {
// GIVEN a notification gets lifetime-extended by a couple of them
mNoMan.retractNotif(notif2.sbn, REASON_UNKNOWN);
- assertTrue(mCollection.getNotifs().contains(entry2));
+ assertTrue(mCollection.getActiveNotifs().contains(entry2));
clearInvocations(mExtender1, mExtender2, mExtender3);
// WHEN a lifetime extender makes a reentrant call during cancelLifetimeExtension()
@@ -559,7 +563,7 @@ public class NotifCollectionTest extends SysuiTestCase {
// GIVEN a notification gets lifetime-extended by a couple of them
mNoMan.retractNotif(notif2.sbn, REASON_UNKNOWN);
- assertTrue(mCollection.getNotifs().contains(entry2));
+ assertTrue(mCollection.getActiveNotifs().contains(entry2));
clearInvocations(mExtender1, mExtender2, mExtender3);
// WHEN the notification is reposted
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifListBuilderImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java
index 3e4068b6367c..be067481b779 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifListBuilderImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java
@@ -38,7 +38,7 @@ import android.util.ArrayMap;
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.notification.collection.NotifListBuilderImpl.OnRenderListListener;
+import com.android.systemui.statusbar.notification.collection.ShadeListBuilder.OnRenderListListener;
import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener;
import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeSortListener;
import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeTransformGroupsListener;
@@ -46,6 +46,7 @@ import com.android.systemui.statusbar.notification.collection.listbuilder.plugga
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.SectionsProvider;
+import com.android.systemui.statusbar.notification.collection.notifcollection.CollectionReadyForBuildListener;
import com.android.systemui.statusbar.notification.logging.NotifLog;
import com.android.systemui.util.Assert;
import com.android.systemui.util.time.FakeSystemClock;
@@ -72,9 +73,9 @@ import java.util.stream.Collectors;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
-public class NotifListBuilderImplTest extends SysuiTestCase {
+public class ShadeListBuilderTest extends SysuiTestCase {
- private NotifListBuilderImpl mListBuilder;
+ private ShadeListBuilder mListBuilder;
private FakeSystemClock mSystemClock = new FakeSystemClock();
@Mock private NotifLog mNotifLog;
@@ -99,7 +100,7 @@ public class NotifListBuilderImplTest extends SysuiTestCase {
MockitoAnnotations.initMocks(this);
Assert.sMainLooper = TestableLooper.get(this).getLooper();
- mListBuilder = new NotifListBuilderImpl(mSystemClock, mNotifLog);
+ mListBuilder = new ShadeListBuilder(mSystemClock, mNotifLog);
mListBuilder.setOnRenderListListener(mOnRenderListListener);
mListBuilder.attach(mNotifCollection);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/notifcollection/GroupCoalescerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescerTest.java
index 7ff32401b4be..5e0baf204ecf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/notifcollection/GroupCoalescerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescerTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.statusbar.notification.collection.notifcollection;
+package com.android.systemui.statusbar.notification.collection.coalescer;
import static com.android.internal.util.Preconditions.checkNotNull;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinatorTest.java
index ea6c70a6e142..701cf95736ea 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinatorTest.java
@@ -36,7 +36,7 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.RankingBuilder;
-import com.android.systemui.statusbar.notification.collection.NotifListBuilderImpl;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
@@ -65,7 +65,7 @@ public class DeviceProvisionedCoordinatorTest extends SysuiTestCase {
@Mock private ActivityManagerInternal mActivityMangerInternal;
@Mock private IPackageManager mIPackageManager;
@Mock private DeviceProvisionedController mDeviceProvisionedController;
- @Mock private NotifListBuilderImpl mNotifListBuilder;
+ @Mock private NotifPipeline mNotifPipeline;
private Notification mNotification;
private NotificationEntry mEntry;
private DeviceProvisionedCoordinator mDeviceProvisionedCoordinator;
@@ -84,8 +84,8 @@ public class DeviceProvisionedCoordinatorTest extends SysuiTestCase {
.build();
ArgumentCaptor<NotifFilter> filterCaptor = ArgumentCaptor.forClass(NotifFilter.class);
- mDeviceProvisionedCoordinator.attach(null, mNotifListBuilder);
- verify(mNotifListBuilder, times(1)).addPreGroupFilter(filterCaptor.capture());
+ mDeviceProvisionedCoordinator.attach(mNotifPipeline);
+ verify(mNotifPipeline, times(1)).addPreGroupFilter(filterCaptor.capture());
mDeviceProvisionedFilter = filterCaptor.getValue();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinatorTest.java
index 01bca0dc1078..6cc8dd908760 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinatorTest.java
@@ -36,12 +36,11 @@ import androidx.test.filters.SmallTest;
import com.android.systemui.ForegroundServiceController;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.appops.AppOpsController;
-import com.android.systemui.statusbar.notification.collection.NotifCollection;
-import com.android.systemui.statusbar.notification.collection.NotifLifetimeExtender;
-import com.android.systemui.statusbar.notification.collection.NotifListBuilderImpl;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender;
import org.junit.Before;
import org.junit.Test;
@@ -59,8 +58,7 @@ public class ForegroundCoordinatorTest extends SysuiTestCase {
@Mock private Handler mMainHandler;
@Mock private ForegroundServiceController mForegroundServiceController;
@Mock private AppOpsController mAppOpsController;
- @Mock private NotifListBuilderImpl mNotifListBuilder;
- @Mock private NotifCollection mNotifCollection;
+ @Mock private NotifPipeline mNotifPipeline;
private NotificationEntry mEntry;
private Notification mNotification;
@@ -84,9 +82,9 @@ public class ForegroundCoordinatorTest extends SysuiTestCase {
ArgumentCaptor<NotifLifetimeExtender> lifetimeExtenderCaptor =
ArgumentCaptor.forClass(NotifLifetimeExtender.class);
- mForegroundCoordinator.attach(mNotifCollection, mNotifListBuilder);
- verify(mNotifListBuilder, times(1)).addPreGroupFilter(filterCaptor.capture());
- verify(mNotifCollection, times(1)).addNotificationLifetimeExtender(
+ mForegroundCoordinator.attach(mNotifPipeline);
+ verify(mNotifPipeline, times(1)).addPreGroupFilter(filterCaptor.capture());
+ verify(mNotifPipeline, times(1)).addNotificationLifetimeExtender(
lifetimeExtenderCaptor.capture());
mForegroundFilter = filterCaptor.getValue();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java
index f921cf969e61..5866d90f62bf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java
@@ -41,7 +41,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.RankingBuilder;
import com.android.systemui.statusbar.notification.collection.GroupEntry;
-import com.android.systemui.statusbar.notification.collection.NotifListBuilderImpl;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
@@ -68,7 +68,7 @@ public class KeyguardCoordinatorTest extends SysuiTestCase {
@Mock private StatusBarStateController mStatusBarStateController;
@Mock private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
@Mock private HighPriorityProvider mHighPriorityProvider;
- @Mock private NotifListBuilderImpl mNotifListBuilder;
+ @Mock private NotifPipeline mNotifPipeline;
private NotificationEntry mEntry;
private KeyguardCoordinator mKeyguardCoordinator;
@@ -87,8 +87,8 @@ public class KeyguardCoordinatorTest extends SysuiTestCase {
.build();
ArgumentCaptor<NotifFilter> filterCaptor = ArgumentCaptor.forClass(NotifFilter.class);
- mKeyguardCoordinator.attach(null, mNotifListBuilder);
- verify(mNotifListBuilder, times(1)).addPreRenderFilter(filterCaptor.capture());
+ mKeyguardCoordinator.attach(mNotifPipeline);
+ verify(mNotifPipeline, times(1)).addPreRenderFilter(filterCaptor.capture());
mKeyguardFilter = filterCaptor.getValue();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java
index d3b16c319692..e84f9cf352ed 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java
@@ -33,7 +33,7 @@ import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.RankingBuilder;
-import com.android.systemui.statusbar.notification.collection.NotifListBuilderImpl;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
@@ -50,7 +50,7 @@ import org.mockito.MockitoAnnotations;
public class RankingCoordinatorTest extends SysuiTestCase {
@Mock private StatusBarStateController mStatusBarStateController;
- @Mock private NotifListBuilderImpl mNotifListBuilder;
+ @Mock private NotifPipeline mNotifPipeline;
private NotificationEntry mEntry;
private RankingCoordinator mRankingCoordinator;
private NotifFilter mRankingFilter;
@@ -62,8 +62,8 @@ public class RankingCoordinatorTest extends SysuiTestCase {
mEntry = new NotificationEntryBuilder().build();
ArgumentCaptor<NotifFilter> filterCaptor = ArgumentCaptor.forClass(NotifFilter.class);
- mRankingCoordinator.attach(null, mNotifListBuilder);
- verify(mNotifListBuilder, times(1)).addPreGroupFilter(filterCaptor.capture());
+ mRankingCoordinator.attach(mNotifPipeline);
+ verify(mNotifPipeline, times(1)).addPreGroupFilter(filterCaptor.capture());
mRankingFilter = filterCaptor.getValue();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
index 9bd3914da3da..d9939f485ce5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
@@ -71,7 +71,7 @@ import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.NotificationRankingManager;
-import com.android.systemui.statusbar.notification.collection.NotificationRowBinder;
+import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder;
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
import com.android.systemui.statusbar.notification.logging.NotifLog;
import com.android.systemui.statusbar.notification.people.PeopleHubSectionFooterViewAdapter;
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 5ac7bfbfd296..782e14c83951 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
@@ -54,7 +54,7 @@ import com.android.systemui.statusbar.notification.NotificationInterruptionState
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
-import com.android.systemui.statusbar.notification.collection.NotificationRowBinderImpl;
+import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 560aadb93a14..fee48522683d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -120,8 +120,8 @@ import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
-import com.android.systemui.statusbar.notification.collection.NotificationRowBinderImpl;
-import com.android.systemui.statusbar.notification.collection.init.NewNotifPipeline;
+import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
+import com.android.systemui.statusbar.notification.collection.init.NotifPipelineInitializer;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
@@ -214,7 +214,7 @@ public class StatusBarTest extends SysuiTestCase {
@Mock private NotificationWakeUpCoordinator mNotificationWakeUpCoordinator;
@Mock private KeyguardBypassController mKeyguardBypassController;
@Mock private DynamicPrivacyController mDynamicPrivacyController;
- @Mock private NewNotifPipeline mNewNotifPipeline;
+ @Mock private NotifPipelineInitializer mNewNotifPipeline;
@Mock private ZenModeController mZenModeController;
@Mock private AutoHideController mAutoHideController;
@Mock private NotificationViewHierarchyManager mNotificationViewHierarchyManager;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
index 4103d7189266..cd89d3c32697 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
@@ -30,12 +30,12 @@ import android.telephony.CellSignalStrength;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper.RunWithLooper;
-import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.TelephonyIntents;
import com.android.settingslib.graph.SignalDrawable;
import com.android.settingslib.net.DataUsageController;
@@ -418,7 +418,7 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest {
intent.putExtra(TelephonyIntents.EXTRA_SHOW_PLMN, showPlmn);
intent.putExtra(TelephonyIntents.EXTRA_PLMN, plmn);
- intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, mSubId);
+ SubscriptionManager.putSubscriptionIdExtra(intent, mSubId);
return intent;
}
diff --git a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java
index e1fe3bfda4a8..900c67198677 100644
--- a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java
@@ -501,13 +501,15 @@ public class TetheringTest {
p2pInfo.groupFormed = isGroupFormed;
p2pInfo.isGroupOwner = isGroupOwner;
- WifiP2pGroup group = new WifiP2pGroup();
- group.setIsGroupOwner(isGroupOwner);
- group.setInterface(ifname);
+ WifiP2pGroup group = mock(WifiP2pGroup.class);
+ when(group.isGroupOwner()).thenReturn(isGroupOwner);
+ when(group.getInterface()).thenReturn(ifname);
+
+ final Intent intent = mock(Intent.class);
+ when(intent.getAction()).thenReturn(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
+ when(intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO)).thenReturn(p2pInfo);
+ when(intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_GROUP)).thenReturn(group);
- final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
- intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO, p2pInfo);
- intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_GROUP, group);
mServiceContext.sendBroadcastAsUserMultiplePermissions(intent, UserHandle.ALL,
P2P_RECEIVER_PERMISSIONS_FOR_BROADCAST);
}
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index f34b5e71ad7b..7d354d20cb67 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -162,6 +162,9 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
/** uid the session is for */
public final int uid;
+ /** user id the session is for */
+ public final int userId;
+
/** ID of the task associated with this session's activity */
public final int taskId;
@@ -613,7 +616,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
int newState, int flags) {
if (isInlineSuggestionsEnabled()) {
mInlineSuggestionsRequestCallback = new InlineSuggestionsRequestCallbackImpl();
- mInputMethodManagerInternal.onCreateInlineSuggestionsRequest(
+ mInputMethodManagerInternal.onCreateInlineSuggestionsRequest(userId,
mComponentName, mCurrentViewId, mInlineSuggestionsRequestCallback);
}
@@ -759,6 +762,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
mFlags = flags;
this.taskId = taskId;
this.uid = uid;
+ this.userId = userId;
mStartTime = SystemClock.elapsedRealtime();
mService = service;
mLock = lock;
diff --git a/services/backup/java/com/android/server/backup/internal/BackupHandler.java b/services/backup/java/com/android/server/backup/internal/BackupHandler.java
index eb6262094849..b06fc52a24c2 100644
--- a/services/backup/java/com/android/server/backup/internal/BackupHandler.java
+++ b/services/backup/java/com/android/server/backup/internal/BackupHandler.java
@@ -21,12 +21,10 @@ import static com.android.server.backup.BackupManagerService.MORE_DEBUG;
import static com.android.server.backup.BackupManagerService.TAG;
import android.app.backup.RestoreSet;
-import android.content.Intent;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.os.RemoteException;
-import android.os.UserHandle;
import android.util.EventLog;
import android.util.Pair;
import android.util.Slog;
@@ -40,7 +38,6 @@ import com.android.server.backup.DataChangedJournal;
import com.android.server.backup.TransportManager;
import com.android.server.backup.UserBackupManagerService;
import com.android.server.backup.fullbackup.PerformAdbBackupTask;
-import com.android.server.backup.fullbackup.PerformFullTransportBackupTask;
import com.android.server.backup.keyvalue.BackupRequest;
import com.android.server.backup.keyvalue.KeyValueBackupTask;
import com.android.server.backup.params.AdbBackupParams;
@@ -73,10 +70,7 @@ public class BackupHandler extends Handler {
public static final int MSG_RESTORE_SESSION_TIMEOUT = 8;
public static final int MSG_FULL_CONFIRMATION_TIMEOUT = 9;
public static final int MSG_RUN_ADB_RESTORE = 10;
- public static final int MSG_RETRY_INIT = 11;
public static final int MSG_RETRY_CLEAR = 12;
- public static final int MSG_WIDGET_BROADCAST = 13;
- public static final int MSG_RUN_FULL_TRANSPORT_BACKUP = 14;
public static final int MSG_REQUEST_BACKUP = 15;
public static final int MSG_SCHEDULE_BACKUP_PACKAGE = 16;
public static final int MSG_BACKUP_OPERATION_TIMEOUT = 17;
@@ -279,12 +273,6 @@ public class BackupHandler extends Handler {
break;
}
- case MSG_RUN_FULL_TRANSPORT_BACKUP: {
- PerformFullTransportBackupTask task = (PerformFullTransportBackupTask) msg.obj;
- (new Thread(task, "transport-backup")).start();
- break;
- }
-
case MSG_RUN_RESTORE: {
RestoreParams params = (RestoreParams) msg.obj;
Slog.d(TAG, "MSG_RUN_RESTORE observer=" + params.observer);
@@ -445,12 +433,6 @@ public class BackupHandler extends Handler {
break;
}
- case MSG_WIDGET_BROADCAST: {
- final Intent intent = (Intent) msg.obj;
- backupManagerService.getContext().sendBroadcastAsUser(intent, UserHandle.SYSTEM);
- break;
- }
-
case MSG_REQUEST_BACKUP: {
BackupParams params = (BackupParams) msg.obj;
if (MORE_DEBUG) {
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index f4962e53662c..5435cbad870f 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -5505,7 +5505,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
// changes that would conflict throughout the automerger graph. Having this method temporarily
// helps with the process of going through with all these dependent changes across the entire
// tree.
- public int registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo,
+ /**
+ * Register a new agent. {@see #registerNetworkAgent} below.
+ */
+ public Network registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo,
LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
int currentScore, NetworkAgentConfig networkAgentConfig) {
return registerNetworkAgent(messenger, networkInfo, linkProperties, networkCapabilities,
@@ -5526,8 +5529,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
* {@link NetworkAgentInfo#getCurrentScore}.
* @param networkAgentConfig metadata about the network. This is never updated.
* @param providerId the ID of the provider owning this NetworkAgent.
+ * @return the network created for this agent.
*/
- public int registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo,
+ public Network registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo,
LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
int currentScore, NetworkAgentConfig networkAgentConfig, int providerId) {
enforceNetworkFactoryPermission();
@@ -5560,7 +5564,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
// If the network disconnects or sends any other event before that, messages are deferred by
// NetworkAgent until nai.asyncChannel.connect(), which will be called when finalizing the
// registration.
- return nai.network.netId;
+ return nai.network;
}
private void handleRegisterNetworkAgent(NetworkAgentInfo nai, INetworkMonitor networkMonitor) {
diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
index b26ef92557e1..d1d1cb3566d2 100644
--- a/services/core/java/com/android/server/NetworkScoreService.java
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -523,7 +523,7 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
@Override
public void accept(INetworkScoreCache networkScoreCache, Object cookie) {
- int filterType = NetworkScoreManager.CACHE_FILTER_NONE;
+ int filterType = NetworkScoreManager.SCORE_FILTER_NONE;
if (cookie instanceof Integer) {
filterType = (Integer) cookie;
}
@@ -547,17 +547,17 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
private List<ScoredNetwork> filterScores(List<ScoredNetwork> scoredNetworkList,
int filterType) {
switch (filterType) {
- case NetworkScoreManager.CACHE_FILTER_NONE:
+ case NetworkScoreManager.SCORE_FILTER_NONE:
return scoredNetworkList;
- case NetworkScoreManager.CACHE_FILTER_CURRENT_NETWORK:
+ case NetworkScoreManager.SCORE_FILTER_CURRENT_NETWORK:
if (mCurrentNetworkFilter == null) {
mCurrentNetworkFilter =
new CurrentNetworkScoreCacheFilter(new WifiInfoSupplier(mContext));
}
return mCurrentNetworkFilter.apply(scoredNetworkList);
- case NetworkScoreManager.CACHE_FILTER_SCAN_RESULTS:
+ case NetworkScoreManager.SCORE_FILTER_SCAN_RESULTS:
if (mScanResultsFilter == null) {
mScanResultsFilter = new ScanResultsScoreCacheFilter(
new ScanResultsSupplier(mContext));
diff --git a/services/core/java/com/android/server/TestNetworkService.java b/services/core/java/com/android/server/TestNetworkService.java
index c27b0da780b7..ed3bab97ca19 100644
--- a/services/core/java/com/android/server/TestNetworkService.java
+++ b/services/core/java/com/android/server/TestNetworkService.java
@@ -218,7 +218,7 @@ class TestNetworkService extends ITestNetworkManager.Stub {
// Has to be in TestNetworkAgent to ensure all teardown codepaths properly clean up
// resources, even for binder death or unwanted calls.
synchronized (mTestNetworkTracker) {
- mTestNetworkTracker.remove(netId);
+ mTestNetworkTracker.remove(network.netId);
}
}
}
@@ -337,7 +337,7 @@ class TestNetworkService extends ITestNetworkManager.Stub {
callingUid,
binder);
- mTestNetworkTracker.put(agent.netId, agent);
+ mTestNetworkTracker.put(agent.network.netId, agent);
}
} catch (SocketException e) {
throw new UncheckedIOException(e);
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index a372fca07728..debc2a116934 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -2129,16 +2129,6 @@ public class AccountManagerService
}
@Override
- public void removeAccount(IAccountManagerResponse response, Account account,
- boolean expectActivityLaunch) {
- removeAccountAsUser(
- response,
- account,
- expectActivityLaunch,
- UserHandle.getCallingUserId());
- }
-
- @Override
public void removeAccountAsUser(IAccountManagerResponse response, Account account,
boolean expectActivityLaunch, int userId) {
final int callingUid = Binder.getCallingUid();
@@ -4454,12 +4444,6 @@ public class AccountManagerService
@Override
@NonNull
- public Account[] getAccounts(String type, String opPackageName) {
- return getAccountsAsUser(type, UserHandle.getCallingUserId(), opPackageName);
- }
-
- @Override
- @NonNull
public Account[] getAccountsForPackage(String packageName, int uid, String opPackageName) {
int callingUid = Binder.getCallingUid();
if (!UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index c21adb08270e..8f6d981064de 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -16408,6 +16408,22 @@ public class ActivityManagerService extends IActivityManager.Stub
}
@Override
+ public boolean updateMccMncConfiguration(String mcc, String mnc) {
+ int mccInt, mncInt;
+ try {
+ mccInt = Integer.parseInt(mcc);
+ mncInt = Integer.parseInt(mnc);
+ } catch (NumberFormatException | StringIndexOutOfBoundsException ex) {
+ Slog.e(TAG, "Error parsing mcc: " + mcc + " mnc: " + mnc + ". ex=" + ex);
+ return false;
+ }
+ Configuration config = new Configuration();
+ config.mcc = mccInt;
+ config.mnc = mncInt == 0 ? Configuration.MNC_ZERO : mncInt;
+ return mActivityTaskManager.updateConfiguration(config);
+ }
+
+ @Override
public int getLaunchedFromUid(IBinder activityToken) {
return mActivityTaskManager.getLaunchedFromUid(activityToken);
}
diff --git a/services/core/java/com/android/server/compat/CompatConfig.java b/services/core/java/com/android/server/compat/CompatConfig.java
index f15d999e1006..8d261762a19b 100644
--- a/services/core/java/com/android/server/compat/CompatConfig.java
+++ b/services/core/java/com/android/server/compat/CompatConfig.java
@@ -367,6 +367,8 @@ final class CompatConfig {
CompatConfig config = new CompatConfig(androidBuildClassifier, context);
config.initConfigFromLib(Environment.buildPath(
Environment.getRootDirectory(), "etc", "compatconfig"));
+ config.initConfigFromLib(Environment.buildPath(
+ Environment.getRootDirectory(), "system_ext", "etc", "compatconfig"));
return config;
}
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 476f3f823def..1d2a9059c453 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -848,7 +848,7 @@ public class Vpn {
}
public int getNetId() {
- return mNetworkAgent != null ? mNetworkAgent.netId : NETID_UNSET;
+ return mNetworkAgent != null ? mNetworkAgent.network.netId : NETID_UNSET;
}
private LinkProperties makeLinkProperties() {
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java
index 2c3c70fc3da2..9c421524d723 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java
@@ -68,8 +68,9 @@ public abstract class InputMethodManagerInternal {
* @param autofillId {@link AutofillId} of currently focused field.
* @param cb {@link IInlineSuggestionsRequestCallback} used to pass back the request object.
*/
- public abstract void onCreateInlineSuggestionsRequest(ComponentName componentName,
- AutofillId autofillId, IInlineSuggestionsRequestCallback cb);
+ public abstract void onCreateInlineSuggestionsRequest(@UserIdInt int userId,
+ ComponentName componentName, AutofillId autofillId,
+ IInlineSuggestionsRequestCallback cb);
/**
* Force switch to the enabled input method by {@code imeId} for current user. If the input
@@ -107,8 +108,9 @@ public abstract class InputMethodManagerInternal {
}
@Override
- public void onCreateInlineSuggestionsRequest(ComponentName componentName,
- AutofillId autofillId, IInlineSuggestionsRequestCallback cb) {
+ public void onCreateInlineSuggestionsRequest(int userId,
+ ComponentName componentName, AutofillId autofillId,
+ IInlineSuggestionsRequestCallback cb) {
}
@Override
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index d4b13faf3195..0bf65bd6f739 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -111,6 +111,7 @@ import android.view.WindowManager.LayoutParams;
import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
import android.view.autofill.AutofillId;
import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InlineSuggestionsRequest;
import android.view.inputmethod.InputBinding;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputConnectionInspector;
@@ -142,6 +143,7 @@ import com.android.internal.os.TransferPipe;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.view.IInlineSuggestionsRequestCallback;
+import com.android.internal.view.IInlineSuggestionsResponseCallback;
import com.android.internal.view.IInputContext;
import com.android.internal.view.IInputMethod;
import com.android.internal.view.IInputMethodClient;
@@ -1790,15 +1792,18 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
@GuardedBy("mMethodMap")
- private void onCreateInlineSuggestionsRequestLocked(ComponentName componentName,
- AutofillId autofillId, IInlineSuggestionsRequestCallback callback) {
-
+ private void onCreateInlineSuggestionsRequestLocked(@UserIdInt int userId,
+ ComponentName componentName, AutofillId autofillId,
+ IInlineSuggestionsRequestCallback callback) {
final InputMethodInfo imi = mMethodMap.get(mCurMethodId);
try {
- if (imi != null && imi.isInlineSuggestionsEnabled() && mCurMethod != null) {
+ if (userId == mSettings.getCurrentUserId() && imi != null
+ && imi.isInlineSuggestionsEnabled() && mCurMethod != null) {
executeOrSendMessage(mCurMethod,
mCaller.obtainMessageOOOO(MSG_INLINE_SUGGESTIONS_REQUEST, mCurMethod,
- componentName, autofillId, callback));
+ componentName, autofillId,
+ new InlineSuggestionsRequestCallbackDecorator(callback,
+ imi.getPackageName())));
} else {
callback.onInlineSuggestionsUnsupported();
}
@@ -1808,6 +1813,42 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
/**
+ * The decorator which validates the host package name in the
+ * {@link InlineSuggestionsRequest} argument to make sure it matches the IME package name.
+ */
+ private static final class InlineSuggestionsRequestCallbackDecorator
+ extends IInlineSuggestionsRequestCallback.Stub {
+ @NonNull
+ private final IInlineSuggestionsRequestCallback mCallback;
+ @NonNull
+ private final String mImePackageName;
+
+ InlineSuggestionsRequestCallbackDecorator(
+ @NonNull IInlineSuggestionsRequestCallback callback,
+ @NonNull String imePackageName) {
+ mCallback = callback;
+ mImePackageName = imePackageName;
+ }
+
+ @Override
+ public void onInlineSuggestionsUnsupported() throws RemoteException {
+ mCallback.onInlineSuggestionsUnsupported();
+ }
+
+ @Override
+ public void onInlineSuggestionsRequest(InlineSuggestionsRequest request,
+ IInlineSuggestionsResponseCallback callback) throws RemoteException {
+ if (!mImePackageName.equals(request.getHostPackageName())) {
+ throw new SecurityException(
+ "Host package name in the provide request=[" + request.getHostPackageName()
+ + "] doesn't match the IME package name=[" + mImePackageName
+ + "].");
+ }
+ mCallback.onInlineSuggestionsRequest(request, callback);
+ }
+ }
+
+ /**
* @param imiId if null, returns enabled subtypes for the current imi
* @return enabled subtypes of the specified imi
*/
@@ -4471,10 +4512,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
}
- private void onCreateInlineSuggestionsRequest(ComponentName componentName,
- AutofillId autofillId, IInlineSuggestionsRequestCallback callback) {
+ private void onCreateInlineSuggestionsRequest(@UserIdInt int userId,
+ ComponentName componentName, AutofillId autofillId,
+ IInlineSuggestionsRequestCallback callback) {
synchronized (mMethodMap) {
- onCreateInlineSuggestionsRequestLocked(componentName, autofillId, callback);
+ onCreateInlineSuggestionsRequestLocked(userId, componentName, autofillId, callback);
}
}
@@ -4542,9 +4584,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
@Override
- public void onCreateInlineSuggestionsRequest(ComponentName componentName,
+ public void onCreateInlineSuggestionsRequest(int userId, ComponentName componentName,
AutofillId autofillId, IInlineSuggestionsRequestCallback cb) {
- mService.onCreateInlineSuggestionsRequest(componentName, autofillId, cb);
+ mService.onCreateInlineSuggestionsRequest(userId, componentName, autofillId, cb);
}
@Override
diff --git a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
index 20d7955e0c77..f09795fbea01 100644
--- a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
@@ -191,8 +191,9 @@ public final class MultiClientInputMethodManagerService {
}
@Override
- public void onCreateInlineSuggestionsRequest(ComponentName componentName,
- AutofillId autofillId, IInlineSuggestionsRequestCallback cb) {
+ public void onCreateInlineSuggestionsRequest(int userId,
+ ComponentName componentName, AutofillId autofillId,
+ IInlineSuggestionsRequestCallback cb) {
try {
//TODO(b/137800469): support multi client IMEs.
cb.onInlineSuggestionsUnsupported();
diff --git a/services/core/java/com/android/server/media/MediaRoute2Provider.java b/services/core/java/com/android/server/media/MediaRoute2Provider.java
index 0d315cd6863d..408c1c9b7d18 100644
--- a/services/core/java/com/android/server/media/MediaRoute2Provider.java
+++ b/services/core/java/com/android/server/media/MediaRoute2Provider.java
@@ -23,18 +23,22 @@ import android.content.Intent;
import android.media.MediaRoute2ProviderInfo;
import android.media.RoutingSessionInfo;
+import com.android.internal.annotations.GuardedBy;
+
import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
import java.util.Objects;
abstract class MediaRoute2Provider {
final ComponentName mComponentName;
final String mUniqueId;
+ final Object mLock = new Object();
Callback mCallback;
private volatile MediaRoute2ProviderInfo mProviderInfo;
- private volatile List<RoutingSessionInfo> mSessionInfos = Collections.emptyList();
+
+ @GuardedBy("mLock")
+ final List<RoutingSessionInfo> mSessionInfos = new ArrayList<>();
MediaRoute2Provider(@NonNull ComponentName componentName) {
mComponentName = Objects.requireNonNull(componentName, "Component name must not be null.");
@@ -69,11 +73,12 @@ abstract class MediaRoute2Provider {
@NonNull
public List<RoutingSessionInfo> getSessionInfos() {
- return mSessionInfos;
+ synchronized (mLock) {
+ return mSessionInfos;
+ }
}
- void setProviderState(MediaRoute2ProviderInfo providerInfo,
- List<RoutingSessionInfo> sessionInfos) {
+ void setProviderState(MediaRoute2ProviderInfo providerInfo) {
if (providerInfo == null) {
mProviderInfo = null;
} else {
@@ -81,14 +86,6 @@ abstract class MediaRoute2Provider {
.setUniqueId(mUniqueId)
.build();
}
- List<RoutingSessionInfo> sessionInfoWithProviderId = new ArrayList<RoutingSessionInfo>();
- for (RoutingSessionInfo sessionInfo : sessionInfos) {
- sessionInfoWithProviderId.add(
- new RoutingSessionInfo.Builder(sessionInfo)
- .setProviderId(mUniqueId)
- .build());
- }
- mSessionInfos = sessionInfoWithProviderId;
}
void notifyProviderState() {
@@ -97,9 +94,8 @@ abstract class MediaRoute2Provider {
}
}
- void setAndNotifyProviderState(MediaRoute2ProviderInfo providerInfo,
- List<RoutingSessionInfo> sessionInfos) {
- setProviderState(providerInfo, sessionInfos);
+ void setAndNotifyProviderState(MediaRoute2ProviderInfo providerInfo) {
+ setProviderState(providerInfo);
notifyProviderState();
}
@@ -112,10 +108,9 @@ abstract class MediaRoute2Provider {
void onProviderStateChanged(@Nullable MediaRoute2Provider provider);
void onSessionCreated(@NonNull MediaRoute2Provider provider,
@Nullable RoutingSessionInfo sessionInfo, long requestId);
- // TODO: Remove this when MediaRouter2ServiceImpl notifies clients of session changes.
- void onSessionInfoChanged(@NonNull MediaRoute2Provider provider,
+ void onSessionCreationFailed(@NonNull MediaRoute2Provider provider, long requestId);
+ void onSessionUpdated(@NonNull MediaRoute2Provider provider,
@NonNull RoutingSessionInfo sessionInfo);
- // TODO: Call this when service actually notifies of session release.
void onSessionReleased(@NonNull MediaRoute2Provider provider,
@NonNull RoutingSessionInfo sessionInfo);
}
diff --git a/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java b/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java
index c0ad46f5fa06..3840d0206016 100644
--- a/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java
+++ b/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java
@@ -17,7 +17,6 @@
package com.android.server.media;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -37,8 +36,6 @@ import android.util.Slog;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
-import java.util.Collections;
-import java.util.List;
import java.util.Objects;
/**
@@ -270,35 +267,69 @@ final class MediaRoute2ProviderProxy extends MediaRoute2Provider implements Serv
}
private void onProviderStateUpdated(Connection connection,
- MediaRoute2ProviderInfo providerInfo, List<RoutingSessionInfo> sessionInfos) {
+ MediaRoute2ProviderInfo providerInfo) {
if (mActiveConnection != connection) {
return;
}
if (DEBUG) {
Slog.d(TAG, this + ": State changed ");
}
- setAndNotifyProviderState(providerInfo, sessionInfos);
+ setAndNotifyProviderState(providerInfo);
}
- private void onSessionCreated(Connection connection, @Nullable RoutingSessionInfo sessionInfo,
+ private void onSessionCreated(Connection connection, RoutingSessionInfo sessionInfo,
long requestId) {
if (mActiveConnection != connection) {
return;
}
- if (sessionInfo != null) {
- sessionInfo = new RoutingSessionInfo.Builder(sessionInfo)
- .setProviderId(getUniqueId())
- .build();
+
+ if (sessionInfo == null) {
+ Slog.w(TAG, "onSessionCreated: Ignoring null sessionInfo sent from " + mComponentName);
+ return;
}
+
+ sessionInfo = new RoutingSessionInfo.Builder(sessionInfo)
+ .setProviderId(getUniqueId())
+ .build();
+
+ boolean duplicateSessionAlreadyExists = false;
+ synchronized (mLock) {
+ for (int i = 0; i < mSessionInfos.size(); i++) {
+ if (mSessionInfos.get(i).getId().equals(sessionInfo.getId())) {
+ duplicateSessionAlreadyExists = true;
+ break;
+ }
+ }
+ mSessionInfos.add(sessionInfo);
+ }
+
+ if (duplicateSessionAlreadyExists) {
+ Slog.w(TAG, "onSessionCreated: Duplicate session already exists. Ignoring.");
+ return;
+ }
+
mCallback.onSessionCreated(this, sessionInfo, requestId);
}
- private void onSessionInfoChanged(Connection connection, RoutingSessionInfo sessionInfo) {
+ private void onSessionCreationFailed(Connection connection, long requestId) {
+ if (mActiveConnection != connection) {
+ return;
+ }
+
+ if (requestId == MediaRoute2ProviderService.REQUEST_ID_UNKNOWN) {
+ Slog.w(TAG, "onSessionCreationFailed: Ignoring requestId REQUEST_ID_UNKNOWN");
+ return;
+ }
+
+ mCallback.onSessionCreationFailed(this, requestId);
+ }
+
+ private void onSessionUpdated(Connection connection, RoutingSessionInfo sessionInfo) {
if (mActiveConnection != connection) {
return;
}
if (sessionInfo == null) {
- Slog.w(TAG, "onSessionInfoChanged: Ignoring null sessionInfo sent from "
+ Slog.w(TAG, "onSessionUpdated: Ignoring null sessionInfo sent from "
+ mComponentName);
return;
}
@@ -307,7 +338,55 @@ final class MediaRoute2ProviderProxy extends MediaRoute2Provider implements Serv
.setProviderId(getUniqueId())
.build();
- mCallback.onSessionInfoChanged(this, sessionInfo);
+ boolean found = false;
+ synchronized (mLock) {
+ for (int i = 0; i < mSessionInfos.size(); i++) {
+ if (mSessionInfos.get(i).getId().equals(sessionInfo.getId())) {
+ mSessionInfos.set(i, sessionInfo);
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if (!found) {
+ Slog.w(TAG, "onSessionUpdated: Matching session info not found");
+ return;
+ }
+
+ mCallback.onSessionUpdated(this, sessionInfo);
+ }
+
+ private void onSessionReleased(Connection connection, RoutingSessionInfo sessionInfo) {
+ if (mActiveConnection != connection) {
+ return;
+ }
+ if (sessionInfo == null) {
+ Slog.w(TAG, "onSessionReleased: Ignoring null sessionInfo sent from " + mComponentName);
+ return;
+ }
+
+ sessionInfo = new RoutingSessionInfo.Builder(sessionInfo)
+ .setProviderId(getUniqueId())
+ .build();
+
+ boolean found = false;
+ synchronized (mLock) {
+ for (int i = 0; i < mSessionInfos.size(); i++) {
+ if (mSessionInfos.get(i).getId().equals(sessionInfo.getId())) {
+ mSessionInfos.remove(i);
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if (!found) {
+ Slog.w(TAG, "onSessionReleased: Matching session info not found");
+ return;
+ }
+
+ mCallback.onSessionReleased(this, sessionInfo);
}
private void disconnect() {
@@ -315,7 +394,7 @@ final class MediaRoute2ProviderProxy extends MediaRoute2Provider implements Serv
mConnectionReady = false;
mActiveConnection.dispose();
mActiveConnection = null;
- setAndNotifyProviderState(null, Collections.emptyList());
+ setAndNotifyProviderState(null);
}
}
@@ -421,19 +500,24 @@ final class MediaRoute2ProviderProxy extends MediaRoute2Provider implements Serv
mHandler.post(() -> onConnectionDied(Connection.this));
}
- void postProviderStateUpdated(MediaRoute2ProviderInfo providerInfo,
- List<RoutingSessionInfo> sessionInfos) {
- mHandler.post(() -> onProviderStateUpdated(Connection.this,
- providerInfo, sessionInfos));
+ void postProviderStateUpdated(MediaRoute2ProviderInfo providerInfo) {
+ mHandler.post(() -> onProviderStateUpdated(Connection.this, providerInfo));
}
- void postSessionCreated(@Nullable RoutingSessionInfo sessionInfo, long requestId) {
- mHandler.post(() -> onSessionCreated(Connection.this, sessionInfo,
- requestId));
+ void postSessionCreated(RoutingSessionInfo sessionInfo, long requestId) {
+ mHandler.post(() -> onSessionCreated(Connection.this, sessionInfo, requestId));
}
- void postSessionInfoChanged(RoutingSessionInfo sessionInfo) {
- mHandler.post(() -> onSessionInfoChanged(Connection.this, sessionInfo));
+ void postSessionCreationFailed(long requestId) {
+ mHandler.post(() -> onSessionCreationFailed(Connection.this, requestId));
+ }
+
+ void postSessionUpdated(RoutingSessionInfo sessionInfo) {
+ mHandler.post(() -> onSessionUpdated(Connection.this, sessionInfo));
+ }
+
+ void postSessionReleased(RoutingSessionInfo sessionInfo) {
+ mHandler.post(() -> onSessionReleased(Connection.this, sessionInfo));
}
}
@@ -449,16 +533,15 @@ final class MediaRoute2ProviderProxy extends MediaRoute2Provider implements Serv
}
@Override
- public void updateState(MediaRoute2ProviderInfo providerInfo,
- List<RoutingSessionInfo> sessionInfos) {
+ public void updateState(MediaRoute2ProviderInfo providerInfo) {
Connection connection = mConnectionRef.get();
if (connection != null) {
- connection.postProviderStateUpdated(providerInfo, sessionInfos);
+ connection.postProviderStateUpdated(providerInfo);
}
}
@Override
- public void notifySessionCreated(@Nullable RoutingSessionInfo sessionInfo, long requestId) {
+ public void notifySessionCreated(RoutingSessionInfo sessionInfo, long requestId) {
Connection connection = mConnectionRef.get();
if (connection != null) {
connection.postSessionCreated(sessionInfo, requestId);
@@ -466,10 +549,26 @@ final class MediaRoute2ProviderProxy extends MediaRoute2Provider implements Serv
}
@Override
- public void notifySessionInfoChanged(RoutingSessionInfo sessionInfo) {
+ public void notifySessionCreationFailed(long requestId) {
+ Connection connection = mConnectionRef.get();
+ if (connection != null) {
+ connection.postSessionCreationFailed(requestId);
+ }
+ }
+
+ @Override
+ public void notifySessionUpdated(RoutingSessionInfo sessionInfo) {
+ Connection connection = mConnectionRef.get();
+ if (connection != null) {
+ connection.postSessionUpdated(sessionInfo);
+ }
+ }
+
+ @Override
+ public void notifySessionReleased(RoutingSessionInfo sessionInfo) {
Connection connection = mConnectionRef.get();
if (connection != null) {
- connection.postSessionInfoChanged(sessionInfo);
+ connection.postSessionReleased(sessionInfo);
}
}
}
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index c48c90db30d1..d940e3587794 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -22,7 +22,6 @@ import static android.media.MediaRouter2Utils.getProviderId;
import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
@@ -31,6 +30,7 @@ import android.media.IMediaRouter2Client;
import android.media.IMediaRouter2Manager;
import android.media.MediaRoute2Info;
import android.media.MediaRoute2ProviderInfo;
+import android.media.MediaRoute2ProviderService;
import android.media.RouteDiscoveryPreference;
import android.media.RoutingSessionInfo;
import android.os.Binder;
@@ -876,13 +876,19 @@ class MediaRouter2ServiceImpl {
@Override
public void onSessionCreated(@NonNull MediaRoute2Provider provider,
- @Nullable RoutingSessionInfo sessionInfo, long requestId) {
+ @NonNull RoutingSessionInfo sessionInfo, long requestId) {
sendMessage(PooledLambda.obtainMessage(UserHandler::onSessionCreatedOnHandler,
this, provider, sessionInfo, requestId));
}
@Override
- public void onSessionInfoChanged(@NonNull MediaRoute2Provider provider,
+ public void onSessionCreationFailed(@NonNull MediaRoute2Provider provider, long requestId) {
+ sendMessage(PooledLambda.obtainMessage(UserHandler::onSessionCreationFailedOnHandler,
+ this, provider, requestId));
+ }
+
+ @Override
+ public void onSessionUpdated(@NonNull MediaRoute2Provider provider,
@NonNull RoutingSessionInfo sessionInfo) {
sendMessage(PooledLambda.obtainMessage(UserHandler::onSessionInfoChangedOnHandler,
this, provider, sessionInfo));
@@ -1132,7 +1138,14 @@ class MediaRouter2ServiceImpl {
}
private void onSessionCreatedOnHandler(@NonNull MediaRoute2Provider provider,
- @Nullable RoutingSessionInfo sessionInfo, long requestId) {
+ @NonNull RoutingSessionInfo sessionInfo, long requestId) {
+
+ if (requestId == MediaRoute2ProviderService.REQUEST_ID_UNKNOWN) {
+ // The session is created without any matching request.
+ // TODO: Tell managers for the session creation
+ return;
+ }
+
SessionCreationRequest matchingRequest = null;
for (SessionCreationRequest request : mSessionCreationRequests) {
@@ -1182,6 +1195,30 @@ class MediaRouter2ServiceImpl {
// TODO: Tell managers for the session creation
}
+ private void onSessionCreationFailedOnHandler(@NonNull MediaRoute2Provider provider,
+ long requestId) {
+ SessionCreationRequest matchingRequest = null;
+
+ for (SessionCreationRequest request : mSessionCreationRequests) {
+ if (request.mRequestId == requestId
+ && TextUtils.equals(
+ request.mRoute.getProviderId(), provider.getUniqueId())) {
+ matchingRequest = request;
+ break;
+ }
+ }
+
+ if (matchingRequest == null) {
+ Slog.w(TAG, "Ignoring session creation failed result for unknown request. "
+ + "requestId=" + requestId);
+ return;
+ }
+
+ mSessionCreationRequests.remove(matchingRequest);
+ notifySessionCreationFailed(matchingRequest.mClientRecord,
+ toClientRequestId(requestId));
+ }
+
private void onSessionInfoChangedOnHandler(@NonNull MediaRoute2Provider provider,
@NonNull RoutingSessionInfo sessionInfo) {
diff --git a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
index 961d3d01a67d..6695227fd236 100644
--- a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
+++ b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
@@ -169,7 +169,7 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
for (MediaRoute2Info route : mBluetoothRoutes) {
builder.addRoute(route);
}
- setProviderState(builder.build(), Collections.emptyList());
+ setProviderState(builder.build());
mHandler.post(() -> notifyProviderState());
}
@@ -212,6 +212,6 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
for (MediaRoute2Info route : mBluetoothRoutes) {
builder.addRoute(route);
}
- setAndNotifyProviderState(builder.build(), Collections.emptyList());
+ setAndNotifyProviderState(builder.build());
}
}
diff --git a/services/core/java/com/android/server/pm/InstantAppRegistry.java b/services/core/java/com/android/server/pm/InstantAppRegistry.java
index ffcd6cf8603c..bcfe5773cfa4 100644
--- a/services/core/java/com/android/server/pm/InstantAppRegistry.java
+++ b/services/core/java/com/android/server/pm/InstantAppRegistry.java
@@ -338,9 +338,8 @@ class InstantAppRegistry {
}
@GuardedBy("mService.mLock")
- public void onPackageUninstalledLPw(@NonNull AndroidPackage pkg,
+ public void onPackageUninstalledLPw(@NonNull AndroidPackage pkg, @Nullable PackageSetting ps,
@NonNull int[] userIds) {
- PackageSetting ps = mService.getPackageSetting(pkg.getPackageName());
if (ps == null) {
return;
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index dad32cd6c83e..159b4e49bfea 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -17502,7 +17502,8 @@ public class PackageManagerService extends IPackageManager.Stub
synchronized (mLock) {
if (res) {
if (pkg != null) {
- mInstantAppRegistry.onPackageUninstalledLPw(pkg, info.removedUsers);
+ mInstantAppRegistry.onPackageUninstalledLPw(pkg, uninstalledPs,
+ info.removedUsers);
}
updateSequenceNumberLP(uninstalledPs, info.removedUsers);
updateInstantAppInstallerLocked(packageName);
diff --git a/services/core/java/com/android/server/policy/LegacyGlobalActions.java b/services/core/java/com/android/server/policy/LegacyGlobalActions.java
index 52714933c8e2..6daf5162ebad 100644
--- a/services/core/java/com/android/server/policy/LegacyGlobalActions.java
+++ b/services/core/java/com/android/server/policy/LegacyGlobalActions.java
@@ -743,8 +743,8 @@ class LegacyGlobalActions implements DialogInterface.OnDismissListener, DialogIn
} else if (TelephonyManager.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED.equals(action)) {
// Airplane mode can be changed after ECM exits if airplane toggle button
// is pressed during ECM mode
- if (!(intent.getBooleanExtra("PHONE_IN_ECM_STATE", false)) &&
- mIsWaitingForEcmExit) {
+ if (!(intent.getBooleanExtra(TelephonyManager.EXTRA_PHONE_IN_ECM_STATE, false))
+ && mIsWaitingForEcmExit) {
mIsWaitingForEcmExit = false;
changeAirplaneModeSystemSetting(true);
}
diff --git a/services/core/java/com/android/server/stats/StatsPullAtomService.java b/services/core/java/com/android/server/stats/StatsPullAtomService.java
index a75f1c210bc0..5ee7eff20e24 100644
--- a/services/core/java/com/android/server/stats/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/StatsPullAtomService.java
@@ -186,6 +186,12 @@ public class StatsPullAtomService extends SystemService {
private static final String TAG = "StatsPullAtomService";
private static final boolean DEBUG = true;
+ private static final String RESULT_RECEIVER_CONTROLLER_KEY = "controller_activity";
+ /**
+ * How long to wait on an individual subsystem to return its stats.
+ */
+ private static final long EXTERNAL_STATS_SYNC_TIMEOUT_MILLIS = 2000;
+
private final Object mNetworkStatsLock = new Object();
@GuardedBy("mNetworkStatsLock")
private INetworkStatsService mNetworkStatsService;
@@ -327,11 +333,12 @@ public class StatsPullAtomService extends SystemService {
}
private void registerWifiBytesTransfer() {
int tagId = StatsLog.WIFI_BYTES_TRANSFER;
- PullAtomMetadata metaData = PullAtomMetadata.newBuilder()
- .setAdditiveFields(new int[] {2, 3, 4, 5}).build();
+ PullAtomMetadata metadata = PullAtomMetadata.newBuilder()
+ .setAdditiveFields(new int[] {2, 3, 4, 5})
+ .build();
mStatsManager.registerPullAtomCallback(
tagId,
- metaData,
+ metadata,
(atomTag, data) -> pullWifiBytesTransfer(atomTag, data),
Executors.newSingleThreadExecutor()
);
@@ -356,6 +363,7 @@ public class StatsPullAtomService extends SystemService {
addNetworkStats(atomTag, pulledData, stats, false);
} catch (RemoteException e) {
Slog.e(TAG, "Pulling netstats for wifi bytes has error", e);
+ return StatsManager.PULL_SKIP;
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -382,36 +390,224 @@ public class StatsPullAtomService extends SystemService {
}
}
+ /**
+ * Allows rollups per UID but keeping the set (foreground/background) slicing.
+ * Adapted from groupedByUid in frameworks/base/core/java/android/net/NetworkStats.java
+ */
+ private NetworkStats rollupNetworkStatsByFGBG(NetworkStats stats) {
+ final NetworkStats ret = new NetworkStats(stats.getElapsedRealtime(), 1);
+
+ final NetworkStats.Entry entry = new NetworkStats.Entry();
+ entry.iface = NetworkStats.IFACE_ALL;
+ entry.tag = NetworkStats.TAG_NONE;
+ entry.metered = NetworkStats.METERED_ALL;
+ entry.roaming = NetworkStats.ROAMING_ALL;
+
+ int size = stats.size();
+ NetworkStats.Entry recycle = new NetworkStats.Entry(); // Used for retrieving values
+ for (int i = 0; i < size; i++) {
+ stats.getValues(i, recycle);
+
+ // Skip specific tags, since already counted in TAG_NONE
+ if (recycle.tag != NetworkStats.TAG_NONE) continue;
+
+ entry.set = recycle.set; // Allows slicing by background/foreground
+ entry.uid = recycle.uid;
+ entry.rxBytes = recycle.rxBytes;
+ entry.rxPackets = recycle.rxPackets;
+ entry.txBytes = recycle.txBytes;
+ entry.txPackets = recycle.txPackets;
+ // Operations purposefully omitted since we don't use them for statsd.
+ ret.combineValues(entry);
+ }
+ return ret;
+ }
+
private void registerWifiBytesTransferBackground() {
- // No op.
+ int tagId = StatsLog.WIFI_BYTES_TRANSFER_BY_FG_BG;
+ PullAtomMetadata metadata = PullAtomMetadata.newBuilder()
+ .setAdditiveFields(new int[] {3, 4, 5, 6})
+ .build();
+ mStatsManager.registerPullAtomCallback(
+ tagId,
+ metadata,
+ (atomTag, data) -> pullWifiBytesTransferBackground(atomTag, data),
+ Executors.newSingleThreadExecutor()
+ );
}
- private void pullWifiBytesTransferBackground() {
- // No op.
+ private int pullWifiBytesTransferBackground(int atomTag, List<StatsEvent> pulledData) {
+ INetworkStatsService networkStatsService = getINetworkStatsService();
+ if (networkStatsService == null) {
+ Slog.e(TAG, "NetworkStats Service is not available!");
+ return StatsManager.PULL_SKIP;
+ }
+ long token = Binder.clearCallingIdentity();
+ try {
+ BatteryStatsInternal bs = LocalServices.getService(BatteryStatsInternal.class);
+ String[] ifaces = bs.getWifiIfaces();
+ if (ifaces.length == 0) {
+ return StatsManager.PULL_SKIP;
+ }
+ NetworkStats stats = rollupNetworkStatsByFGBG(
+ networkStatsService.getDetailedUidStats(ifaces));
+ addNetworkStats(atomTag, pulledData, stats, true);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Pulling netstats for wifi bytes w/ fg/bg has error", e);
+ return StatsManager.PULL_SKIP;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ return StatsManager.PULL_SUCCESS;
}
private void registerMobileBytesTransfer() {
- // No op.
+ int tagId = StatsLog.MOBILE_BYTES_TRANSFER;
+ PullAtomMetadata metadata = PullAtomMetadata.newBuilder()
+ .setAdditiveFields(new int[] {2, 3, 4, 5})
+ .build();
+ mStatsManager.registerPullAtomCallback(
+ tagId,
+ metadata,
+ (atomTag, data) -> pullMobileBytesTransfer(atomTag, data),
+ Executors.newSingleThreadExecutor()
+ );
}
- private void pullMobileBytesTransfer() {
- // No op.
+ private int pullMobileBytesTransfer(int atomTag, List<StatsEvent> pulledData) {
+ INetworkStatsService networkStatsService = getINetworkStatsService();
+ if (networkStatsService == null) {
+ Slog.e(TAG, "NetworkStats Service is not available!");
+ return StatsManager.PULL_SKIP;
+ }
+ long token = Binder.clearCallingIdentity();
+ try {
+ BatteryStatsInternal bs = LocalServices.getService(BatteryStatsInternal.class);
+ String[] ifaces = bs.getMobileIfaces();
+ if (ifaces.length == 0) {
+ return StatsManager.PULL_SKIP;
+ }
+ // Combine all the metrics per Uid into one record.
+ NetworkStats stats = networkStatsService.getDetailedUidStats(ifaces).groupedByUid();
+ addNetworkStats(atomTag, pulledData, stats, false);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Pulling netstats for mobile bytes has error", e);
+ return StatsManager.PULL_SKIP;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ return StatsManager.PULL_SUCCESS;
}
private void registerMobileBytesTransferBackground() {
- // No op.
+ int tagId = StatsLog.MOBILE_BYTES_TRANSFER_BY_FG_BG;
+ PullAtomMetadata metadata = PullAtomMetadata.newBuilder()
+ .setAdditiveFields(new int[] {3, 4, 5, 6})
+ .build();
+ mStatsManager.registerPullAtomCallback(
+ tagId,
+ metadata,
+ (atomTag, data) -> pullMobileBytesTransferBackground(atomTag, data),
+ Executors.newSingleThreadExecutor()
+ );
}
- private void pullMobileBytesTransferBackground() {
- // No op.
+ private int pullMobileBytesTransferBackground(int atomTag, List<StatsEvent> pulledData) {
+ INetworkStatsService networkStatsService = getINetworkStatsService();
+ if (networkStatsService == null) {
+ Slog.e(TAG, "NetworkStats Service is not available!");
+ return StatsManager.PULL_SKIP;
+ }
+ long token = Binder.clearCallingIdentity();
+ try {
+ BatteryStatsInternal bs = LocalServices.getService(BatteryStatsInternal.class);
+ String[] ifaces = bs.getMobileIfaces();
+ if (ifaces.length == 0) {
+ return StatsManager.PULL_SKIP;
+ }
+ NetworkStats stats = rollupNetworkStatsByFGBG(
+ networkStatsService.getDetailedUidStats(ifaces));
+ addNetworkStats(atomTag, pulledData, stats, true);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Pulling netstats for mobile bytes w/ fg/bg has error", e);
+ return StatsManager.PULL_SKIP;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ return StatsManager.PULL_SUCCESS;
}
private void registerBluetoothBytesTransfer() {
- // No op.
+ int tagId = StatsLog.BLUETOOTH_BYTES_TRANSFER;
+ PullAtomMetadata metadata = PullAtomMetadata.newBuilder()
+ .setAdditiveFields(new int[] {2, 3})
+ .build();
+ mStatsManager.registerPullAtomCallback(
+ tagId,
+ metadata,
+ (atomTag, data) -> pullBluetoothBytesTransfer(atomTag, data),
+ Executors.newSingleThreadExecutor()
+ );
}
- private void pullBluetoothBytesTransfer() {
- // No op.
+ /**
+ * Helper method to extract the Parcelable controller info from a
+ * SynchronousResultReceiver.
+ */
+ private static <T extends Parcelable> T awaitControllerInfo(
+ @Nullable SynchronousResultReceiver receiver) {
+ if (receiver == null) {
+ return null;
+ }
+
+ try {
+ final SynchronousResultReceiver.Result result =
+ receiver.awaitResult(EXTERNAL_STATS_SYNC_TIMEOUT_MILLIS);
+ if (result.bundle != null) {
+ // This is the final destination for the Bundle.
+ result.bundle.setDefusable(true);
+
+ final T data = result.bundle.getParcelable(RESULT_RECEIVER_CONTROLLER_KEY);
+ if (data != null) {
+ return data;
+ }
+ }
+ Slog.e(TAG, "no controller energy info supplied for " + receiver.getName());
+ } catch (TimeoutException e) {
+ Slog.w(TAG, "timeout reading " + receiver.getName() + " stats");
+ }
+ return null;
+ }
+
+ private synchronized BluetoothActivityEnergyInfo fetchBluetoothData() {
+ // TODO: Investigate whether the synchronized keyword is needed.
+ final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+ if (adapter != null) {
+ SynchronousResultReceiver bluetoothReceiver = new SynchronousResultReceiver(
+ "bluetooth");
+ adapter.requestControllerActivityEnergyInfo(bluetoothReceiver);
+ return awaitControllerInfo(bluetoothReceiver);
+ } else {
+ Slog.e(TAG, "Failed to get bluetooth adapter!");
+ return null;
+ }
+ }
+
+ private int pullBluetoothBytesTransfer(int atomTag, List<StatsEvent> pulledData) {
+ BluetoothActivityEnergyInfo info = fetchBluetoothData();
+ if (info == null || info.getUidTraffic() == null) {
+ return StatsManager.PULL_SKIP;
+ }
+ for (UidTraffic traffic : info.getUidTraffic()) {
+ StatsEvent e = StatsEvent.newBuilder()
+ .setAtomId(atomTag)
+ .writeInt(traffic.getUid())
+ .writeLong(traffic.getRxBytes())
+ .writeLong(traffic.getTxBytes())
+ .build();
+ pulledData.add(e);
+ }
+ return StatsManager.PULL_SUCCESS;
}
private void registerKernelWakelock() {
@@ -479,11 +675,31 @@ public class StatsPullAtomService extends SystemService {
}
private void registerBluetoothActivityInfo() {
- // No op.
+ int tagId = StatsLog.BLUETOOTH_ACTIVITY_INFO;
+ mStatsManager.registerPullAtomCallback(
+ tagId,
+ /* metadata */ null,
+ (atomTag, data) -> pullBluetoothActivityInfo(atomTag, data),
+ Executors.newSingleThreadExecutor()
+ );
}
- private void pullBluetoothActivityInfo() {
- // No op.
+ private int pullBluetoothActivityInfo(int atomTag, List<StatsEvent> pulledData) {
+ BluetoothActivityEnergyInfo info = fetchBluetoothData();
+ if (info == null) {
+ return StatsManager.PULL_SKIP;
+ }
+ StatsEvent e = StatsEvent.newBuilder()
+ .setAtomId(atomTag)
+ .writeLong(info.getTimeStamp())
+ .writeInt(info.getBluetoothStackState())
+ .writeLong(info.getControllerTxTimeMillis())
+ .writeLong(info.getControllerRxTimeMillis())
+ .writeLong(info.getControllerIdleTimeMillis())
+ .writeLong(info.getControllerEnergyUsed())
+ .build();
+ pulledData.add(e);
+ return StatsManager.PULL_SUCCESS;
}
private void registerSystemElapsedRealtime() {
@@ -695,11 +911,26 @@ public class StatsPullAtomService extends SystemService {
}
private void registerPowerProfile() {
- // No op.
+ int tagId = StatsLog.POWER_PROFILE;
+ mStatsManager.registerPullAtomCallback(
+ tagId,
+ /* PullAtomMetadata */ null,
+ (atomTag, data) -> pullPowerProfile(atomTag, data),
+ Executors.newSingleThreadExecutor()
+ );
}
- private void pullPowerProfile() {
- // No op.
+ private int pullPowerProfile(int atomTag, List<StatsEvent> pulledData) {
+ PowerProfile powerProfile = new PowerProfile(mContext);
+ ProtoOutputStream proto = new ProtoOutputStream();
+ powerProfile.dumpDebug(proto);
+ proto.flush();
+ StatsEvent e = StatsEvent.newBuilder()
+ .setAtomId(atomTag)
+ .writeByteArray(proto.getBytes())
+ .build();
+ pulledData.add(e);
+ return StatsManager.PULL_SUCCESS;
}
private void registerProcessCpuTime() {
diff --git a/services/core/jni/com_android_server_net_NetworkStatsService.cpp b/services/core/jni/com_android_server_net_NetworkStatsService.cpp
index 4696dd0bb88b..0275f3ea32f7 100644
--- a/services/core/jni/com_android_server_net_NetworkStatsService.cpp
+++ b/services/core/jni/com_android_server_net_NetworkStatsService.cpp
@@ -33,7 +33,6 @@
#include "bpf/BpfUtils.h"
#include "netdbpf/BpfNetworkStats.h"
-using android::bpf::Stats;
using android::bpf::bpfGetUidStats;
using android::bpf::bpfGetIfaceStats;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 6b81fdd2d270..485899ef05e3 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -23,7 +23,6 @@ import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
import static android.app.admin.DeviceAdminReceiver.EXTRA_TRANSFER_OWNERSHIP_ADMIN_EXTRAS_BUNDLE;
import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_USER;
import static android.app.admin.DevicePolicyManager.CODE_ACCOUNTS_NOT_EMPTY;
-import static android.app.admin.DevicePolicyManager.CODE_ADD_MANAGED_PROFILE_DISALLOWED;
import static android.app.admin.DevicePolicyManager.CODE_CANNOT_ADD_MANAGED_PROFILE;
import static android.app.admin.DevicePolicyManager.CODE_DEVICE_ADMIN_NOT_SUPPORTED;
import static android.app.admin.DevicePolicyManager.CODE_HAS_DEVICE_OWNER;
@@ -4118,6 +4117,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (mUserManager.hasUserRestriction(UserManager.DISALLOW_ADD_USER, userHandle)) {
mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_USER, false, userHandle);
}
+ // When a device owner is set, the system automatically restricts adding a managed profile.
+ // Remove this restriction when the device owner is cleared.
+ if (mUserManager.hasUserRestriction(UserManager.DISALLOW_ADD_MANAGED_PROFILE, userHandle)) {
+ mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_MANAGED_PROFILE, false,
+ userHandle);
+ }
}
/**
@@ -8056,10 +8061,19 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
updateDeviceOwnerLocked();
setDeviceOwnerSystemPropertyLocked();
- // TODO Send to system too?
- mInjector.binderWithCleanCallingIdentity(
- () -> sendOwnerChangedBroadcast(DevicePolicyManager.ACTION_DEVICE_OWNER_CHANGED,
- userId));
+ mInjector.binderWithCleanCallingIdentity(() -> {
+ // Restrict adding a managed profile when a device owner is set on the device.
+ // That is to prevent the co-existence of a managed profile and a device owner
+ // on the same device.
+ // Instead, the device may be provisioned with an organization-owned managed
+ // profile, such that the admin on that managed profile has extended management
+ // capabilities that can affect the entire device (but not access private data
+ // on the primary profile).
+ mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_MANAGED_PROFILE, true,
+ UserHandle.of(userId));
+ // TODO Send to system too?
+ sendOwnerChangedBroadcast(DevicePolicyManager.ACTION_DEVICE_OWNER_CHANGED, userId);
+ });
mDeviceAdminServiceController.startServiceForOwner(
admin.getPackageName(), userId, "set-device-owner");
@@ -8322,6 +8336,17 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
throw new IllegalArgumentException("Not active admin: " + who);
}
+ final int parentUserId = getProfileParentId(userHandle);
+ // When trying to set a profile owner on a new user, it may be that this user is
+ // a profile - but it may not be a managed profile if there's a restriction on the
+ // parent to add managed profiles (e.g. if the device has a device owner).
+ if (parentUserId != userHandle && mUserManager.hasUserRestriction(
+ UserManager.DISALLOW_ADD_MANAGED_PROFILE,
+ UserHandle.of(parentUserId))) {
+ Slog.i(LOG_TAG, "Cannot set profile owner because of restriction.");
+ return false;
+ }
+
if (isAdb()) {
// Log profile owner provisioning was started using adb.
MetricsLogger.action(mContext, PROVISIONING_ENTRY_POINT_ADB, LOG_TAG_PROFILE_OWNER);
@@ -12387,25 +12412,41 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final long ident = mInjector.binderClearCallingIdentity();
try {
final UserHandle callingUserHandle = UserHandle.of(callingUserId);
- final ComponentName ownerAdmin = getOwnerComponent(packageName, callingUserId);
- if (mUserManager.hasUserRestriction(UserManager.DISALLOW_ADD_MANAGED_PROFILE,
- callingUserHandle)) {
- // An admin can initiate provisioning if it has set the restriction.
- if (ownerAdmin == null || isAdminAffectedByRestriction(ownerAdmin,
- UserManager.DISALLOW_ADD_MANAGED_PROFILE, callingUserId)) {
- return CODE_ADD_MANAGED_PROFILE_DISALLOWED;
- }
- }
- boolean canRemoveProfile = true;
- if (mUserManager.hasUserRestriction(UserManager.DISALLOW_REMOVE_MANAGED_PROFILE,
- callingUserHandle)) {
- // We can remove a profile if the admin itself has set the restriction.
- if (ownerAdmin == null || isAdminAffectedByRestriction(ownerAdmin,
- UserManager.DISALLOW_REMOVE_MANAGED_PROFILE,
- callingUserId)) {
- canRemoveProfile = false;
- }
+ final boolean hasDeviceOwner;
+ synchronized (getLockObject()) {
+ hasDeviceOwner = getDeviceOwnerAdminLocked() != null;
+ }
+
+ final boolean addingProfileRestricted = mUserManager.hasUserRestriction(
+ UserManager.DISALLOW_ADD_MANAGED_PROFILE, callingUserHandle);
+
+ UserInfo parentUser = mUserManager.getProfileParent(callingUserId);
+ final boolean addingProfileRestrictedOnParent = (parentUser != null)
+ && mUserManager.hasUserRestriction(
+ UserManager.DISALLOW_ADD_MANAGED_PROFILE,
+ UserHandle.of(parentUser.id));
+
+ Slog.i(LOG_TAG, String.format(
+ "When checking for managed profile provisioning: Has device owner? %b, adding"
+ + " profile restricted? %b, adding profile restricted on parent? %b",
+ hasDeviceOwner, addingProfileRestricted, addingProfileRestrictedOnParent));
+
+ // If there's a device owner, the restriction on adding a managed profile must be set
+ // somewhere.
+ if (hasDeviceOwner && !addingProfileRestricted && !addingProfileRestrictedOnParent) {
+ Slog.wtf(LOG_TAG, "Has a device owner but no restriction on adding a profile.");
+ }
+
+ // Do not allow adding a managed profile if there's a restriction, either on the current
+ // user or its parent user.
+ if (addingProfileRestricted || addingProfileRestrictedOnParent) {
+ return CODE_CANNOT_ADD_MANAGED_PROFILE;
}
+ // If there's a restriction on removing the managed profile then we have to take it
+ // into account when checking whether more profiles can be added.
+ boolean canRemoveProfile =
+ !mUserManager.hasUserRestriction(UserManager.DISALLOW_REMOVE_MANAGED_PROFILE,
+ callingUserHandle);
if (!mUserManager.canAddMoreManagedProfiles(callingUserId, canRemoveProfile)) {
return CODE_CANNOT_ADD_MANAGED_PROFILE;
}
diff --git a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
index 2fb2021de200..e609adc2a067 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
@@ -16,7 +16,7 @@
package com.android.server;
-import static android.net.NetworkScoreManager.CACHE_FILTER_NONE;
+import static android.net.NetworkScoreManager.SCORE_FILTER_NONE;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
@@ -306,7 +306,7 @@ public class NetworkScoreServiceTest {
bindToScorer(true /*callerIsScorer*/);
mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI,
- mNetworkScoreCache, CACHE_FILTER_NONE);
+ mNetworkScoreCache, SCORE_FILTER_NONE);
mNetworkScoreService.updateScores(new ScoredNetwork[]{SCORED_NETWORK});
@@ -321,9 +321,9 @@ public class NetworkScoreServiceTest {
bindToScorer(true /*callerIsScorer*/);
mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI,
- mNetworkScoreCache, CACHE_FILTER_NONE);
+ mNetworkScoreCache, SCORE_FILTER_NONE);
mNetworkScoreService.registerNetworkScoreCache(
- NetworkKey.TYPE_WIFI, mNetworkScoreCache2, CACHE_FILTER_NONE);
+ NetworkKey.TYPE_WIFI, mNetworkScoreCache2, SCORE_FILTER_NONE);
// updateScores should update both caches
mNetworkScoreService.updateScores(new ScoredNetwork[]{SCORED_NETWORK});
@@ -378,7 +378,7 @@ public class NetworkScoreServiceTest {
bindToScorer(true /*callerIsScorer*/);
mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache,
- CACHE_FILTER_NONE);
+ SCORE_FILTER_NONE);
mNetworkScoreService.clearScores();
verify(mNetworkScoreCache).clearScores();
@@ -392,7 +392,7 @@ public class NetworkScoreServiceTest {
.thenReturn(PackageManager.PERMISSION_GRANTED);
mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache,
- CACHE_FILTER_NONE);
+ SCORE_FILTER_NONE);
mNetworkScoreService.clearScores();
verify(mNetworkScoreCache).clearScores();
@@ -472,7 +472,7 @@ public class NetworkScoreServiceTest {
try {
mNetworkScoreService.registerNetworkScoreCache(
- NetworkKey.TYPE_WIFI, mNetworkScoreCache, CACHE_FILTER_NONE);
+ NetworkKey.TYPE_WIFI, mNetworkScoreCache, SCORE_FILTER_NONE);
fail("SecurityException expected");
} catch (SecurityException e) {
// expected
@@ -615,7 +615,7 @@ public class NetworkScoreServiceTest {
new ArrayList<>(scoredNetworkList),
NetworkKey.TYPE_WIFI, mCurrentNetworkFilter, mScanResultsFilter);
- consumer.accept(mNetworkScoreCache, NetworkScoreManager.CACHE_FILTER_NONE);
+ consumer.accept(mNetworkScoreCache, NetworkScoreManager.SCORE_FILTER_NONE);
verify(mNetworkScoreCache).updateScores(scoredNetworkList);
verifyZeroInteractions(mCurrentNetworkFilter, mScanResultsFilter);
@@ -656,7 +656,7 @@ public class NetworkScoreServiceTest {
Collections.emptyList(),
NetworkKey.TYPE_WIFI, mCurrentNetworkFilter, mScanResultsFilter);
- consumer.accept(mNetworkScoreCache, NetworkScoreManager.CACHE_FILTER_NONE);
+ consumer.accept(mNetworkScoreCache, NetworkScoreManager.SCORE_FILTER_NONE);
verifyZeroInteractions(mNetworkScoreCache, mCurrentNetworkFilter, mScanResultsFilter);
}
@@ -673,7 +673,7 @@ public class NetworkScoreServiceTest {
List<ScoredNetwork> filteredList = new ArrayList<>(scoredNetworkList);
filteredList.remove(SCORED_NETWORK);
when(mCurrentNetworkFilter.apply(scoredNetworkList)).thenReturn(filteredList);
- consumer.accept(mNetworkScoreCache, NetworkScoreManager.CACHE_FILTER_CURRENT_NETWORK);
+ consumer.accept(mNetworkScoreCache, NetworkScoreManager.SCORE_FILTER_CURRENT_NETWORK);
verify(mNetworkScoreCache).updateScores(filteredList);
verifyZeroInteractions(mScanResultsFilter);
@@ -691,7 +691,7 @@ public class NetworkScoreServiceTest {
List<ScoredNetwork> filteredList = new ArrayList<>(scoredNetworkList);
filteredList.remove(SCORED_NETWORK);
when(mScanResultsFilter.apply(scoredNetworkList)).thenReturn(filteredList);
- consumer.accept(mNetworkScoreCache, NetworkScoreManager.CACHE_FILTER_SCAN_RESULTS);
+ consumer.accept(mNetworkScoreCache, NetworkScoreManager.SCORE_FILTER_SCAN_RESULTS);
verify(mNetworkScoreCache).updateScores(filteredList);
verifyZeroInteractions(mCurrentNetworkFilter);
diff --git a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
index 0f11566f512c..39a3aae767ea 100644
--- a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
@@ -212,7 +212,8 @@ public class AccountManagerServiceTest extends AndroidTestCase {
String[] list = new String[]{AccountManagerServiceTestFixtures.CALLER_PACKAGE};
when(mMockPackageManager.getPackagesForUid(anyInt())).thenReturn(list);
- Account[] accounts = mAms.getAccounts(null, mContext.getOpPackageName());
+ Account[] accounts = mAms.getAccountsAsUser(null,
+ UserHandle.getCallingUserId(), mContext.getOpPackageName());
Arrays.sort(accounts, new AccountSorter());
assertEquals(6, accounts.length);
assertEquals(a11, accounts[0]);
@@ -222,8 +223,8 @@ public class AccountManagerServiceTest extends AndroidTestCase {
assertEquals(a22, accounts[4]);
assertEquals(a32, accounts[5]);
- accounts = mAms.getAccounts(AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1,
- mContext.getOpPackageName());
+ accounts = mAms.getAccountsAsUser(AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1,
+ UserHandle.getCallingUserId(), mContext.getOpPackageName());
Arrays.sort(accounts, new AccountSorter());
assertEquals(3, accounts.length);
assertEquals(a11, accounts[0]);
@@ -232,8 +233,8 @@ public class AccountManagerServiceTest extends AndroidTestCase {
mAms.removeAccountInternal(a21);
- accounts = mAms.getAccounts(AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1,
- mContext.getOpPackageName());
+ accounts = mAms.getAccountsAsUser(AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1,
+ UserHandle.getCallingUserId(), mContext.getOpPackageName());
Arrays.sort(accounts, new AccountSorter());
assertEquals(2, accounts.length);
assertEquals(a11, accounts[0]);
@@ -373,7 +374,8 @@ public class AccountManagerServiceTest extends AndroidTestCase {
unlockSystemUser();
String[] list = new String[]{AccountManagerServiceTestFixtures.CALLER_PACKAGE};
when(mMockPackageManager.getPackagesForUid(anyInt())).thenReturn(list);
- Account[] accounts = mAms.getAccounts(null, mContext.getOpPackageName());
+ Account[] accounts = mAms.getAccountsAsUser(null, UserHandle.getCallingUserId(),
+ mContext.getOpPackageName());
assertEquals("1 account should be migrated", 1, accounts.length);
assertEquals(PreNTestDatabaseHelper.ACCOUNT_NAME, accounts[0].name);
assertEquals(PreNTestDatabaseHelper.ACCOUNT_PASSWORD, mAms.getPassword(accounts[0]));
@@ -2980,7 +2982,8 @@ public class AccountManagerServiceTest extends AndroidTestCase {
Log.d(TAG, logPrefix + " getAccounts started");
long ti = System.currentTimeMillis();
try {
- Account[] accounts = mAms.getAccounts(null, mContext.getOpPackageName());
+ Account[] accounts = mAms.getAccountsAsUser(null,
+ UserHandle.getCallingUserId(), mContext.getOpPackageName());
if (accounts == null || accounts.length != 1
|| !AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1.equals(
accounts[0].type)) {
@@ -3051,7 +3054,8 @@ public class AccountManagerServiceTest extends AndroidTestCase {
Log.d(TAG, logPrefix + " getAccounts started");
long ti = System.currentTimeMillis();
try {
- Account[] accounts = mAms.getAccounts(null, mContext.getOpPackageName());
+ Account[] accounts = mAms.getAccountsAsUser(null,
+ UserHandle.getCallingUserId(), mContext.getOpPackageName());
if (accounts == null || accounts.length != 1
|| !AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1.equals(
accounts[0].type)) {
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 21034d3de9b4..45729e5fd41f 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -34,6 +34,7 @@ import static com.android.server.testutils.TestUtils.assertExpectException;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyObject;
@@ -275,6 +276,29 @@ public class DevicePolicyManagerTest extends DpmTestBase {
}).when(getServices().userManager).getApplicationRestrictions(
anyString(), any(UserHandle.class));
+ // Emulate UserManager.setUserRestriction/getUserRestrictions
+ final Map<UserHandle, Bundle> userRestrictions = new HashMap<>();
+
+ doAnswer((Answer<Void>) invocation -> {
+ String key = (String) invocation.getArguments()[0];
+ boolean value = (Boolean) invocation.getArguments()[1];
+ UserHandle user = (UserHandle) invocation.getArguments()[2];
+ Bundle userBundle = userRestrictions.getOrDefault(user, new Bundle());
+ userBundle.putBoolean(key, value);
+
+ userRestrictions.put(user, userBundle);
+ return null;
+ }).when(getServices().userManager).setUserRestriction(
+ anyString(), anyBoolean(), any(UserHandle.class));
+
+ doAnswer((Answer<Boolean>) invocation -> {
+ String key = (String) invocation.getArguments()[0];
+ UserHandle user = (UserHandle) invocation.getArguments()[1];
+ Bundle userBundle = userRestrictions.getOrDefault(user, new Bundle());
+ return userBundle.getBoolean(key);
+ }).when(getServices().userManager).hasUserRestriction(
+ anyString(), any(UserHandle.class));
+
// Add the first secondary user.
getServices().addUser(DpmMockContext.CALLER_USER_HANDLE, 0,
UserManager.USER_TYPE_FULL_SECONDARY);
@@ -822,10 +846,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
final int MANAGED_PROFILE_ADMIN_UID =
UserHandle.getUid(MANAGED_PROFILE_USER_ID, DpmMockContext.SYSTEM_UID);
- // Setup device owner.
mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
mContext.packageName = admin1.getPackageName();
- setupDeviceOwner();
// Add a managed profile belonging to the system user.
addManagedProfile(admin1, MANAGED_PROFILE_ADMIN_UID, admin1);
@@ -833,18 +855,13 @@ public class DevicePolicyManagerTest extends DpmTestBase {
// Change the parent user's password.
dpm.reportPasswordChanged(UserHandle.USER_SYSTEM);
- // Both the device owner and the managed profile owner should receive this broadcast.
+ // The managed profile owner should receive this broadcast.
final Intent intent = new Intent(DeviceAdminReceiver.ACTION_PASSWORD_CHANGED);
intent.setComponent(admin1);
intent.putExtra(Intent.EXTRA_USER, UserHandle.of(UserHandle.USER_SYSTEM));
verify(mContext.spiedContext, times(1)).sendBroadcastAsUser(
MockUtils.checkIntent(intent),
- MockUtils.checkUserHandle(UserHandle.USER_SYSTEM),
- eq(null),
- any(Bundle.class));
- verify(mContext.spiedContext, times(1)).sendBroadcastAsUser(
- MockUtils.checkIntent(intent),
MockUtils.checkUserHandle(MANAGED_PROFILE_USER_ID),
eq(null),
any(Bundle.class));
@@ -864,12 +881,11 @@ public class DevicePolicyManagerTest extends DpmTestBase {
final int MANAGED_PROFILE_ADMIN_UID =
UserHandle.getUid(MANAGED_PROFILE_USER_ID, DpmMockContext.SYSTEM_UID);
- // Setup device owner.
+ // Configure system as having separate profile challenge.
mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
mContext.packageName = admin1.getPackageName();
doReturn(true).when(getServices().lockPatternUtils)
.isSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID);
- setupDeviceOwner();
// Add a managed profile belonging to the system user.
addManagedProfile(admin1, MANAGED_PROFILE_ADMIN_UID, admin1);
@@ -954,6 +970,10 @@ public class DevicePolicyManagerTest extends DpmTestBase {
verify(getServices().iactivityManager, times(1)).updateDeviceOwner(
eq(admin1.getPackageName()));
+ verify(getServices().userManager, times(1)).setUserRestriction(
+ eq(UserManager.DISALLOW_ADD_MANAGED_PROFILE),
+ eq(true), eq(UserHandle.SYSTEM));
+
verify(mContext.spiedContext, times(1)).sendBroadcastAsUser(
MockUtils.checkIntentAction(DevicePolicyManager.ACTION_DEVICE_OWNER_CHANGED),
MockUtils.checkUserHandle(UserHandle.USER_SYSTEM));
@@ -2005,12 +2025,11 @@ public class DevicePolicyManagerTest extends DpmTestBase {
assertNoDeviceOwnerRestrictions();
- // Initialize DPMS again and check that the user restriction wasn't enabled again.
reset(getServices().userManagerInternal);
- initializeDpms();
- assertTrue(dpm.isDeviceOwnerApp(admin1.getPackageName()));
- assertNotNull(dpms.getDeviceOwnerAdminLocked());
+ // Ensure the DISALLOW_REMOVE_MANAGED_PROFILES restriction doesn't show up as a
+ // restriction to the device owner.
+ dpm.addUserRestriction(admin1, UserManager.DISALLOW_REMOVE_MANAGED_PROFILE);
assertNoDeviceOwnerRestrictions();
}
@@ -3106,7 +3125,6 @@ public class DevicePolicyManagerTest extends DpmTestBase {
setup_nonSplitUser_withDo_primaryUser();
final int MANAGED_PROFILE_USER_ID = 18;
final int MANAGED_PROFILE_ADMIN_UID = UserHandle.getUid(MANAGED_PROFILE_USER_ID, 1308);
- addManagedProfile(admin1, MANAGED_PROFILE_ADMIN_UID, admin1);
when(getServices().userManager.canAddMoreManagedProfiles(UserHandle.USER_SYSTEM,
false /* we can't remove a managed profile */)).thenReturn(false);
when(getServices().userManager.canAddMoreManagedProfiles(UserHandle.USER_SYSTEM,
@@ -3158,41 +3176,16 @@ public class DevicePolicyManagerTest extends DpmTestBase {
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE, false);
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_FINANCED_DEVICE, false);
- // COMP mode is allowed.
+ // COMP mode NOT is allowed.
assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
- DevicePolicyManager.CODE_OK);
- assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, true);
+ DevicePolicyManager.CODE_CANNOT_ADD_MANAGED_PROFILE);
+ assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, false);
- // And other DPCs can also provision a managed profile (DO + BYOD case).
+ // And other DPCs can NOT provision a managed profile.
assertCheckProvisioningPreCondition(
DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
DpmMockContext.ANOTHER_PACKAGE_NAME,
- DevicePolicyManager.CODE_OK);
- assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, true,
- DpmMockContext.ANOTHER_PACKAGE_NAME, DpmMockContext.ANOTHER_UID);
- }
-
- public void testProvisioning_nonSplitUser_withDo_primaryUser_restrictedByDo() throws Exception {
- setup_nonSplitUser_withDo_primaryUser();
- mContext.packageName = admin1.getPackageName();
- mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
- // The DO should be allowed to initiate provisioning if it set the restriction itself, but
- // other packages should be forbidden.
- when(getServices().userManager.hasUserRestriction(
- eq(UserManager.DISALLOW_ADD_MANAGED_PROFILE),
- eq(UserHandle.getUserHandleForUid(mContext.binder.callingUid))))
- .thenReturn(true);
- when(getServices().userManager.getUserRestrictionSource(
- eq(UserManager.DISALLOW_ADD_MANAGED_PROFILE),
- eq(UserHandle.getUserHandleForUid(mContext.binder.callingUid))))
- .thenReturn(UserManager.RESTRICTION_SOURCE_DEVICE_OWNER);
- assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
- DevicePolicyManager.CODE_OK);
- assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, true);
- assertCheckProvisioningPreCondition(
- DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
- DpmMockContext.ANOTHER_PACKAGE_NAME,
- DevicePolicyManager.CODE_ADD_MANAGED_PROFILE_DISALLOWED);
+ DevicePolicyManager.CODE_CANNOT_ADD_MANAGED_PROFILE);
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, false,
DpmMockContext.ANOTHER_PACKAGE_NAME, DpmMockContext.ANOTHER_UID);
}
@@ -3213,31 +3206,46 @@ public class DevicePolicyManagerTest extends DpmTestBase {
eq(UserHandle.getUserHandleForUid(mContext.binder.callingUid))))
.thenReturn(UserManager.RESTRICTION_SOURCE_SYSTEM);
assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
- DevicePolicyManager.CODE_ADD_MANAGED_PROFILE_DISALLOWED);
+ DevicePolicyManager.CODE_CANNOT_ADD_MANAGED_PROFILE);
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, false);
assertCheckProvisioningPreCondition(
DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
DpmMockContext.ANOTHER_PACKAGE_NAME,
- DevicePolicyManager.CODE_ADD_MANAGED_PROFILE_DISALLOWED);
+ DevicePolicyManager.CODE_CANNOT_ADD_MANAGED_PROFILE);
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, false,
DpmMockContext.ANOTHER_PACKAGE_NAME, DpmMockContext.ANOTHER_UID);
}
- public void testCheckProvisioningPreCondition_nonSplitUser_comp() throws Exception {
+ public void testCheckCannotSetProfileOwnerWithDeviceOwner() throws Exception {
+ setup_nonSplitUser_withDo_primaryUser();
+ final int managedProfileUserId = 18;
+ final int managedProfileAdminUid = UserHandle.getUid(managedProfileUserId, 1308);
+
+ final int userId = UserHandle.getUserId(managedProfileAdminUid);
+ getServices().addUser(userId, 0, UserManager.USER_TYPE_PROFILE_MANAGED,
+ UserHandle.USER_SYSTEM);
+ mContext.callerPermissions.addAll(OWNER_SETUP_PERMISSIONS);
+ setUpPackageManagerForFakeAdmin(admin1, managedProfileAdminUid, admin1);
+ dpm.setActiveAdmin(admin1, false, userId);
+ assertFalse(dpm.setProfileOwner(admin1, null, userId));
+ mContext.callerPermissions.removeAll(OWNER_SETUP_PERMISSIONS);
+ }
+
+ public void testCheckProvisioningPreCondition_nonSplitUser_attemptingComp() throws Exception {
setup_nonSplitUser_withDo_primaryUser_ManagedProfile();
mContext.packageName = admin1.getPackageName();
mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
// We can delete the managed profile to create a new one, so provisioning is allowed.
assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
- DevicePolicyManager.CODE_OK);
- assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, true);
+ DevicePolicyManager.CODE_CANNOT_ADD_MANAGED_PROFILE);
+ assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, false);
assertCheckProvisioningPreCondition(
DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
DpmMockContext.ANOTHER_PACKAGE_NAME,
- DevicePolicyManager.CODE_OK);
- assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, true,
+ DevicePolicyManager.CODE_CANNOT_ADD_MANAGED_PROFILE);
+ assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, false,
DpmMockContext.ANOTHER_PACKAGE_NAME, DpmMockContext.ANOTHER_UID);
}
@@ -3265,8 +3273,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
// But the device owner can still do it because it has set the restriction itself.
assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
- DevicePolicyManager.CODE_OK);
- assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, true);
+ DevicePolicyManager.CODE_CANNOT_ADD_MANAGED_PROFILE);
+ assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, false);
}
private void setup_splitUser_firstBoot_systemUser() throws Exception {
@@ -3475,6 +3483,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
when(getServices().ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0))
.thenReturn(true);
when(getServices().userManagerForMock.isSplitSystemUser()).thenReturn(true);
+ when(getServices().userManager.getProfileParent(DpmMockContext.CALLER_USER_HANDLE))
+ .thenReturn(new UserInfo(UserHandle.USER_SYSTEM, "user system", 0));
when(getServices().userManager.canAddMoreManagedProfiles(DpmMockContext.CALLER_USER_HANDLE,
true)).thenReturn(true);
setUserSetupCompleteForUser(false, DpmMockContext.CALLER_USER_HANDLE);
@@ -3487,7 +3497,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
setup_provisionManagedProfileWithDeviceOwner_primaryUser();
setUpPackageManagerForAdmin(admin1, mContext.binder.callingUid);
mContext.packageName = admin1.getPackageName();
- assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, true);
+ assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, false);
}
public void testCheckProvisioningPreCondition_provisionManagedProfileWithDeviceOwner_primaryUser()
@@ -3495,9 +3505,9 @@ public class DevicePolicyManagerTest extends DpmTestBase {
setup_provisionManagedProfileWithDeviceOwner_primaryUser();
mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
- // COMP mode is allowed.
+ // COMP mode is NOT allowed.
assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
- DevicePolicyManager.CODE_OK);
+ DevicePolicyManager.CODE_CANNOT_ADD_MANAGED_PROFILE);
}
private void setup_provisionManagedProfileCantRemoveUser_primaryUser() throws Exception {
@@ -4014,11 +4024,6 @@ public class DevicePolicyManagerTest extends DpmTestBase {
List<UserHandle> targetUsers = dpm.getBindDeviceAdminTargetUsers(admin1);
MoreAsserts.assertEmpty(targetUsers);
- // Setup a managed profile managed by the same admin.
- final int MANAGED_PROFILE_USER_ID = 15;
- final int MANAGED_PROFILE_ADMIN_UID = UserHandle.getUid(MANAGED_PROFILE_USER_ID, 20456);
- addManagedProfile(admin1, MANAGED_PROFILE_ADMIN_UID, admin1);
-
// Add a secondary user, it should never talk with.
final int ANOTHER_USER_ID = 36;
getServices().addUser(ANOTHER_USER_ID, 0, UserManager.USER_TYPE_FULL_SECONDARY);
@@ -4028,30 +4033,11 @@ public class DevicePolicyManagerTest extends DpmTestBase {
targetUsers = dpm.getBindDeviceAdminTargetUsers(admin1);
MoreAsserts.assertEmpty(targetUsers);
- mContext.binder.callingUid = MANAGED_PROFILE_ADMIN_UID;
- targetUsers = dpm.getBindDeviceAdminTargetUsers(admin1);
- MoreAsserts.assertEmpty(targetUsers);
-
// Setting affiliation ids
final Set<String> userAffiliationIds = Collections.singleton("some.affiliation-id");
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
dpm.setAffiliationIds(admin1, userAffiliationIds);
- mContext.binder.callingUid = MANAGED_PROFILE_ADMIN_UID;
- dpm.setAffiliationIds(admin1, userAffiliationIds);
-
- // Calling from device owner admin, the result list should just contain the managed
- // profile user id.
- mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
- targetUsers = dpm.getBindDeviceAdminTargetUsers(admin1);
- MoreAsserts.assertContentsInAnyOrder(targetUsers, UserHandle.of(MANAGED_PROFILE_USER_ID));
-
- // Calling from managed profile admin, the result list should just contain the system
- // user id.
- mContext.binder.callingUid = MANAGED_PROFILE_ADMIN_UID;
- targetUsers = dpm.getBindDeviceAdminTargetUsers(admin1);
- MoreAsserts.assertContentsInAnyOrder(targetUsers, UserHandle.SYSTEM);
-
// Changing affiliation ids in one
dpm.setAffiliationIds(admin1, Collections.singleton("some-different-affiliation-id"));
@@ -4065,38 +4051,6 @@ public class DevicePolicyManagerTest extends DpmTestBase {
MoreAsserts.assertEmpty(targetUsers);
}
- public void testGetBindDeviceAdminTargetUsers_differentPackage() throws Exception {
- // Setup a device owner.
- mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
- setupDeviceOwner();
-
- // Set up a managed profile managed by different package.
- final int MANAGED_PROFILE_USER_ID = 15;
- final int MANAGED_PROFILE_ADMIN_UID = UserHandle.getUid(MANAGED_PROFILE_USER_ID, 20456);
- final ComponentName adminDifferentPackage =
- new ComponentName("another.package", "whatever.class");
- addManagedProfile(adminDifferentPackage, MANAGED_PROFILE_ADMIN_UID, admin2);
-
- // Setting affiliation ids
- final Set<String> userAffiliationIds = Collections.singleton("some-affiliation-id");
- dpm.setAffiliationIds(admin1, userAffiliationIds);
-
- mContext.binder.callingUid = MANAGED_PROFILE_ADMIN_UID;
- dpm.setAffiliationIds(adminDifferentPackage, userAffiliationIds);
-
- // Calling from device owner admin, we should get zero bind device admin target users as
- // their packages are different.
- mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
- List<UserHandle> targetUsers = dpm.getBindDeviceAdminTargetUsers(admin1);
- MoreAsserts.assertEmpty(targetUsers);
-
- // Calling from managed profile admin, we should still get zero target users for the same
- // reason.
- mContext.binder.callingUid = MANAGED_PROFILE_ADMIN_UID;
- targetUsers = dpm.getBindDeviceAdminTargetUsers(adminDifferentPackage);
- MoreAsserts.assertEmpty(targetUsers);
- }
-
private void verifyLockTaskState(int userId) throws Exception {
verifyLockTaskState(userId, new String[0],
DevicePolicyManager.LOCK_TASK_FEATURE_GLOBAL_ACTIONS);
@@ -4133,79 +4087,6 @@ public class DevicePolicyManagerTest extends DpmTestBase {
() -> dpm.setLockTaskFeatures(who, flags));
}
- public void testLockTaskPolicyAllowedForAffiliatedUsers() throws Exception {
- // Setup a device owner.
- mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
- setupDeviceOwner();
- // Lock task policy is updated when loading user data.
- verifyLockTaskState(UserHandle.USER_SYSTEM);
-
- // Set up a managed profile managed by different package (package name shouldn't matter)
- final int MANAGED_PROFILE_USER_ID = 15;
- final int MANAGED_PROFILE_ADMIN_UID = UserHandle.getUid(MANAGED_PROFILE_USER_ID, 20456);
- final ComponentName adminDifferentPackage =
- new ComponentName("another.package", "whatever.class");
- addManagedProfile(adminDifferentPackage, MANAGED_PROFILE_ADMIN_UID, admin2);
- verifyLockTaskState(MANAGED_PROFILE_USER_ID);
-
- // Setup a PO on the secondary user
- mContext.binder.callingUid = DpmMockContext.CALLER_UID;
- setAsProfileOwner(admin3);
- verifyLockTaskState(DpmMockContext.CALLER_USER_HANDLE);
-
- // The DO can still set lock task packages
- final String[] doPackages = {"doPackage1", "doPackage2"};
- final int flags = DevicePolicyManager.LOCK_TASK_FEATURE_NOTIFICATIONS
- | DevicePolicyManager.LOCK_TASK_FEATURE_HOME
- | DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW;
- verifyCanSetLockTask(DpmMockContext.CALLER_SYSTEM_USER_UID, UserHandle.USER_SYSTEM, admin1, doPackages, flags);
-
- final String[] secondaryPoPackages = {"secondaryPoPackage1", "secondaryPoPackage2"};
- final int secondaryPoFlags = DevicePolicyManager.LOCK_TASK_FEATURE_NOTIFICATIONS
- | DevicePolicyManager.LOCK_TASK_FEATURE_HOME
- | DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW;
- verifyCanNotSetLockTask(DpmMockContext.CALLER_UID, admin3, secondaryPoPackages, secondaryPoFlags);
-
- // Managed profile is unaffiliated - shouldn't be able to setLockTaskPackages.
- mContext.binder.callingUid = MANAGED_PROFILE_ADMIN_UID;
- final String[] poPackages = {"poPackage1", "poPackage2"};
- final int poFlags = DevicePolicyManager.LOCK_TASK_FEATURE_NOTIFICATIONS
- | DevicePolicyManager.LOCK_TASK_FEATURE_HOME
- | DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW;
- verifyCanNotSetLockTask(MANAGED_PROFILE_ADMIN_UID, adminDifferentPackage, poPackages, poFlags);
-
- // Setting same affiliation ids
- final Set<String> userAffiliationIds = Collections.singleton("some-affiliation-id");
- mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
- dpm.setAffiliationIds(admin1, userAffiliationIds);
-
- mContext.binder.callingUid = MANAGED_PROFILE_ADMIN_UID;
- dpm.setAffiliationIds(adminDifferentPackage, userAffiliationIds);
-
- // Now the managed profile can set lock task packages.
- dpm.setLockTaskPackages(adminDifferentPackage, poPackages);
- MoreAsserts.assertEquals(poPackages, dpm.getLockTaskPackages(adminDifferentPackage));
- assertTrue(dpm.isLockTaskPermitted("poPackage1"));
- assertFalse(dpm.isLockTaskPermitted("doPackage2"));
- // And it can set lock task features.
- dpm.setLockTaskFeatures(adminDifferentPackage, poFlags);
- verifyLockTaskState(MANAGED_PROFILE_USER_ID, poPackages, poFlags);
-
- // Unaffiliate the profile, lock task mode no longer available on the profile.
- dpm.setAffiliationIds(adminDifferentPackage, Collections.emptySet());
- assertFalse(dpm.isLockTaskPermitted("poPackage1"));
- // Lock task packages cleared when loading user data and when the user becomes unaffiliated.
- verify(getServices().iactivityManager, times(2)).updateLockTaskPackages(
- MANAGED_PROFILE_USER_ID, new String[0]);
- verify(getServices().iactivityTaskManager, times(2)).updateLockTaskFeatures(
- MANAGED_PROFILE_USER_ID, DevicePolicyManager.LOCK_TASK_FEATURE_NONE);
-
- // Verify that lock task packages were not cleared for the DO
- mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
- assertTrue(dpm.isLockTaskPermitted("doPackage1"));
-
- }
-
public void testLockTaskPolicyForProfileOwner() throws Exception {
// Setup a PO
mContext.binder.callingUid = DpmMockContext.CALLER_UID;
diff --git a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
index 1dd7e64690c7..6aca58f400b3 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
@@ -23,7 +23,8 @@ import static android.app.usage.UsageEvents.Event.SLICE_PINNED_PRIV;
import static android.app.usage.UsageEvents.Event.SYSTEM_INTERACTION;
import static android.app.usage.UsageEvents.Event.USER_INTERACTION;
import static android.app.usage.UsageStatsManager.REASON_MAIN_DEFAULT;
-import static android.app.usage.UsageStatsManager.REASON_MAIN_FORCED;
+import static android.app.usage.UsageStatsManager.REASON_MAIN_FORCED_BY_SYSTEM;
+import static android.app.usage.UsageStatsManager.REASON_MAIN_FORCED_BY_USER;
import static android.app.usage.UsageStatsManager.REASON_MAIN_PREDICTED;
import static android.app.usage.UsageStatsManager.REASON_MAIN_TIMEOUT;
import static android.app.usage.UsageStatsManager.REASON_MAIN_USAGE;
@@ -501,12 +502,18 @@ public class AppStandbyControllerTests {
// Can force to NEVER
mInjector.mElapsedRealtime = HOUR_MS;
mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_NEVER,
- REASON_MAIN_FORCED);
+ REASON_MAIN_FORCED_BY_USER);
assertEquals(STANDBY_BUCKET_NEVER, getStandbyBucket(mController, PACKAGE_1));
- // Prediction can't override FORCED reason
+ // Prediction can't override FORCED reasons
+ mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE,
+ REASON_MAIN_FORCED_BY_SYSTEM);
+ mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET,
+ REASON_MAIN_PREDICTED);
+ assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1));
+
mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT,
- REASON_MAIN_FORCED);
+ REASON_MAIN_FORCED_BY_USER);
mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET,
REASON_MAIN_PREDICTED);
assertEquals(STANDBY_BUCKET_FREQUENT, getStandbyBucket(mController, PACKAGE_1));
@@ -631,7 +638,7 @@ public class AppStandbyControllerTests {
mInjector.mElapsedRealtime = 1 * RARE_THRESHOLD + 100;
// Make sure app is in NEVER bucket
mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_NEVER,
- REASON_MAIN_FORCED);
+ REASON_MAIN_FORCED_BY_USER);
mController.checkIdleStates(USER_ID);
assertBucket(STANDBY_BUCKET_NEVER);
diff --git a/telecomm/TEST_MAPPING b/telecomm/TEST_MAPPING
new file mode 100644
index 000000000000..d58566673eec
--- /dev/null
+++ b/telecomm/TEST_MAPPING
@@ -0,0 +1,29 @@
+{
+ "presubmit": [
+ {
+ "name": "TeleServiceTests",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
+ },
+ {
+ "name": "TelecomUnitTests",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
+ },
+ {
+ "name": "TelephonyProviderTests",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
+ }
+ ]
+}
+
diff --git a/telephony/TEST_MAPPING b/telephony/TEST_MAPPING
new file mode 100644
index 000000000000..d58566673eec
--- /dev/null
+++ b/telephony/TEST_MAPPING
@@ -0,0 +1,29 @@
+{
+ "presubmit": [
+ {
+ "name": "TeleServiceTests",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
+ },
+ {
+ "name": "TelecomUnitTests",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
+ },
+ {
+ "name": "TelephonyProviderTests",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
+ }
+ ]
+}
+
diff --git a/telephony/java/android/telephony/PreciseDataConnectionState.java b/telephony/java/android/telephony/PreciseDataConnectionState.java
index 31434c1d2adf..5e2e554b7764 100644
--- a/telephony/java/android/telephony/PreciseDataConnectionState.java
+++ b/telephony/java/android/telephony/PreciseDataConnectionState.java
@@ -20,6 +20,9 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
+import android.compat.Compatibility;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledAfter;
import android.compat.annotation.UnsupportedAppUsage;
import android.net.LinkProperties;
import android.os.Build;
@@ -31,8 +34,6 @@ import android.telephony.Annotation.DataState;
import android.telephony.Annotation.NetworkType;
import android.telephony.data.ApnSetting;
-import dalvik.system.VMRuntime;
-
import java.util.Objects;
@@ -134,6 +135,13 @@ public final class PreciseDataConnectionState implements Parcelable {
}
/**
+ * To check the SDK version for {@link PreciseDataConnectionState#getDataConnectionState}.
+ */
+ @ChangeId
+ @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.R)
+ private static final long GET_DATA_CONNECTION_STATE_CODE_CHANGE = 147600208L;
+
+ /**
* Returns the state of data connection that supported the apn types returned by
* {@link #getDataConnectionApnTypeBitMask()}
*
@@ -144,7 +152,7 @@ public final class PreciseDataConnectionState implements Parcelable {
@SystemApi
public @DataState int getDataConnectionState() {
if (mState == TelephonyManager.DATA_DISCONNECTING
- && VMRuntime.getRuntime().getTargetSdkVersion() < Build.VERSION_CODES.R) {
+ && !Compatibility.isChangeEnabled(GET_DATA_CONNECTION_STATE_CODE_CHANGE)) {
return TelephonyManager.DATA_CONNECTED;
}
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index da0ac39fe1d3..8ed4ee594d73 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -281,6 +281,42 @@ public final class SmsManager {
*/
public static final int SMS_MESSAGE_PERIOD_NOT_SPECIFIED = -1;
+ /** @hide */
+ @IntDef(prefix = { "PREMIUM_SMS_CONSENT" }, value = {
+ SmsManager.PREMIUM_SMS_CONSENT_UNKNOWN,
+ SmsManager.PREMIUM_SMS_CONSENT_ASK_USER,
+ SmsManager.PREMIUM_SMS_CONSENT_NEVER_ALLOW,
+ SmsManager.PREMIUM_SMS_CONSENT_ALWAYS_ALLOW
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface PremiumSmsConsent {}
+
+ /** Premium SMS Consent for the package is unknown. This indicates that the user
+ * has not set a permission for this package, because this package has never tried
+ * to send a premium SMS.
+ * @hide
+ */
+ @SystemApi
+ public static final int PREMIUM_SMS_CONSENT_UNKNOWN = 0;
+
+ /** Default premium SMS Consent (ask user for each premium SMS sent).
+ * @hide
+ */
+ @SystemApi
+ public static final int PREMIUM_SMS_CONSENT_ASK_USER = 1;
+
+ /** Premium SMS Consent when the owner has denied the app from sending premium SMS.
+ * @hide
+ */
+ @SystemApi
+ public static final int PREMIUM_SMS_CONSENT_NEVER_ALLOW = 2;
+
+ /** Premium SMS Consent when the owner has allowed the app to send premium SMS.
+ * @hide
+ */
+ @SystemApi
+ public static final int PREMIUM_SMS_CONSENT_ALWAYS_ALLOW = 3;
+
// result of asking the user for a subscription to perform an operation.
private interface SubscriptionResolverResult {
void onSuccess(int subId);
@@ -744,7 +780,11 @@ public final class SmsManager {
"Invalid pdu format. format must be either 3gpp or 3gpp2");
}
try {
- ISms iSms = TelephonyManager.getSmsService();
+ ISms iSms = ISms.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSmsServiceRegisterer()
+ .get());
if (iSms != null) {
iSms.injectSmsPduForSubscriber(
getSubscriptionId(), pdu, format, receivedIntent);
@@ -1567,7 +1607,7 @@ public final class SmsManager {
* the service does not exist.
*/
private static ISms getISmsServiceOrThrow() {
- ISms iSms = TelephonyManager.getSmsService();
+ ISms iSms = getISmsService();
if (iSms == null) {
throw new UnsupportedOperationException("Sms is not supported");
}
@@ -1575,7 +1615,11 @@ public final class SmsManager {
}
private static ISms getISmsService() {
- return TelephonyManager.getSmsService();
+ return ISms.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSmsServiceRegisterer()
+ .get());
}
/**
@@ -2009,7 +2053,11 @@ public final class SmsManager {
public boolean isSMSPromptEnabled() {
ISms iSms = null;
try {
- iSms = TelephonyManager.getSmsService();
+ iSms = ISms.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSmsServiceRegisterer()
+ .get());
return iSms.isSMSPromptEnabled();
} catch (RemoteException ex) {
return false;
@@ -2857,4 +2905,53 @@ public final class SmsManager {
}
return false;
}
+
+ /**
+ * Gets the premium SMS permission for the specified package. If the package has never
+ * been seen before, the default {@link SmsManager#PREMIUM_SMS_PERMISSION_ASK_USER}
+ * will be returned.
+ * @param packageName the name of the package to query permission
+ * @return one of {@link SmsManager#PREMIUM_SMS_CONSENT_UNKNOWN},
+ * {@link SmsManager#PREMIUM_SMS_CONSENT_ASK_USER},
+ * {@link SmsManager#PREMIUM_SMS_CONSENT_NEVER_ALLOW}, or
+ * {@link SmsManager#PREMIUM_SMS_CONSENT_ALWAYS_ALLOW}
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ public @PremiumSmsConsent int getPremiumSmsConsent(@NonNull String packageName) {
+ int permission = 0;
+ try {
+ ISms iSms = getISmsService();
+ if (iSms != null) {
+ permission = iSms.getPremiumSmsPermission(packageName);
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "getPremiumSmsPermission() RemoteException", e);
+ }
+ return permission;
+ }
+
+ /**
+ * Sets the premium SMS permission for the specified package and save the value asynchronously
+ * to persistent storage.
+ * @param packageName the name of the package to set permission
+ * @param permission one of {@link SmsManager#PREMIUM_SMS_CONSENT_ASK_USER},
+ * {@link SmsManager#PREMIUM_SMS_CONSENT_NEVER_ALLOW}, or
+ * {@link SmsManager#PREMIUM_SMS_CONSENT_ALWAYS_ALLOW}
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ public void setPremiumSmsConsent(
+ @NonNull String packageName, @PremiumSmsConsent int permission) {
+ try {
+ ISms iSms = getISmsService();
+ if (iSms != null) {
+ iSms.setPremiumSmsPermission(packageName, permission);
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "setPremiumSmsPermission() RemoteException", e);
+ }
+ }
}
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index cb4462f88581..36f541f0a81d 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -16,8 +16,6 @@
package android.telephony;
-import com.android.telephony.Rlog;
-
import static android.net.NetworkPolicyManager.OVERRIDE_CONGESTED;
import static android.net.NetworkPolicyManager.OVERRIDE_UNMETERED;
@@ -67,6 +65,7 @@ import com.android.internal.telephony.ISub;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.util.HandlerExecutor;
import com.android.internal.util.Preconditions;
+import com.android.telephony.Rlog;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -1146,7 +1145,11 @@ public class SubscriptionManager {
SubscriptionInfo subInfo = null;
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
subInfo = iSub.getActiveSubscriptionInfo(subId, mContext.getOpPackageName(),
mContext.getFeatureId());
@@ -1180,7 +1183,11 @@ public class SubscriptionManager {
SubscriptionInfo result = null;
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
result = iSub.getActiveSubscriptionInfoForIccId(iccId, mContext.getOpPackageName(),
mContext.getFeatureId());
@@ -1214,7 +1221,11 @@ public class SubscriptionManager {
SubscriptionInfo result = null;
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
result = iSub.getActiveSubscriptionInfoForSimSlotIndex(slotIndex,
mContext.getOpPackageName(), mContext.getFeatureId());
@@ -1238,7 +1249,11 @@ public class SubscriptionManager {
List<SubscriptionInfo> result = null;
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
result = iSub.getAllSubInfoList(mContext.getOpPackageName(),
mContext.getFeatureId());
@@ -1319,7 +1334,11 @@ public class SubscriptionManager {
List<SubscriptionInfo> activeList = null;
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
activeList = iSub.getActiveSubscriptionInfoList(mContext.getOpPackageName(),
mContext.getFeatureId());
@@ -1370,7 +1389,11 @@ public class SubscriptionManager {
List<SubscriptionInfo> result = null;
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
result = iSub.getAvailableSubscriptionInfoList(mContext.getOpPackageName(),
mContext.getFeatureId());
@@ -1409,7 +1432,11 @@ public class SubscriptionManager {
List<SubscriptionInfo> result = null;
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
result = iSub.getAccessibleSubscriptionInfoList(mContext.getOpPackageName());
}
@@ -1438,7 +1465,11 @@ public class SubscriptionManager {
public void requestEmbeddedSubscriptionInfoListRefresh() {
int cardId = TelephonyManager.from(mContext).getCardIdForDefaultEuicc();
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
iSub.requestEmbeddedSubscriptionInfoListRefresh(cardId);
}
@@ -1467,7 +1498,11 @@ public class SubscriptionManager {
@SystemApi
public void requestEmbeddedSubscriptionInfoListRefresh(int cardId) {
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
iSub.requestEmbeddedSubscriptionInfoListRefresh(cardId);
}
@@ -1488,7 +1523,11 @@ public class SubscriptionManager {
int result = 0;
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
result = iSub.getAllSubInfoCount(mContext.getOpPackageName(),
mContext.getFeatureId());
@@ -1517,7 +1556,11 @@ public class SubscriptionManager {
int result = 0;
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
result = iSub.getActiveSubInfoCount(mContext.getOpPackageName(),
mContext.getFeatureId());
@@ -1538,7 +1581,11 @@ public class SubscriptionManager {
int result = 0;
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
result = iSub.getActiveSubInfoCountMax();
}
@@ -1595,7 +1642,11 @@ public class SubscriptionManager {
}
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub == null) {
Log.e(LOG_TAG, "[addSubscriptionInfoRecord]- ISub service is null");
return;
@@ -1629,7 +1680,11 @@ public class SubscriptionManager {
}
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub == null) {
Log.e(LOG_TAG, "[removeSubscriptionInfoRecord]- ISub service is null");
return;
@@ -1732,7 +1787,11 @@ public class SubscriptionManager {
int result = INVALID_SIM_SLOT_INDEX;
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
result = iSub.getSlotIndex(subscriptionId);
}
@@ -1766,7 +1825,11 @@ public class SubscriptionManager {
int[] subId = null;
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
subId = iSub.getSubId(slotIndex);
}
@@ -1790,7 +1853,11 @@ public class SubscriptionManager {
int result = INVALID_PHONE_INDEX;
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
result = iSub.getPhoneId(subId);
}
@@ -1824,7 +1891,11 @@ public class SubscriptionManager {
int subId = INVALID_SUBSCRIPTION_ID;
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
subId = iSub.getDefaultSubId();
}
@@ -1847,7 +1918,11 @@ public class SubscriptionManager {
int subId = INVALID_SUBSCRIPTION_ID;
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
subId = iSub.getDefaultVoiceSubId();
}
@@ -1877,7 +1952,11 @@ public class SubscriptionManager {
public void setDefaultVoiceSubscriptionId(int subscriptionId) {
if (VDBG) logd("setDefaultVoiceSubId sub id = " + subscriptionId);
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
iSub.setDefaultVoiceSubId(subscriptionId);
}
@@ -1925,7 +2004,11 @@ public class SubscriptionManager {
int subId = INVALID_SUBSCRIPTION_ID;
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
subId = iSub.getDefaultSmsSubId();
}
@@ -1951,7 +2034,11 @@ public class SubscriptionManager {
public void setDefaultSmsSubId(int subscriptionId) {
if (VDBG) logd("setDefaultSmsSubId sub id = " + subscriptionId);
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
iSub.setDefaultSmsSubId(subscriptionId);
}
@@ -1989,7 +2076,11 @@ public class SubscriptionManager {
int subId = INVALID_SUBSCRIPTION_ID;
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
subId = iSub.getDefaultDataSubId();
}
@@ -2015,7 +2106,11 @@ public class SubscriptionManager {
public void setDefaultDataSubId(int subscriptionId) {
if (VDBG) logd("setDataSubscription sub id = " + subscriptionId);
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
iSub.setDefaultDataSubId(subscriptionId);
}
@@ -2046,7 +2141,11 @@ public class SubscriptionManager {
/** @hide */
public void clearSubscriptionInfo() {
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
iSub.clearSubInfo();
}
@@ -2140,10 +2239,9 @@ public class SubscriptionManager {
@UnsupportedAppUsage
public static void putPhoneIdAndSubIdExtra(Intent intent, int phoneId, int subId) {
if (VDBG) logd("putPhoneIdAndSubIdExtra: phoneId=" + phoneId + " subId=" + subId);
- intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
- intent.putExtra(EXTRA_SUBSCRIPTION_INDEX, subId);
intent.putExtra(EXTRA_SLOT_INDEX, phoneId);
intent.putExtra(PhoneConstants.PHONE_KEY, phoneId);
+ putSubscriptionIdExtra(intent, subId);
}
/**
@@ -2182,7 +2280,11 @@ public class SubscriptionManager {
*/
public @NonNull int[] getActiveSubscriptionIdList(boolean visibleOnly) {
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
int[] subId = iSub.getActiveSubIdList(visibleOnly);
if (subId != null) return subId;
@@ -2233,7 +2335,11 @@ public class SubscriptionManager {
int simState = TelephonyManager.SIM_STATE_UNKNOWN;
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
simState = iSub.getSimStateForSlotIndex(slotIndex);
}
@@ -2252,7 +2358,11 @@ public class SubscriptionManager {
*/
public static void setSubscriptionProperty(int subId, String propKey, String propValue) {
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
iSub.setSubscriptionProperty(subId, propKey, propValue);
}
@@ -2272,7 +2382,11 @@ public class SubscriptionManager {
Context context) {
String resultValue = null;
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
resultValue = iSub.getSubscriptionProperty(subId, propKey,
context.getOpPackageName(), context.getFeatureId());
@@ -2414,7 +2528,11 @@ public class SubscriptionManager {
@UnsupportedAppUsage
public boolean isActiveSubId(int subId) {
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
return iSub.isActiveSubId(subId, mContext.getOpPackageName(),
mContext.getFeatureId());
@@ -2717,7 +2835,11 @@ public class SubscriptionManager {
@TelephonyManager.SetOpportunisticSubscriptionResult Consumer<Integer> callback) {
if (VDBG) logd("[setPreferredDataSubscriptionId]+ subId:" + subId);
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub == null) return;
ISetOpportunisticDataCallback callbackStub = new ISetOpportunisticDataCallback.Stub() {
@@ -2760,7 +2882,11 @@ public class SubscriptionManager {
public int getPreferredDataSubscriptionId() {
int preferredSubId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
preferredSubId = iSub.getPreferredDataSubscriptionId();
}
@@ -2791,7 +2917,11 @@ public class SubscriptionManager {
List<SubscriptionInfo> subInfoList = null;
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
subInfoList = iSub.getOpportunisticSubscriptions(contextPkg, contextFeature);
}
@@ -2892,7 +3022,11 @@ public class SubscriptionManager {
ParcelUuid groupUuid = null;
int[] subIdArray = subIdList.stream().mapToInt(i->i).toArray();
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
groupUuid = iSub.createSubscriptionGroup(subIdArray, pkgForDebug);
} else {
@@ -2942,7 +3076,11 @@ public class SubscriptionManager {
int[] subIdArray = subIdList.stream().mapToInt(i->i).toArray();
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
iSub.addSubscriptionsIntoGroup(subIdArray, groupUuid, pkgForDebug);
} else {
@@ -2994,7 +3132,11 @@ public class SubscriptionManager {
int[] subIdArray = subIdList.stream().mapToInt(i->i).toArray();
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
iSub.removeSubscriptionsFromGroup(subIdArray, groupUuid, pkgForDebug);
} else {
@@ -3039,7 +3181,11 @@ public class SubscriptionManager {
List<SubscriptionInfo> result = null;
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
result = iSub.getSubscriptionsInGroup(groupUuid, contextPkg, contextFeature);
} else {
@@ -3152,7 +3298,11 @@ public class SubscriptionManager {
logd("setSubscriptionActivated subId= " + subscriptionId + " enable " + enable);
}
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
return iSub.setSubscriptionEnabled(enable, subscriptionId);
}
@@ -3241,7 +3391,11 @@ public class SubscriptionManager {
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public boolean isSubscriptionEnabled(int subscriptionId) {
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
return iSub.isSubscriptionEnabled(subscriptionId);
}
@@ -3264,7 +3418,11 @@ public class SubscriptionManager {
int subId = INVALID_SUBSCRIPTION_ID;
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
subId = iSub.getEnabledSubscriptionId(slotIndex);
}
@@ -3290,7 +3448,11 @@ public class SubscriptionManager {
int result = 0;
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
result = helper.callMethod(iSub);
}
@@ -3313,7 +3475,11 @@ public class SubscriptionManager {
*/
public static int getActiveDataSubscriptionId() {
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
return iSub.getActiveDataSubscriptionId();
}
@@ -3321,4 +3487,19 @@ public class SubscriptionManager {
}
return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
}
+
+ /**
+ * Helper method that puts a subscription id on an intent with the constants:
+ * PhoneConstant.SUBSCRIPTION_KEY and SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX.
+ * Both constants are used to support backwards compatibility. Once we know we got all places,
+ * we can remove PhoneConstants.SUBSCRIPTION_KEY.
+ * @param intent Intent to put sub id on.
+ * @param subId SubscriptionId to put on intent.
+ *
+ * @hide
+ */
+ public static void putSubscriptionIdExtra(Intent intent, int subId) {
+ intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId);
+ intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
+ }
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 00d9f3ca1728..0ffeccfa6a23 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -57,7 +57,6 @@ import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
-import android.os.IBinder;
import android.os.PersistableBundle;
import android.os.Process;
import android.os.RemoteException;
@@ -95,15 +94,12 @@ import android.util.Log;
import android.util.Pair;
import com.android.ims.internal.IImsServiceFeatureCallback;
-import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.CellNetworkScanResult;
import com.android.internal.telephony.INumberVerificationCallback;
import com.android.internal.telephony.IOns;
import com.android.internal.telephony.IPhoneSubInfo;
import com.android.internal.telephony.ISetOpportunisticDataCallback;
-import com.android.internal.telephony.ISms;
-import com.android.internal.telephony.ISub;
import com.android.internal.telephony.ITelephony;
import com.android.internal.telephony.ITelephonyRegistry;
import com.android.internal.telephony.IUpdateAvailableNetworksCallback;
@@ -113,8 +109,6 @@ import com.android.internal.telephony.RILConstants;
import com.android.internal.telephony.SmsApplication;
import com.android.telephony.Rlog;
-import dalvik.system.VMRuntime;
-
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.annotation.Retention;
@@ -305,21 +299,6 @@ public class TelephonyManager {
private SubscriptionManager mSubscriptionManager;
private TelephonyScanManager mTelephonyScanManager;
- /** Cached service handles, cleared by resetServiceHandles() at death */
- private static final Object sCacheLock = new Object();
-
- /** @hide */
- private static boolean sServiceHandleCacheEnabled = true;
-
- @GuardedBy("sCacheLock")
- private static IPhoneSubInfo sIPhoneSubInfo;
- @GuardedBy("sCacheLock")
- private static ISub sISub;
- @GuardedBy("sCacheLock")
- private static ISms sISms;
- @GuardedBy("sCacheLock")
- private static final DeathRecipient sServiceDeath = new DeathRecipient();
-
/** Enum indicating multisim variants
* DSDS - Dual SIM Dual Standby
* DSDA - Dual SIM Dual Active
@@ -1465,7 +1444,8 @@ public class TelephonyManager {
/**
* <p>Broadcast Action: The emergency callback mode is changed.
* <ul>
- * <li><em>phoneinECMState</em> - A boolean value,true=phone in ECM, false=ECM off</li>
+ * <li><em>EXTRA_PHONE_IN_ECM_STATE</em> - A boolean value,true=phone in ECM,
+ * false=ECM off</li>
* </ul>
* <p class="note">
* You can <em>not</em> receive this through components declared
@@ -1475,12 +1455,25 @@ public class TelephonyManager {
*
* <p class="note">This is a protected intent that can only be sent by the system.
*
+ * @see #EXTRA_PHONE_IN_ECM_STATE
+ *
* @hide
*/
@SystemApi
@SuppressLint("ActionValue")
- public static final String ACTION_EMERGENCY_CALLBACK_MODE_CHANGED
- = "android.intent.action.EMERGENCY_CALLBACK_MODE_CHANGED";
+ public static final String ACTION_EMERGENCY_CALLBACK_MODE_CHANGED =
+ "android.intent.action.EMERGENCY_CALLBACK_MODE_CHANGED";
+
+
+ /**
+ * Extra included in {@link #ACTION_EMERGENCY_CALLBACK_MODE_CHANGED}.
+ * Indicates whether the phone is in an emergency phone state.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final String EXTRA_PHONE_IN_ECM_STATE =
+ "android.telephony.extra.PHONE_IN_ECM_STATE";
/**
* <p>Broadcast Action: when data connections get redirected with validation failure.
@@ -1672,8 +1665,8 @@ public class TelephonyManager {
/**
* <p>Broadcast Action: The emergency call state is changed.
* <ul>
- * <li><em>phoneInEmergencyCall</em> - A boolean value, true if phone in emergency call,
- * false otherwise</li>
+ * <li><em>EXTRA_PHONE_IN_EMERGENCY_CALL</em> - A boolean value, true if phone in emergency
+ * call, false otherwise</li>
* </ul>
* <p class="note">
* You can <em>not</em> receive this through components declared
@@ -1683,12 +1676,25 @@ public class TelephonyManager {
*
* <p class="note">This is a protected intent that can only be sent by the system.
*
+ * @see #EXTRA_PHONE_IN_EMERGENCY_CALL
+ *
* @hide
*/
@SystemApi
@SuppressLint("ActionValue")
- public static final String ACTION_EMERGENCY_CALL_STATE_CHANGED
- = "android.intent.action.EMERGENCY_CALL_STATE_CHANGED";
+ public static final String ACTION_EMERGENCY_CALL_STATE_CHANGED =
+ "android.intent.action.EMERGENCY_CALL_STATE_CHANGED";
+
+
+ /**
+ * Extra included in {@link #ACTION_EMERGENCY_CALL_STATE_CHANGED}.
+ * It indicates whether the phone is making an emergency call.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final String EXTRA_PHONE_IN_EMERGENCY_CALL =
+ "android.telephony.extra.PHONE_IN_EMERGENCY_CALL";
/**
* <p>Broadcast Action: It indicates the Emergency callback mode blocks datacall/sms
@@ -1701,8 +1707,8 @@ public class TelephonyManager {
* @hide
*/
@SystemApi
- public static final String ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS
- = "android.telephony.action.SHOW_NOTICE_ECM_BLOCK_OTHERS";
+ public static final String ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS =
+ "android.telephony.action.SHOW_NOTICE_ECM_BLOCK_OTHERS";
/**
* Broadcast Action: The default data subscription has changed in a multi-SIM device.
@@ -1715,8 +1721,8 @@ public class TelephonyManager {
*/
@SystemApi
@SuppressLint("ActionValue")
- public static final String ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED
- = "android.intent.action.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED";
+ public static final String ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED =
+ "android.intent.action.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED";
/**
* Broadcast Action: The default voice subscription has changed in a mult-SIm device.
@@ -1729,8 +1735,8 @@ public class TelephonyManager {
*/
@SystemApi
@SuppressLint("ActionValue")
- public static final String ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED
- = "android.intent.action.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED";
+ public static final String ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED =
+ "android.intent.action.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED";
/**
* Broadcast Action: This triggers a client initiated OMA-DM session to the OMA server.
@@ -1743,8 +1749,8 @@ public class TelephonyManager {
*/
@SystemApi
@SuppressLint("ActionValue")
- public static final String ACTION_REQUEST_OMADM_CONFIGURATION_UPDATE
- = "com.android.omadm.service.CONFIGURATION_UPDATE";
+ public static final String ACTION_REQUEST_OMADM_CONFIGURATION_UPDATE =
+ "com.android.omadm.service.CONFIGURATION_UPDATE";
//
//
@@ -1868,7 +1874,7 @@ public class TelephonyManager {
public String getDeviceId(int slotIndex) {
// FIXME this assumes phoneId == slotIndex
try {
- IPhoneSubInfo info = getSubscriberInfoService();
+ IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
return info.getDeviceIdForPhone(slotIndex, mContext.getOpPackageName(),
@@ -2122,7 +2128,7 @@ public class TelephonyManager {
private String getNaiBySubscriberId(int subId) {
try {
- IPhoneSubInfo info = getSubscriberInfoService();
+ IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
String nai = info.getNaiForSubscriber(subId, mContext.getOpPackageName(),
@@ -3811,7 +3817,7 @@ public class TelephonyManager {
@UnsupportedAppUsage
public String getSimSerialNumber(int subId) {
try {
- IPhoneSubInfo info = getSubscriberInfoService();
+ IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
return info.getIccSerialNumberForSubscriber(subId, mContext.getOpPackageName(),
@@ -4085,7 +4091,7 @@ public class TelephonyManager {
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
public String getSubscriberId(int subId) {
try {
- IPhoneSubInfo info = getSubscriberInfoService();
+ IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
return info.getSubscriberIdForSubscriber(subId, mContext.getOpPackageName(),
@@ -4121,7 +4127,7 @@ public class TelephonyManager {
@Nullable
public ImsiEncryptionInfo getCarrierInfoForImsiEncryption(@KeyType int keyType) {
try {
- IPhoneSubInfo info = getSubscriberInfoService();
+ IPhoneSubInfo info = getSubscriberInfo();
if (info == null) {
Rlog.e(TAG,"IMSI error: Subscriber Info is null");
return null;
@@ -4164,7 +4170,7 @@ public class TelephonyManager {
@SystemApi
public void resetCarrierKeysForImsiEncryption() {
try {
- IPhoneSubInfo info = getSubscriberInfoService();
+ IPhoneSubInfo info = getSubscriberInfo();
if (info == null) {
Rlog.e(TAG, "IMSI error: Subscriber Info is null");
if (!isSystemProcess()) {
@@ -4229,7 +4235,7 @@ public class TelephonyManager {
*/
public void setCarrierInfoForImsiEncryption(ImsiEncryptionInfo imsiEncryptionInfo) {
try {
- IPhoneSubInfo info = getSubscriberInfoService();
+ IPhoneSubInfo info = getSubscriberInfo();
if (info == null) return;
info.setCarrierInfoForImsiEncryption(mSubId, mContext.getOpPackageName(),
imsiEncryptionInfo);
@@ -4253,7 +4259,7 @@ public class TelephonyManager {
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public String getGroupIdLevel1() {
try {
- IPhoneSubInfo info = getSubscriberInfoService();
+ IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
return info.getGroupIdLevel1ForSubscriber(getSubId(), mContext.getOpPackageName(),
@@ -4277,7 +4283,7 @@ public class TelephonyManager {
@UnsupportedAppUsage
public String getGroupIdLevel1(int subId) {
try {
- IPhoneSubInfo info = getSubscriberInfoService();
+ IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
return info.getGroupIdLevel1ForSubscriber(subId, mContext.getOpPackageName(),
@@ -4340,7 +4346,7 @@ public class TelephonyManager {
return number;
}
try {
- IPhoneSubInfo info = getSubscriberInfoService();
+ IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
return info.getLine1NumberForSubscriber(subId, mContext.getOpPackageName(),
@@ -4431,7 +4437,7 @@ public class TelephonyManager {
return alphaTag;
}
try {
- IPhoneSubInfo info = getSubscriberInfoService();
+ IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
return info.getLine1AlphaTagForSubscriber(subId, getOpPackageName(),
@@ -4519,7 +4525,7 @@ public class TelephonyManager {
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
public String getMsisdn(int subId) {
try {
- IPhoneSubInfo info = getSubscriberInfoService();
+ IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
return info.getMsisdnForSubscriber(subId, getOpPackageName(), getFeatureId());
@@ -4553,7 +4559,7 @@ public class TelephonyManager {
@UnsupportedAppUsage
public String getVoiceMailNumber(int subId) {
try {
- IPhoneSubInfo info = getSubscriberInfoService();
+ IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
return info.getVoiceMailNumberForSubscriber(subId, getOpPackageName(),
@@ -5152,7 +5158,7 @@ public class TelephonyManager {
@UnsupportedAppUsage
public String getVoiceMailAlphaTag(int subId) {
try {
- IPhoneSubInfo info = getSubscriberInfoService();
+ IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
return info.getVoiceMailAlphaTagForSubscriber(subId, getOpPackageName(),
@@ -5200,7 +5206,7 @@ public class TelephonyManager {
@UnsupportedAppUsage
public String getIsimImpi() {
try {
- IPhoneSubInfo info = getSubscriberInfoService();
+ IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
//get the Isim Impi based on subId
@@ -5227,7 +5233,7 @@ public class TelephonyManager {
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public String getIsimDomain() {
try {
- IPhoneSubInfo info = getSubscriberInfoService();
+ IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
//get the Isim Domain based on subId
@@ -5251,7 +5257,7 @@ public class TelephonyManager {
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public String[] getIsimImpu() {
try {
- IPhoneSubInfo info = getSubscriberInfoService();
+ IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
//get the Isim Impu based on subId
@@ -5264,6 +5270,19 @@ public class TelephonyManager {
}
}
+ /**
+ * @hide
+ */
+ @UnsupportedAppUsage
+ private IPhoneSubInfo getSubscriberInfo() {
+ // get it each time because that process crashes a lot
+ return IPhoneSubInfo.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getPhoneSubServiceRegisterer()
+ .get());
+ }
+
/**
* Device call state: No activity.
*/
@@ -5417,6 +5436,13 @@ public class TelephonyManager {
public static final int DATA_DISCONNECTING = 4;
/**
+ * To check the SDK version for {@link TelephonyManager#getDataState}.
+ */
+ @ChangeId
+ @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.R)
+ private static final long GET_DATA_STATE_CODE_CHANGE = 147600208L;
+
+ /**
* Returns a constant indicating the current data connection state
* (cellular).
*
@@ -5434,7 +5460,7 @@ public class TelephonyManager {
int state = telephony.getDataStateForSubId(
getSubId(SubscriptionManager.getActiveDataSubscriptionId()));
if (state == TelephonyManager.DATA_DISCONNECTING
- && VMRuntime.getRuntime().getTargetSdkVersion() < Build.VERSION_CODES.R) {
+ && !Compatibility.isChangeEnabled(GET_DATA_STATE_CODE_CHANGE)) {
return TelephonyManager.DATA_CONNECTED;
}
@@ -5496,6 +5522,13 @@ public class TelephonyManager {
//
/**
+ * To check the SDK version for {@link TelephonyManager#listen}.
+ */
+ @ChangeId
+ @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.Q)
+ private static final long LISTEN_CODE_CHANGE = 147600208L;
+
+ /**
* Registers a listener object to receive notification of changes
* in specified telephony states.
* <p>
@@ -5534,7 +5567,7 @@ public class TelephonyManager {
// subId from PhoneStateListener is deprecated Q on forward, use the subId from
// TelephonyManager instance. keep using subId from PhoneStateListener for pre-Q.
int subId = mSubId;
- if (VMRuntime.getRuntime().getTargetSdkVersion() >= Build.VERSION_CODES.Q) {
+ if (Compatibility.isChangeEnabled(LISTEN_CODE_CHANGE)) {
// since mSubId in PhoneStateListener is deprecated from Q on forward, this is
// the only place to set mSubId and its for "informational" only.
// TODO: remove this once we completely get rid of mSubId in PhoneStateListener
@@ -7000,7 +7033,7 @@ public class TelephonyManager {
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public String getIsimIst() {
try {
- IPhoneSubInfo info = getSubscriberInfoService();
+ IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
//get the Isim Ist based on subId
@@ -7022,7 +7055,7 @@ public class TelephonyManager {
@UnsupportedAppUsage
public String[] getIsimPcscf() {
try {
- IPhoneSubInfo info = getSubscriberInfoService();
+ IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
//get the Isim Pcscf based on subId
@@ -7103,7 +7136,7 @@ public class TelephonyManager {
@UnsupportedAppUsage
public String getIccAuthentication(int subId, int appType, int authType, String data) {
try {
- IPhoneSubInfo info = getSubscriberInfoService();
+ IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
return info.getIccSimChallengeResponse(subId, appType, authType, data);
@@ -12379,150 +12412,4 @@ public class TelephonyManager {
}
return false;
}
-
- private static class DeathRecipient implements IBinder.DeathRecipient {
- @Override
- public void binderDied() {
- resetServiceCache();
- }
- }
-
- /**
- * Reset everything in the service cache; if one handle died then they are
- * all probably broken.
- * @hide
- */
- private static void resetServiceCache() {
- synchronized (sCacheLock) {
- if (sISub != null) {
- sISub.asBinder().unlinkToDeath(sServiceDeath, 0);
- sISub = null;
- }
- if (sISms != null) {
- sISms.asBinder().unlinkToDeath(sServiceDeath, 0);
- sISms = null;
- }
- if (sIPhoneSubInfo != null) {
- sIPhoneSubInfo.asBinder().unlinkToDeath(sServiceDeath, 0);
- sIPhoneSubInfo = null;
- }
- }
- }
-
- /**
- * @hide
- */
- static IPhoneSubInfo getSubscriberInfoService() {
- if (!sServiceHandleCacheEnabled) {
- return IPhoneSubInfo.Stub.asInterface(
- TelephonyFrameworkInitializer
- .getTelephonyServiceManager()
- .getPhoneSubServiceRegisterer()
- .get());
- }
-
- if (sIPhoneSubInfo == null) {
- IPhoneSubInfo temp = IPhoneSubInfo.Stub.asInterface(
- TelephonyFrameworkInitializer
- .getTelephonyServiceManager()
- .getPhoneSubServiceRegisterer()
- .get());
- synchronized (sCacheLock) {
- if (sIPhoneSubInfo == null && temp != null) {
- try {
- sIPhoneSubInfo = temp;
- sIPhoneSubInfo.asBinder().linkToDeath(sServiceDeath, 0);
- } catch (Exception e) {
- // something has gone horribly wrong
- sIPhoneSubInfo = null;
- }
- }
- }
- }
- return sIPhoneSubInfo;
- }
-
- /**
- * @hide
- */
- static ISub getSubscriptionService() {
- if (!sServiceHandleCacheEnabled) {
- return ISub.Stub.asInterface(
- TelephonyFrameworkInitializer
- .getTelephonyServiceManager()
- .getSubscriptionServiceRegisterer()
- .get());
- }
-
- if (sISub == null) {
- ISub temp = ISub.Stub.asInterface(
- TelephonyFrameworkInitializer
- .getTelephonyServiceManager()
- .getSubscriptionServiceRegisterer()
- .get());
- synchronized (sCacheLock) {
- if (sISub == null && temp != null) {
- try {
- sISub = temp;
- sISub.asBinder().linkToDeath(sServiceDeath, 0);
- } catch (Exception e) {
- // something has gone horribly wrong
- sISub = null;
- }
- }
- }
- }
- return sISub;
- }
-
- /**
- * @hide
- */
- static ISms getSmsService() {
- if (!sServiceHandleCacheEnabled) {
- return ISms.Stub.asInterface(
- TelephonyFrameworkInitializer
- .getTelephonyServiceManager()
- .getSmsServiceRegisterer()
- .get());
- }
-
- if (sISms == null) {
- ISms temp = ISms.Stub.asInterface(
- TelephonyFrameworkInitializer
- .getTelephonyServiceManager()
- .getSmsServiceRegisterer()
- .get());
- synchronized (sCacheLock) {
- if (sISms == null && temp != null) {
- try {
- sISms = temp;
- sISms.asBinder().linkToDeath(sServiceDeath, 0);
- } catch (Exception e) {
- // something has gone horribly wrong
- sISms = null;
- }
- }
- }
- }
- return sISms;
- }
-
- /**
- * Disables service handle caching for tests that utilize mock services.
- * @hide
- */
- @VisibleForTesting
- public static void disableServiceHandleCaching() {
- sServiceHandleCacheEnabled = false;
- }
-
- /**
- * Reenables service handle caching.
- * @hide
- */
- @VisibleForTesting
- public static void enableServiceHandleCaching() {
- sServiceHandleCacheEnabled = true;
- }
}
diff --git a/telephony/java/com/android/internal/telephony/PhoneConstants.java b/telephony/java/com/android/internal/telephony/PhoneConstants.java
index 51701eb4ace5..db8c84560282 100644
--- a/telephony/java/com/android/internal/telephony/PhoneConstants.java
+++ b/telephony/java/com/android/internal/telephony/PhoneConstants.java
@@ -100,9 +100,6 @@ public class PhoneConstants {
public static final String DATA_APN_TYPE_KEY = "apnType";
public static final String DATA_APN_KEY = "apn";
- public static final String PHONE_IN_ECM_STATE = "phoneinECMState";
- public static final String PHONE_IN_EMERGENCY_CALL = "phoneInEmergencyCall";
-
/**
* Return codes for supplyPinReturnResult and
* supplyPukReturnResult APIs
diff --git a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java
index 0ab5c97d317e..11d5b250d752 100644
--- a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java
+++ b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java
@@ -222,7 +222,7 @@ public class NetworkAgentWrapper implements TestableNetworkCallback.HasNetwork {
@Override
public Network getNetwork() {
- return new Network(mNetworkAgent.netId);
+ return mNetworkAgent.network;
}
public void expectPreventReconnectReceived(long timeoutMs) {
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index b2d363e27839..1901a1db633b 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -575,7 +575,7 @@ public class ConnectivityServiceTest {
}
};
- assertEquals(na.netId, nmNetworkCaptor.getValue().netId);
+ assertEquals(na.network.netId, nmNetworkCaptor.getValue().netId);
mNmCallbacks = nmCbCaptor.getValue();
mNmCallbacks.onNetworkMonitorCreated(mNetworkMonitor);
diff --git a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java
index 9e915aec6832..e863266c4b49 100644
--- a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java
+++ b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java
@@ -35,7 +35,6 @@ import android.net.ConnectivityManager;
import android.net.IDnsResolver;
import android.net.INetd;
import android.net.Network;
-import android.net.NetworkAgentConfig;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.NetworkProvider;
@@ -75,7 +74,6 @@ public class LingerMonitorTest {
@Mock INetd mNetd;
@Mock INetworkManagementService mNMS;
@Mock Context mCtx;
- @Mock NetworkAgentConfig mAgentConfig;
@Mock NetworkNotificationManager mNotifier;
@Mock Resources mResources;
@@ -358,7 +356,7 @@ public class LingerMonitorTest {
NetworkScore ns = new NetworkScore();
ns.putIntExtension(NetworkScore.LEGACY_SCORE, 50);
NetworkAgentInfo nai = new NetworkAgentInfo(null, null, new Network(netId), info, null,
- caps, ns, mCtx, null, mAgentConfig, mConnService, mNetd, mDnsResolver, mNMS,
+ caps, ns, mCtx, null, null /* config */, mConnService, mNetd, mDnsResolver, mNMS,
NetworkProvider.ID_NONE);
nai.everValidated = true;
return nai;
diff --git a/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java b/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java
index cf70f5d499d1..9b248878fe96 100644
--- a/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java
+++ b/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java
@@ -63,7 +63,6 @@ public class Nat464XlatTest {
static final int NETID = 42;
@Mock ConnectivityService mConnectivity;
- @Mock NetworkAgentConfig mAgentConfig;
@Mock IDnsResolver mDnsResolver;
@Mock INetd mNetd;
@Mock INetworkManagementService mNms;
@@ -72,6 +71,7 @@ public class Nat464XlatTest {
TestLooper mLooper;
Handler mHandler;
+ NetworkAgentConfig mAgentConfig = new NetworkAgentConfig();
Nat464Xlat makeNat464Xlat() {
return new Nat464Xlat(mNai, mNetd, mDnsResolver, mNms) {
diff --git a/wifi/Android.bp b/wifi/Android.bp
index 6326f14bc6fd..70c9befce66a 100644
--- a/wifi/Android.bp
+++ b/wifi/Android.bp
@@ -50,6 +50,8 @@ test_access_hidden_api_whitelist = [
"//frameworks/opt/net/wifi/libs/WifiTrackerLib/tests",
"//external/robolectric-shadows:__subpackages__",
+ "//frameworks/base/packages/SettingsLib/tests/integ",
+ "//external/sl4a:__subpackages__",
]
// wifi-service needs pre-jarjared version of framework-wifi so it can reference copied utility
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index c6aca07ebe94..341330587614 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -23,6 +23,8 @@ import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
@@ -793,10 +795,19 @@ public class ScanResult implements Parcelable {
}
}
- /** empty scan result
+ /**
+ * Construct an empty scan result.
*
- * {@hide}
- * */
+ * Test code has a need to construct a ScanResult in a specific state.
+ * (Note that mocking using Mockito does not work if the object needs to be parceled and
+ * unparceled.)
+ * Export a @SystemApi default constructor to allow tests to construct an empty ScanResult
+ * object. The test can then directly set the fields it cares about.
+ *
+ * @hide
+ */
+ @SystemApi
+ @VisibleForTesting
public ScanResult() {
}
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index f4c5b9168cd0..ee2b57535b50 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -39,6 +39,8 @@ import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
@@ -1208,22 +1210,27 @@ public class WifiConfiguration implements Parcelable {
*/
@SystemApi
public static class NetworkSelectionStatus {
- // Quality Network Selection Status enable, temporary disabled, permanently disabled
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = "NETWORK_SELECTION_",
+ value = {
+ NETWORK_SELECTION_ENABLED,
+ NETWORK_SELECTION_TEMPORARY_DISABLED,
+ NETWORK_SELECTION_PERMANENTLY_DISABLED})
+ public @interface NetworkEnabledStatus {}
/**
- * This network is allowed to join Quality Network Selection
- * @hide
+ * This network will be considered as a potential candidate to connect to during network
+ * selection.
*/
public static final int NETWORK_SELECTION_ENABLED = 0;
/**
- * network was temporary disabled. Can be re-enabled after a time period expire
- * @hide
+ * This network was temporary disabled. May be re-enabled after a time out.
*/
- public static final int NETWORK_SELECTION_TEMPORARY_DISABLED = 1;
+ public static final int NETWORK_SELECTION_TEMPORARY_DISABLED = 1;
/**
- * network was permanently disabled.
- * @hide
+ * This network was permanently disabled.
*/
- public static final int NETWORK_SELECTION_PERMANENTLY_DISABLED = 2;
+ public static final int NETWORK_SELECTION_PERMANENTLY_DISABLED = 2;
/**
* Maximum Network selection status
* @hide
@@ -1455,6 +1462,7 @@ public class WifiConfiguration implements Parcelable {
* Network selection status, should be in one of three status: enable, temporaily disabled
* or permanently disabled
*/
+ @NetworkEnabledStatus
private int mStatus;
/**
@@ -1635,6 +1643,56 @@ public class WifiConfiguration implements Parcelable {
}
/**
+ * NetworkSelectionStatus exports an immutable public API.
+ * However, test code has a need to construct a NetworkSelectionStatus in a specific state.
+ * (Note that mocking using Mockito does not work if the object needs to be parceled and
+ * unparceled.)
+ * Export a @SystemApi Builder to allow tests to construct a NetworkSelectionStatus object
+ * in the desired state, without sacrificing NetworkSelectionStatus's immutability.
+ */
+ @VisibleForTesting
+ public static final class Builder {
+ private final NetworkSelectionStatus mNetworkSelectionStatus =
+ new NetworkSelectionStatus();
+
+ /**
+ * Set the current network selection status.
+ * One of:
+ * {@link #NETWORK_SELECTION_ENABLED},
+ * {@link #NETWORK_SELECTION_TEMPORARY_DISABLED},
+ * {@link #NETWORK_SELECTION_PERMANENTLY_DISABLED}
+ * @see NetworkSelectionStatus#getNetworkSelectionStatus()
+ */
+ @NonNull
+ public Builder setNetworkSelectionStatus(@NetworkEnabledStatus int status) {
+ mNetworkSelectionStatus.setNetworkSelectionStatus(status);
+ return this;
+ }
+
+ /**
+ *
+ * Set the current network's disable reason.
+ * One of the {@link #NETWORK_SELECTION_ENABLE} or DISABLED_* constants.
+ * e.g. {@link #DISABLED_ASSOCIATION_REJECTION}.
+ * @see NetworkSelectionStatus#getNetworkSelectionDisableReason()
+ */
+ @NonNull
+ public Builder setNetworkSelectionDisableReason(
+ @NetworkSelectionDisableReason int reason) {
+ mNetworkSelectionStatus.setNetworkSelectionDisableReason(reason);
+ return this;
+ }
+
+ /**
+ * Build a NetworkSelectionStatus object.
+ */
+ @NonNull
+ public NetworkSelectionStatus build() {
+ return mNetworkSelectionStatus;
+ }
+ }
+
+ /**
* Get the network disable reason string for a reason code (for debugging).
* @param reason specific error reason. One of the {@link #NETWORK_SELECTION_ENABLE} or
* DISABLED_* constants e.g. {@link #DISABLED_ASSOCIATION_REJECTION}.
@@ -1660,10 +1718,13 @@ public class WifiConfiguration implements Parcelable {
}
/**
- * get current network network selection status
- * @return return current network network selection status
- * @hide
+ * Get the current network network selection status.
+ * One of:
+ * {@link #NETWORK_SELECTION_ENABLED},
+ * {@link #NETWORK_SELECTION_TEMPORARY_DISABLED},
+ * {@link #NETWORK_SELECTION_PERMANENTLY_DISABLED}
*/
+ @NetworkEnabledStatus
public int getNetworkSelectionStatus() {
return mStatus;
}
@@ -1965,10 +2026,11 @@ public class WifiConfiguration implements Parcelable {
}
/**
- * Set the network selection status
+ * Set the network selection status.
* @hide
*/
- public void setNetworkSelectionStatus(NetworkSelectionStatus status) {
+ @SystemApi
+ public void setNetworkSelectionStatus(@NonNull NetworkSelectionStatus status) {
mNetworkSelectionStatus = status;
}
diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
index 41f7c6e2bb0d..5edcc2df3804 100644
--- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -1028,8 +1028,10 @@ public class WifiEnterpriseConfig implements Parcelable {
}
/**
- * @hide
+ * Get the client private key as supplied in {@link #setClientKeyEntryWithCertificateChain}, or
+ * null if unset.
*/
+ @Nullable
public PrivateKey getClientPrivateKey() {
return mClientPrivateKey;
}
diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index 62337cbf7e22..51b15afec3ab 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -17,6 +17,7 @@
package android.net.wifi;
import android.annotation.IntRange;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.compat.annotation.UnsupportedAppUsage;
@@ -27,6 +28,8 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
@@ -356,6 +359,72 @@ public class WifiInfo implements Parcelable {
}
}
+ /**
+ * WifiInfo exports an immutable public API.
+ * However, test code has a need to construct a WifiInfo in a specific state.
+ * (Note that mocking using Mockito does not work if the object needs to be parceled and
+ * unparceled.)
+ * Export a @SystemApi Builder to allow tests to construct a WifiInfo object
+ * in the desired state, without sacrificing WifiInfo's immutability.
+ *
+ * @hide
+ */
+ // This builder was not made public to reduce confusion for external developers as there are
+ // no legitimate uses for this builder except for testing.
+ @SystemApi
+ @VisibleForTesting
+ public static final class Builder {
+ private final WifiInfo mWifiInfo = new WifiInfo();
+
+ /**
+ * Set the SSID, in the form of a raw byte array.
+ * @see WifiInfo#getSSID()
+ */
+ @NonNull
+ public Builder setSsid(@NonNull byte[] ssid) {
+ mWifiInfo.setSSID(WifiSsid.createFromByteArray(ssid));
+ return this;
+ }
+
+ /**
+ * Set the BSSID.
+ * @see WifiInfo#getBSSID()
+ */
+ @NonNull
+ public Builder setBssid(@NonNull String bssid) {
+ mWifiInfo.setBSSID(bssid);
+ return this;
+ }
+
+ /**
+ * Set the RSSI, in dBm.
+ * @see WifiInfo#getRssi()
+ */
+ @NonNull
+ public Builder setRssi(int rssi) {
+ mWifiInfo.setRssi(rssi);
+ return this;
+ }
+
+ /**
+ * Set the network ID.
+ * @see WifiInfo#getNetworkId()
+ */
+ @NonNull
+ public Builder setNetworkId(int networkId) {
+ mWifiInfo.setNetworkId(networkId);
+ return this;
+ }
+
+ /**
+ * Build a WifiInfo object.
+ */
+ @NonNull
+ public WifiInfo build() {
+ return mWifiInfo;
+ }
+ }
+
/** @hide */
public void setSSID(WifiSsid wifiSsid) {
mWifiSsid = wifiSsid;
diff --git a/wifi/tests/Android.bp b/wifi/tests/Android.bp
new file mode 100644
index 000000000000..6a39959e8cfd
--- /dev/null
+++ b/wifi/tests/Android.bp
@@ -0,0 +1,50 @@
+// Copyright (C) 2020 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.
+
+// Make test APK
+// ============================================================
+
+android_test {
+ name: "FrameworksWifiApiTests",
+
+ defaults: ["framework-wifi-test-defaults"],
+
+ srcs: ["**/*.java"],
+
+ jacoco: {
+ include_filter: ["android.net.wifi.*"],
+ // TODO(b/147521214) need to exclude test classes
+ exclude_filter: [],
+ },
+
+ static_libs: [
+ "androidx.test.rules",
+ "core-test-rules",
+ "guava",
+ "mockito-target-minus-junit4",
+ "net-tests-utils",
+ "frameworks-base-testutils",
+ "truth-prebuilt",
+ ],
+
+ libs: [
+ "android.test.runner",
+ "android.test.base",
+ ],
+
+ test_suites: [
+ "device-tests",
+ "mts",
+ ],
+}
diff --git a/wifi/tests/Android.mk b/wifi/tests/Android.mk
deleted file mode 100644
index d2c385b46eb1..000000000000
--- a/wifi/tests/Android.mk
+++ /dev/null
@@ -1,66 +0,0 @@
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-
-# Make test APK
-# ============================================================
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-# This list is generated from the java source files in this module
-# The list is a comma separated list of class names with * matching zero or more characters.
-# Example:
-# Input files: src/com/android/server/wifi/Test.java src/com/android/server/wifi/AnotherTest.java
-# Generated exclude list: com.android.server.wifi.Test*,com.android.server.wifi.AnotherTest*
-
-# Filter all src files to just java files
-local_java_files := $(filter %.java,$(LOCAL_SRC_FILES))
-# Transform java file names into full class names.
-# This only works if the class name matches the file name and the directory structure
-# matches the package.
-local_classes := $(subst /,.,$(patsubst src/%.java,%,$(local_java_files)))
-# Convert class name list to jacoco exclude list
-# This appends a * to all classes and replace the space separators with commas.
-# These patterns will match all classes in this module and their inner classes.
-jacoco_exclude := $(subst $(space),$(comma),$(patsubst %,%*,$(local_classes)))
-
-jacoco_include := android.net.wifi.*
-
-LOCAL_JACK_COVERAGE_INCLUDE_FILTER := $(jacoco_include)
-LOCAL_JACK_COVERAGE_EXCLUDE_FILTER := $(jacoco_exclude)
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- androidx.test.rules \
- core-test-rules \
- guava \
- mockito-target-minus-junit4 \
- net-tests-utils \
- frameworks-base-testutils \
- truth-prebuilt \
-
-LOCAL_JAVA_LIBRARIES := \
- android.test.runner \
- android.test.base \
-
-LOCAL_PACKAGE_NAME := FrameworksWifiApiTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_COMPATIBILITY_SUITE := \
- device-tests \
- mts \
-
-include $(BUILD_PACKAGE)