summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt95
-rw-r--r--api/system-current.txt112
-rw-r--r--api/test-current.txt32
-rw-r--r--cmds/idmap2/Android.bp3
-rw-r--r--cmds/idmap2/idmap2/Create.cpp31
-rw-r--r--cmds/idmap2/idmap2/Scan.cpp107
-rw-r--r--cmds/idmap2/idmap2d/Idmap2Service.cpp22
-rw-r--r--cmds/idmap2/idmap2d/Idmap2Service.h7
-rw-r--r--cmds/idmap2/idmap2d/aidl/android/os/IIdmap2.aidl13
-rw-r--r--cmds/idmap2/include/idmap2/CommandLineOptions.h3
-rw-r--r--cmds/idmap2/include/idmap2/Idmap.h11
-rw-r--r--cmds/idmap2/include/idmap2/Policies.h41
-rw-r--r--cmds/idmap2/libidmap2/CommandLineOptions.cpp23
-rw-r--r--cmds/idmap2/libidmap2/Idmap.cpp31
-rw-r--r--cmds/idmap2/libidmap2/Policies.cpp57
-rw-r--r--cmds/idmap2/tests/BinaryStreamVisitorTests.cpp42
-rw-r--r--cmds/idmap2/tests/CommandLineOptionsTests.cpp56
-rw-r--r--cmds/idmap2/tests/FileUtilsTests.cpp14
-rw-r--r--cmds/idmap2/tests/Idmap2BinaryTests.cpp32
-rw-r--r--cmds/idmap2/tests/IdmapTests.cpp129
-rw-r--r--cmds/idmap2/tests/PoliciesTests.cpp70
-rw-r--r--cmds/idmap2/tests/PrettyPrintVisitorTests.cpp5
-rw-r--r--cmds/idmap2/tests/RawPrintVisitorTests.cpp5
-rw-r--r--cmds/idmap2/tests/data/system-overlay-invalid/AndroidManifest.xml21
-rw-r--r--cmds/idmap2/tests/data/system-overlay-invalid/build26
-rw-r--r--cmds/idmap2/tests/data/system-overlay-invalid/res/values/values.xml29
-rw-r--r--cmds/idmap2/tests/data/system-overlay-invalid/system-overlay-invalid.apkbin0 -> 1427 bytes
-rw-r--r--cmds/idmap2/tests/data/system-overlay/AndroidManifest.xml21
-rw-r--r--cmds/idmap2/tests/data/system-overlay/build26
-rw-r--r--cmds/idmap2/tests/data/system-overlay/res/values/values.xml22
-rw-r--r--cmds/idmap2/tests/data/system-overlay/system-overlay.apkbin0 -> 1283 bytes
-rw-r--r--cmds/idmap2/tests/data/target/res/values/overlayable.xml48
-rw-r--r--cmds/idmap2/tests/data/target/res/values/values.xml8
-rw-r--r--cmds/idmap2/tests/data/target/target.apkbin2173 -> 3669 bytes
-rw-r--r--cmds/statsd/src/atoms.proto21
-rw-r--r--config/hiddenapi-greylist.txt24
-rw-r--r--core/java/android/app/Activity.java20
-rw-r--r--core/java/android/content/Intent.java12
-rw-r--r--core/java/android/content/pm/IShortcutService.aidl4
-rw-r--r--core/java/android/content/pm/ShortcutInfo.java114
-rw-r--r--core/java/android/content/pm/ShortcutManager.java86
-rw-r--r--core/java/android/content/res/Resources.java6
-rw-r--r--core/java/android/hardware/display/BrightnessConfiguration.java15
-rw-r--r--core/java/android/hardware/display/BrightnessCorrection.java40
-rw-r--r--core/java/android/net/NetworkSpecifier.java27
-rw-r--r--core/java/android/os/GraphicsEnvironment.java15
-rw-r--r--core/java/android/os/VintfObject.java37
-rw-r--r--core/java/android/os/VintfRuntimeInfo.java31
-rw-r--r--core/java/android/provider/DeviceConfig.java7
-rw-r--r--core/java/android/provider/FontsContract.java12
-rw-r--r--core/java/android/view/LayoutInflater.java274
-rw-r--r--core/java/android/view/PointerIcon.java54
-rw-r--r--core/java/android/view/SurfaceControl.java47
-rw-r--r--core/java/android/view/contentcapture/ChildContentCaptureSession.java5
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureManager.java32
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureSession.java84
-rw-r--r--core/java/android/view/contentcapture/MainContentCaptureSession.java77
-rw-r--r--core/java/com/android/internal/app/ChooserActivity.java165
-rw-r--r--core/java/com/android/internal/infra/AbstractRemoteService.java8
-rw-r--r--core/jni/android_media_AudioRecord.cpp41
-rw-r--r--core/jni/android_view_InputEventSender.cpp1
-rw-r--r--core/jni/android_view_SurfaceControl.cpp29
-rw-r--r--core/jni/com_android_internal_os_Zygote.cpp9
-rw-r--r--core/proto/android/app/settings_enums.proto2079
-rw-r--r--core/res/AndroidManifest.xml1
-rw-r--r--core/res/res/drawable/perm_group_activity_recognition.xml29
-rw-r--r--core/res/res/drawable/perm_group_sensors.xml16
-rw-r--r--core/res/res/values/config.xml25
-rw-r--r--core/res/res/values/public.xml5
-rw-r--r--core/res/res/values/symbols.xml4
-rw-r--r--core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java18
-rw-r--r--core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderEndToEndTest.java214
-rw-r--r--libs/androidfw/include/androidfw/ResourceTypes.h4
-rw-r--r--libs/androidfw/tests/LoadedArsc_test.cpp1
-rw-r--r--libs/androidfw/tests/data/overlayable/overlayable.apkbin5523 -> 3443 bytes
-rw-r--r--libs/androidfw/tests/data/overlayable/res/values/overlayable.xml4
-rw-r--r--libs/input/PointerController.cpp8
-rw-r--r--libs/input/PointerController.h6
-rw-r--r--media/Android.bp17
-rw-r--r--media/java/android/media/AudioRecord.java34
-rw-r--r--media/java/android/media/Controller2Link.java53
-rw-r--r--media/java/android/media/IMediaController2.aidl7
-rw-r--r--media/java/android/media/MediaCodec.java35
-rw-r--r--media/java/android/media/MediaCodecInfo.java377
-rw-r--r--media/java/android/media/MediaCodecList.java6
-rw-r--r--media/java/android/media/MediaConstants.java1
-rw-r--r--media/java/android/media/MediaController2.java150
-rw-r--r--media/java/android/media/MediaFormat.java1
-rw-r--r--media/java/android/media/MediaSession2.java59
-rw-r--r--media/java/android/media/MicrophoneDirection.java62
-rw-r--r--media/java/android/media/session/MediaSessionProviderService.java35
-rw-r--r--media/jni/android_media_MediaCodec.cpp28
-rw-r--r--media/jni/android_media_MediaCodecList.cpp80
-rw-r--r--media/packages/MediaCore/Android.bp21
-rw-r--r--media/packages/MediaCore/AndroidManifest.xml32
-rw-r--r--media/packages/MediaCore/res/values/strings.xml21
-rw-r--r--media/packages/MediaCore/src/com/android/media/AmlMediaSessionProviderService.java37
-rw-r--r--native/android/sensor.cpp5
-rw-r--r--packages/SystemUI/res-keyguard/layout/bubble_clock.xml10
-rw-r--r--packages/SystemUI/res-keyguard/layout/digital_clock.xml11
-rw-r--r--packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml12
-rw-r--r--packages/SystemUI/res-keyguard/layout/stretchanalog_clock.xml10
-rw-r--r--packages/SystemUI/res-keyguard/layout/text_clock.xml29
-rw-r--r--packages/SystemUI/res-keyguard/layout/type_clock.xml55
-rw-r--r--packages/SystemUI/res-keyguard/values/colors.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values/strings.xml83
-rw-r--r--packages/SystemUI/res/layout/global_actions_wrapped.xml1
-rw-r--r--packages/SystemUI/res/values/config.xml2
-rw-r--r--packages/SystemUI/res/values/ids.xml3
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java11
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java4
-rw-r--r--packages/SystemUI/src/com/android/keyguard/clock/ClockLayout.java8
-rw-r--r--packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClock.java1
-rw-r--r--packages/SystemUI/src/com/android/keyguard/clock/TypeClockController.java106
-rw-r--r--packages/SystemUI/src/com/android/keyguard/clock/TypographicClock.java110
-rw-r--r--packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java77
-rw-r--r--packages/SystemUI/src/com/android/systemui/MultiListLayout.java124
-rw-r--r--packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java99
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyTile.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java55
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationListController.java117
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationAssistantAction.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBackAction.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java92
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java241
-rw-r--r--proto/src/metrics_constants/metrics_constants.proto6
-rw-r--r--services/autofill/java/com/android/server/autofill/AutofillManagerService.java12
-rw-r--r--services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java9
-rw-r--r--services/autofill/java/com/android/server/autofill/Session.java7
-rw-r--r--services/backup/java/com/android/server/backup/UserBackupManagerService.java20
-rw-r--r--services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java9
-rw-r--r--services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java30
-rw-r--r--services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java15
-rw-r--r--services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java2
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java6
-rw-r--r--services/core/java/com/android/server/am/OomAdjuster.java5
-rw-r--r--services/core/java/com/android/server/input/InputManagerService.java24
-rw-r--r--services/core/java/com/android/server/om/IdmapManager.java84
-rw-r--r--services/core/java/com/android/server/om/OverlayManagerServiceImpl.java4
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java75
-rw-r--r--services/core/java/com/android/server/pm/Settings.java6
-rw-r--r--services/core/java/com/android/server/pm/ShortcutPackage.java51
-rw-r--r--services/core/java/com/android/server/pm/ShortcutService.java18
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java26
-rw-r--r--services/core/java/com/android/server/policy/WindowManagerPolicy.java3
-rw-r--r--services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java2
-rw-r--r--services/core/java/com/android/server/role/RoleManagerService.java5
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java7
-rw-r--r--services/core/java/com/android/server/wm/ActivityStackSupervisor.java3
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java60
-rw-r--r--services/core/java/com/android/server/wm/DisplayRotation.java30
-rw-r--r--services/core/java/com/android/server/wm/RootActivityContainer.java2
-rw-r--r--services/core/java/com/android/server/wm/TaskTapPointerEventListener.java22
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java2
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java8
-rw-r--r--services/core/jni/com_android_server_input_InputManagerService.cpp45
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java9
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java34
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java5
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java44
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java1
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java1
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityStartControllerTests.java1
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java1
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java15
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java1
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/PendingRemoteAnimationRegistryTest.java1
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java1
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java1
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java1
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TestSystemServices.java (renamed from services/tests/wmtests/src/com/android/server/wm/WmServiceUtils.java)6
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java10
-rw-r--r--telephony/java/android/telephony/CarrierRestrictionRules.aidl20
-rw-r--r--telephony/java/android/telephony/CarrierRestrictionRules.java277
-rw-r--r--telephony/java/android/telephony/PhoneStateListener.java8
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java112
-rw-r--r--telephony/java/android/telephony/emergency/EmergencyNumber.java38
-rw-r--r--telephony/java/android/telephony/ims/ImsCallProfile.java30
-rw-r--r--telephony/java/android/telephony/ims/ImsMmTelManager.java55
-rw-r--r--telephony/java/android/telephony/ims/ProvisioningManager.java25
-rw-r--r--telephony/java/com/android/internal/telephony/ITelephony.aidl37
-rw-r--r--tests/ActivityViewTest/AndroidManifest.xml5
-rw-r--r--tests/ActivityViewTest/res/layout/activity_view_main_activity.xml6
-rw-r--r--tests/ActivityViewTest/res/layout/activity_view_visibility_activity.xml46
-rw-r--r--tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewMainActivity.java3
-rw-r--r--tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewTestActivity.java3
-rw-r--r--tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewVisibilityActivity.java75
-rw-r--r--tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java153
-rw-r--r--tests/net/java/com/android/server/ConnectivityServiceTest.java109
-rw-r--r--tools/aapt2/ResourceParser.cpp2
-rw-r--r--tools/aapt2/ResourceParser_test.cpp17
-rw-r--r--tools/aapt2/ResourceTable.h3
-rw-r--r--tools/aapt2/ResourceTable_test.cpp4
-rw-r--r--tools/aapt2/Resources.proto1
-rw-r--r--tools/aapt2/format/binary/BinaryResourceParser.cpp4
-rw-r--r--tools/aapt2/format/binary/TableFlattener.cpp3
-rw-r--r--tools/aapt2/format/binary/TableFlattener_test.cpp16
-rw-r--r--tools/aapt2/format/proto/ProtoDeserialize.cpp3
-rw-r--r--tools/aapt2/format/proto/ProtoSerialize.cpp3
-rw-r--r--tools/aapt2/format/proto/ProtoSerialize_test.cpp4
-rw-r--r--tools/aapt2/link/TableMerger_test.cpp4
-rw-r--r--wifi/java/android/net/wifi/WifiInfo.java2
-rw-r--r--wifi/java/android/net/wifi/WifiManager.java37
-rw-r--r--wifi/java/android/net/wifi/WifiNetworkAgentSpecifier.java5
-rw-r--r--wifi/java/android/net/wifi/WifiNetworkSpecifier.java6
-rw-r--r--wifi/java/android/net/wifi/WifiNetworkSuggestion.java3
-rw-r--r--wifi/java/android/net/wifi/hotspot2/OsuProvider.java13
-rw-r--r--wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java2
217 files changed, 8031 insertions, 1086 deletions
diff --git a/api/current.txt b/api/current.txt
index eebe9a3c50c6..36a21c75c591 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -10375,6 +10375,7 @@ package android.content {
field public static final java.lang.String EXTRA_RETURN_RESULT = "android.intent.extra.RETURN_RESULT";
field public static final deprecated java.lang.String EXTRA_SHORTCUT_ICON = "android.intent.extra.shortcut.ICON";
field public static final deprecated java.lang.String EXTRA_SHORTCUT_ICON_RESOURCE = "android.intent.extra.shortcut.ICON_RESOURCE";
+ field public static final java.lang.String EXTRA_SHORTCUT_ID = "android.intent.extra.shortcut.ID";
field public static final deprecated java.lang.String EXTRA_SHORTCUT_INTENT = "android.intent.extra.shortcut.INTENT";
field public static final deprecated java.lang.String EXTRA_SHORTCUT_NAME = "android.intent.extra.shortcut.NAME";
field public static final java.lang.String EXTRA_SHUTDOWN_USERSPACE_ONLY = "android.intent.extra.SHUTDOWN_USERSPACE_ONLY";
@@ -11950,6 +11951,9 @@ package android.content.pm {
method public android.content.pm.ShortcutInfo.Builder setIntent(android.content.Intent);
method public android.content.pm.ShortcutInfo.Builder setIntents(android.content.Intent[]);
method public android.content.pm.ShortcutInfo.Builder setLongLabel(java.lang.CharSequence);
+ method public android.content.pm.ShortcutInfo.Builder setLongLived();
+ method public android.content.pm.ShortcutInfo.Builder setPerson(android.app.Person);
+ method public android.content.pm.ShortcutInfo.Builder setPersons(android.app.Person[]);
method public android.content.pm.ShortcutInfo.Builder setRank(int);
method public android.content.pm.ShortcutInfo.Builder setShortLabel(java.lang.CharSequence);
}
@@ -12290,6 +12294,7 @@ package android.content.res {
method public void parseBundleExtra(java.lang.String, android.util.AttributeSet, android.os.Bundle) throws org.xmlpull.v1.XmlPullParserException;
method public void parseBundleExtras(android.content.res.XmlResourceParser, android.os.Bundle) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public deprecated void updateConfiguration(android.content.res.Configuration, android.util.DisplayMetrics);
+ field public static final int ID_NULL = 0; // 0x0
}
public static class Resources.NotFoundException extends java.lang.RuntimeException {
@@ -24146,6 +24151,7 @@ package android.media {
method public int dequeueOutputBuffer(android.media.MediaCodec.BufferInfo, long);
method protected void finalize();
method public void flush();
+ method public java.lang.String getCanonicalName();
method public android.media.MediaCodecInfo getCodecInfo();
method public java.nio.ByteBuffer getInputBuffer(int);
method public deprecated java.nio.ByteBuffer[] getInputBuffers();
@@ -24272,10 +24278,15 @@ package android.media {
}
public final class MediaCodecInfo {
+ method public java.lang.String getCanonicalName();
method public android.media.MediaCodecInfo.CodecCapabilities getCapabilitiesForType(java.lang.String);
method public java.lang.String getName();
method public java.lang.String[] getSupportedTypes();
+ method public boolean isAlias();
method public boolean isEncoder();
+ method public boolean isHardwareAccelerated();
+ method public boolean isSoftwareOnly();
+ method public boolean isVendor();
}
public static final class MediaCodecInfo.AudioCapabilities {
@@ -24351,7 +24362,10 @@ package android.media {
field public static final deprecated int COLOR_QCOM_FormatYUV420SemiPlanar = 2141391872; // 0x7fa30c00
field public static final deprecated int COLOR_TI_FormatYUV420PackedSemiPlanar = 2130706688; // 0x7f000100
field public static final java.lang.String FEATURE_AdaptivePlayback = "adaptive-playback";
+ field public static final java.lang.String FEATURE_DynamicTimestamp = "dynamic-timestamp";
+ field public static final java.lang.String FEATURE_FrameParsing = "frame-parsing";
field public static final java.lang.String FEATURE_IntraRefresh = "intra-refresh";
+ field public static final java.lang.String FEATURE_MultipleFrames = "multiple-frames";
field public static final java.lang.String FEATURE_PartialFrame = "partial-frame";
field public static final java.lang.String FEATURE_SecurePlayback = "secure-playback";
field public static final java.lang.String FEATURE_TunneledPlayback = "tunneled-playback";
@@ -24373,6 +24387,33 @@ package android.media {
field public static final int AACObjectSSR = 3; // 0x3
field public static final int AACObjectScalable = 6; // 0x6
field public static final int AACObjectXHE = 42; // 0x2a
+ field public static final int AV1Level2 = 1; // 0x1
+ field public static final int AV1Level21 = 2; // 0x2
+ field public static final int AV1Level22 = 4; // 0x4
+ field public static final int AV1Level23 = 8; // 0x8
+ field public static final int AV1Level3 = 16; // 0x10
+ field public static final int AV1Level31 = 32; // 0x20
+ field public static final int AV1Level32 = 64; // 0x40
+ field public static final int AV1Level33 = 128; // 0x80
+ field public static final int AV1Level4 = 256; // 0x100
+ field public static final int AV1Level41 = 512; // 0x200
+ field public static final int AV1Level42 = 1024; // 0x400
+ field public static final int AV1Level43 = 2048; // 0x800
+ field public static final int AV1Level5 = 4096; // 0x1000
+ field public static final int AV1Level51 = 8192; // 0x2000
+ field public static final int AV1Level52 = 16384; // 0x4000
+ field public static final int AV1Level53 = 32768; // 0x8000
+ field public static final int AV1Level6 = 65536; // 0x10000
+ field public static final int AV1Level61 = 131072; // 0x20000
+ field public static final int AV1Level62 = 262144; // 0x40000
+ field public static final int AV1Level63 = 524288; // 0x80000
+ field public static final int AV1Level7 = 1048576; // 0x100000
+ field public static final int AV1Level71 = 2097152; // 0x200000
+ field public static final int AV1Level72 = 4194304; // 0x400000
+ field public static final int AV1Level73 = 8388608; // 0x800000
+ field public static final int AV1Profile0 = 1; // 0x1
+ field public static final int AV1Profile1 = 2; // 0x2
+ field public static final int AV1Profile2 = 4; // 0x4
field public static final int AVCLevel1 = 1; // 0x1
field public static final int AVCLevel11 = 4; // 0x4
field public static final int AVCLevel12 = 8; // 0x8
@@ -24390,6 +24431,9 @@ package android.media {
field public static final int AVCLevel5 = 16384; // 0x4000
field public static final int AVCLevel51 = 32768; // 0x8000
field public static final int AVCLevel52 = 65536; // 0x10000
+ field public static final int AVCLevel6 = 131072; // 0x20000
+ field public static final int AVCLevel61 = 262144; // 0x40000
+ field public static final int AVCLevel62 = 524288; // 0x80000
field public static final int AVCProfileBaseline = 1; // 0x1
field public static final int AVCProfileConstrainedBaseline = 65536; // 0x10000
field public static final int AVCProfileConstrainedHigh = 524288; // 0x80000
@@ -24552,12 +24596,53 @@ package android.media {
method public android.util.Range<java.lang.Double> getSupportedFrameRatesFor(int, int);
method public android.util.Range<java.lang.Integer> getSupportedHeights();
method public android.util.Range<java.lang.Integer> getSupportedHeightsFor(int);
+ method public java.util.List<android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint> getSupportedPerformancePoints();
method public android.util.Range<java.lang.Integer> getSupportedWidths();
method public android.util.Range<java.lang.Integer> getSupportedWidthsFor(int);
method public int getWidthAlignment();
method public boolean isSizeSupported(int, int);
}
+ public static final class MediaCodecInfo.VideoCapabilities.PerformancePoint {
+ method public boolean covers(android.media.MediaFormat);
+ field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_100;
+ field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_120;
+ field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_200;
+ field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_24;
+ field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_240;
+ field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_25;
+ field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_30;
+ field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_50;
+ field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_60;
+ field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_100;
+ field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_120;
+ field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_200;
+ field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_24;
+ field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_240;
+ field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_25;
+ field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_30;
+ field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_50;
+ field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_60;
+ field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint SD_24;
+ field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint SD_25;
+ field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint SD_30;
+ field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint SD_48;
+ field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint SD_50;
+ field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint SD_60;
+ field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_100;
+ field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_120;
+ field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_200;
+ field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_24;
+ field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_240;
+ field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_25;
+ field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_30;
+ field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_50;
+ field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_60;
+ field public final int frameRate;
+ field public final int height;
+ field public final int width;
+ }
+
public final class MediaCodecList {
ctor public MediaCodecList(int);
method public java.lang.String findDecoderForFormat(android.media.MediaFormat);
@@ -24574,6 +24659,7 @@ package android.media {
ctor public MediaController2(android.content.Context, android.media.Session2Token, java.util.concurrent.Executor, android.media.MediaController2.ControllerCallback);
method public void cancelSessionCommand(java.lang.Object);
method public void close();
+ method public boolean isPlaybackActive();
method public java.lang.Object sendSessionCommand(android.media.Session2Command, android.os.Bundle);
}
@@ -24582,6 +24668,7 @@ package android.media {
method public void onCommandResult(android.media.MediaController2, java.lang.Object, android.media.Session2Command, android.media.Session2Command.Result);
method public void onConnected(android.media.MediaController2, android.media.Session2CommandGroup);
method public void onDisconnected(android.media.MediaController2);
+ method public void onPlaybackActiveChanged(android.media.MediaController2, boolean);
method public android.media.Session2Command.Result onSessionCommand(android.media.MediaController2, android.media.Session2Command, android.os.Bundle);
}
@@ -25010,6 +25097,7 @@ package android.media {
field public static final java.lang.String MIMETYPE_TEXT_CEA_708 = "text/cea-708";
field public static final java.lang.String MIMETYPE_TEXT_SUBRIP = "application/x-subrip";
field public static final java.lang.String MIMETYPE_TEXT_VTT = "text/vtt";
+ field public static final java.lang.String MIMETYPE_VIDEO_AV1 = "video/av01";
field public static final java.lang.String MIMETYPE_VIDEO_AVC = "video/avc";
field public static final java.lang.String MIMETYPE_VIDEO_DOLBY_VISION = "video/dolby-vision";
field public static final java.lang.String MIMETYPE_VIDEO_H263 = "video/3gpp";
@@ -25923,7 +26011,9 @@ package android.media {
method public void close();
method public java.lang.String getSessionId();
method public android.media.Session2Token getSessionToken();
+ method public boolean isPlaybackActive();
method public java.lang.Object sendSessionCommand(android.media.MediaSession2.ControllerInfo, android.media.Session2Command, android.os.Bundle);
+ method public void setPlaybackActive(boolean);
}
public static final class MediaSession2.Builder {
@@ -29831,7 +29921,7 @@ package android.net.wifi {
method public android.net.wifi.WifiInfo getConnectionInfo();
method public android.net.DhcpInfo getDhcpInfo();
method public int getMaxNumberOfNetworkSuggestionsPerApp();
- method public java.util.List<android.net.wifi.hotspot2.PasspointConfiguration> getPasspointConfigurations();
+ method public deprecated java.util.List<android.net.wifi.hotspot2.PasspointConfiguration> getPasspointConfigurations();
method public java.util.List<android.net.wifi.ScanResult> getScanResults();
method public int getWifiState();
method public boolean is5GHzBandSupported();
@@ -29851,7 +29941,7 @@ package android.net.wifi {
method public deprecated boolean reconnect();
method public deprecated boolean removeNetwork(int);
method public int removeNetworkSuggestions(java.util.List<android.net.wifi.WifiNetworkSuggestion>);
- method public void removePasspointConfiguration(java.lang.String);
+ method public deprecated void removePasspointConfiguration(java.lang.String);
method public deprecated boolean saveConfiguration();
method public void setTdlsEnabled(java.net.InetAddress, boolean);
method public void setTdlsEnabledWithMacAddress(java.lang.String, boolean);
@@ -52589,6 +52679,7 @@ package android.view.contentcapture {
method public final void notifyViewAppeared(android.view.ViewStructure);
method public final void notifyViewDisappeared(android.view.autofill.AutofillId);
method public final void notifyViewTextChanged(android.view.autofill.AutofillId, java.lang.CharSequence, int);
+ method public final void notifyViewsDisappeared(android.view.autofill.AutofillId, int[]);
field public static final int FLAG_USER_INPUT = 1; // 0x1
}
diff --git a/api/system-current.txt b/api/system-current.txt
index 7ea7afbb8d20..5b153f04945b 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -197,6 +197,7 @@ package android {
}
public static final class R.array {
+ field public static final int config_defaultRoleHolders = 17235974; // 0x1070006
field public static final int config_keySystemUuidMapping = 17235973; // 0x1070005
}
@@ -1570,6 +1571,18 @@ package android.content.pm {
field public int requestRes;
}
+ public class ShortcutManager {
+ method public java.util.List<android.content.pm.ShortcutManager.ShareShortcutInfo> getShareTargets(android.content.IntentFilter);
+ }
+
+ public static final class ShortcutManager.ShareShortcutInfo implements android.os.Parcelable {
+ method public int describeContents();
+ method public android.content.pm.ShortcutInfo getShortcutInfo();
+ method public android.content.ComponentName getTargetComponent();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.content.pm.ShortcutManager.ShareShortcutInfo> CREATOR;
+ }
+
public final class SuspendDialogInfo implements android.os.Parcelable {
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
@@ -4143,12 +4156,19 @@ package android.net.wifi {
field public static final int WPA2_PSK = 4; // 0x4
}
+ public class WifiInfo implements android.os.Parcelable {
+ method public boolean isOsuAp();
+ }
+
public class WifiManager {
method public void connect(android.net.wifi.WifiConfiguration, android.net.wifi.WifiManager.ActionListener);
method public void connect(int, android.net.wifi.WifiManager.ActionListener);
method public void disable(int, android.net.wifi.WifiManager.ActionListener);
method public void disableEphemeralNetwork(java.lang.String);
method public void forget(int, android.net.wifi.WifiManager.ActionListener);
+ method public java.util.List<android.util.Pair<android.net.wifi.WifiConfiguration, java.util.Map<java.lang.Integer, java.util.List<android.net.wifi.ScanResult>>>> getAllMatchingWifiConfigs(java.util.List<android.net.wifi.ScanResult>);
+ method public java.util.Map<android.net.wifi.hotspot2.OsuProvider, java.util.List<android.net.wifi.ScanResult>> getMatchingOsuProviders(java.util.List<android.net.wifi.ScanResult>);
+ method public java.util.Map<android.net.wifi.hotspot2.OsuProvider, android.net.wifi.hotspot2.PasspointConfiguration> getMatchingPasspointConfigsForOsuProviders(java.util.Set<android.net.wifi.hotspot2.OsuProvider>);
method public java.util.List<android.net.wifi.WifiConfiguration> getPrivilegedConfiguredNetworks();
method public android.net.wifi.WifiConfiguration getWifiApConfiguration();
method public int getWifiApState();
@@ -4163,6 +4183,7 @@ package android.net.wifi {
method public void startEasyConnectAsConfiguratorInitiator(java.lang.String, int, int, android.os.Handler, android.net.wifi.EasyConnectStatusCallback);
method public void startEasyConnectAsEnrolleeInitiator(java.lang.String, android.os.Handler, android.net.wifi.EasyConnectStatusCallback);
method public boolean startScan(android.os.WorkSource);
+ method public void startSubscriptionProvisioning(android.net.wifi.hotspot2.OsuProvider, android.net.wifi.hotspot2.ProvisioningCallback, android.os.Handler);
method public void stopEasyConnectSession();
method public void unregisterNetworkRequestMatchCallback(android.net.wifi.WifiManager.NetworkRequestMatchCallback);
field public static final int CHANGE_REASON_ADDED = 0; // 0x0
@@ -4182,6 +4203,8 @@ package android.net.wifi {
field public static final java.lang.String EXTRA_WIFI_CONFIGURATION = "wifiConfiguration";
field public static final java.lang.String EXTRA_WIFI_CREDENTIAL_EVENT_TYPE = "et";
field public static final java.lang.String EXTRA_WIFI_CREDENTIAL_SSID = "ssid";
+ field public static final int PASSPOINT_HOME_NETWORK = 0; // 0x0
+ field public static final int PASSPOINT_ROAMING_NETWORK = 1; // 0x1
field public static final java.lang.String WIFI_AP_STATE_CHANGED_ACTION = "android.net.wifi.WIFI_AP_STATE_CHANGED";
field public static final int WIFI_AP_STATE_DISABLED = 11; // 0xb
field public static final int WIFI_AP_STATE_DISABLING = 10; // 0xa
@@ -4358,6 +4381,59 @@ package android.net.wifi.aware {
}
+package android.net.wifi.hotspot2 {
+
+ public final class OsuProvider implements android.os.Parcelable {
+ method public int describeContents();
+ method public java.lang.String getFriendlyName();
+ method public android.net.Uri getServerUri();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.OsuProvider> CREATOR;
+ }
+
+ public abstract class ProvisioningCallback {
+ ctor public ProvisioningCallback();
+ method public abstract void onProvisioningComplete();
+ method public abstract void onProvisioningFailure(int);
+ method public abstract void onProvisioningStatus(int);
+ field public static final int OSU_FAILURE_ADD_PASSPOINT_CONFIGURATION = 22; // 0x16
+ field public static final int OSU_FAILURE_AP_CONNECTION = 1; // 0x1
+ field public static final int OSU_FAILURE_INVALID_SERVER_URL = 8; // 0x8
+ field public static final int OSU_FAILURE_NO_AAA_SERVER_TRUST_ROOT_NODE = 17; // 0x11
+ field public static final int OSU_FAILURE_NO_AAA_TRUST_ROOT_CERTIFICATE = 21; // 0x15
+ field public static final int OSU_FAILURE_NO_OSU_ACTIVITY_FOUND = 14; // 0xe
+ field public static final int OSU_FAILURE_NO_POLICY_SERVER_TRUST_ROOT_NODE = 19; // 0x13
+ field public static final int OSU_FAILURE_NO_PPS_MO = 16; // 0x10
+ field public static final int OSU_FAILURE_NO_REMEDIATION_SERVER_TRUST_ROOT_NODE = 18; // 0x12
+ field public static final int OSU_FAILURE_OSU_PROVIDER_NOT_FOUND = 23; // 0x17
+ field public static final int OSU_FAILURE_PROVISIONING_ABORTED = 6; // 0x6
+ field public static final int OSU_FAILURE_PROVISIONING_NOT_AVAILABLE = 7; // 0x7
+ field public static final int OSU_FAILURE_RETRIEVE_TRUST_ROOT_CERTIFICATES = 20; // 0x14
+ field public static final int OSU_FAILURE_SERVER_CONNECTION = 3; // 0x3
+ field public static final int OSU_FAILURE_SERVER_URL_INVALID = 2; // 0x2
+ field public static final int OSU_FAILURE_SERVER_VALIDATION = 4; // 0x4
+ field public static final int OSU_FAILURE_SERVICE_PROVIDER_VERIFICATION = 5; // 0x5
+ field public static final int OSU_FAILURE_SOAP_MESSAGE_EXCHANGE = 11; // 0xb
+ field public static final int OSU_FAILURE_START_REDIRECT_LISTENER = 12; // 0xc
+ field public static final int OSU_FAILURE_TIMED_OUT_REDIRECT_LISTENER = 13; // 0xd
+ field public static final int OSU_FAILURE_UNEXPECTED_COMMAND_TYPE = 9; // 0x9
+ field public static final int OSU_FAILURE_UNEXPECTED_SOAP_MESSAGE_STATUS = 15; // 0xf
+ field public static final int OSU_FAILURE_UNEXPECTED_SOAP_MESSAGE_TYPE = 10; // 0xa
+ field public static final int OSU_STATUS_AP_CONNECTED = 2; // 0x2
+ field public static final int OSU_STATUS_AP_CONNECTING = 1; // 0x1
+ field public static final int OSU_STATUS_INIT_SOAP_EXCHANGE = 6; // 0x6
+ field public static final int OSU_STATUS_REDIRECT_RESPONSE_RECEIVED = 8; // 0x8
+ field public static final int OSU_STATUS_RETRIEVING_TRUST_ROOT_CERTS = 11; // 0xb
+ field public static final int OSU_STATUS_SECOND_SOAP_EXCHANGE = 9; // 0x9
+ field public static final int OSU_STATUS_SERVER_CONNECTED = 5; // 0x5
+ field public static final int OSU_STATUS_SERVER_CONNECTING = 3; // 0x3
+ field public static final int OSU_STATUS_SERVER_VALIDATED = 4; // 0x4
+ field public static final int OSU_STATUS_THIRD_SOAP_EXCHANGE = 10; // 0xa
+ field public static final int OSU_STATUS_WAITING_FOR_REDIRECT_RESPONSE = 7; // 0x7
+ }
+
+}
+
package android.net.wifi.rtt {
public static final class RangingRequest.Builder {
@@ -5028,6 +5104,7 @@ package android.provider {
method public static void removeOnPropertyChangedListener(android.provider.DeviceConfig.OnPropertyChangedListener);
method public static void resetToDefaults(int, java.lang.String);
method public static boolean setProperty(java.lang.String, java.lang.String, java.lang.String, boolean);
+ field public static final java.lang.String NAMESPACE_GAME_DRIVER = "game_driver";
field public static final java.lang.String NAMESPACE_INPUT_NATIVE_BOOT = "input_native_boot";
}
@@ -6270,6 +6347,30 @@ package android.telephony {
field public static final java.lang.String KEY_CARRIER_SETUP_APP_STRING = "carrier_setup_app_string";
}
+ public final class CarrierRestrictionRules implements android.os.Parcelable {
+ method public int describeContents();
+ method public java.util.List<android.service.carrier.CarrierIdentifier> getAllowedCarriers();
+ method public int getDefaultCarrierRestriction();
+ method public java.util.List<android.service.carrier.CarrierIdentifier> getExcludedCarriers();
+ method public int getMultiSimPolicy();
+ method public boolean isAllCarriersAllowed();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final int CARRIER_RESTRICTION_DEFAULT_ALLOWED = 1; // 0x1
+ field public static final int CARRIER_RESTRICTION_DEFAULT_NOT_ALLOWED = 0; // 0x0
+ field public static final android.os.Parcelable.Creator<android.telephony.CarrierRestrictionRules> CREATOR;
+ field public static final int MULTISIM_POLICY_NONE = 0; // 0x0
+ field public static final int MULTISIM_POLICY_ONE_VALID_SIM_MUST_BE_PRESENT = 1; // 0x1
+ }
+
+ public static class CarrierRestrictionRules.Builder {
+ method public android.telephony.CarrierRestrictionRules build();
+ method public android.telephony.CarrierRestrictionRules.Builder setAllCarriersAllowed();
+ method public android.telephony.CarrierRestrictionRules.Builder setAllowedCarriers(java.util.List<android.service.carrier.CarrierIdentifier>);
+ method public android.telephony.CarrierRestrictionRules.Builder setDefaultCarrierRestriction(int);
+ method public android.telephony.CarrierRestrictionRules.Builder setExcludedCarriers(java.util.List<android.service.carrier.CarrierIdentifier>);
+ method public android.telephony.CarrierRestrictionRules.Builder setMultiSimPolicy(int);
+ }
+
public final class DataFailCause {
field public static final int ACTIVATION_REJECT_GGSN = 30; // 0x1e
field public static final int ACTIVATION_REJECT_UNSPECIFIED = 31; // 0x1f
@@ -6765,10 +6866,11 @@ package android.telephony {
method public boolean enableDataConnectivity();
method public void enableVideoCalling(boolean);
method public java.lang.String getAidForAppType(int);
- method public java.util.List<android.service.carrier.CarrierIdentifier> getAllowedCarriers(int);
+ method public deprecated java.util.List<android.service.carrier.CarrierIdentifier> getAllowedCarriers(int);
method public int getCardIdForDefaultEuicc();
method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent);
method public java.util.List<java.lang.String> getCarrierPackageNamesForIntentAndPhone(android.content.Intent, int);
+ method public android.telephony.CarrierRestrictionRules getCarrierRestrictionRules();
method public java.lang.String getCdmaMdn();
method public java.lang.String getCdmaMdn(int);
method public java.lang.String getCdmaMin();
@@ -6807,8 +6909,9 @@ package android.telephony {
method public void requestCellInfoUpdate(android.os.WorkSource, java.util.concurrent.Executor, android.telephony.TelephonyManager.CellInfoCallback);
method public void requestNumberVerification(android.telephony.PhoneNumberRange, long, java.util.concurrent.Executor, android.telephony.NumberVerificationCallback);
method public boolean resetRadioConfig();
- method public int setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>);
+ method public deprecated int setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>);
method public void setCarrierDataEnabled(boolean);
+ method public int setCarrierRestrictionRules(android.telephony.CarrierRestrictionRules);
method public void setDataActivationState(int);
method public deprecated void setDataEnabled(int, boolean);
method public void setDataRoamingEnabled(boolean);
@@ -6860,6 +6963,9 @@ package android.telephony {
field public static final int RADIO_POWER_OFF = 0; // 0x0
field public static final int RADIO_POWER_ON = 1; // 0x1
field public static final int RADIO_POWER_UNAVAILABLE = 2; // 0x2
+ field public static final int SET_CARRIER_RESTRICTION_ERROR = 2; // 0x2
+ field public static final int SET_CARRIER_RESTRICTION_NOT_SUPPORTED = 1; // 0x1
+ field public static final int SET_CARRIER_RESTRICTION_SUCCESS = 0; // 0x0
field public static final int SIM_ACTIVATION_STATE_ACTIVATED = 2; // 0x2
field public static final int SIM_ACTIVATION_STATE_ACTIVATING = 1; // 0x1
field public static final int SIM_ACTIVATION_STATE_DEACTIVATED = 3; // 0x3
@@ -7190,6 +7296,7 @@ package android.telephony.ims {
method public int getServiceType();
method public static int getVideoStateFromCallType(int);
method public static int getVideoStateFromImsCallProfile(android.telephony.ims.ImsCallProfile);
+ method public boolean isEmergencyCallTesting();
method public boolean isVideoCall();
method public boolean isVideoPaused();
method public static int presentationToOir(int);
@@ -7198,6 +7305,7 @@ package android.telephony.ims {
method public void setCallExtraInt(java.lang.String, int);
method public void setCallRestrictCause(int);
method public void setEmergencyCallRouting(int);
+ method public void setEmergencyCallTesting(boolean);
method public void setEmergencyServiceCategories(int);
method public void setEmergencyUrns(java.util.List<java.lang.String>);
method public void updateCallExtras(android.telephony.ims.ImsCallProfile);
diff --git a/api/test-current.txt b/api/test-current.txt
index 846442dbe031..e0e0f3506ad4 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -580,6 +580,8 @@ package android.hardware.display {
public final class BrightnessConfiguration implements android.os.Parcelable {
method public int describeContents();
+ method public android.hardware.display.BrightnessCorrection getCorrectionByCategory(int);
+ method public android.hardware.display.BrightnessCorrection getCorrectionByPackageName(java.lang.String);
method public android.util.Pair<float[], float[]> getCurve();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.hardware.display.BrightnessConfiguration> CREATOR;
@@ -587,10 +589,22 @@ package android.hardware.display {
public static class BrightnessConfiguration.Builder {
ctor public BrightnessConfiguration.Builder(float[], float[]);
+ method public android.hardware.display.BrightnessConfiguration.Builder addCorrectionByCategory(int, android.hardware.display.BrightnessCorrection);
+ method public android.hardware.display.BrightnessConfiguration.Builder addCorrectionByPackageName(java.lang.String, android.hardware.display.BrightnessCorrection);
method public android.hardware.display.BrightnessConfiguration build();
+ method public int getMaxCorrectionsByCategory();
+ method public int getMaxCorrectionsByPackageName();
method public android.hardware.display.BrightnessConfiguration.Builder setDescription(java.lang.String);
}
+ public final class BrightnessCorrection implements android.os.Parcelable {
+ method public float apply(float);
+ method public static android.hardware.display.BrightnessCorrection createScaleAndTranslateLog(float, float);
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.hardware.display.BrightnessCorrection> CREATOR;
+ }
+
public final class DisplayManager {
method public java.util.List<android.hardware.display.AmbientBrightnessDayStats> getAmbientBrightnessStats();
method public android.hardware.display.BrightnessConfiguration getBrightnessConfiguration();
@@ -1104,6 +1118,24 @@ package android.os {
field public static final android.os.Parcelable.Creator<android.os.VibrationEffect.Waveform> CREATOR;
}
+ public class VintfObject {
+ method public static java.lang.String[] getHalNamesAndVersions();
+ method public static java.lang.String getSepolicyVersion();
+ method public static java.lang.Long getTargetFrameworkCompatibilityMatrixVersion();
+ method public static java.util.Map<java.lang.String, java.lang.String[]> getVndkSnapshots();
+ method public static java.lang.String[] report();
+ }
+
+ public class VintfRuntimeInfo {
+ method public static java.lang.String getCpuInfo();
+ method public static java.lang.String getHardwareId();
+ method public static java.lang.String getKernelVersion();
+ method public static java.lang.String getNodeName();
+ method public static java.lang.String getOsName();
+ method public static java.lang.String getOsRelease();
+ method public static java.lang.String getOsVersion();
+ }
+
public class WorkSource implements android.os.Parcelable {
ctor public WorkSource(int);
method public boolean add(int);
diff --git a/cmds/idmap2/Android.bp b/cmds/idmap2/Android.bp
index abe18ba8a415..803f83c0bc6f 100644
--- a/cmds/idmap2/Android.bp
+++ b/cmds/idmap2/Android.bp
@@ -20,6 +20,7 @@ cc_defaults {
"misc-*",
"modernize-*",
"readability-*",
+ "-modernize-avoid-c-arrays",
],
tidy_flags: [
"-system-headers",
@@ -38,6 +39,7 @@ cc_library {
"libidmap2/CommandLineOptions.cpp",
"libidmap2/FileUtils.cpp",
"libidmap2/Idmap.cpp",
+ "libidmap2/Policies.cpp",
"libidmap2/PrettyPrintVisitor.cpp",
"libidmap2/RawPrintVisitor.cpp",
"libidmap2/ResourceUtils.cpp",
@@ -87,6 +89,7 @@ cc_test {
"tests/Idmap2BinaryTests.cpp",
"tests/IdmapTests.cpp",
"tests/Main.cpp",
+ "tests/PoliciesTests.cpp",
"tests/PrettyPrintVisitorTests.cpp",
"tests/RawPrintVisitorTests.cpp",
"tests/ResourceUtilsTests.cpp",
diff --git a/cmds/idmap2/idmap2/Create.cpp b/cmds/idmap2/idmap2/Create.cpp
index b07567331e85..c455ac0f83af 100644
--- a/cmds/idmap2/idmap2/Create.cpp
+++ b/cmds/idmap2/idmap2/Create.cpp
@@ -27,17 +27,25 @@
#include "idmap2/CommandLineOptions.h"
#include "idmap2/FileUtils.h"
#include "idmap2/Idmap.h"
+#include "idmap2/Policies.h"
+#include "idmap2/Result.h"
using android::ApkAssets;
using android::idmap2::BinaryStreamVisitor;
using android::idmap2::CommandLineOptions;
using android::idmap2::Idmap;
+using android::idmap2::PoliciesToBitmask;
+using android::idmap2::PolicyBitmask;
+using android::idmap2::PolicyFlags;
+using android::idmap2::Result;
using android::idmap2::utils::kIdmapFilePermissionMask;
bool Create(const std::vector<std::string>& args, std::ostream& out_error) {
std::string target_apk_path;
std::string overlay_apk_path;
std::string idmap_path;
+ std::vector<std::string> policies;
+ bool ignore_overlayable;
const CommandLineOptions opts =
CommandLineOptions("idmap2 create")
@@ -47,12 +55,28 @@ bool Create(const std::vector<std::string>& args, std::ostream& out_error) {
.MandatoryOption("--overlay-apk-path",
"input: path to apk which contains the new resource values",
&overlay_apk_path)
- .MandatoryOption("--idmap-path", "output: path to where to write idmap file",
- &idmap_path);
+ .MandatoryOption("--idmap-path", "output: path to where to write idmap file", &idmap_path)
+ .OptionalOption("--policy",
+ "input: an overlayable policy this overlay fulfills "
+ "(if none or supplied, the overlay policy will default to \"public\")",
+ &policies)
+ .OptionalFlag("--ignore-overlayable", "disables overlayable and policy checks",
+ &ignore_overlayable);
if (!opts.Parse(args, out_error)) {
return false;
}
+ PolicyBitmask fulfilled_policies = 0;
+ if (auto result = PoliciesToBitmask(policies, out_error)) {
+ fulfilled_policies |= *result;
+ } else {
+ return false;
+ }
+
+ if (fulfilled_policies == 0) {
+ fulfilled_policies |= PolicyFlags::POLICY_PUBLIC;
+ }
+
const std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
if (!target_apk) {
out_error << "error: failed to load apk " << target_apk_path << std::endl;
@@ -66,7 +90,8 @@ bool Create(const std::vector<std::string>& args, std::ostream& out_error) {
}
const std::unique_ptr<const Idmap> idmap =
- Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, out_error);
+ Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
+ fulfilled_policies, !ignore_overlayable, out_error);
if (!idmap) {
return false;
}
diff --git a/cmds/idmap2/idmap2/Scan.cpp b/cmds/idmap2/idmap2/Scan.cpp
index 4f88127f8af1..a269ee958497 100644
--- a/cmds/idmap2/idmap2/Scan.cpp
+++ b/cmds/idmap2/idmap2/Scan.cpp
@@ -21,8 +21,11 @@
#include <set>
#include <sstream>
#include <string>
+#include <utility>
#include <vector>
+#include "android-base/properties.h"
+
#include "idmap2/CommandLineOptions.h"
#include "idmap2/FileUtils.h"
#include "idmap2/Idmap.h"
@@ -34,6 +37,10 @@
using android::idmap2::CommandLineOptions;
using android::idmap2::Idmap;
using android::idmap2::MemoryChunk;
+using android::idmap2::PoliciesToBitmask;
+using android::idmap2::PolicyBitmask;
+using android::idmap2::PolicyFlags;
+using android::idmap2::Result;
using android::idmap2::Xml;
using android::idmap2::ZipFile;
using android::idmap2::utils::FindFiles;
@@ -45,11 +52,19 @@ struct InputOverlay {
return priority < rhs.priority || (priority == rhs.priority && apk_path < rhs.apk_path);
}
- std::string apk_path; // NOLINT(misc-non-private-member-variables-in-classes)
- std::string idmap_path; // NOLINT(misc-non-private-member-variables-in-classes)
- int priority; // NOLINT(misc-non-private-member-variables-in-classes)
+ std::string apk_path; // NOLINT(misc-non-private-member-variables-in-classes)
+ std::string idmap_path; // NOLINT(misc-non-private-member-variables-in-classes)
+ int priority; // NOLINT(misc-non-private-member-variables-in-classes)
+ std::vector<std::string> policies; // NOLINT(misc-non-private-member-variables-in-classes)
+ bool ignore_overlayable; // NOLINT(misc-non-private-member-variables-in-classes)
};
+bool VendorIsQOrLater() {
+ // STOPSHIP(b/119390857): Check api version once Q sdk version is finalized
+ std::string version = android::base::GetProperty("ro.vndk.version", "Q");
+ return version == "Q" || version == "q";
+}
+
std::unique_ptr<std::vector<std::string>> FindApkFiles(const std::vector<std::string>& dirs,
bool recursive, std::ostream& out_error) {
const auto predicate = [](unsigned char type, const std::string& path) -> bool {
@@ -70,6 +85,22 @@ std::unique_ptr<std::vector<std::string>> FindApkFiles(const std::vector<std::st
return std::make_unique<std::vector<std::string>>(paths.cbegin(), paths.cend());
}
+PolicyBitmask PolicyForPath(const std::string& apk_path) {
+ static const std::vector<std::pair<std::string, PolicyBitmask>> values = {
+ {"/product/", PolicyFlags::POLICY_PRODUCT_PARTITION},
+ {"/system/", PolicyFlags::POLICY_SYSTEM_PARTITION},
+ {"/vendor/", PolicyFlags::POLICY_VENDOR_PARTITION},
+ };
+
+ for (auto const& pair : values) {
+ if (apk_path.compare(0, pair.first.size(), pair.first) == 0) {
+ return pair.second | PolicyFlags::POLICY_PUBLIC;
+ }
+ }
+
+ return PolicyFlags::POLICY_PUBLIC;
+}
+
} // namespace
bool Scan(const std::vector<std::string>& args, std::ostream& out_error) {
@@ -77,6 +108,7 @@ bool Scan(const std::vector<std::string>& args, std::ostream& out_error) {
std::string target_package_name;
std::string target_apk_path;
std::string output_directory;
+ std::vector<std::string> override_policies;
bool recursive = false;
const CommandLineOptions opts =
@@ -89,7 +121,12 @@ bool Scan(const std::vector<std::string>& args, std::ostream& out_error) {
.MandatoryOption("--target-apk-path", "path to target apk", &target_apk_path)
.MandatoryOption("--output-directory",
"directory in which to write artifacts (idmap files and overlays.list)",
- &output_directory);
+ &output_directory)
+ .OptionalOption(
+ "--override-policy",
+ "input: an overlayable policy this overlay fulfills "
+ "(if none or supplied, the overlays will not have their policies overriden",
+ &override_policies);
if (!opts.Parse(args, out_error)) {
return false;
}
@@ -144,29 +181,63 @@ bool Scan(const std::vector<std::string>& args, std::ostream& out_error) {
continue;
}
- // Sort the static overlays in ascending priority order
+ PolicyBitmask fulfilled_policies;
+ if (!override_policies.empty()) {
+ if (Result<PolicyBitmask> result = PoliciesToBitmask(override_policies, out_error)) {
+ fulfilled_policies = *result;
+ } else {
+ return false;
+ }
+ } else {
+ fulfilled_policies = PolicyForPath(path);
+ }
+
+ bool ignore_overlayable = false;
+ if ((fulfilled_policies & PolicyFlags::POLICY_VENDOR_PARTITION) != 0 && !VendorIsQOrLater()) {
+ // If the overlay is on a pre-Q vendor partition, do not enforce overlayable
+ // restrictions on this overlay because the pre-Q platform has no understanding of
+ // overlayable.
+ ignore_overlayable = true;
+ }
+
std::string idmap_path = Idmap::CanonicalIdmapPathFor(output_directory, path);
- InputOverlay input{path, idmap_path, priority};
+
+ // Sort the static overlays in ascending priority order
+ InputOverlay input{path, idmap_path, priority, override_policies, ignore_overlayable};
interesting_apks.insert(
std::lower_bound(interesting_apks.begin(), interesting_apks.end(), input), input);
}
std::stringstream stream;
for (const auto& overlay : interesting_apks) {
+ // Create the idmap for the overlay if it currently does not exist or if it is not up to date.
std::stringstream dev_null;
- if (!Verify(std::vector<std::string>({"--idmap-path", overlay.idmap_path}), dev_null) &&
- !Create(std::vector<std::string>({
- "--target-apk-path",
- target_apk_path,
- "--overlay-apk-path",
- overlay.apk_path,
- "--idmap-path",
- overlay.idmap_path,
- }),
- out_error)) {
- return false;
+
+ std::vector<std::string> verify_args = {"--idmap-path", overlay.idmap_path};
+ for (const std::string& policy : overlay.policies) {
+ verify_args.emplace_back("--policy");
+ verify_args.emplace_back(policy);
}
- stream << overlay.idmap_path << std::endl;
+
+ if (!Verify(std::vector<std::string>(verify_args), dev_null)) {
+ std::vector<std::string> create_args = {"--target-apk-path", target_apk_path,
+ "--overlay-apk-path", overlay.apk_path,
+ "--idmap-path", overlay.idmap_path};
+ if (overlay.ignore_overlayable) {
+ create_args.emplace_back("--ignore-overlayable");
+ }
+
+ for (const std::string& policy : overlay.policies) {
+ verify_args.emplace_back("--policy");
+ verify_args.emplace_back(policy);
+ }
+
+ if (!Create(create_args, out_error)) {
+ return false;
+ }
+ }
+
+ stream << overlay.idmap_path << std::endl;
}
std::cout << stream.str();
diff --git a/cmds/idmap2/idmap2d/Idmap2Service.cpp b/cmds/idmap2/idmap2d/Idmap2Service.cpp
index d2e46e15fc59..a3c752718ee2 100644
--- a/cmds/idmap2/idmap2d/Idmap2Service.cpp
+++ b/cmds/idmap2/idmap2d/Idmap2Service.cpp
@@ -26,12 +26,15 @@
#include <string>
#include "android-base/macros.h"
+#include "android-base/stringprintf.h"
#include "utils/String8.h"
#include "utils/Trace.h"
#include "idmap2/BinaryStreamVisitor.h"
#include "idmap2/FileUtils.h"
#include "idmap2/Idmap.h"
+#include "idmap2/Policies.h"
+#include "idmap2/Result.h"
#include "idmap2d/Idmap2Service.h"
@@ -39,6 +42,8 @@ using android::binder::Status;
using android::idmap2::BinaryStreamVisitor;
using android::idmap2::Idmap;
using android::idmap2::IdmapHeader;
+using android::idmap2::PolicyBitmask;
+using android::idmap2::Result;
using android::idmap2::utils::kIdmapFilePermissionMask;
namespace {
@@ -54,6 +59,10 @@ Status error(const std::string& msg) {
return Status::fromExceptionCode(Status::EX_NONE, msg.c_str());
}
+PolicyBitmask ConvertAidlArgToPolicyBitmask(int32_t arg) {
+ return static_cast<PolicyBitmask>(arg);
+}
+
} // namespace
namespace android::os {
@@ -78,6 +87,8 @@ Status Idmap2Service::removeIdmap(const std::string& overlay_apk_path,
}
Status Idmap2Service::verifyIdmap(const std::string& overlay_apk_path,
+ int32_t fulfilled_policies ATTRIBUTE_UNUSED,
+ bool enforce_overlayable ATTRIBUTE_UNUSED,
int32_t user_id ATTRIBUTE_UNUSED, bool* _aidl_return) {
assert(_aidl_return);
const std::string idmap_path = Idmap::CanonicalIdmapPathFor(kIdmapCacheDir, overlay_apk_path);
@@ -86,11 +97,15 @@ Status Idmap2Service::verifyIdmap(const std::string& overlay_apk_path,
fin.close();
std::stringstream dev_null;
*_aidl_return = header && header->IsUpToDate(dev_null);
+
+ // TODO(b/119328308): Check that the set of fulfilled policies of the overlay has not changed
+
return ok();
}
Status Idmap2Service::createIdmap(const std::string& target_apk_path,
- const std::string& overlay_apk_path, int32_t user_id,
+ const std::string& overlay_apk_path, int32_t fulfilled_policies,
+ bool enforce_overlayable, int32_t user_id,
std::unique_ptr<std::string>* _aidl_return) {
assert(_aidl_return);
std::stringstream trace;
@@ -101,6 +116,8 @@ Status Idmap2Service::createIdmap(const std::string& target_apk_path,
_aidl_return->reset(nullptr);
+ const PolicyBitmask policy_bitmask = ConvertAidlArgToPolicyBitmask(fulfilled_policies);
+
const std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
if (!target_apk) {
return error("failed to load apk " + target_apk_path);
@@ -113,7 +130,8 @@ Status Idmap2Service::createIdmap(const std::string& target_apk_path,
std::stringstream err;
const std::unique_ptr<const Idmap> idmap =
- Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, err);
+ Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
+ policy_bitmask, enforce_overlayable, err);
if (!idmap) {
return error(err.str());
}
diff --git a/cmds/idmap2/idmap2d/Idmap2Service.h b/cmds/idmap2/idmap2d/Idmap2Service.h
index e0bc22e9e9e6..1aab0598449b 100644
--- a/cmds/idmap2/idmap2d/Idmap2Service.h
+++ b/cmds/idmap2/idmap2d/Idmap2Service.h
@@ -39,11 +39,12 @@ class Idmap2Service : public BinderService<Idmap2Service>, public BnIdmap2 {
binder::Status removeIdmap(const std::string& overlay_apk_path, int32_t user_id,
bool* _aidl_return);
- binder::Status verifyIdmap(const std::string& overlay_apk_path, int32_t user_id,
- bool* _aidl_return);
+ binder::Status verifyIdmap(const std::string& overlay_apk_path, int32_t fulfilled_policies,
+ bool enforce_overlayable, int32_t user_id, bool* _aidl_return);
binder::Status createIdmap(const std::string& target_apk_path,
- const std::string& overlay_apk_path, int32_t user_id,
+ const std::string& overlay_apk_path, int32_t fulfilled_policies,
+ bool enforce_overlayable, int32_t user_id,
std::unique_ptr<std::string>* _aidl_return);
};
diff --git a/cmds/idmap2/idmap2d/aidl/android/os/IIdmap2.aidl b/cmds/idmap2/idmap2d/aidl/android/os/IIdmap2.aidl
index d475417a0935..ea7274f3ea58 100644
--- a/cmds/idmap2/idmap2d/aidl/android/os/IIdmap2.aidl
+++ b/cmds/idmap2/idmap2d/aidl/android/os/IIdmap2.aidl
@@ -20,9 +20,18 @@ package android.os;
* @hide
*/
interface IIdmap2 {
+ const int POLICY_PUBLIC = 0x00000001;
+ const int POLICY_SYSTEM_PARTITION = 0x00000002;
+ const int POLICY_VENDOR_PARTITION = 0x00000004;
+ const int POLICY_PRODUCT_PARTITION = 0x00000008;
+
@utf8InCpp String getIdmapPath(@utf8InCpp String overlayApkPath, int userId);
boolean removeIdmap(@utf8InCpp String overlayApkPath, int userId);
- boolean verifyIdmap(@utf8InCpp String overlayApkPath, int userId);
+ boolean verifyIdmap(@utf8InCpp String overlayApkPath, int fulfilledPolicies,
+ boolean enforceOverlayable, int userId);
@nullable @utf8InCpp String createIdmap(@utf8InCpp String targetApkPath,
- @utf8InCpp String overlayApkPath, int userId);
+ @utf8InCpp String overlayApkPath,
+ int fulfilledPolicies,
+ boolean enforceOverlayable,
+ int userId);
}
diff --git a/cmds/idmap2/include/idmap2/CommandLineOptions.h b/cmds/idmap2/include/idmap2/CommandLineOptions.h
index b93e71631d08..6db6bf9ea8ad 100644
--- a/cmds/idmap2/include/idmap2/CommandLineOptions.h
+++ b/cmds/idmap2/include/idmap2/CommandLineOptions.h
@@ -44,6 +44,8 @@ class CommandLineOptions {
std::vector<std::string>* value);
CommandLineOptions& OptionalOption(const std::string& name, const std::string& description,
std::string* value);
+ CommandLineOptions& OptionalOption(const std::string& name, const std::string& description,
+ std::vector<std::string>* value);
bool Parse(const std::vector<std::string>& argv, std::ostream& outError) const;
void Usage(std::ostream& out) const;
@@ -56,6 +58,7 @@ class CommandLineOptions {
COUNT_OPTIONAL,
COUNT_EXACTLY_ONCE,
COUNT_ONCE_OR_MORE,
+ COUNT_OPTIONAL_ONCE_OR_MORE,
} count;
bool argument;
};
diff --git a/cmds/idmap2/include/idmap2/Idmap.h b/cmds/idmap2/include/idmap2/Idmap.h
index b989e4c3f9d1..1666dc8a3bbd 100644
--- a/cmds/idmap2/include/idmap2/Idmap.h
+++ b/cmds/idmap2/include/idmap2/Idmap.h
@@ -57,6 +57,8 @@
#include "androidfw/ResourceTypes.h"
#include "androidfw/StringPiece.h"
+#include "idmap2/Policies.h"
+
namespace android::idmap2 {
class Idmap;
@@ -233,11 +235,10 @@ class Idmap {
// file is used; change this in the next version of idmap to use a named
// package instead; also update FromApkAssets to take additional parameters:
// the target and overlay package names
- static std::unique_ptr<const Idmap> FromApkAssets(const std::string& target_apk_path,
- const ApkAssets& target_apk_assets,
- const std::string& overlay_apk_path,
- const ApkAssets& overlay_apk_assets,
- std::ostream& out_error);
+ static std::unique_ptr<const Idmap> FromApkAssets(
+ const std::string& target_apk_path, const ApkAssets& target_apk_assets,
+ const std::string& overlay_apk_path, const ApkAssets& overlay_apk_assets,
+ const PolicyBitmask& fulfilled_policies, bool enforce_overlayable, std::ostream& out_error);
inline const std::unique_ptr<const IdmapHeader>& GetHeader() const {
return header_;
diff --git a/cmds/idmap2/include/idmap2/Policies.h b/cmds/idmap2/include/idmap2/Policies.h
new file mode 100644
index 000000000000..eecee25445e2
--- /dev/null
+++ b/cmds/idmap2/include/idmap2/Policies.h
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+#include <ostream>
+#include <string>
+#include <vector>
+
+#include "androidfw/ResourceTypes.h"
+#include "androidfw/StringPiece.h"
+
+#include "Result.h"
+
+#ifndef IDMAP2_INCLUDE_IDMAP2_POLICIES_H_
+#define IDMAP2_INCLUDE_IDMAP2_POLICIES_H_
+
+namespace android::idmap2 {
+
+using PolicyFlags = ResTable_overlayable_policy_header::PolicyFlags;
+using PolicyBitmask = uint32_t;
+
+// Parses a the string representation of a set of policies into a bitmask. The format of the string
+// is the same as for the <policy> element.
+Result<PolicyBitmask> PoliciesToBitmask(const std::vector<std::string>& policies,
+ std::ostream& err);
+
+} // namespace android::idmap2
+
+#endif // IDMAP2_INCLUDE_IDMAP2_POLICIES_H_
diff --git a/cmds/idmap2/libidmap2/CommandLineOptions.cpp b/cmds/idmap2/libidmap2/CommandLineOptions.cpp
index cabc8f398c46..a49a607091a4 100644
--- a/cmds/idmap2/libidmap2/CommandLineOptions.cpp
+++ b/cmds/idmap2/libidmap2/CommandLineOptions.cpp
@@ -68,9 +68,18 @@ CommandLineOptions& CommandLineOptions::OptionalOption(const std::string& name,
return *this;
}
+CommandLineOptions& CommandLineOptions::OptionalOption(const std::string& name,
+ const std::string& description,
+ std::vector<std::string>* value) {
+ assert(value != nullptr);
+ auto func = [value](const std::string& arg) -> void { value->push_back(arg); };
+ options_.push_back(Option{name, description, func, Option::COUNT_OPTIONAL_ONCE_OR_MORE, true});
+ return *this;
+}
+
bool CommandLineOptions::Parse(const std::vector<std::string>& argv, std::ostream& outError) const {
const auto pivot = std::partition(options_.begin(), options_.end(), [](const Option& opt) {
- return opt.count != Option::COUNT_OPTIONAL;
+ return opt.count != Option::COUNT_OPTIONAL && opt.count != Option::COUNT_OPTIONAL_ONCE_OR_MORE;
});
std::set<std::string> mandatory_opts;
std::transform(options_.begin(), pivot, std::inserter(mandatory_opts, mandatory_opts.end()),
@@ -122,7 +131,8 @@ void CommandLineOptions::Usage(std::ostream& out) const {
size_t maxLength = 0;
out << "usage: " << name_;
for (const Option& opt : options_) {
- const bool mandatory = opt.count != Option::COUNT_OPTIONAL;
+ const bool mandatory =
+ opt.count != Option::COUNT_OPTIONAL && opt.count != Option::COUNT_OPTIONAL_ONCE_OR_MORE;
out << " ";
if (!mandatory) {
out << "[";
@@ -134,9 +144,15 @@ void CommandLineOptions::Usage(std::ostream& out) const {
out << opt.name;
maxLength = std::max(maxLength, opt.name.size());
}
+
+ if (opt.count == Option::COUNT_OPTIONAL_ONCE_OR_MORE) {
+ out << " [..]";
+ }
+
if (!mandatory) {
out << "]";
}
+
if (opt.count == Option::COUNT_ONCE_OR_MORE) {
out << " [" << opt.name << " arg [..]]";
}
@@ -150,7 +166,8 @@ void CommandLineOptions::Usage(std::ostream& out) const {
out << opt.name;
}
out << " " << opt.description;
- if (opt.count == Option::COUNT_ONCE_OR_MORE) {
+ if (opt.count == Option::COUNT_ONCE_OR_MORE ||
+ opt.count == Option::COUNT_OPTIONAL_ONCE_OR_MORE) {
out << " (can be provided multiple times)";
}
out << std::endl;
diff --git a/cmds/idmap2/libidmap2/Idmap.cpp b/cmds/idmap2/libidmap2/Idmap.cpp
index 37d6af8fa477..2890ae11b0af 100644
--- a/cmds/idmap2/libidmap2/Idmap.cpp
+++ b/cmds/idmap2/libidmap2/Idmap.cpp
@@ -274,11 +274,23 @@ std::unique_ptr<const Idmap> Idmap::FromBinaryStream(std::istream& stream,
return std::move(idmap);
}
-std::unique_ptr<const Idmap> Idmap::FromApkAssets(const std::string& target_apk_path,
- const ApkAssets& target_apk_assets,
- const std::string& overlay_apk_path,
- const ApkAssets& overlay_apk_assets,
- std::ostream& out_error) {
+bool CheckOverlayable(const LoadedPackage& target_package, PolicyBitmask fulfilled_polices,
+ ResourceId resid) {
+ const OverlayableInfo* info = target_package.GetOverlayableInfo(resid);
+ if (info == nullptr) {
+ // If the resource does not have an overlayable definition, allow the resource to be overlaid.
+ // Once overlayable enforcement is turned on, this check will return false.
+ return true;
+ }
+
+ // Enforce policy restrictions if the resource is declared as overlayable.
+ return (info->policy_flags & fulfilled_polices) != 0;
+}
+
+std::unique_ptr<const Idmap> Idmap::FromApkAssets(
+ const std::string& target_apk_path, const ApkAssets& target_apk_assets,
+ const std::string& overlay_apk_path, const ApkAssets& overlay_apk_assets,
+ const PolicyBitmask& fulfilled_policies, bool enforce_overlayable, std::ostream& out_error) {
AssetManager2 target_asset_manager;
if (!target_asset_manager.SetApkAssets({&target_apk_assets}, true, false)) {
out_error << "error: failed to create target asset manager" << std::endl;
@@ -380,6 +392,15 @@ std::unique_ptr<const Idmap> Idmap::FromApkAssets(const std::string& target_apk_
if (target_resid == 0) {
continue;
}
+
+ if (enforce_overlayable && !CheckOverlayable(*target_pkg, fulfilled_policies, target_resid)) {
+ // The resources must be defined as overlayable and the overlay must fulfill at least one
+ // policy enforced on the overlayable resource
+ LOG(WARNING) << "overlay \"" << overlay_apk_path << "\" is not allowed to overlay resource \""
+ << full_name << "\"" << std::endl;
+ continue;
+ }
+
matching_resources.Add(target_resid, overlay_resid);
}
diff --git a/cmds/idmap2/libidmap2/Policies.cpp b/cmds/idmap2/libidmap2/Policies.cpp
new file mode 100644
index 000000000000..0f87ef0c4ea9
--- /dev/null
+++ b/cmds/idmap2/libidmap2/Policies.cpp
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+#include <iterator>
+#include <map>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "androidfw/ResourceTypes.h"
+
+#include "idmap2/Idmap.h"
+#include "idmap2/Policies.h"
+#include "idmap2/Result.h"
+
+namespace android::idmap2 {
+
+namespace {
+
+const std::map<android::StringPiece, PolicyFlags> kStringToFlag = {
+ {"public", PolicyFlags::POLICY_PUBLIC},
+ {"product", PolicyFlags::POLICY_PRODUCT_PARTITION},
+ {"system", PolicyFlags::POLICY_SYSTEM_PARTITION},
+ {"vendor", PolicyFlags::POLICY_VENDOR_PARTITION},
+};
+} // namespace
+
+Result<PolicyBitmask> PoliciesToBitmask(const std::vector<std::string>& policies,
+ std::ostream& err) {
+ PolicyBitmask bitmask = 0;
+ for (const std::string& policy : policies) {
+ const auto iter = kStringToFlag.find(policy);
+ if (iter != kStringToFlag.end()) {
+ bitmask |= iter->second;
+ } else {
+ err << "error: unknown policy \"" << policy << "\"";
+ return kResultError;
+ }
+ }
+
+ return Result<PolicyBitmask>(bitmask);
+}
+
+} // namespace android::idmap2
diff --git a/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp b/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp
index 2698ac0a734d..35ec1ff1dbb5 100644
--- a/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp
+++ b/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp
@@ -78,7 +78,8 @@ TEST(BinaryStreamVisitorTests, CreateIdmapFromApkAssetsInteropWithLoadedIdmap) {
std::stringstream error;
std::unique_ptr<const Idmap> idmap =
- Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, error);
+ Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
+ PolicyFlags::POLICY_PUBLIC, /* enforce_overlayable */ true, error);
ASSERT_THAT(idmap, NotNull());
std::stringstream stream;
@@ -101,25 +102,52 @@ TEST(BinaryStreamVisitorTests, CreateIdmapFromApkAssetsInteropWithLoadedIdmap) {
header = loaded_idmap->GetEntryMapForType(0x02);
ASSERT_THAT(header, NotNull());
- success = LoadedIdmap::Lookup(header, 0x0002, &entry);
+ success = LoadedIdmap::Lookup(header, 0x0000, &entry); // string/a
ASSERT_FALSE(success);
- success = LoadedIdmap::Lookup(header, 0x0003, &entry);
+ success = LoadedIdmap::Lookup(header, 0x0001, &entry); // string/b
+ ASSERT_FALSE(success);
+
+ success = LoadedIdmap::Lookup(header, 0x0002, &entry); // string/c
+ ASSERT_FALSE(success);
+
+ success = LoadedIdmap::Lookup(header, 0x0003, &entry); // string/not_overlayable
+ ASSERT_FALSE(success);
+
+ success = LoadedIdmap::Lookup(header, 0x0004, &entry); // string/policy_product
+ ASSERT_FALSE(success);
+
+ success = LoadedIdmap::Lookup(header, 0x0005, &entry); // string/policy_public
+ ASSERT_FALSE(success);
+
+ success = LoadedIdmap::Lookup(header, 0x0006, &entry); // string/policy_system
+ ASSERT_FALSE(success);
+
+ success = LoadedIdmap::Lookup(header, 0x0007, &entry); // string/policy_system_vendor
+ ASSERT_FALSE(success);
+
+ success = LoadedIdmap::Lookup(header, 0x0008, &entry); // string/str1
ASSERT_TRUE(success);
ASSERT_EQ(entry, 0x0000);
- success = LoadedIdmap::Lookup(header, 0x0004, &entry);
+ success = LoadedIdmap::Lookup(header, 0x0009, &entry); // string/str2
ASSERT_FALSE(success);
- success = LoadedIdmap::Lookup(header, 0x0005, &entry);
+ success = LoadedIdmap::Lookup(header, 0x000a, &entry); // string/str3
ASSERT_TRUE(success);
ASSERT_EQ(entry, 0x0001);
- success = LoadedIdmap::Lookup(header, 0x0006, &entry);
+ success = LoadedIdmap::Lookup(header, 0x000b, &entry); // string/str4
ASSERT_TRUE(success);
ASSERT_EQ(entry, 0x0002);
- success = LoadedIdmap::Lookup(header, 0x0007, &entry);
+ success = LoadedIdmap::Lookup(header, 0x000c, &entry); // string/x
+ ASSERT_FALSE(success);
+
+ success = LoadedIdmap::Lookup(header, 0x000d, &entry); // string/y
+ ASSERT_FALSE(success);
+
+ success = LoadedIdmap::Lookup(header, 0x000e, &entry); // string/z
ASSERT_FALSE(success);
}
diff --git a/cmds/idmap2/tests/CommandLineOptionsTests.cpp b/cmds/idmap2/tests/CommandLineOptionsTests.cpp
index c27d27a16b94..39f18d3336af 100644
--- a/cmds/idmap2/tests/CommandLineOptionsTests.cpp
+++ b/cmds/idmap2/tests/CommandLineOptionsTests.cpp
@@ -121,6 +121,56 @@ TEST(CommandLineOptionsTests, OptionalOption) {
ASSERT_FALSE(success);
}
+TEST(CommandLineOptionsTests, OptionalOptionList) {
+ std::vector<std::string> foo;
+ std::vector<std::string> bar;
+ CommandLineOptions opts = CommandLineOptions("test")
+ .OptionalOption("--foo", "", &foo)
+ .OptionalOption("--bar", "", &bar);
+ std::ostream fakeStdErr(nullptr);
+ bool success = opts.Parse({"--foo", "FOO", "--bar", "BAR"}, fakeStdErr);
+ ASSERT_TRUE(success);
+ ASSERT_EQ(foo.size(), 1U);
+ ASSERT_EQ(foo[0], "FOO");
+ ASSERT_EQ(bar.size(), 1U);
+ ASSERT_EQ(bar[0], "BAR");
+
+ foo.clear();
+ bar.clear();
+ success = opts.Parse({"--foo", "BAZ"}, fakeStdErr);
+ ASSERT_TRUE(success);
+ ASSERT_EQ(foo.size(), 1U);
+ ASSERT_EQ(foo[0], "BAZ");
+ ASSERT_EQ(bar.size(), 0U);
+
+ foo.clear();
+ bar.clear();
+ success =
+ opts.Parse({"--foo", "BAZ", "--foo", "BIZ", "--bar", "FIZ", "--bar", "FUZZ"}, fakeStdErr);
+ ASSERT_TRUE(success);
+ ASSERT_EQ(foo.size(), 2U);
+ ASSERT_EQ(foo[0], "BAZ");
+ ASSERT_EQ(foo[1], "BIZ");
+ ASSERT_EQ(bar.size(), 2U);
+ ASSERT_EQ(bar[0], "FIZ");
+ ASSERT_EQ(bar[1], "FUZZ");
+
+ foo.clear();
+ bar.clear();
+ success = opts.Parse({"--foo"}, fakeStdErr);
+ ASSERT_FALSE(success);
+
+ foo.clear();
+ bar.clear();
+ success = opts.Parse({"--foo", "--bar", "BAR"}, fakeStdErr);
+ ASSERT_FALSE(success);
+
+ foo.clear();
+ bar.clear();
+ success = opts.Parse({"--foo", "FOO", "--bar"}, fakeStdErr);
+ ASSERT_FALSE(success);
+}
+
TEST(CommandLineOptionsTests, CornerCases) {
std::string foo;
std::string bar;
@@ -172,6 +222,7 @@ TEST(CommandLineOptionsTests, Usage) {
bool arg5 = false;
bool arg6 = false;
std::vector<std::string> arg7;
+ std::vector<std::string> arg8;
CommandLineOptions opts = CommandLineOptions("test")
.MandatoryOption("--aa", "description-aa", &arg1)
.OptionalFlag("--bb", "description-bb", &arg5)
@@ -179,12 +230,13 @@ TEST(CommandLineOptionsTests, Usage) {
.OptionalOption("--dd", "description-dd", &arg3)
.MandatoryOption("--ee", "description-ee", &arg4)
.OptionalFlag("--ff", "description-ff", &arg6)
- .MandatoryOption("--gg", "description-gg", &arg7);
+ .MandatoryOption("--gg", "description-gg", &arg7)
+ .OptionalOption("--hh", "description-hh", &arg8);
std::stringstream stream;
opts.Usage(stream);
const std::string s = stream.str();
ASSERT_NE(s.find("usage: test --aa arg [--bb] [--cc arg] [--dd arg] --ee arg [--ff] --gg arg "
- "[--gg arg [..]]"),
+ "[--gg arg [..]] [--hh arg [..]]"),
std::string::npos);
ASSERT_NE(s.find("--aa arg description-aa"), std::string::npos);
ASSERT_NE(s.find("--ff description-ff"), std::string::npos);
diff --git a/cmds/idmap2/tests/FileUtilsTests.cpp b/cmds/idmap2/tests/FileUtilsTests.cpp
index 4bf832a34691..d9d9a7f829cf 100644
--- a/cmds/idmap2/tests/FileUtilsTests.cpp
+++ b/cmds/idmap2/tests/FileUtilsTests.cpp
@@ -37,10 +37,10 @@ TEST(FileUtilsTests, FindFilesFindEverythingNonRecursive) {
[](unsigned char type ATTRIBUTE_UNUSED,
const std::string& path ATTRIBUTE_UNUSED) -> bool { return true; });
ASSERT_THAT(v, NotNull());
- ASSERT_EQ(v->size(), 4U);
- ASSERT_EQ(
- std::set<std::string>(v->begin(), v->end()),
- std::set<std::string>({root + "/.", root + "/..", root + "/overlay", root + "/target"}));
+ ASSERT_EQ(v->size(), 6U);
+ ASSERT_EQ(std::set<std::string>(v->begin(), v->end()),
+ std::set<std::string>({root + "/.", root + "/..", root + "/overlay", root + "/target",
+ root + "/system-overlay", root + "/system-overlay-invalid"}));
}
TEST(FileUtilsTests, FindFilesFindApkFilesRecursive) {
@@ -49,11 +49,13 @@ TEST(FileUtilsTests, FindFilesFindApkFilesRecursive) {
return type == DT_REG && path.size() > 4 && path.compare(path.size() - 4, 4, ".apk") == 0;
});
ASSERT_THAT(v, NotNull());
- ASSERT_EQ(v->size(), 4U);
+ ASSERT_EQ(v->size(), 6U);
ASSERT_EQ(std::set<std::string>(v->begin(), v->end()),
std::set<std::string>({root + "/target/target.apk", root + "/overlay/overlay.apk",
root + "/overlay/overlay-static-1.apk",
- root + "/overlay/overlay-static-2.apk"}));
+ root + "/overlay/overlay-static-2.apk",
+ root + "/system-overlay/system-overlay.apk",
+ root + "/system-overlay-invalid/system-overlay-invalid.apk"}));
}
TEST(FileUtilsTests, ReadFile) {
diff --git a/cmds/idmap2/tests/Idmap2BinaryTests.cpp b/cmds/idmap2/tests/Idmap2BinaryTests.cpp
index 22f48e9a396f..0c8f164bf096 100644
--- a/cmds/idmap2/tests/Idmap2BinaryTests.cpp
+++ b/cmds/idmap2/tests/Idmap2BinaryTests.cpp
@@ -38,6 +38,7 @@
#include "gtest/gtest.h"
#include "androidfw/PosixUtils.h"
+
#include "idmap2/FileUtils.h"
#include "idmap2/Idmap.h"
@@ -114,8 +115,9 @@ TEST_F(Idmap2BinaryTests, Dump) {
ASSERT_THAT(result, NotNull());
ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
ASSERT_NE(result->stdout.find("0x7f010000 -> 0x7f010000 integer/int1"), std::string::npos);
- ASSERT_NE(result->stdout.find("0x7f020003 -> 0x7f020000 string/str1"), std::string::npos);
- ASSERT_NE(result->stdout.find("0x7f020005 -> 0x7f020001 string/str3"), std::string::npos);
+ ASSERT_NE(result->stdout.find("0x7f020008 -> 0x7f020000 string/str1"), std::string::npos);
+ ASSERT_NE(result->stdout.find("0x7f02000a -> 0x7f020001 string/str3"), std::string::npos);
+ ASSERT_NE(result->stdout.find("0x7f02000b -> 0x7f020002 string/str4"), std::string::npos);
ASSERT_EQ(result->stdout.find("00000210: 007f target package id"), std::string::npos);
// clang-format off
@@ -157,7 +159,8 @@ TEST_F(Idmap2BinaryTests, Scan) {
"--recursive",
"--target-package-name", "test.target",
"--target-apk-path", GetTargetApkPath(),
- "--output-directory", GetTempDirPath()});
+ "--output-directory", GetTempDirPath(),
+ "--override-policy", "public"});
// clang-format on
ASSERT_THAT(result, NotNull());
ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
@@ -190,7 +193,8 @@ TEST_F(Idmap2BinaryTests, Scan) {
"--input-directory", GetTestDataPath() + "/overlay",
"--target-package-name", "test.target",
"--target-apk-path", GetTargetApkPath(),
- "--output-directory", GetTempDirPath()});
+ "--output-directory", GetTempDirPath(),
+ "--override-policy", "public"});
// clang-format on
ASSERT_THAT(result, NotNull());
ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
@@ -207,7 +211,8 @@ TEST_F(Idmap2BinaryTests, Scan) {
"--recursive",
"--target-package-name", "test.target",
"--target-apk-path", GetTargetApkPath(),
- "--output-directory", GetTempDirPath()});
+ "--output-directory", GetTempDirPath(),
+ "--override-policy", "public"});
// clang-format on
ASSERT_THAT(result, NotNull());
ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
@@ -222,7 +227,8 @@ TEST_F(Idmap2BinaryTests, Scan) {
"--input-directory", GetTempDirPath(),
"--target-package-name", "test.target",
"--target-apk-path", GetTargetApkPath(),
- "--output-directory", GetTempDirPath()});
+ "--output-directory", GetTempDirPath(),
+ "--override-policy", "public"});
// clang-format on
ASSERT_THAT(result, NotNull());
ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
@@ -245,7 +251,7 @@ TEST_F(Idmap2BinaryTests, Lookup) {
"lookup",
"--idmap-path", GetIdmapPath(),
"--config", "",
- "--resid", "0x7f020003"}); // string/str1
+ "--resid", "0x7f020008"}); // string/str1
// clang-format on
ASSERT_THAT(result, NotNull());
ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
@@ -310,6 +316,18 @@ TEST_F(Idmap2BinaryTests, InvalidCommandLineOptions) {
// clang-format on
ASSERT_THAT(result, NotNull());
ASSERT_NE(result->status, EXIT_SUCCESS);
+
+ // unknown policy
+ // clang-format off
+ result = ExecuteBinary({"idmap2",
+ "create",
+ "--target-apk-path", GetTargetApkPath(),
+ "--overlay-apk-path", GetOverlayApkPath(),
+ "--idmap-path", GetIdmapPath(),
+ "--policy", "this-does-not-exist"});
+ // clang-format on
+ ASSERT_THAT(result, NotNull());
+ ASSERT_NE(result->status, EXIT_SUCCESS);
}
} // namespace android::idmap2
diff --git a/cmds/idmap2/tests/IdmapTests.cpp b/cmds/idmap2/tests/IdmapTests.cpp
index 963f22ec8d72..c6eb71cbeb72 100644
--- a/cmds/idmap2/tests/IdmapTests.cpp
+++ b/cmds/idmap2/tests/IdmapTests.cpp
@@ -184,13 +184,14 @@ TEST(IdmapTests, CreateIdmapFromApkAssets) {
std::stringstream error;
std::unique_ptr<const Idmap> idmap =
- Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, error);
+ Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
+ PolicyFlags::POLICY_PUBLIC, /* enforce_overlayable */ true, error);
ASSERT_THAT(idmap, NotNull());
ASSERT_THAT(idmap->GetHeader(), NotNull());
ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U);
ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x01U);
- ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), 0xf5ad1d1d);
+ ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), 0xca2093da);
ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), 0xd470336b);
ASSERT_EQ(idmap->GetHeader()->GetTargetPath().to_string(), target_apk_path);
ASSERT_EQ(idmap->GetHeader()->GetOverlayPath(), overlay_apk_path);
@@ -216,13 +217,127 @@ TEST(IdmapTests, CreateIdmapFromApkAssets) {
ASSERT_EQ(types[1]->GetTargetTypeId(), 0x02U);
ASSERT_EQ(types[1]->GetOverlayTypeId(), 0x02U);
ASSERT_EQ(types[1]->GetEntryCount(), 4U);
- ASSERT_EQ(types[1]->GetEntryOffset(), 3U);
+ ASSERT_EQ(types[1]->GetEntryOffset(), 8U);
ASSERT_EQ(types[1]->GetEntry(0), 0x0000U);
ASSERT_EQ(types[1]->GetEntry(1), kNoEntry);
ASSERT_EQ(types[1]->GetEntry(2), 0x0001U);
ASSERT_EQ(types[1]->GetEntry(3), 0x0002U);
}
+TEST(IdmapTests, CreateIdmapFromApkAssetsPolicySystemPublic) {
+ const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
+ std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
+ ASSERT_THAT(target_apk, NotNull());
+
+ const std::string overlay_apk_path(GetTestDataPath() + "/system-overlay/system-overlay.apk");
+ std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
+ ASSERT_THAT(overlay_apk, NotNull());
+
+ std::stringstream error;
+ std::unique_ptr<const Idmap> idmap =
+ Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
+ PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
+ /* enforce_overlayable */ true, error);
+ ASSERT_THAT(idmap, NotNull());
+
+ const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
+ ASSERT_EQ(dataBlocks.size(), 1U);
+
+ const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
+
+ ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
+ ASSERT_EQ(data->GetHeader()->GetTypeCount(), 1U);
+
+ const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
+ ASSERT_EQ(types.size(), 1U);
+
+ ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
+ ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
+ ASSERT_EQ(types[0]->GetEntryCount(), 3U);
+ ASSERT_EQ(types[0]->GetEntryOffset(), 5U);
+ ASSERT_EQ(types[0]->GetEntry(0), 0x0000U); // string/policy_public
+ ASSERT_EQ(types[0]->GetEntry(1), 0x0001U); // string/policy_system
+ ASSERT_EQ(types[0]->GetEntry(2), 0x0002U); // string/policy_system_vendor
+}
+
+TEST(IdmapTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalid) {
+ const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
+ std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
+ ASSERT_THAT(target_apk, NotNull());
+
+ const std::string overlay_apk_path(GetTestDataPath() +
+ "/system-overlay-invalid/system-overlay-invalid.apk");
+ std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
+ ASSERT_THAT(overlay_apk, NotNull());
+
+ std::stringstream error;
+ std::unique_ptr<const Idmap> idmap =
+ Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
+ PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
+ /* enforce_overlayable */ true, error);
+ ASSERT_THAT(idmap, NotNull());
+
+ const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
+ ASSERT_EQ(dataBlocks.size(), 1U);
+
+ const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
+
+ ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
+ ASSERT_EQ(data->GetHeader()->GetTypeCount(), 1U);
+
+ const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
+ ASSERT_EQ(types.size(), 1U);
+
+ ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
+ ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
+ ASSERT_EQ(types[0]->GetEntryCount(), 5U);
+ ASSERT_EQ(types[0]->GetEntryOffset(), 3U);
+ ASSERT_EQ(types[0]->GetEntry(0), 0x0000U); // string/not_overlayable
+ ASSERT_EQ(types[0]->GetEntry(1), kNoEntry); // string/policy_product
+ ASSERT_EQ(types[0]->GetEntry(2), 0x0002U); // string/policy_public
+ ASSERT_EQ(types[0]->GetEntry(3), 0x0003U); // string/policy_system
+ ASSERT_EQ(types[0]->GetEntry(4), 0x0004U); // string/policy_system_vendor
+}
+
+TEST(IdmapTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalidIgnoreOverlayable) {
+ const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
+ std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
+ ASSERT_THAT(target_apk, NotNull());
+
+ const std::string overlay_apk_path(GetTestDataPath() +
+ "/system-overlay-invalid/system-overlay-invalid.apk");
+ std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
+ ASSERT_THAT(overlay_apk, NotNull());
+
+ std::stringstream error;
+ std::unique_ptr<const Idmap> idmap =
+ Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
+ PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
+ /* enforce_overlayable */ false, error);
+ ASSERT_THAT(idmap, NotNull());
+
+ const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
+ ASSERT_EQ(dataBlocks.size(), 1U);
+
+ const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
+
+ ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
+ ASSERT_EQ(data->GetHeader()->GetTypeCount(), 1U);
+
+ const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
+ ASSERT_EQ(types.size(), 1U);
+
+ ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
+ ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
+ ASSERT_EQ(types[0]->GetEntryCount(), 5U);
+ ASSERT_EQ(types[0]->GetEntryOffset(), 3U);
+ ASSERT_EQ(types[0]->GetEntry(0), 0x0000U); // string/not_overlayable
+ ASSERT_EQ(types[0]->GetEntry(1), 0x0001U); // string/policy_product
+ ASSERT_EQ(types[0]->GetEntry(2), 0x0002U); // string/policy_public
+ ASSERT_EQ(types[0]->GetEntry(3), 0x0003U); // string/policy_system
+ ASSERT_EQ(types[0]->GetEntry(4), 0x0004U); // string/policy_system_vendor
+}
+
TEST(IdmapTests, FailToCreateIdmapFromApkAssetsIfPathTooLong) {
std::string target_apk_path(GetTestDataPath());
for (int i = 0; i < 32; i++) {
@@ -239,7 +354,8 @@ TEST(IdmapTests, FailToCreateIdmapFromApkAssetsIfPathTooLong) {
std::stringstream error;
std::unique_ptr<const Idmap> idmap =
- Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, error);
+ Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
+ PolicyFlags::POLICY_PUBLIC, /* enforce_overlayable */ true, error);
ASSERT_THAT(idmap, IsNull());
}
@@ -255,8 +371,9 @@ TEST(IdmapTests, IdmapHeaderIsUpToDate) {
ASSERT_THAT(overlay_apk, NotNull());
std::stringstream error;
- std::unique_ptr<const Idmap> idmap =
- Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, error);
+ std::unique_ptr<const Idmap> idmap = Idmap::FromApkAssets(
+ target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, PolicyFlags::POLICY_PUBLIC,
+ /* enforce_overlayable */ true, error);
ASSERT_THAT(idmap, NotNull());
std::stringstream stream;
diff --git a/cmds/idmap2/tests/PoliciesTests.cpp b/cmds/idmap2/tests/PoliciesTests.cpp
new file mode 100644
index 000000000000..ab567adc6f19
--- /dev/null
+++ b/cmds/idmap2/tests/PoliciesTests.cpp
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+
+#include <string>
+
+#include "gtest/gtest.h"
+
+#include "TestHelpers.h"
+#include "idmap2/Policies.h"
+
+using android::idmap2::PolicyBitmask;
+using android::idmap2::PolicyFlags;
+
+namespace android::idmap2 {
+
+TEST(PoliciesTests, PoliciesToBitmasks) {
+ const Result<PolicyBitmask> bitmask1 = PoliciesToBitmask({"system"}, std::cerr);
+ ASSERT_NE(bitmask1, kResultError);
+ ASSERT_EQ(bitmask1, PolicyFlags::POLICY_SYSTEM_PARTITION);
+
+ const Result<PolicyBitmask> bitmask2 = PoliciesToBitmask({"system", "vendor"}, std::cerr);
+ ASSERT_NE(bitmask2, kResultError);
+ ASSERT_EQ(bitmask2, PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_VENDOR_PARTITION);
+
+ const Result<PolicyBitmask> bitmask3 = PoliciesToBitmask({"vendor", "system"}, std::cerr);
+ ASSERT_NE(bitmask3, kResultError);
+ ASSERT_EQ(bitmask3, PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_VENDOR_PARTITION);
+
+ const Result<PolicyBitmask> bitmask4 =
+ PoliciesToBitmask({"public", "product", "system", "vendor"}, std::cerr);
+ ASSERT_NE(bitmask4, kResultError);
+ ASSERT_EQ(bitmask4, PolicyFlags::POLICY_PUBLIC | PolicyFlags::POLICY_PRODUCT_PARTITION |
+ PolicyFlags::POLICY_SYSTEM_PARTITION |
+ PolicyFlags::POLICY_VENDOR_PARTITION);
+
+ const Result<PolicyBitmask> bitmask5 =
+ PoliciesToBitmask({"system", "system", "system"}, std::cerr);
+ ASSERT_NE(bitmask5, kResultError);
+ ASSERT_EQ(bitmask5, PolicyFlags::POLICY_SYSTEM_PARTITION);
+
+ const Result<PolicyBitmask> bitmask6 = PoliciesToBitmask({""}, std::cerr);
+ ASSERT_EQ(bitmask6, kResultError);
+
+ const Result<PolicyBitmask> bitmask7 = PoliciesToBitmask({"foo"}, std::cerr);
+ ASSERT_EQ(bitmask7, kResultError);
+
+ const Result<PolicyBitmask> bitmask8 = PoliciesToBitmask({"system", "foo"}, std::cerr);
+ ASSERT_EQ(bitmask8, kResultError);
+
+ const Result<PolicyBitmask> bitmask9 = PoliciesToBitmask({"system", ""}, std::cerr);
+ ASSERT_EQ(bitmask9, kResultError);
+
+ const Result<PolicyBitmask> bitmask10 = PoliciesToBitmask({"system "}, std::cerr);
+ ASSERT_EQ(bitmask10, kResultError);
+}
+
+} // namespace android::idmap2
diff --git a/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp b/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp
index 7736bc063131..eaa47cd79533 100644
--- a/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp
+++ b/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp
@@ -25,6 +25,7 @@
#include "androidfw/Idmap.h"
#include "idmap2/Idmap.h"
+#include "idmap2/Policies.h"
#include "idmap2/PrettyPrintVisitor.h"
#include "TestHelpers.h"
@@ -32,6 +33,7 @@
using ::testing::NotNull;
using android::ApkAssets;
+using android::idmap2::PolicyBitmask;
namespace android::idmap2 {
@@ -46,7 +48,8 @@ TEST(PrettyPrintVisitorTests, CreatePrettyPrintVisitor) {
std::stringstream error;
std::unique_ptr<const Idmap> idmap =
- Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, error);
+ Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
+ PolicyFlags::POLICY_PUBLIC, /* enforce_overlayable */ true, error);
ASSERT_THAT(idmap, NotNull());
std::stringstream stream;
diff --git a/cmds/idmap2/tests/RawPrintVisitorTests.cpp b/cmds/idmap2/tests/RawPrintVisitorTests.cpp
index 0318cd20a9bb..b58c61a0c284 100644
--- a/cmds/idmap2/tests/RawPrintVisitorTests.cpp
+++ b/cmds/idmap2/tests/RawPrintVisitorTests.cpp
@@ -42,7 +42,8 @@ TEST(RawPrintVisitorTests, CreateRawPrintVisitor) {
std::stringstream error;
std::unique_ptr<const Idmap> idmap =
- Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, error);
+ Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
+ PolicyFlags::POLICY_PUBLIC, /* enforce_overlayable */ true, error);
ASSERT_THAT(idmap, NotNull());
std::stringstream stream;
@@ -51,7 +52,7 @@ TEST(RawPrintVisitorTests, CreateRawPrintVisitor) {
ASSERT_NE(stream.str().find("00000000: 504d4449 magic\n"), std::string::npos);
ASSERT_NE(stream.str().find("00000004: 00000001 version\n"), std::string::npos);
- ASSERT_NE(stream.str().find("00000008: f5ad1d1d target crc\n"), std::string::npos);
+ ASSERT_NE(stream.str().find("00000008: ca2093da target crc\n"), std::string::npos);
ASSERT_NE(stream.str().find("0000000c: d470336b overlay crc\n"), std::string::npos);
ASSERT_NE(stream.str().find("0000021c: 00000000 0x7f010000 -> 0x7f010000 integer/int1\n"),
std::string::npos);
diff --git a/cmds/idmap2/tests/data/system-overlay-invalid/AndroidManifest.xml b/cmds/idmap2/tests/data/system-overlay-invalid/AndroidManifest.xml
new file mode 100644
index 000000000000..977cd97f21c3
--- /dev/null
+++ b/cmds/idmap2/tests/data/system-overlay-invalid/AndroidManifest.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="test.overlay.system.invalid">
+ <overlay
+ android:targetPackage="test.target" />
+</manifest>
diff --git a/cmds/idmap2/tests/data/system-overlay-invalid/build b/cmds/idmap2/tests/data/system-overlay-invalid/build
new file mode 100644
index 000000000000..920e1f8ad6f3
--- /dev/null
+++ b/cmds/idmap2/tests/data/system-overlay-invalid/build
@@ -0,0 +1,26 @@
+# 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.
+
+FRAMEWORK_RES_APK=${ANDROID_BUILD_TOP}/prebuilts/sdk/current/public/android.jar
+
+aapt2 compile --dir res -o compiled.flata
+
+aapt2 link \
+ --no-resource-removal \
+ -I "$FRAMEWORK_RES_APK" \
+ --manifest AndroidManifest.xml \
+ -o system-overlay-invalid.apk \
+ compiled.flata
+
+rm compiled.flata
diff --git a/cmds/idmap2/tests/data/system-overlay-invalid/res/values/values.xml b/cmds/idmap2/tests/data/system-overlay-invalid/res/values/values.xml
new file mode 100644
index 000000000000..512770722a4b
--- /dev/null
+++ b/cmds/idmap2/tests/data/system-overlay-invalid/res/values/values.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <!-- This overlay will fulfill the policies "public|system". This allows it overlay the
+ following resources. -->
+ <string name="policy_system">policy_system</string>
+ <string name="policy_system_vendor">policy_system_vendor</string>
+ <string name="policy_public">policy_public</string>
+
+ <!-- It also requests to overlay a resource that belongs to a policy the overlay does not
+ fulfill.-->
+ <string name="policy_product">policy_product</string>
+
+ <!-- It also requests to overlay a resource that is not declared as overlayable.-->
+ <string name="not_overlayable">not_overlayable</string>
+</resources>
diff --git a/cmds/idmap2/tests/data/system-overlay-invalid/system-overlay-invalid.apk b/cmds/idmap2/tests/data/system-overlay-invalid/system-overlay-invalid.apk
new file mode 100644
index 000000000000..c367f82e21e6
--- /dev/null
+++ b/cmds/idmap2/tests/data/system-overlay-invalid/system-overlay-invalid.apk
Binary files differ
diff --git a/cmds/idmap2/tests/data/system-overlay/AndroidManifest.xml b/cmds/idmap2/tests/data/system-overlay/AndroidManifest.xml
new file mode 100644
index 000000000000..8af9064ba64f
--- /dev/null
+++ b/cmds/idmap2/tests/data/system-overlay/AndroidManifest.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="test.overlay.system">
+ <overlay
+ android:targetPackage="test.target" />
+</manifest>
diff --git a/cmds/idmap2/tests/data/system-overlay/build b/cmds/idmap2/tests/data/system-overlay/build
new file mode 100644
index 000000000000..be0d2390f535
--- /dev/null
+++ b/cmds/idmap2/tests/data/system-overlay/build
@@ -0,0 +1,26 @@
+# 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.
+
+FRAMEWORK_RES_APK=${ANDROID_BUILD_TOP}/prebuilts/sdk/current/public/android.jar
+
+aapt2 compile --dir res -o compiled.flata
+
+aapt2 link \
+ --no-resource-removal \
+ -I "$FRAMEWORK_RES_APK" \
+ --manifest AndroidManifest.xml \
+ -o system-overlay.apk \
+ compiled.flata
+
+rm compiled.flata
diff --git a/cmds/idmap2/tests/data/system-overlay/res/values/values.xml b/cmds/idmap2/tests/data/system-overlay/res/values/values.xml
new file mode 100644
index 000000000000..6aaa0b02639e
--- /dev/null
+++ b/cmds/idmap2/tests/data/system-overlay/res/values/values.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <!-- This overlay will fulfill the policies "public|system". This allows it overlay the
+ following resources. -->
+ <string name="policy_system">policy_system</string>
+ <string name="policy_system_vendor">policy_system_vendor</string>
+ <string name="policy_public">policy_public</string>
+</resources>
diff --git a/cmds/idmap2/tests/data/system-overlay/system-overlay.apk b/cmds/idmap2/tests/data/system-overlay/system-overlay.apk
new file mode 100644
index 000000000000..90f30eb68c15
--- /dev/null
+++ b/cmds/idmap2/tests/data/system-overlay/system-overlay.apk
Binary files differ
diff --git a/cmds/idmap2/tests/data/target/res/values/overlayable.xml b/cmds/idmap2/tests/data/target/res/values/overlayable.xml
new file mode 100644
index 000000000000..de19e6fcd022
--- /dev/null
+++ b/cmds/idmap2/tests/data/target/res/values/overlayable.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+<overlayable name="TestResources">
+ <!-- Publicly overlayable resources -->
+ <item type="string" name="a" />
+ <item type="string" name="b" />
+ <item type="string" name="c" />
+ <item type="string" name="str1" />
+ <item type="string" name="str2" />
+ <item type="string" name="str3" />
+ <item type="string" name="str4" />
+ <item type="string" name="x" />
+ <item type="string" name="y" />
+ <item type="string" name="z" />
+ <item type="integer" name="int1" />
+
+ <!-- Resources with partition restrictins -->
+ <policy type="system">
+ <item type="string" name="policy_system" />
+ </policy>
+
+ <policy type="system|vendor">
+ <item type="string" name="policy_system_vendor" />
+ </policy>
+
+ <policy type="product">
+ <item type="string" name="policy_product" />
+ </policy>
+
+ <policy type="public">
+ <item type="string" name="policy_public" />
+ </policy>
+</overlayable>
+</resources> \ No newline at end of file
diff --git a/cmds/idmap2/tests/data/target/res/values/values.xml b/cmds/idmap2/tests/data/target/res/values/values.xml
index 56bf0d60021a..ef9012e49300 100644
--- a/cmds/idmap2/tests/data/target/res/values/values.xml
+++ b/cmds/idmap2/tests/data/target/res/values/values.xml
@@ -25,4 +25,12 @@
<string name="y">y</string>
<string name="z">z</string>
<integer name="int1">1</integer>
+
+ <!-- This resources is not marked as overlayable -->
+ <string name="not_overlayable">not_overlayable</string>
+
+ <string name="policy_system">policy_system</string>
+ <string name="policy_system_vendor">policy_system_vendor</string>
+ <string name="policy_product">policy_product</string>
+ <string name="policy_public">policy_public</string>
</resources>
diff --git a/cmds/idmap2/tests/data/target/target.apk b/cmds/idmap2/tests/data/target/target.apk
index 18ecc276caae..9a6220dbe3ca 100644
--- a/cmds/idmap2/tests/data/target/target.apk
+++ b/cmds/idmap2/tests/data/target/target.apk
Binary files differ
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index f75e58406a83..7ceef999d6af 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -3375,7 +3375,8 @@ message PackageAssociationSourceProcessStatsProto {
optional int32 process_uid = 1;
// Process name.
optional string process_name = 2;
-
+ // Package name.
+ optional string package_name = 7;
// Total count of the times this association appeared.
optional int32 total_count = 3;
@@ -3454,6 +3455,9 @@ message ProcessStatsSectionProto {
}
repeated Status status = 7;
+ // Number of pages available of various types and sizes, representation fragmentation.
+ repeated ProcessStatsAvailablePagesProto available_pages = 10;
+
// Stats for each process.
repeated ProcessStatsProto process_stats = 8;
@@ -3461,6 +3465,21 @@ message ProcessStatsSectionProto {
repeated ProcessStatsPackageProto package_stats = 9;
}
+message ProcessStatsAvailablePagesProto {
+ // Node these pages are in (as per /proc/pagetypeinfo)
+ optional int32 node = 1;
+
+ // Zone these pages are in (as per /proc/pagetypeinfo)
+ optional string zone = 2;
+
+ // Label for the type of these pages (as per /proc/pagetypeinfo)
+ optional string label = 3;
+
+ // Distribution of number of pages available by order size. First entry in array is
+ // order 0, second is order 1, etc. Each order increase is a doubling of page size.
+ repeated int32 pages_per_order = 4;
+}
+
/**
* Pulled from ProcessStatsService.java
*/
diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt
index 5392a3c428c1..02eff0b6cee2 100644
--- a/config/hiddenapi-greylist.txt
+++ b/config/hiddenapi-greylist.txt
@@ -1108,18 +1108,6 @@ Landroid/os/UserManager;->isUserUnlocked(I)Z
Landroid/os/UserManager;->mService:Landroid/os/IUserManager;
Landroid/os/UserManager;->removeUser(I)Z
Landroid/os/Vibrator;-><init>()V
-Landroid/os/VintfObject;->getHalNamesAndVersions()[Ljava/lang/String;
-Landroid/os/VintfObject;->getSepolicyVersion()Ljava/lang/String;
-Landroid/os/VintfObject;->getTargetFrameworkCompatibilityMatrixVersion()Ljava/lang/Long;
-Landroid/os/VintfObject;->getVndkSnapshots()Ljava/util/Map;
-Landroid/os/VintfObject;->report()[Ljava/lang/String;
-Landroid/os/VintfRuntimeInfo;->getCpuInfo()Ljava/lang/String;
-Landroid/os/VintfRuntimeInfo;->getHardwareId()Ljava/lang/String;
-Landroid/os/VintfRuntimeInfo;->getKernelVersion()Ljava/lang/String;
-Landroid/os/VintfRuntimeInfo;->getNodeName()Ljava/lang/String;
-Landroid/os/VintfRuntimeInfo;->getOsName()Ljava/lang/String;
-Landroid/os/VintfRuntimeInfo;->getOsRelease()Ljava/lang/String;
-Landroid/os/VintfRuntimeInfo;->getOsVersion()Ljava/lang/String;
Landroid/os/WorkSource;-><init>(Landroid/os/Parcel;)V
Landroid/os/WorkSource;->mNames:[Ljava/lang/String;
Landroid/os/WorkSource;->mNum:I
@@ -1824,22 +1812,10 @@ Lcom/android/internal/os/RuntimeInit;->getApplicationObject()Landroid/os/IBinder
Lcom/android/internal/os/RuntimeInit;->initialized:Z
Lcom/android/internal/os/RuntimeInit;->main([Ljava/lang/String;)V
Lcom/android/internal/os/RuntimeInit;->mApplicationObject:Landroid/os/IBinder;
-Lcom/android/internal/os/ZygoteConnection$Arguments;-><init>([Ljava/lang/String;)V
-Lcom/android/internal/os/ZygoteConnection$Arguments;->effectiveCapabilities:J
-Lcom/android/internal/os/ZygoteConnection$Arguments;->gid:I
-Lcom/android/internal/os/ZygoteConnection$Arguments;->gids:[I
-Lcom/android/internal/os/ZygoteConnection$Arguments;->permittedCapabilities:J
-Lcom/android/internal/os/ZygoteConnection$Arguments;->remainingArgs:[Ljava/lang/String;
-Lcom/android/internal/os/ZygoteConnection$Arguments;->rlimits:Ljava/util/ArrayList;
-Lcom/android/internal/os/ZygoteConnection$Arguments;->uid:I
-Lcom/android/internal/os/ZygoteConnection;->applyUidSecurityPolicy(Lcom/android/internal/os/ZygoteConnection$Arguments;Landroid/net/Credentials;)V
Lcom/android/internal/os/ZygoteConnection;->closeSocket()V
-Lcom/android/internal/os/ZygoteConnection;->getFileDesciptor()Ljava/io/FileDescriptor;
-Lcom/android/internal/os/ZygoteConnection;->intArray2d:[[I
Lcom/android/internal/os/ZygoteConnection;->mSocket:Landroid/net/LocalSocket;
Lcom/android/internal/os/ZygoteConnection;->mSocketOutStream:Ljava/io/DataOutputStream;
Lcom/android/internal/os/ZygoteConnection;->peer:Landroid/net/Credentials;
-Lcom/android/internal/os/ZygoteConnection;->readArgumentList()[Ljava/lang/String;
Lcom/android/internal/os/ZygoteInit;->main([Ljava/lang/String;)V
Lcom/android/internal/os/ZygoteInit;->mResources:Landroid/content/res/Resources;
Lcom/android/internal/os/ZygoteSecurityException;-><init>(Ljava/lang/String;)V
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index d374f1c0acdf..836627efb379 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -124,6 +124,7 @@ import android.view.autofill.AutofillPopupWindow;
import android.view.autofill.IAutofillWindowPresenter;
import android.view.contentcapture.ContentCaptureContext;
import android.view.contentcapture.ContentCaptureManager;
+import android.view.contentcapture.ContentCaptureSession;
import android.widget.AdapterView;
import android.widget.Toast;
import android.widget.Toolbar;
@@ -1034,13 +1035,15 @@ public class Activity extends ContextThemeWrapper
}
/** @hide */ private static final int CONTENT_CAPTURE_START = 1;
- /** @hide */ private static final int CONTENT_CAPTURE_FLUSH = 2;
- /** @hide */ private static final int CONTENT_CAPTURE_STOP = 3;
+ /** @hide */ private static final int CONTENT_CAPTURE_PAUSE = 2;
+ /** @hide */ private static final int CONTENT_CAPTURE_RESUME = 3;
+ /** @hide */ private static final int CONTENT_CAPTURE_STOP = 4;
/** @hide */
@IntDef(prefix = { "CONTENT_CAPTURE_" }, value = {
CONTENT_CAPTURE_START,
- CONTENT_CAPTURE_FLUSH,
+ CONTENT_CAPTURE_PAUSE,
+ CONTENT_CAPTURE_RESUME,
CONTENT_CAPTURE_STOP
})
@Retention(RetentionPolicy.SOURCE)
@@ -1062,8 +1065,11 @@ public class Activity extends ContextThemeWrapper
}
cm.onActivityStarted(mToken, getComponentName(), flags);
break;
- case CONTENT_CAPTURE_FLUSH:
- cm.flush();
+ case CONTENT_CAPTURE_PAUSE:
+ cm.flush(ContentCaptureSession.FLUSH_REASON_ACTIVITY_PAUSED);
+ break;
+ case CONTENT_CAPTURE_RESUME:
+ cm.flush(ContentCaptureSession.FLUSH_REASON_ACTIVITY_RESUMED);
break;
case CONTENT_CAPTURE_STOP:
cm.onActivityStopped();
@@ -1755,7 +1761,7 @@ public class Activity extends ContextThemeWrapper
}
}
mCalled = true;
- notifyContentCaptureManagerIfNeeded(CONTENT_CAPTURE_FLUSH);
+ notifyContentCaptureManagerIfNeeded(CONTENT_CAPTURE_RESUME);
}
/**
@@ -2149,7 +2155,7 @@ public class Activity extends ContextThemeWrapper
}
}
mCalled = true;
- notifyContentCaptureManagerIfNeeded(CONTENT_CAPTURE_FLUSH);
+ notifyContentCaptureManagerIfNeeded(CONTENT_CAPTURE_PAUSE);
}
/**
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index d27cce535c3b..8497656df2be 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -33,6 +33,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.ComponentInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.content.pm.ShortcutInfo;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Rect;
@@ -1954,6 +1955,17 @@ public class Intent implements Parcelable, Cloneable {
public static final String EXTRA_LAUNCHER_EXTRAS = "android.intent.extra.LAUNCHER_EXTRAS";
/**
+ * Intent extra: ID of the shortcut used to send the share intent.
+ *
+ * @see ShortcutInfo#getId()
+ *
+ * <p>
+ * Type: String
+ * </p>
+ */
+ public static final String EXTRA_SHORTCUT_ID = "android.intent.extra.shortcut.ID";
+
+ /**
* Activity action: Launch UI to manage which apps have a given permission.
* <p>
* Input: {@link #EXTRA_PERMISSION_NAME} specifies the permission group
diff --git a/core/java/android/content/pm/IShortcutService.aidl b/core/java/android/content/pm/IShortcutService.aidl
index 03124be7ab7d..c702b16c97f6 100644
--- a/core/java/android/content/pm/IShortcutService.aidl
+++ b/core/java/android/content/pm/IShortcutService.aidl
@@ -16,6 +16,7 @@
package android.content.pm;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.IntentSender;
import android.content.pm.ParceledListSlice;
import android.content.pm.ShortcutInfo;
@@ -72,4 +73,7 @@ interface IShortcutService {
void applyRestore(in byte[] payload, int user);
boolean isRequestPinItemSupported(int user, int requestType);
+
+ // System API used by framework's ShareSheet (ChooserActivity)
+ ParceledListSlice getShareTargets(String packageName, in IntentFilter filter, int userId);
} \ No newline at end of file
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
index ec2e2fd474a2..fe68b8a048c2 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -21,6 +21,7 @@ import android.annotation.Nullable;
import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.annotation.UserIdInt;
+import android.app.Person;
import android.app.TaskStackBuilder;
import android.content.ComponentName;
import android.content.Context;
@@ -111,6 +112,9 @@ public final class ShortcutInfo implements Parcelable {
public static final int FLAG_SHADOW = 1 << 12;
/** @hide */
+ public static final int FLAG_LONG_LIVED = 1 << 13;
+
+ /** @hide */
@IntDef(flag = true, prefix = { "FLAG_" }, value = {
FLAG_DYNAMIC,
FLAG_PINNED,
@@ -124,6 +128,8 @@ public final class ShortcutInfo implements Parcelable {
FLAG_ADAPTIVE_BITMAP,
FLAG_RETURNED_BY_SERVICE,
FLAG_ICON_FILE_PENDING_SAVE,
+ FLAG_SHADOW,
+ FLAG_LONG_LIVED,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ShortcutFlags {}
@@ -344,6 +350,9 @@ public final class ShortcutInfo implements Parcelable {
@Nullable
private PersistableBundle[] mIntentPersistableExtrases;
+ @Nullable
+ private Person[] mPersons;
+
private int mRank;
/**
@@ -399,6 +408,10 @@ public final class ShortcutInfo implements Parcelable {
mCategories = cloneCategories(b.mCategories);
mIntents = cloneIntents(b.mIntents);
fixUpIntentExtras();
+ mPersons = clonePersons(b.mPersons);
+ if (b.mIsLongLived) {
+ setLongLived();
+ }
mRank = b.mRank;
mExtras = b.mExtras;
updateTimestamp();
@@ -465,6 +478,20 @@ public final class ShortcutInfo implements Parcelable {
return ret;
}
+ private static Person[] clonePersons(Person[] persons) {
+ if (persons == null) {
+ return null;
+ }
+ final Person[] ret = new Person[persons.length];
+ for (int i = 0; i < ret.length; i++) {
+ if (persons[i] != null) {
+ // Don't need to keep the icon, remove it to save space
+ ret[i] = persons[i].toBuilder().setIcon(null).build();
+ }
+ }
+ return ret;
+ }
+
/**
* Throws if any of the mandatory fields is not set.
*
@@ -511,6 +538,7 @@ public final class ShortcutInfo implements Parcelable {
mDisabledMessage = source.mDisabledMessage;
mDisabledMessageResId = source.mDisabledMessageResId;
mCategories = cloneCategories(source.mCategories);
+ mPersons = clonePersons(source.mPersons);
if ((cloneFlags & CLONE_REMOVE_INTENT) == 0) {
mIntents = cloneIntents(source.mIntents);
mIntentPersistableExtrases =
@@ -833,6 +861,9 @@ public final class ShortcutInfo implements Parcelable {
if (source.mCategories != null) {
mCategories = cloneCategories(source.mCategories);
}
+ if (source.mPersons != null) {
+ mPersons = clonePersons(source.mPersons);
+ }
if (source.mIntents != null) {
mIntents = cloneIntents(source.mIntents);
mIntentPersistableExtrases =
@@ -901,6 +932,10 @@ public final class ShortcutInfo implements Parcelable {
private Intent[] mIntents;
+ private Person[] mPersons;
+
+ private boolean mIsLongLived;
+
private int mRank = RANK_NOT_SET;
private PersistableBundle mExtras;
@@ -1165,6 +1200,53 @@ public final class ShortcutInfo implements Parcelable {
}
/**
+ * Add a person that is relevant to this shortcut. Alternatively,
+ * {@link #setPersons(Person[])} can be used to add multiple persons to a shortcut.
+ *
+ * <p> This is an optional field, but the addition of person may cause this shortcut to
+ * appear more prominently in the user interface (e.g. ShareSheet).
+ *
+ * <p> A person should usually contain a uri in order to benefit from the ranking boost.
+ * However, even if no uri is provided, it's beneficial to provide people in the shortcut,
+ * such that listeners and voice only devices can announce and handle them properly.
+ *
+ * @see Person
+ * @see #setPersons(Person[])
+ */
+ @NonNull
+ public Builder setPerson(@NonNull Person person) {
+ return setPersons(new Person[]{person});
+ }
+
+ /**
+ * Sets multiple persons instead of a single person.
+ *
+ * @see Person
+ * @see #setPerson(Person)
+ */
+ @NonNull
+ public Builder setPersons(@NonNull Person[] persons) {
+ Preconditions.checkNotNull(persons, "persons cannot be null");
+ Preconditions.checkNotNull(persons.length, "persons cannot be empty");
+ for (Person person : persons) {
+ Preconditions.checkNotNull(person, "persons cannot contain null");
+ }
+ mPersons = clonePersons(persons);
+ return this;
+ }
+
+ /**
+ * Sets if a shortcut would be valid even if it has been unpublished/invisible by the app
+ * (as a dynamic or pinned shortcut). If it is long lived, it can be cached by various
+ * system services even after it has been unpublished as a dynamic shortcut.
+ */
+ @NonNull
+ public Builder setLongLived() {
+ mIsLongLived = true;
+ return this;
+ }
+
+ /**
* "Rank" of a shortcut, which is a non-negative value that's used by the launcher app
* to sort shortcuts.
*
@@ -1395,6 +1477,16 @@ public final class ShortcutInfo implements Parcelable {
}
/**
+ * Return the Persons set with {@link Builder#setPersons(Person[])}.
+ *
+ * @hide
+ */
+ @Nullable
+ public Person[] getPersons() {
+ return clonePersons(mPersons);
+ }
+
+ /**
* The extras in the intents. We convert extras into {@link PersistableBundle} so we can
* persist them.
* @hide
@@ -1525,6 +1617,16 @@ public final class ShortcutInfo implements Parcelable {
addFlags(FLAG_RETURNED_BY_SERVICE);
}
+ /** @hide */
+ public boolean isLongLived() {
+ return hasFlags(FLAG_LONG_LIVED);
+ }
+
+ /** @hide */
+ public void setLongLived() {
+ addFlags(FLAG_LONG_LIVED);
+ }
+
/** Return whether a shortcut is dynamic. */
public boolean isDynamic() {
return hasFlags(FLAG_DYNAMIC);
@@ -1893,6 +1995,8 @@ public final class ShortcutInfo implements Parcelable {
mCategories.add(source.readString().intern());
}
}
+
+ mPersons = source.readParcelableArray(cl, Person.class);
}
@Override
@@ -1940,6 +2044,8 @@ public final class ShortcutInfo implements Parcelable {
} else {
dest.writeInt(0);
}
+
+ dest.writeParcelableArray(mPersons, flags);
}
public static final Creator<ShortcutInfo> CREATOR =
@@ -2040,6 +2146,9 @@ public final class ShortcutInfo implements Parcelable {
if (isReturnedByServer()) {
sb.append("Rets");
}
+ if (isLongLived()) {
+ sb.append("Liv");
+ }
sb.append("]");
addIndentOrComma(sb, indent);
@@ -2094,6 +2203,11 @@ public final class ShortcutInfo implements Parcelable {
addIndentOrComma(sb, indent);
+ sb.append("persons=");
+ sb.append(mPersons);
+
+ addIndentOrComma(sb, indent);
+
sb.append("icon=");
sb.append(mIcon);
diff --git a/core/java/android/content/pm/ShortcutManager.java b/core/java/android/content/pm/ShortcutManager.java
index 2d590033259f..4f7acd96aa6b 100644
--- a/core/java/android/content/pm/ShortcutManager.java
+++ b/core/java/android/content/pm/ShortcutManager.java
@@ -17,17 +17,22 @@ package android.content.pm;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.annotation.UserIdInt;
import android.app.usage.UsageStatsManager;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.IntentSender;
import android.graphics.drawable.AdaptiveIconDrawable;
import android.os.Build;
import android.os.Build.VERSION_CODES;
+import android.os.Parcel;
+import android.os.Parcelable;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -549,4 +554,85 @@ public class ShortcutManager {
protected int injectMyUserId() {
return mContext.getUserId();
}
+
+ /**
+ * Used by framework's ShareSheet (ChooserActivity.java) to retrieve all of the direct share
+ * targets that match the given IntentFilter.
+ *
+ * @param filter IntentFilter that will be used to retrieve the matching {@link ShortcutInfo}s.
+ * @return List of {@link ShareShortcutInfo}s that match the given IntentFilter.
+ * @hide
+ */
+ @NonNull
+ @SystemApi
+ public List<ShareShortcutInfo> getShareTargets(@NonNull IntentFilter filter) {
+ try {
+ return mService.getShareTargets(mContext.getPackageName(), filter,
+ injectMyUserId()).getList();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Represents the result of a query return by {@link #getShareTargets(IntentFilter)}.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final class ShareShortcutInfo implements Parcelable {
+ private final ShortcutInfo mShortcutInfo;
+ private final ComponentName mTargetComponent;
+
+ /**
+ * @hide
+ */
+ public ShareShortcutInfo(@NonNull ShortcutInfo shortcutInfo,
+ @NonNull ComponentName targetComponent) {
+ if (shortcutInfo == null) {
+ throw new NullPointerException("shortcut info is null");
+ }
+ if (targetComponent == null) {
+ throw new NullPointerException("target component is null");
+ }
+
+ mShortcutInfo = shortcutInfo;
+ mTargetComponent = targetComponent;
+ }
+
+ private ShareShortcutInfo(Parcel in) {
+ mShortcutInfo = in.readParcelable(ShortcutInfo.class.getClassLoader());
+ mTargetComponent = in.readParcelable(ComponentName.class.getClassLoader());
+ }
+
+ public ShortcutInfo getShortcutInfo() {
+ return mShortcutInfo;
+ }
+
+ public ComponentName getTargetComponent() {
+ return mTargetComponent;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeParcelable(mShortcutInfo, flags);
+ dest.writeParcelable(mTargetComponent, flags);
+ }
+
+ public static final Parcelable.Creator<ShareShortcutInfo> CREATOR =
+ new Parcelable.Creator<ShareShortcutInfo>() {
+ public ShareShortcutInfo createFromParcel(Parcel in) {
+ return new ShareShortcutInfo(in);
+ }
+
+ public ShareShortcutInfo[] newArray(int size) {
+ return new ShareShortcutInfo[size];
+ }
+ };
+ }
}
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index c4b315ec90c8..dcd6e2ed94c7 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -98,6 +98,12 @@ import java.util.ArrayList;
* href="{@docRoot}guide/topics/resources/index.html">Application Resources</a>.</p>
*/
public class Resources {
+ /**
+ * The {@code null} resource ID. This denotes an invalid resource ID that is returned by the
+ * system when a resource is not found or the value is set to {@code @null} in XML.
+ */
+ public static final @AnyRes int ID_NULL = 0;
+
static final String TAG = "Resources";
private static final Object sSync = new Object();
diff --git a/core/java/android/hardware/display/BrightnessConfiguration.java b/core/java/android/hardware/display/BrightnessConfiguration.java
index be054297c769..8c74ddc7698c 100644
--- a/core/java/android/hardware/display/BrightnessConfiguration.java
+++ b/core/java/android/hardware/display/BrightnessConfiguration.java
@@ -91,9 +91,7 @@ public final class BrightnessConfiguration implements Parcelable {
*
* @return The matching brightness correction, or null.
*
- * @hide
*/
- @SystemApi
@Nullable
public BrightnessCorrection getCorrectionByPackageName(String packageName) {
return mCorrectionsByPackageName.get(packageName);
@@ -106,10 +104,7 @@ public final class BrightnessConfiguration implements Parcelable {
* The app category.
*
* @return The matching brightness correction, or null.
- *
- * @hide
*/
- @SystemApi
@Nullable
public BrightnessCorrection getCorrectionByCategory(int category) {
return mCorrectionsByCategory.get(category);
@@ -416,9 +411,7 @@ public final class BrightnessConfiguration implements Parcelable {
*
* @return The maximum number of corrections by package name allowed.
*
- * @hide
*/
- @SystemApi
public int getMaxCorrectionsByPackageName() {
return MAX_CORRECTIONS_BY_PACKAGE_NAME;
}
@@ -428,9 +421,7 @@ public final class BrightnessConfiguration implements Parcelable {
*
* @return The maximum number of corrections by category allowed.
*
- * @hide
*/
- @SystemApi
public int getMaxCorrectionsByCategory() {
return MAX_CORRECTIONS_BY_CATEGORY;
}
@@ -451,9 +442,7 @@ public final class BrightnessConfiguration implements Parcelable {
* Maximum number of corrections by package name exceeded (see
* {@link #getMaxCorrectionsByPackageName}).
*
- * @hide
*/
- @SystemApi
public Builder addCorrectionByPackageName(String packageName,
BrightnessCorrection correction) {
if (mCorrectionsByPackageName.size() >= getMaxCorrectionsByPackageName()) {
@@ -479,9 +468,7 @@ public final class BrightnessConfiguration implements Parcelable {
* Maximum number of corrections by category exceeded (see
* {@link #getMaxCorrectionsByCategory}).
*
- * @hide
*/
- @SystemApi
public Builder addCorrectionByCategory(@ApplicationInfo.Category int category,
BrightnessCorrection correction) {
if (mCorrectionsByCategory.size() >= getMaxCorrectionsByCategory()) {
@@ -504,8 +491,6 @@ public final class BrightnessConfiguration implements Parcelable {
/**
* Builds the {@link BrightnessConfiguration}.
- *
- * A brightness curve <b>must</b> be set before calling this.
*/
public BrightnessConfiguration build() {
if (mCurveLux == null || mCurveNits == null) {
diff --git a/core/java/android/hardware/display/BrightnessCorrection.java b/core/java/android/hardware/display/BrightnessCorrection.java
index c4e0e3b723cd..6a073ffaaa5b 100644
--- a/core/java/android/hardware/display/BrightnessCorrection.java
+++ b/core/java/android/hardware/display/BrightnessCorrection.java
@@ -18,6 +18,7 @@ package android.hardware.display;
import android.annotation.NonNull;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.MathUtils;
@@ -41,6 +42,7 @@ import java.io.IOException;
* @hide
*/
@SystemApi
+@TestApi
public final class BrightnessCorrection implements Parcelable {
private static final int SCALE_AND_TRANSLATE_LOG = 1;
@@ -98,6 +100,24 @@ public final class BrightnessCorrection implements Parcelable {
return mImplementation.toString();
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof BrightnessCorrection)) {
+ return false;
+ }
+ BrightnessCorrection other = (BrightnessCorrection) o;
+ return other.mImplementation.equals(mImplementation);
+ }
+
+ @Override
+ public int hashCode() {
+ return mImplementation.hashCode();
+ }
+
public static final Creator<BrightnessCorrection> CREATOR =
new Creator<BrightnessCorrection>() {
public BrightnessCorrection createFromParcel(Parcel in) {
@@ -215,6 +235,26 @@ public final class BrightnessCorrection implements Parcelable {
}
@Override
+ public boolean equals(Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof ScaleAndTranslateLog)) {
+ return false;
+ }
+ ScaleAndTranslateLog other = (ScaleAndTranslateLog) o;
+ return other.mScale == mScale && other.mTranslate == mTranslate;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 1;
+ result = result * 31 + Float.hashCode(mScale);
+ result = result * 31 + Float.hashCode(mTranslate);
+ return result;
+ }
+
+ @Override
public void writeToParcel(Parcel dest) {
dest.writeInt(SCALE_AND_TRANSLATE_LOG);
dest.writeFloat(mScale);
diff --git a/core/java/android/net/NetworkSpecifier.java b/core/java/android/net/NetworkSpecifier.java
index be2f9551daff..fcfb72035c19 100644
--- a/core/java/android/net/NetworkSpecifier.java
+++ b/core/java/android/net/NetworkSpecifier.java
@@ -17,7 +17,7 @@
package android.net;
/**
- * Describes specific properties of a network for use in a {@link NetworkRequest}.
+ * Describes specific properties of a requested network for use in a {@link NetworkRequest}.
*
* Applications cannot instantiate this class by themselves, but can obtain instances of
* subclasses of this class via other APIs.
@@ -49,4 +49,29 @@ public abstract class NetworkSpecifier {
public void assertValidFromUid(int requestorUid) {
// empty
}
+
+ /**
+ * Optional method which can be overridden by concrete implementations of NetworkSpecifier to
+ * perform any redaction of information from the NetworkSpecifier, e.g. if it contains
+ * sensitive information. The default implementation simply returns the object itself - i.e.
+ * no information is redacted. A concrete implementation may return a modified (copy) of the
+ * NetworkSpecifier, or even return a null to fully remove all information.
+ * <p>
+ * This method is relevant to NetworkSpecifier objects used by agents - those are shared with
+ * apps by default. Some agents may store sensitive matching information in the specifier,
+ * e.g. a Wi-Fi SSID (which should not be shared since it may leak location). Those classes
+ * can redact to a null. Other agents use the Network Specifier to share public information
+ * with apps - those should not be redacted.
+ * <p>
+ * The default implementation redacts no information.
+ *
+ * @return A NetworkSpecifier object to be passed along to the requesting app.
+ *
+ * @hide
+ */
+ public NetworkSpecifier redact() {
+ // TODO (b/122160111): convert default to null once all platform NetworkSpecifiers
+ // implement this method.
+ return this;
+ }
}
diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java
index e4622dbdc379..f51ba9a41a2b 100644
--- a/core/java/android/os/GraphicsEnvironment.java
+++ b/core/java/android/os/GraphicsEnvironment.java
@@ -306,9 +306,18 @@ public class GraphicsEnvironment {
String packageName,
String paths,
String devOptIn) {
- // Check for temporary rules if debuggable or root
- if (!isDebuggable(context) && !(getCanLoadSystemLibraries() == 1)) {
- Log.v(TAG, "Skipping loading temporary rules file");
+ /**
+ * We only want to load a temp rules file for:
+ * - apps that are marked 'debuggable' in their manifest
+ * - devices that are running a userdebug build (ro.debuggable) or can inject libraries for
+ * debugging (PR_SET_DUMPABLE).
+ */
+ boolean appIsDebuggable = isDebuggable(context);
+ boolean deviceIsDebuggable = getCanLoadSystemLibraries() == 1;
+ if (!(appIsDebuggable || deviceIsDebuggable)) {
+ Log.v(TAG, "Skipping loading temporary rules file: "
+ + "appIsDebuggable = " + appIsDebuggable + ", "
+ + "adbRootEnabled = " + deviceIsDebuggable);
return false;
}
diff --git a/core/java/android/os/VintfObject.java b/core/java/android/os/VintfObject.java
index fb22194098b6..23c54f450a67 100644
--- a/core/java/android/os/VintfObject.java
+++ b/core/java/android/os/VintfObject.java
@@ -16,23 +16,27 @@
package android.os;
-import java.util.Map;
+import android.annotation.TestApi;
+import java.util.Map;
/**
* Java API for libvintf.
+ *
* @hide
*/
+@TestApi
public class VintfObject {
- /// ---------- OTA
-
/**
* Slurps all device information (both manifests and both matrices)
* and report them.
* If any error in getting one of the manifests, it is not included in
* the list.
+ *
+ * @hide
*/
+ @TestApi
public static native String[] report();
/**
@@ -44,6 +48,8 @@ public class VintfObject {
* @return = 0 if success (compatible)
* > 0 if incompatible
* < 0 if any error (mount partition fails, illformed XML, etc.)
+ *
+ * @hide
*/
public static native int verify(String[] packageInfo);
@@ -55,22 +61,28 @@ public class VintfObject {
* @return = 0 if success (compatible)
* > 0 if incompatible
* < 0 if any error (mount partition fails, illformed XML, etc.)
+ *
+ * @hide
*/
public static native int verifyWithoutAvb();
- /// ---------- CTS Device Info
-
/**
* @return a list of HAL names and versions that is supported by this
* device as stated in device and framework manifests. For example,
* ["android.hidl.manager@1.0", "android.hardware.camera.device@1.0",
* "android.hardware.camera.device@3.2"]. There are no duplicates.
+ *
+ * @hide
*/
+ @TestApi
public static native String[] getHalNamesAndVersions();
/**
* @return the BOARD_SEPOLICY_VERS build flag available in device manifest.
+ *
+ * @hide
*/
+ @TestApi
public static native String getSepolicyVersion();
/**
@@ -78,13 +90,22 @@ public class VintfObject {
* specified in framework manifest. For example,
* [("27", ["libjpeg.so", "libbase.so"]),
* ("28", ["libjpeg.so", "libbase.so"])]
+ *
+ * @hide
*/
+ @TestApi
public static native Map<String, String[]> getVndkSnapshots();
/**
- * @return target FCM version, a number specified in the device manifest
- * indicating the FCM version that the device manifest implements. Null if
- * device manifest doesn't specify this number (for legacy devices).
+ * @return Target Framework Compatibility Matrix (FCM) version, a number
+ * specified in the device manifest indicating the FCM version that the
+ * device manifest implements. Null if device manifest doesn't specify this
+ * number (for legacy devices).
+ *
+ * @hide
*/
+ @TestApi
public static native Long getTargetFrameworkCompatibilityMatrixVersion();
+
+ private VintfObject() {}
}
diff --git a/core/java/android/os/VintfRuntimeInfo.java b/core/java/android/os/VintfRuntimeInfo.java
index 29698b9fa684..f17039ba9bf4 100644
--- a/core/java/android/os/VintfRuntimeInfo.java
+++ b/core/java/android/os/VintfRuntimeInfo.java
@@ -16,55 +16,84 @@
package android.os;
+import android.annotation.TestApi;
+
/**
* Java API for ::android::vintf::RuntimeInfo. Methods return null / 0 on any error.
*
* @hide
*/
+@TestApi
public class VintfRuntimeInfo {
private VintfRuntimeInfo() {}
/**
* @return /sys/fs/selinux/policyvers, via security_policyvers() native call
+ *
+ * @hide
*/
public static native long getKernelSepolicyVersion();
/**
* @return content of /proc/cpuinfo
+ *
+ * @hide
*/
+ @TestApi
public static native String getCpuInfo();
/**
* @return os name extracted from uname() native call
+ *
+ * @hide
*/
+ @TestApi
public static native String getOsName();
/**
* @return node name extracted from uname() native call
+ *
+ * @hide
*/
+ @TestApi
public static native String getNodeName();
/**
* @return os release extracted from uname() native call
+ *
+ * @hide
*/
+ @TestApi
public static native String getOsRelease();
/**
* @return os version extracted from uname() native call
+ *
+ * @hide
*/
+ @TestApi
public static native String getOsVersion();
/**
* @return hardware id extracted from uname() native call
+ *
+ * @hide
*/
+ @TestApi
public static native String getHardwareId();
/**
* @return kernel version extracted from uname() native call. Format is
* {@code x.y.z}.
+ *
+ * @hide
*/
+ @TestApi
public static native String getKernelVersion();
/**
* @return libavb version in OS. Format is {@code x.y}.
+ *
+ * @hide
*/
public static native String getBootAvbVersion();
/**
* @return libavb version in bootloader. Format is {@code x.y}.
+ *
+ * @hide
*/
public static native String getBootVbmetaAvbVersion();
-
}
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 44cb2212cd0c..af8146e85ec0 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -53,6 +53,13 @@ public final class DeviceConfig {
public static final Uri CONTENT_URI = Uri.parse("content://" + Settings.AUTHORITY + "/config");
/**
+ * Namespace for all Game Driver features.
+ * @hide
+ */
+ @SystemApi
+ public static final String NAMESPACE_GAME_DRIVER = "game_driver";
+
+ /**
* Namespace for all input-related features that are used at the native level.
* These features are applied at reboot.
*
diff --git a/core/java/android/provider/FontsContract.java b/core/java/android/provider/FontsContract.java
index 8e37559001db..e931826d2455 100644
--- a/core/java/android/provider/FontsContract.java
+++ b/core/java/android/provider/FontsContract.java
@@ -34,6 +34,7 @@ import android.graphics.fonts.FontFamily;
import android.graphics.fonts.FontStyle;
import android.graphics.fonts.FontVariationAxis;
import android.net.Uri;
+import android.os.Build.VERSION_CODES;
import android.os.CancellationSignal;
import android.os.Handler;
import android.os.HandlerThread;
@@ -651,7 +652,16 @@ public class FontsContract {
if (familyBuilder == null) {
familyBuilder = new FontFamily.Builder(font);
} else {
- familyBuilder.addFont(font);
+ try {
+ familyBuilder.addFont(font);
+ } catch (IllegalArgumentException e) {
+ if (context.getApplicationInfo().targetSdkVersion <= VERSION_CODES.P) {
+ // Surpress the IllegalArgumentException for keeping the backward
+ // compatibility.
+ continue;
+ }
+ throw e;
+ }
}
} catch (IOException e) {
continue;
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index ffd4156b5bfd..dc7c343c2c3e 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -22,6 +22,7 @@ import android.annotation.Nullable;
import android.annotation.SystemService;
import android.annotation.UnsupportedAppUsage;
import android.content.Context;
+import android.content.pm.ApplicationInfo;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
@@ -29,6 +30,7 @@ import android.graphics.Canvas;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
+import android.os.SystemProperties;
import android.os.Trace;
import android.util.AttributeSet;
import android.util.Log;
@@ -38,6 +40,9 @@ import android.widget.FrameLayout;
import com.android.internal.R;
+import dalvik.system.PathClassLoader;
+import java.io.File;
+import java.lang.reflect.Method;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -72,6 +77,10 @@ public abstract class LayoutInflater {
private static final String TAG = LayoutInflater.class.getSimpleName();
private static final boolean DEBUG = false;
+ private static final String USE_PRECOMPILED_LAYOUT_SYSTEM_PROPERTY
+ = "view.precompiled_layout_enabled";
+ private static final String COMPILED_VIEW_DEX_FILE_NAME = "/compiled_view.dex";
+
/** Empty stack trace used to avoid log spam in re-throw exceptions. */
private static final StackTraceElement[] EMPTY_STACK_TRACE = new StackTraceElement[0];
@@ -93,6 +102,13 @@ public abstract class LayoutInflater {
private Factory2 mPrivateFactory;
private Filter mFilter;
+ // Indicates whether we should try to inflate layouts using a precompiled layout instead of
+ // inflating from the XML resource.
+ private boolean mUseCompiledView;
+ // This variable holds the classloader that will be used to look for precompiled layouts. The
+ // The classloader includes the generated compiled_view.dex file.
+ private ClassLoader mPrecompiledClassLoader;
+
@UnsupportedAppUsage
final Object[] mConstructorArgs = new Object[2];
@@ -223,6 +239,7 @@ public abstract class LayoutInflater {
*/
protected LayoutInflater(Context context) {
mContext = context;
+ initPrecompiledViews();
}
/**
@@ -239,6 +256,7 @@ public abstract class LayoutInflater {
mFactory2 = original.mFactory2;
mPrivateFactory = original.mPrivateFactory;
setFilter(original.mFilter);
+ initPrecompiledViews();
}
/**
@@ -380,6 +398,41 @@ public abstract class LayoutInflater {
}
}
+ private void initPrecompiledViews() {
+ // Check if precompiled layouts are enabled by a system property.
+ mUseCompiledView =
+ SystemProperties.getBoolean(USE_PRECOMPILED_LAYOUT_SYSTEM_PROPERTY, false);
+ if (!mUseCompiledView) {
+ return;
+ }
+
+ // Make sure the application allows code generation
+ ApplicationInfo appInfo = mContext.getApplicationInfo();
+ if ((appInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_PREFER_CODE_INTEGRITY) != 0
+ || appInfo.isPrivilegedApp()) {
+ mUseCompiledView = false;
+ return;
+ }
+
+ // Try to load the precompiled layout file.
+ try {
+ mPrecompiledClassLoader = mContext.getClassLoader();
+ String dexFile = mContext.getCodeCacheDir() + COMPILED_VIEW_DEX_FILE_NAME;
+ if (new File(dexFile).exists()) {
+ mPrecompiledClassLoader = new PathClassLoader(dexFile, mPrecompiledClassLoader);
+ } else {
+ // If the precompiled layout file doesn't exist, then disable precompiled
+ // layouts.
+ mUseCompiledView = false;
+ }
+ } catch (Throwable e) {
+ if (DEBUG) {
+ Log.e(TAG, "Failed to initialized precompiled views layouts", e);
+ }
+ mUseCompiledView = false;
+ }
+ }
+
/**
* Inflate a new view hierarchy from the specified xml resource. Throws
* {@link InflateException} if there is an error.
@@ -436,10 +489,14 @@ public abstract class LayoutInflater {
final Resources res = getContext().getResources();
if (DEBUG) {
Log.d(TAG, "INFLATING from resource: \"" + res.getResourceName(resource) + "\" ("
- + Integer.toHexString(resource) + ")");
+ + Integer.toHexString(resource) + ")");
}
- final XmlResourceParser parser = res.getLayout(resource);
+ View view = tryInflatePrecompiled(resource, res, root, attachToRoot);
+ if (view != null) {
+ return view;
+ }
+ XmlResourceParser parser = res.getLayout(resource);
try {
return inflate(parser, root, attachToRoot);
} finally {
@@ -447,6 +504,73 @@ public abstract class LayoutInflater {
}
}
+ private @Nullable
+ View tryInflatePrecompiled(@LayoutRes int resource, Resources res, @Nullable ViewGroup root,
+ boolean attachToRoot) {
+ if (!mUseCompiledView) {
+ return null;
+ }
+
+ Trace.traceBegin(Trace.TRACE_TAG_VIEW, "inflate (precompiled)");
+
+ // Try to inflate using a precompiled layout.
+ String pkg = res.getResourcePackageName(resource);
+ String layout = res.getResourceEntryName(resource);
+
+ try {
+ Class clazz = mPrecompiledClassLoader.loadClass("" + pkg + ".CompiledView");
+ Method inflater = clazz.getMethod(layout, Context.class, int.class);
+ View view = (View) inflater.invoke(null, mContext, resource);
+
+ if (view != null && root != null) {
+ // We were able to use the precompiled inflater, but now we need to do some work to
+ // attach the view to the root correctly.
+ XmlResourceParser parser = res.getLayout(resource);
+ try {
+ AttributeSet attrs = Xml.asAttributeSet(parser);
+ advanceToRootNode(parser);
+ ViewGroup.LayoutParams params = root.generateLayoutParams(attrs);
+
+ if (attachToRoot) {
+ root.addView(view, params);
+ } else {
+ view.setLayoutParams(params);
+ }
+ } finally {
+ parser.close();
+ }
+ }
+
+ return view;
+ } catch (Throwable e) {
+ if (DEBUG) {
+ Log.e(TAG, "Failed to use precompiled view", e);
+ }
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+ }
+ return null;
+ }
+
+ /**
+ * Advances the given parser to the first START_TAG. Throws InflateException if no start tag is
+ * found.
+ */
+ private void advanceToRootNode(XmlPullParser parser)
+ throws InflateException, IOException, XmlPullParserException {
+ // Look for the root node.
+ int type;
+ while ((type = parser.next()) != XmlPullParser.START_TAG &&
+ type != XmlPullParser.END_DOCUMENT) {
+ // Empty
+ }
+
+ if (type != XmlPullParser.START_TAG) {
+ throw new InflateException(parser.getPositionDescription()
+ + ": No start tag found!");
+ }
+ }
+
/**
* Inflate a new view hierarchy from the specified XML node. Throws
* {@link InflateException} if there is an error.
@@ -480,18 +604,7 @@ public abstract class LayoutInflater {
View result = root;
try {
- // Look for the root node.
- int type;
- while ((type = parser.next()) != XmlPullParser.START_TAG &&
- type != XmlPullParser.END_DOCUMENT) {
- // Empty
- }
-
- if (type != XmlPullParser.START_TAG) {
- throw new InflateException(parser.getPositionDescription()
- + ": No start tag found!");
- }
-
+ advanceToRootNode(parser);
final String name = parser.getName();
if (DEBUG) {
@@ -994,82 +1107,85 @@ public abstract class LayoutInflater {
+ "reference. The layout ID " + value + " is not valid.");
}
- final XmlResourceParser childParser = context.getResources().getLayout(layout);
+ final View precompiled = tryInflatePrecompiled(layout, context.getResources(),
+ (ViewGroup) parent, /*attachToRoot=*/true);
+ if (precompiled == null) {
+ final XmlResourceParser childParser = context.getResources().getLayout(layout);
- try {
- final AttributeSet childAttrs = Xml.asAttributeSet(childParser);
+ try {
+ final AttributeSet childAttrs = Xml.asAttributeSet(childParser);
- while ((type = childParser.next()) != XmlPullParser.START_TAG &&
- type != XmlPullParser.END_DOCUMENT) {
- // Empty.
- }
+ while ((type = childParser.next()) != XmlPullParser.START_TAG &&
+ type != XmlPullParser.END_DOCUMENT) {
+ // Empty.
+ }
- if (type != XmlPullParser.START_TAG) {
- throw new InflateException(childParser.getPositionDescription() +
- ": No start tag found!");
- }
+ if (type != XmlPullParser.START_TAG) {
+ throw new InflateException(childParser.getPositionDescription() +
+ ": No start tag found!");
+ }
- final String childName = childParser.getName();
+ final String childName = childParser.getName();
- if (TAG_MERGE.equals(childName)) {
- // The <merge> tag doesn't support android:theme, so
- // nothing special to do here.
- rInflate(childParser, parent, context, childAttrs, false);
- } else {
- final View view = createViewFromTag(parent, childName,
- context, childAttrs, hasThemeOverride);
- final ViewGroup group = (ViewGroup) parent;
-
- final TypedArray a = context.obtainStyledAttributes(
- attrs, R.styleable.Include);
- final int id = a.getResourceId(R.styleable.Include_id, View.NO_ID);
- final int visibility = a.getInt(R.styleable.Include_visibility, -1);
- a.recycle();
-
- // We try to load the layout params set in the <include /> tag.
- // If the parent can't generate layout params (ex. missing width
- // or height for the framework ViewGroups, though this is not
- // necessarily true of all ViewGroups) then we expect it to throw
- // a runtime exception.
- // We catch this exception and set localParams accordingly: true
- // means we successfully loaded layout params from the <include>
- // tag, false means we need to rely on the included layout params.
- ViewGroup.LayoutParams params = null;
- try {
- params = group.generateLayoutParams(attrs);
- } catch (RuntimeException e) {
- // Ignore, just fail over to child attrs.
- }
- if (params == null) {
- params = group.generateLayoutParams(childAttrs);
- }
- view.setLayoutParams(params);
+ if (TAG_MERGE.equals(childName)) {
+ // The <merge> tag doesn't support android:theme, so
+ // nothing special to do here.
+ rInflate(childParser, parent, context, childAttrs, false);
+ } else {
+ final View view = createViewFromTag(parent, childName,
+ context, childAttrs, hasThemeOverride);
+ final ViewGroup group = (ViewGroup) parent;
+
+ final TypedArray a = context.obtainStyledAttributes(
+ attrs, R.styleable.Include);
+ final int id = a.getResourceId(R.styleable.Include_id, View.NO_ID);
+ final int visibility = a.getInt(R.styleable.Include_visibility, -1);
+ a.recycle();
+
+ // We try to load the layout params set in the <include /> tag.
+ // If the parent can't generate layout params (ex. missing width
+ // or height for the framework ViewGroups, though this is not
+ // necessarily true of all ViewGroups) then we expect it to throw
+ // a runtime exception.
+ // We catch this exception and set localParams accordingly: true
+ // means we successfully loaded layout params from the <include>
+ // tag, false means we need to rely on the included layout params.
+ ViewGroup.LayoutParams params = null;
+ try {
+ params = group.generateLayoutParams(attrs);
+ } catch (RuntimeException e) {
+ // Ignore, just fail over to child attrs.
+ }
+ if (params == null) {
+ params = group.generateLayoutParams(childAttrs);
+ }
+ view.setLayoutParams(params);
- // Inflate all children.
- rInflateChildren(childParser, view, childAttrs, true);
+ // Inflate all children.
+ rInflateChildren(childParser, view, childAttrs, true);
- if (id != View.NO_ID) {
- view.setId(id);
- }
+ if (id != View.NO_ID) {
+ view.setId(id);
+ }
- switch (visibility) {
- case 0:
- view.setVisibility(View.VISIBLE);
- break;
- case 1:
- view.setVisibility(View.INVISIBLE);
- break;
- case 2:
- view.setVisibility(View.GONE);
- break;
- }
+ switch (visibility) {
+ case 0:
+ view.setVisibility(View.VISIBLE);
+ break;
+ case 1:
+ view.setVisibility(View.INVISIBLE);
+ break;
+ case 2:
+ view.setVisibility(View.GONE);
+ break;
+ }
- group.addView(view);
+ group.addView(view);
+ }
+ } finally {
+ childParser.close();
}
- } finally {
- childParser.close();
}
-
LayoutInflater.consumeChildElements(parser);
}
diff --git a/core/java/android/view/PointerIcon.java b/core/java/android/view/PointerIcon.java
index cf11fd04efdf..c3d13bd46eb3 100644
--- a/core/java/android/view/PointerIcon.java
+++ b/core/java/android/view/PointerIcon.java
@@ -31,6 +31,7 @@ import android.graphics.RectF;
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
+import android.hardware.display.DisplayManager;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
@@ -144,7 +145,8 @@ public final class PointerIcon implements Parcelable {
public static final int TYPE_DEFAULT = TYPE_ARROW;
private static final PointerIcon gNullIcon = new PointerIcon(TYPE_NULL);
- private static final SparseArray<PointerIcon> gSystemIcons = new SparseArray<PointerIcon>();
+ private static final SparseArray<SparseArray<PointerIcon>> gSystemIconsByDisplay =
+ new SparseArray<SparseArray<PointerIcon>>();
private static boolean sUseLargeIcons = false;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
@@ -163,6 +165,12 @@ public final class PointerIcon implements Parcelable {
@UnsupportedAppUsage
private int mDurationPerFrame;
+ /**
+ * Listener for displays lifecycle.
+ * @hide
+ */
+ private static DisplayManager.DisplayListener sDisplayListener;
+
private PointerIcon(int type) {
mType = type;
}
@@ -211,7 +219,19 @@ public final class PointerIcon implements Parcelable {
return gNullIcon;
}
- PointerIcon icon = gSystemIcons.get(type);
+ if (sDisplayListener == null) {
+ registerDisplayListener(context);
+ }
+
+ final int displayId = context.getDisplayId();
+ SparseArray<PointerIcon> systemIcons = gSystemIconsByDisplay.get(displayId);
+ if (systemIcons == null) {
+ systemIcons = new SparseArray<>();
+ gSystemIconsByDisplay.put(displayId, systemIcons);
+ }
+
+ PointerIcon icon = systemIcons.get(type);
+ // Reload if not in the same display.
if (icon != null) {
return icon;
}
@@ -240,7 +260,7 @@ public final class PointerIcon implements Parcelable {
} else {
icon.loadResource(context, context.getResources(), resourceId);
}
- gSystemIcons.append(type, icon);
+ systemIcons.append(type, icon);
return icon;
}
@@ -250,7 +270,7 @@ public final class PointerIcon implements Parcelable {
*/
public static void setUseLargeIcons(boolean use) {
sUseLargeIcons = use;
- gSystemIcons.clear();
+ gSystemIconsByDisplay.clear();
}
/**
@@ -576,4 +596,30 @@ public final class PointerIcon implements Parcelable {
return 0;
}
}
+
+ /**
+ * Manage system icon cache handled by display lifecycle.
+ * @param context The context.
+ */
+ private static void registerDisplayListener(@NonNull Context context) {
+ sDisplayListener = new DisplayManager.DisplayListener() {
+ @Override
+ public void onDisplayAdded(int displayId) {
+ }
+
+ @Override
+ public void onDisplayRemoved(int displayId) {
+ gSystemIconsByDisplay.remove(displayId);
+ }
+
+ @Override
+ public void onDisplayChanged(int displayId) {
+ gSystemIconsByDisplay.remove(displayId);
+ }
+ };
+
+ DisplayManager displayManager = context.getSystemService(DisplayManager.class);
+ displayManager.registerDisplayListener(sDisplayListener, null /* handler */);
+ }
+
}
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index ff5120d09e25..5e98236f7535 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -30,6 +30,7 @@ import static android.view.SurfaceControlProto.NAME;
import android.annotation.Size;
import android.annotation.UnsupportedAppUsage;
import android.graphics.Bitmap;
+import android.graphics.ColorSpace;
import android.graphics.GraphicBuffer;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
@@ -141,6 +142,7 @@ public class SurfaceControl implements Parcelable {
private static native int nativeGetActiveConfig(IBinder displayToken);
private static native boolean nativeSetActiveConfig(IBinder displayToken, int id);
private static native int[] nativeGetDisplayColorModes(IBinder displayToken);
+ private static native int[] nativeGetCompositionDataspaces();
private static native int nativeGetActiveColorMode(IBinder displayToken);
private static native boolean nativeSetActiveColorMode(IBinder displayToken,
int colorMode);
@@ -167,6 +169,7 @@ public class SurfaceControl implements Parcelable {
InputWindowHandle handle);
private static native void nativeTransferTouchFocus(long transactionObj, IBinder fromToken,
IBinder toToken);
+ private static native boolean nativeGetProtectedContentSupport();
private final CloseGuard mCloseGuard = CloseGuard.get();
private String mName;
@@ -374,6 +377,13 @@ public class SurfaceControl implements Parcelable {
*/
public static final int WINDOW_TYPE_DONT_SCREENSHOT = 441731;
+ /**
+ * internal representation of how to interpret pixel value, used only to convert to ColorSpace.
+ */
+ private static final int INTERNAL_DATASPACE_SRGB = 142671872;
+ private static final int INTERNAL_DATASPACE_DISPLAY_P3 = 143261696;
+ private static final int INTERNAL_DATASPACE_SCRGB = 411107328;
+
private void assignNativeObject(long nativeObject) {
if (mNativeObject != 0) {
release();
@@ -1516,6 +1526,35 @@ public class SurfaceControl implements Parcelable {
}
/**
+ * Returns an array of color spaces with 2 elements. The first color space is the
+ * default color space and second one is wide color gamut color space.
+ * @hide
+ */
+ public static ColorSpace[] getCompositionColorSpaces() {
+ int[] dataspaces = nativeGetCompositionDataspaces();
+ ColorSpace srgb = ColorSpace.get(ColorSpace.Named.SRGB);
+ ColorSpace[] colorSpaces = { srgb, srgb };
+ if (dataspaces.length == 2) {
+ for (int i = 0; i < 2; ++i) {
+ switch(dataspaces[i]) {
+ case INTERNAL_DATASPACE_DISPLAY_P3:
+ colorSpaces[i] = ColorSpace.get(ColorSpace.Named.DISPLAY_P3);
+ break;
+ case INTERNAL_DATASPACE_SCRGB:
+ colorSpaces[i] = ColorSpace.get(ColorSpace.Named.EXTENDED_SRGB);
+ break;
+ case INTERNAL_DATASPACE_SRGB:
+ // Other dataspace is not recognized, use SRGB color space instead,
+ // the default value of the array is already SRGB, thus do nothing.
+ default:
+ break;
+ }
+ }
+ }
+ return colorSpaces;
+ }
+
+ /**
* @hide
*/
@UnsupportedAppUsage
@@ -1730,6 +1769,14 @@ public class SurfaceControl implements Parcelable {
}
/**
+ * Returns whether protected content is supported in GPU composition.
+ * @hide
+ */
+ public static boolean getProtectedContentSupport() {
+ return nativeGetProtectedContentSupport();
+ }
+
+ /**
* @hide
*/
public static class Transaction implements Closeable {
diff --git a/core/java/android/view/contentcapture/ChildContentCaptureSession.java b/core/java/android/view/contentcapture/ChildContentCaptureSession.java
index 04e725e64e9c..0b39c3ada0b1 100644
--- a/core/java/android/view/contentcapture/ChildContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/ChildContentCaptureSession.java
@@ -68,8 +68,8 @@ final class ChildContentCaptureSession extends ContentCaptureSession {
}
@Override
- void flush() {
- mParent.flush();
+ void flush(@FlushReason int reason) {
+ mParent.flush(reason);
}
@Override
@@ -92,6 +92,7 @@ final class ChildContentCaptureSession extends ContentCaptureSession {
int flags) {
getMainCaptureSession().notifyViewTextChanged(mId, id, text, flags);
}
+
@Override
boolean isContentCaptureEnabled() {
return getMainCaptureSession().isContentCaptureEnabled();
diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java
index 81b2e01dfbc7..413f1a5a8955 100644
--- a/core/java/android/view/contentcapture/ContentCaptureManager.java
+++ b/core/java/android/view/contentcapture/ContentCaptureManager.java
@@ -24,10 +24,11 @@ import android.annotation.UiThread;
import android.content.ComponentName;
import android.content.Context;
import android.os.Handler;
-import android.os.HandlerThread;
import android.os.IBinder;
+import android.os.Looper;
import android.os.RemoteException;
import android.util.Log;
+import android.view.contentcapture.ContentCaptureSession.FlushReason;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.IResultReceiver;
@@ -51,8 +52,6 @@ public final class ContentCaptureManager {
private static final String TAG = ContentCaptureManager.class.getSimpleName();
- private static final String BG_THREAD_NAME = "intel_svc_streamer_thread";
-
/**
* Timeout for calls to system_server.
*/
@@ -89,24 +88,13 @@ public final class ContentCaptureManager {
public ContentCaptureManager(@NonNull Context context,
@Nullable IContentCaptureManager service) {
mContext = Preconditions.checkNotNull(context, "context cannot be null");
- if (VERBOSE) {
- Log.v(TAG, "Constructor for " + context.getPackageName());
- }
- mService = service;
- // TODO(b/119220549): use an existing bg thread instead...
- final HandlerThread bgThread = new HandlerThread(BG_THREAD_NAME);
- bgThread.start();
- mHandler = Handler.createAsync(bgThread.getLooper());
- }
+ if (VERBOSE) Log.v(TAG, "Constructor for " + context.getPackageName());
- @NonNull
- private static Handler newHandler() {
- // TODO(b/119220549): use an existing bg thread instead...
- // TODO(b/119220549): use UI Thread directly (as calls are one-way) or an existing bgThread
- // or a shared thread / handler held at the Application level
- final HandlerThread bgThread = new HandlerThread(BG_THREAD_NAME);
- bgThread.start();
- return Handler.createAsync(bgThread.getLooper());
+ mService = service;
+ // TODO(b/119220549): we might not even need a handler, as the IPCs are oneway. But if we
+ // do, then we should optimize it to run the tests after the Choreographer finishes the most
+ // important steps of the frame.
+ mHandler = Handler.createAsync(Looper.getMainLooper());
}
/**
@@ -154,8 +142,8 @@ public final class ContentCaptureManager {
*
* @hide
*/
- public void flush() {
- getMainContentCaptureSession().flush();
+ public void flush(@FlushReason int reason) {
+ getMainContentCaptureSession().flush(reason);
}
/**
diff --git a/core/java/android/view/contentcapture/ContentCaptureSession.java b/core/java/android/view/contentcapture/ContentCaptureSession.java
index 7bfc5b413615..7fb1fdd2d651 100644
--- a/core/java/android/view/contentcapture/ContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/ContentCaptureSession.java
@@ -19,6 +19,7 @@ import static android.view.contentcapture.ContentCaptureManager.DEBUG;
import static android.view.contentcapture.ContentCaptureManager.VERBOSE;
import android.annotation.CallSuper;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.util.DebugUtils;
@@ -30,11 +31,14 @@ import android.view.contentcapture.ViewNode.ViewStructureImpl;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ArrayUtils;
import com.android.internal.util.Preconditions;
import dalvik.system.CloseGuard;
import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.UUID;
@@ -125,6 +129,32 @@ public abstract class ContentCaptureSession implements AutoCloseable {
private static final int INITIAL_CHILDREN_CAPACITY = 5;
+ /** @hide */
+ public static final int FLUSH_REASON_FULL = 1;
+ /** @hide */
+ public static final int FLUSH_REASON_ACTIVITY_PAUSED = 2;
+ /** @hide */
+ public static final int FLUSH_REASON_ACTIVITY_RESUMED = 3;
+ /** @hide */
+ public static final int FLUSH_REASON_SESSION_STARTED = 4;
+ /** @hide */
+ public static final int FLUSH_REASON_SESSION_FINISHED = 5;
+ /** @hide */
+ public static final int FLUSH_REASON_IDLE_TIMEOUT = 6;
+
+ /** @hide */
+ @IntDef(prefix = { "FLUSH_REASON_" }, value = {
+ FLUSH_REASON_FULL,
+ FLUSH_REASON_ACTIVITY_PAUSED,
+ FLUSH_REASON_ACTIVITY_RESUMED,
+ FLUSH_REASON_SESSION_STARTED,
+ FLUSH_REASON_SESSION_FINISHED,
+ FLUSH_REASON_IDLE_TIMEOUT
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ @interface FlushReason{}
+
+
private final CloseGuard mCloseGuard = CloseGuard.get();
private final Object mLock = new Object();
@@ -212,7 +242,7 @@ public abstract class ContentCaptureSession implements AutoCloseable {
/**
* Flushes the buffered events to the service.
*/
- abstract void flush();
+ abstract void flush(@FlushReason int reason);
/**
* Destroys this session, flushing out all pending notifications to the service.
@@ -250,7 +280,7 @@ public abstract class ContentCaptureSession implements AutoCloseable {
}
try {
- flush();
+ flush(FLUSH_REASON_SESSION_FINISHED);
} finally {
onDestroy();
}
@@ -316,6 +346,31 @@ public abstract class ContentCaptureSession implements AutoCloseable {
abstract void internalNotifyViewDisappeared(@NonNull AutofillId id);
/**
+ * Notifies the Content Capture Service that many nodes has been removed from a virtual view
+ * structure.
+ *
+ * <p>Should only be called by views that handle their own virtual view hierarchy.
+ *
+ * @param hostId id of the view hosting the virtual hierarchy.
+ * @param virtualIds ids of the virtual children.
+ *
+ * @throws IllegalArgumentException if the {@code hostId} is an autofill id for a virtual view.
+ * @throws IllegalArgumentException if {@code virtualIds} is empty
+ */
+ public final void notifyViewsDisappeared(@NonNull AutofillId hostId,
+ @NonNull int[] virtualIds) {
+ Preconditions.checkArgument(!hostId.isVirtual(), "parent cannot be virtual");
+ Preconditions.checkArgument(!ArrayUtils.isEmpty(virtualIds), "virtual ids cannot be empty");
+ if (!isContentCaptureEnabled()) return;
+
+ // TODO(b/121050915): create a new VIEWS_DISAPPEARED event type, which could also be used
+ // to batch delete non-virtual views
+ for (int id : virtualIds) {
+ internalNotifyViewDisappeared(new AutofillId(hostId, id, getIdAsInt()));
+ }
+ }
+
+ /**
* Notifies the Intelligence Service that the value of a text node has been changed.
*
* @param id of the node.
@@ -407,12 +462,31 @@ public abstract class ContentCaptureSession implements AutoCloseable {
return mId;
}
- /**
- * @hide
- */
+ /** @hide */
@NonNull
protected static String getStateAsString(int state) {
return state + " (" + (state == UNKNWON_STATE ? "UNKNOWN"
: DebugUtils.flagsToString(ContentCaptureSession.class, "STATE_", state)) + ")";
}
+
+ /** @hide */
+ @NonNull
+ static String getflushReasonAsString(@FlushReason int reason) {
+ switch (reason) {
+ case FLUSH_REASON_FULL:
+ return "FULL";
+ case FLUSH_REASON_ACTIVITY_PAUSED:
+ return "PAUSED";
+ case FLUSH_REASON_ACTIVITY_RESUMED:
+ return "RESUMED";
+ case FLUSH_REASON_SESSION_STARTED:
+ return "STARTED";
+ case FLUSH_REASON_SESSION_FINISHED:
+ return "FINISHED";
+ case FLUSH_REASON_IDLE_TIMEOUT:
+ return "IDLE";
+ default:
+ return "UNKOWN-" + reason;
+ }
+ }
}
diff --git a/core/java/android/view/contentcapture/MainContentCaptureSession.java b/core/java/android/view/contentcapture/MainContentCaptureSession.java
index a3ff8c09aa0c..f0778fa343b1 100644
--- a/core/java/android/view/contentcapture/MainContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/MainContentCaptureSession.java
@@ -35,7 +35,7 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.IBinder.DeathRecipient;
import android.os.RemoteException;
-import android.os.SystemClock;
+import android.util.LocalLog;
import android.util.Log;
import android.util.TimeUtils;
import android.view.autofill.AutofillId;
@@ -131,6 +131,9 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
// Used just for debugging purposes (on dump)
private long mNextFlush;
+ // TODO(b/121044064): use settings to set size
+ private final LocalLog mFlushHistory = new LocalLog(10);
+
/** @hide */
protected MainContentCaptureSession(@NonNull Context context, @NonNull Handler handler,
@Nullable IContentCaptureManager systemServerInterface,
@@ -172,8 +175,9 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
}
@Override
- void flush() {
- mHandler.sendMessage(obtainMessage(MainContentCaptureSession::handleForceFlush, this));
+ void flush(@FlushReason int reason) {
+ mHandler.sendMessage(
+ obtainMessage(MainContentCaptureSession::handleForceFlush, this, reason));
}
@Override
@@ -264,24 +268,25 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
}
private void handleSendEvent(@NonNull ContentCaptureEvent event, boolean forceFlush) {
- if (!handleHasStarted()
- && event.getType() != ContentCaptureEvent.TYPE_SESSION_STARTED) {
+ final int eventType = event.getType();
+ if (!handleHasStarted() && eventType != ContentCaptureEvent.TYPE_SESSION_STARTED) {
// TODO(b/120494182): comment when this could happen (dialogs?)
Log.v(TAG, "handleSendEvent(" + getDebugState() + ", "
- + ContentCaptureEvent.getTypeAsString(event.getType())
+ + ContentCaptureEvent.getTypeAsString(eventType)
+ "): session not started yet");
return;
}
+ if (VERBOSE) Log.v(TAG, "handleSendEvent(" + getDebugState() + "): " + event);
if (mEvents == null) {
if (VERBOSE) {
Log.v(TAG, "handleSendEvent(" + getDebugState() + ", "
- + ContentCaptureEvent.getTypeAsString(event.getType())
- + "): cCreating buffer for " + MAX_BUFFER_SIZE + " events");
+ + ContentCaptureEvent.getTypeAsString(eventType)
+ + "): creating buffer for " + MAX_BUFFER_SIZE + " events");
}
mEvents = new ArrayList<>(MAX_BUFFER_SIZE);
}
- if (!mEvents.isEmpty() && event.getType() == TYPE_VIEW_TEXT_CHANGED) {
+ if (!mEvents.isEmpty() && eventType == TYPE_VIEW_TEXT_CHANGED) {
final ContentCaptureEvent lastEvent = mEvents.get(mEvents.size() - 1);
// TODO(b/121045053): check if flags match
@@ -304,7 +309,7 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
final boolean bufferEvent = numberEvents < MAX_BUFFER_SIZE;
if (bufferEvent && !forceFlush) {
- handleScheduleFlush(/* checkExisting= */ true);
+ handleScheduleFlush(FLUSH_REASON_IDLE_TIMEOUT, /* checkExisting= */ true);
return;
}
@@ -323,15 +328,26 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
// when it's launched again
return;
}
+ final int flushReason;
+ switch (eventType) {
+ case ContentCaptureEvent.TYPE_SESSION_STARTED:
+ flushReason = FLUSH_REASON_SESSION_STARTED;
+ break;
+ case ContentCaptureEvent.TYPE_SESSION_FINISHED:
+ flushReason = FLUSH_REASON_SESSION_FINISHED;
+ break;
+ default:
+ flushReason = FLUSH_REASON_FULL;
+ }
- handleForceFlush();
+ handleForceFlush(flushReason);
}
private boolean handleHasStarted() {
return mState != UNKNWON_STATE;
}
- private void handleScheduleFlush(boolean checkExisting) {
+ private void handleScheduleFlush(@FlushReason int reason, boolean checkExisting) {
if (!handleHasStarted()) {
Log.v(TAG, "handleScheduleFlush(" + getDebugState() + "): session not started yet");
return;
@@ -340,43 +356,51 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
// "Renew" the flush message by removing the previous one
mHandler.removeMessages(MSG_FLUSH);
}
- mNextFlush = SystemClock.elapsedRealtime() + FLUSHING_FREQUENCY_MS;
+ mNextFlush = System.currentTimeMillis() + FLUSHING_FREQUENCY_MS;
if (VERBOSE) {
- Log.v(TAG, "handleScheduleFlush(" + getDebugState() + "): scheduled to flush in "
- + FLUSHING_FREQUENCY_MS + "ms: " + TimeUtils.formatUptime(mNextFlush));
+ Log.v(TAG, "handleScheduleFlush(" + getDebugState()
+ + ", reason=" + getflushReasonAsString(reason) + "): scheduled to flush in "
+ + FLUSHING_FREQUENCY_MS + "ms: " + TimeUtils.logTimeOfDay(mNextFlush));
}
mHandler.sendMessageDelayed(
- obtainMessage(MainContentCaptureSession::handleFlushIfNeeded, this)
+ obtainMessage(MainContentCaptureSession::handleFlushIfNeeded, this, reason)
.setWhat(MSG_FLUSH), FLUSHING_FREQUENCY_MS);
}
- private void handleFlushIfNeeded() {
+ private void handleFlushIfNeeded(@FlushReason int reason) {
if (mEvents.isEmpty()) {
if (VERBOSE) Log.v(TAG, "Nothing to flush");
return;
}
- handleForceFlush();
+ handleForceFlush(reason);
}
- private void handleForceFlush() {
+ private void handleForceFlush(@FlushReason int reason) {
if (mEvents == null) return;
if (mDirectServiceInterface == null) {
if (VERBOSE) {
Log.v(TAG, "handleForceFlush(" + getDebugState()
+ + ", reason=" + getflushReasonAsString(reason)
+ "): hold your horses, client not ready: " + mEvents);
}
if (!mHandler.hasMessages(MSG_FLUSH)) {
- handleScheduleFlush(/* checkExisting= */ false);
+ handleScheduleFlush(reason, /* checkExisting= */ false);
}
return;
}
final int numberEvents = mEvents.size();
+ final String reasonString = getflushReasonAsString(reason);
+ if (DEBUG) {
+ Log.d(TAG, "Flushing " + numberEvents + " event(s) for " + getDebugState()
+ + ". Reason: " + reasonString);
+ }
+ // Logs reason, size, max size, idle timeout
+ final String logRecord = "r=" + reasonString + " s=" + numberEvents
+ + " m=" + MAX_BUFFER_SIZE + " i=" + FLUSHING_FREQUENCY_MS;
try {
- if (DEBUG) {
- Log.d(TAG, "Flushing " + numberEvents + " event(s) for " + getDebugState());
- }
+ mFlushHistory.log(logRecord);
mHandler.removeMessages(MSG_FLUSH);
final ParceledListSlice<ContentCaptureEvent> events = handleClearEvents();
@@ -500,7 +524,6 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
@Override
void dump(@NonNull String prefix, @NonNull PrintWriter pw) {
- pw.print(prefix); pw.print("id: "); pw.println(mId);
pw.print(prefix); pw.print("mContext: "); pw.println(mContext);
pw.print(prefix); pw.print("user: "); pw.println(mContext.getUserId());
if (mSystemServerInterface != null) {
@@ -535,8 +558,12 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
}
pw.print(prefix); pw.print("flush frequency: "); pw.println(FLUSHING_FREQUENCY_MS);
pw.print(prefix); pw.print("next flush: ");
- TimeUtils.formatDuration(mNextFlush - SystemClock.elapsedRealtime(), pw); pw.println();
+ TimeUtils.formatDuration(mNextFlush - System.currentTimeMillis(), pw);
+ pw.print(" ("); pw.print(TimeUtils.logTimeOfDay(mNextFlush)); pw.println(")");
}
+ pw.print(prefix); pw.println("flush history:");
+ mFlushHistory.reverseDump(/* fd= */ null, pw, /* args= */ null); pw.println();
+
super.dump(prefix, pw);
}
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 4523d3b2739f..b4d8322c7552 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -21,19 +21,24 @@ import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.IntentSender;
import android.content.IntentSender.SendIntentException;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.content.pm.LabeledIntent;
+import android.content.pm.LauncherApps;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
+import android.content.pm.ShortcutInfo;
+import android.content.pm.ShortcutManager;
import android.database.DataSetObserver;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
+import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
@@ -75,6 +80,7 @@ import com.google.android.collect.Lists;
import java.io.File;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
@@ -92,6 +98,15 @@ public class ChooserActivity extends ResolverActivity {
private static final boolean DEBUG = false;
+ /**
+ * If set to true, use ShortcutManager to retrieve the matching direct share targets, instead of
+ * binding to every ChooserTargetService implementation.
+ */
+ // TODO(b/121287573): Replace with a system flag (setprop?)
+ private static final boolean USE_SHORTCUT_MANAGER_FOR_DIRECT_TARGETS = false;
+ // TODO(b/121287224): Re-evaluate this limit
+ private static final int SHARE_TARGET_QUERY_PACKAGE_LIMIT = 20;
+
private static final int QUERY_TARGET_SERVICE_LIMIT = 5;
private static final int WATCHDOG_TIMEOUT_MILLIS = 2000;
@@ -120,6 +135,7 @@ public class ChooserActivity extends ResolverActivity {
private static final int CHOOSER_TARGET_SERVICE_RESULT = 1;
private static final int CHOOSER_TARGET_SERVICE_WATCHDOG_TIMEOUT = 2;
+ private static final int SHORTCUT_MANAGER_SHARE_TARGET_RESULT = 3;
private final Handler mChooserHandler = new Handler() {
@Override
@@ -158,6 +174,18 @@ public class ChooserActivity extends ResolverActivity {
mChooserListAdapter.setShowServiceTargets(true);
break;
+ case SHORTCUT_MANAGER_SHARE_TARGET_RESULT:
+ if (DEBUG) Log.d(TAG, "SHORTCUT_MANAGER_SHARE_TARGET_RESULT");
+ if (isDestroyed()) break;
+ final ServiceResultInfo resultInfo = (ServiceResultInfo) msg.obj;
+ if (resultInfo.resultTargets != null) {
+ mChooserListAdapter.addServiceResults(resultInfo.originalTarget,
+ resultInfo.resultTargets);
+ }
+ sendVoiceChoicesIfNeeded();
+ mChooserListAdapter.setShowServiceTargets(true);
+ break;
+
default:
super.handleMessage(msg);
}
@@ -552,6 +580,94 @@ public class ChooserActivity extends ResolverActivity {
}
}
+ private IntentFilter getTargetIntentFilter() {
+ try {
+ final Intent intent = getTargetIntent();
+ String dataString = intent.getDataString();
+ if (TextUtils.isEmpty(dataString)) {
+ dataString = intent.getType();
+ }
+ return new IntentFilter(intent.getAction(), dataString);
+ } catch (Exception e) {
+ Log.e(TAG, "failed to get target intent filter " + e);
+ return null;
+ }
+ }
+
+ private void queryDirectShareTargets(ChooserListAdapter adapter) {
+ final IntentFilter filter = getTargetIntentFilter();
+ if (filter == null) {
+ return;
+ }
+
+ // Need to keep the original DisplayResolveInfos to be able to reconstruct ServiceResultInfo
+ // and use the old code path. This Ugliness should go away when Sharesheet is refactored.
+ final List<DisplayResolveInfo> driList = new ArrayList<>();
+ int targetsToQuery = 0;
+ for (int i = 0, n = adapter.getDisplayResolveInfoCount(); i < n; i++) {
+ final DisplayResolveInfo dri = adapter.getDisplayResolveInfo(i);
+ if (adapter.getScore(dri) == 0) {
+ // A score of 0 means the app hasn't been used in some time;
+ // don't query it as it's not likely to be relevant.
+ continue;
+ }
+ driList.add(dri);
+ targetsToQuery++;
+ // TODO(b/121287224): Do we need this here? (similar to queryTargetServices)
+ if (targetsToQuery >= SHARE_TARGET_QUERY_PACKAGE_LIMIT) {
+ if (DEBUG) {
+ Log.d(TAG, "queryTargets hit query target limit "
+ + SHARE_TARGET_QUERY_PACKAGE_LIMIT);
+ }
+ break;
+ }
+ }
+
+ AsyncTask.execute(() -> {
+ ShortcutManager sm = (ShortcutManager) getSystemService(Context.SHORTCUT_SERVICE);
+ List<ShortcutManager.ShareShortcutInfo> resultList = sm.getShareTargets(filter);
+
+ // Match ShareShortcutInfos with DisplayResolveInfos to be able to use the old code path
+ // for direct share targets. After ShareSheet is refactored we should use the
+ // ShareShortcutInfos directly.
+ for (int i = 0; i < driList.size(); i++) {
+ List<ChooserTarget> chooserTargets = new ArrayList<>();
+ for (int j = 0; j < resultList.size(); j++) {
+ if (driList.get(i).getResolvedComponentName().equals(
+ resultList.get(j).getTargetComponent())) {
+ chooserTargets.add(convertToChooserTarget(resultList.get(j)));
+ }
+ }
+ if (chooserTargets.isEmpty()) {
+ continue;
+ }
+
+ final Message msg = Message.obtain();
+ msg.what = SHORTCUT_MANAGER_SHARE_TARGET_RESULT;
+ msg.obj = new ServiceResultInfo(driList.get(i), chooserTargets, null);
+ mChooserHandler.sendMessage(msg);
+ }
+ });
+ }
+
+ private ChooserTarget convertToChooserTarget(ShortcutManager.ShareShortcutInfo shareShortcut) {
+ ShortcutInfo shortcutInfo = shareShortcut.getShortcutInfo();
+ Bundle extras = new Bundle();
+ extras.putString(Intent.EXTRA_SHORTCUT_ID, shortcutInfo.getId());
+ return new ChooserTarget(
+ // The name of this target.
+ shortcutInfo.getShortLabel(),
+ // Don't load the icon until it is selected to be shown
+ null,
+ // The ranking score for this target (0.0-1.0); the system will omit items with low
+ // scores when there are too many Direct Share items.
+ 0.5f,
+ // The name of the component to be launched if this target is chosen.
+ shareShortcut.getTargetComponent().clone(),
+ // The extra values here will be merged into the Intent when this target is chosen.
+ extras);
+ }
+
private String convertServiceName(String packageName, String serviceName) {
if (TextUtils.isEmpty(serviceName)) {
return null;
@@ -765,9 +881,8 @@ public class ChooserActivity extends ResolverActivity {
}
}
}
- final Icon icon = chooserTarget.getIcon();
- // TODO do this in the background
- mDisplayIcon = icon != null ? icon.loadDrawable(ChooserActivity.this) : null;
+ // TODO(b/121287224): do this in the background thread, and only for selected targets
+ mDisplayIcon = getChooserTargetIconDrawable(chooserTarget);
if (sourceInfo != null) {
mBackupResolveInfo = null;
@@ -791,6 +906,39 @@ public class ChooserActivity extends ResolverActivity {
mModifiedScore = other.mModifiedScore;
}
+ /**
+ * Since ShortcutInfos are returned by ShortcutManager, we can cache the shortcuts and skip
+ * the call to LauncherApps#getShortcuts(ShortcutQuery).
+ */
+ // TODO(121287224): Refactor code to apply the suggestion above
+ private Drawable getChooserTargetIconDrawable(ChooserTarget target) {
+ final Icon icon = target.getIcon();
+ if (icon != null) {
+ return icon.loadDrawable(ChooserActivity.this);
+ }
+ if (!USE_SHORTCUT_MANAGER_FOR_DIRECT_TARGETS) {
+ return null;
+ }
+
+ Bundle extras = target.getIntentExtras();
+ if (extras == null || !extras.containsKey(Intent.EXTRA_SHORTCUT_ID)) {
+ return null;
+ }
+ CharSequence shortcutId = extras.getCharSequence(Intent.EXTRA_SHORTCUT_ID);
+ LauncherApps launcherApps = (LauncherApps) getSystemService(
+ Context.LAUNCHER_APPS_SERVICE);
+ final LauncherApps.ShortcutQuery q = new LauncherApps.ShortcutQuery();
+ q.setPackage(target.getComponentName().getPackageName());
+ q.setShortcutIds(Arrays.asList(shortcutId.toString()));
+ q.setQueryFlags(LauncherApps.ShortcutQuery.FLAG_MATCH_DYNAMIC);
+ final List<ShortcutInfo> shortcuts = launcherApps.getShortcuts(q, getUser());
+ if (shortcuts != null && shortcuts.size() > 0) {
+ return launcherApps.getShortcutIconDrawable(shortcuts.get(0), 0);
+ }
+
+ return null;
+ }
+
public float getModifiedScore() {
return mModifiedScore;
}
@@ -1030,8 +1178,15 @@ public class ChooserActivity extends ResolverActivity {
mTargetsNeedPruning = true;
}
}
- if (DEBUG) Log.d(TAG, "List built querying services");
- queryTargetServices(this);
+ if (USE_SHORTCUT_MANAGER_FOR_DIRECT_TARGETS) {
+ if (DEBUG) {
+ Log.d(TAG, "querying direct share targets from ShortcutManager");
+ }
+ queryDirectShareTargets(this);
+ } else {
+ if (DEBUG) Log.d(TAG, "List built querying services");
+ queryTargetServices(this);
+ }
}
@Override
diff --git a/core/java/com/android/internal/infra/AbstractRemoteService.java b/core/java/com/android/internal/infra/AbstractRemoteService.java
index 594595843ca7..72c67d7ddc08 100644
--- a/core/java/com/android/internal/infra/AbstractRemoteService.java
+++ b/core/java/com/android/internal/infra/AbstractRemoteService.java
@@ -139,6 +139,14 @@ public abstract class AbstractRemoteService<S extends AbstractRemoteService<S, I
return mDestroyed;
}
+ /**
+ * Gets the name of the service.
+ */
+ @NonNull
+ public final ComponentName getComponentName() {
+ return mComponentName;
+ }
+
private void handleOnConnectedStateChangedInternal(boolean connected) {
if (connected) {
handlePendingRequests();
diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp
index 12a8343b4a5c..67c306413bb2 100644
--- a/core/jni/android_media_AudioRecord.cpp
+++ b/core/jni/android_media_AudioRecord.cpp
@@ -841,6 +841,43 @@ static jint android_media_AudioRecord_get_active_microphones(JNIEnv *env,
return jStatus;
}
+static int android_media_AudioRecord_set_microphone_direction(JNIEnv *env, jobject thiz,
+ jint direction) {
+ sp<AudioRecord> lpRecorder = getAudioRecord(env, thiz);
+ if (lpRecorder == NULL) {
+ jniThrowException(env, "java/lang/IllegalStateException",
+ "Unable to retrieve AudioRecord pointer for setMicrophoneDirection()");
+ return (jint)AUDIO_JAVA_ERROR;
+ }
+
+ jint jStatus = AUDIO_JAVA_SUCCESS;
+ status_t status =
+ lpRecorder->setMicrophoneDirection(static_cast<audio_microphone_direction_t>(direction));
+ if (status != NO_ERROR) {
+ jStatus = nativeToJavaStatus(status);
+ }
+
+ return jStatus;
+}
+
+static int android_media_AudioRecord_set_microphone_field_dimension(JNIEnv *env, jobject thiz,
+ jfloat zoom) {
+ sp<AudioRecord> lpRecorder = getAudioRecord(env, thiz);
+ if (lpRecorder == NULL) {
+ jniThrowException(env, "java/lang/IllegalStateException",
+ "Unable to retrieve AudioRecord pointer for setMicrophoneFieldDimension()");
+ return (jint)AUDIO_JAVA_ERROR;
+ }
+
+ jint jStatus = AUDIO_JAVA_SUCCESS;
+ status_t status = lpRecorder->setMicrophoneFieldDimension(zoom);
+ if (status != NO_ERROR) {
+ jStatus = nativeToJavaStatus(status);
+ }
+
+ return jStatus;
+}
+
// ----------------------------------------------------------------------------
static jint android_media_AudioRecord_get_port_id(JNIEnv *env, jobject thiz) {
sp<AudioRecord> lpRecorder = getAudioRecord(env, thiz);
@@ -896,6 +933,10 @@ static const JNINativeMethod gMethods[] = {
{"native_get_active_microphones", "(Ljava/util/ArrayList;)I",
(void *)android_media_AudioRecord_get_active_microphones},
{"native_getPortId", "()I", (void *)android_media_AudioRecord_get_port_id},
+ {"native_set_microphone_direction", "(I)I",
+ (void *)android_media_AudioRecord_set_microphone_direction},
+ {"native_set_microphone_field_dimension", "(F)I",
+ (void *)android_media_AudioRecord_set_microphone_field_dimension},
};
// field names found in android/media/AudioRecord.java
diff --git a/core/jni/android_view_InputEventSender.cpp b/core/jni/android_view_InputEventSender.cpp
index 10da89227f51..aa10a2f98a7e 100644
--- a/core/jni/android_view_InputEventSender.cpp
+++ b/core/jni/android_view_InputEventSender.cpp
@@ -138,6 +138,7 @@ status_t NativeInputEventSender::sendMotionEvent(uint32_t seq, const MotionEvent
event->getDeviceId(), event->getSource(), event->getDisplayId(),
event->getAction(), event->getActionButton(), event->getFlags(),
event->getEdgeFlags(), event->getMetaState(), event->getButtonState(),
+ event->getClassification(),
event->getXOffset(), event->getYOffset(),
event->getXPrecision(), event->getYPrecision(),
event->getDownTime(), event->getHistoricalEventTime(i),
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 9ce6df1832a6..897427fd8787 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -642,6 +642,27 @@ static jint nativeGetActiveColorMode(JNIEnv* env, jclass, jobject tokenObj) {
return static_cast<jint>(SurfaceComposerClient::getActiveColorMode(token));
}
+static jintArray nativeGetCompositionDataspaces(JNIEnv* env, jclass) {
+ ui::Dataspace defaultDataspace, wcgDataspace;
+ ui::PixelFormat defaultPixelFormat, wcgPixelFormat;
+ if (SurfaceComposerClient::getCompositionPreference(&defaultDataspace,
+ &defaultPixelFormat,
+ &wcgDataspace,
+ &wcgPixelFormat) != NO_ERROR) {
+ return nullptr;
+ }
+ jintArray array = env->NewIntArray(2);
+ if (array == nullptr) {
+ jniThrowException(env, "java/lang/OutOfMemoryError", nullptr);
+ return nullptr;
+ }
+ jint* arrayValues = env->GetIntArrayElements(array, 0);
+ arrayValues[0] = static_cast<jint>(defaultDataspace);
+ arrayValues[1] = static_cast<jint>(wcgDataspace);
+ env->ReleaseIntArrayElements(array, arrayValues, 0);
+ return array;
+}
+
static jboolean nativeSetActiveColorMode(JNIEnv* env, jclass,
jobject tokenObj, jint colorMode) {
sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
@@ -660,6 +681,10 @@ static void nativeSetDisplayPowerMode(JNIEnv* env, jclass clazz, jobject tokenOb
if (t.duration() > 100ms) ALOGD("Excessive delay in setPowerMode()");
}
+static jboolean nativeGetProtectedContentSupport(JNIEnv* env, jclass) {
+ return static_cast<jboolean>(SurfaceComposerClient::getProtectedContentSupport());
+}
+
static jboolean nativeClearContentFrameStats(JNIEnv* env, jclass clazz, jlong nativeObject) {
SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
status_t err = ctrl->clearLayerFrameStats();
@@ -1016,6 +1041,8 @@ static const JNINativeMethod sSurfaceControlMethods[] = {
(void*)nativeGetActiveColorMode},
{"nativeSetActiveColorMode", "(Landroid/os/IBinder;I)Z",
(void*)nativeSetActiveColorMode},
+ {"nativeGetCompositionDataspaces", "()[I",
+ (void*)nativeGetCompositionDataspaces},
{"nativeGetHdrCapabilities", "(Landroid/os/IBinder;)Landroid/view/Display$HdrCapabilities;",
(void*)nativeGetHdrCapabilities },
{"nativeClearContentFrameStats", "(J)Z",
@@ -1028,6 +1055,8 @@ static const JNINativeMethod sSurfaceControlMethods[] = {
(void*)nativeGetAnimationFrameStats },
{"nativeSetDisplayPowerMode", "(Landroid/os/IBinder;I)V",
(void*)nativeSetDisplayPowerMode },
+ {"nativeGetProtectedContentSupport", "()Z",
+ (void*)nativeGetProtectedContentSupport },
{"nativeDeferTransactionUntil", "(JJLandroid/os/IBinder;J)V",
(void*)nativeDeferTransactionUntil },
{"nativeDeferTransactionUntilSurface", "(JJJJ)V",
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index a8e142784397..9e449a20a6f0 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -14,6 +14,15 @@
* limitations under the License.
*/
+/*
+ * Disable optimization of this file if we are compiling with the address
+ * sanitizer. This is a mitigation for b/122921367 and can be removed once the
+ * bug is fixed.
+ */
+#if __has_feature(address_sanitizer)
+#pragma clang optimize off
+#endif
+
#define LOG_TAG "Zygote"
// sys/mount.h has to come before linux/fs.h due to redefinition of MS_RDONLY, MS_BIND, etc
diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto
index 2148273208e5..f68c760a9dbb 100644
--- a/core/proto/android/app/settings_enums.proto
+++ b/core/proto/android/app/settings_enums.proto
@@ -27,9 +27,569 @@ enum Action {
PAGE_VISIBLE = 1;
PAGE_HIDE = 2;
+ // ACTION: Settings > Wi-Fi > [Long press network] > Connect to network
+ // SUBTYPE: true if connecting to a saved network, false if not
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ ACTION_WIFI_CONNECT = 135;
+
+ // ACTION: Settings > Wi-Fi > [Long press network] > Forget network
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ ACTION_WIFI_FORGET = 137;
+
+ // ACTION: Settings > Wi-Fi > Toggle off
+ // SUBTYPE: true if connected to network before toggle, false if not
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ ACTION_WIFI_OFF = 138;
+
+ // ACTION: Settings > Wi-Fi > Toggle on
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ ACTION_WIFI_ON = 139;
+
+ // ACTION: Settings > Bluetooth > Overflow > Rename this device
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ ACTION_BLUETOOTH_RENAME = 161;
+
+ // ACTION: Settings > Bluetooth > Overflow > Show received files
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ ACTION_BLUETOOTH_FILES = 162;
+
+ // ACTION: DND Settings > Priority only allows > Reminder toggle
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ ACTION_ZEN_ALLOW_REMINDERS = 167;
+
+ // ACTION: DND Settings > Priority only allows > Event toggle
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ ACTION_ZEN_ALLOW_EVENTS = 168;
+
+ // ACTION: DND Settings > Priority only allows > Messages
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ ACTION_ZEN_ALLOW_MESSAGES = 169;
+
+ // ACTION: DND Settings > Priority only allows > Calls
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ ACTION_ZEN_ALLOW_CALLS = 170;
+
+ // ACTION: DND Settings > Priority only allows > Repeat callers toggle
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ ACTION_ZEN_ALLOW_REPEAT_CALLS = 171;
+
+ // ACTION: DND Settings > Automatic rules > [Rule] > Delete rule > Delete
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ ACTION_ZEN_DELETE_RULE_OK = 175;
+
+ // ACTION: Settings > More > Airplane mode toggle
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ ACTION_AIRPLANE_TOGGLE = 177;
+
+ // ACTION: Settings > Data usage > Cellular data toggle
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ ACTION_CELL_DATA_TOGGLE = 178;
+
+ // ACTION: Settings > Display > When device is rotated
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ ACTION_ROTATION_LOCK = 203;
+
+ // OPEN: Settings > Search > Perform search
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ ACTION_SEARCH_RESULTS = 226;
+
+ // ACTION: Settings > Security > Nexus Imprint > [Fingerprint] > Delete
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ ACTION_FINGERPRINT_DELETE = 253;
+
+ // ACTION: Settings > Security > Nexus Imprint > [Fingerprint] > Rename
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ ACTION_FINGERPRINT_RENAME = 254;
+
+ // ACTION: Settings -> Developer Options -> Take bug report -> Interactive report
+ // CATEGORY: SETTINGS
+ // OS: N
+ // Interactive bug report initiated from Settings.
+ ACTION_BUGREPORT_FROM_SETTINGS_INTERACTIVE = 294;
+
+ // ACTION: Settings -> Developer Options -> Take bug report -> Full report
+ // CATEGORY: SETTINGS
+ // OS: N
+ // Interactive bug report initiated from Settings.
+ ACTION_BUGREPORT_FROM_SETTINGS_FULL = 295;
+
+ // click on collapsed conditional or clicks expand button
+ ACTION_SETTINGS_CONDITION_EXPAND = 373;
+
+ // click main area of expanded conditional
+ ACTION_SETTINGS_CONDITION_CLICK = 375;
+
+ // click a direct button on expanded conditional
+ ACTION_SETTINGS_CONDITION_BUTTON = 376;
+
+ // Action: user enable / disabled data saver using Settings
+ // OPEN: Settings -> Data Usage -> Data saver -> On/off toggle
+ // VALUE: 1 for enabled, 0 for disabled
+ // CATEGORY: SETTINGS
+ // OS: N
+ ACTION_DATA_SAVER_MODE = 394;
+
+ // User whitelisted an app for Data Saver mode; action pass package name of app
+ // Action: user enable / disabled data saver using Settings
+ // OPEN: Settings -> Data Usage -> Data saver -> Unrestricted data access > APP toggle turned on
+ // or
+ // Settings -> Apps -> APP -> Data usage -> Unrestricted data usage toggle turned on
+ // VALUE: package name of APP
+ // CATEGORY: SETTINGS
+ // OS: N
+ ACTION_DATA_SAVER_WHITELIST = 395;
+
+ // User blacklisted an app for Data Saver mode; action pass package name of app
+ // OPEN: Settings -> Apps -> APP -> Data usage -> Background data toggle turned off
+ // VALUE: package name of APP
+ // CATEGORY: SETTINGS
+ // OS: N
+ ACTION_DATA_SAVER_BLACKLIST = 396;
+
+ // ACTION: Settings -> Storage -> Manage storage -> Click Storage Manager
+ // SUBTYPE: false is off, true is on
+ ACTION_TOGGLE_STORAGE_MANAGER = 489;
+
+ // OPEN: Settings > Display -> Ambient Display
+ // CATEGORY: SETTINGS
+ ACTION_AMBIENT_DISPLAY = 495;
+
+ // ACTION: Allow Battery optimization for an app
+ APP_SPECIAL_PERMISSION_BATTERY_ALLOW = 764;
+
+ // ACTION: Deny Battery optimization for an app
+ APP_SPECIAL_PERMISSION_BATTERY_DENY = 765;
+
+ // ACTION: Enable Device Admin app
+ APP_SPECIAL_PERMISSION_ADMIN_ALLOW = 766;
+
+ // ACTION: Disable Device Admin app
+ APP_SPECIAL_PERMISSION_ADMIN_DENY = 767;
+
+ // ACTION: Allow "Do Not Disturb access" for an app
+ APP_SPECIAL_PERMISSION_DND_ALLOW = 768;
+
+ // ACTION: Deny "Do Not Disturb access" for an app
+ APP_SPECIAL_PERMISSION_DND_DENY = 769;
+
+ // ACTION: Allow "Draw over other apps" for an app
+ APP_SPECIAL_PERMISSION_APPDRAW_ALLOW = 770;
+
+ // ACTION: Deny "Display over other apps" for an app
+ APP_SPECIAL_PERMISSION_APPDRAW_DENY = 771;
+
+ // ACTION: Allow "VR helper services" for an app
+ APP_SPECIAL_PERMISSION_VRHELPER_ALLOW = 772;
+
+ // ACTION: Deny "VR helper services" for an app
+ APP_SPECIAL_PERMISSION_VRHELPER_DENY = 773;
+
+ // ACTION: Allow "Modify system settings" for an app
+ APP_SPECIAL_PERMISSION_SETTINGS_CHANGE_ALLOW = 774;
+
+ // ACTION: Deny "Modify system settings" for an app
+ APP_SPECIAL_PERMISSION_SETTINGS_CHANGE_DENY = 775;
+
+ // ACTION: Allow "Notification access" for an app
+ APP_SPECIAL_PERMISSION_NOTIVIEW_ALLOW = 776;
+
+ // ACTION: Deny "Notification access" for an app
+ APP_SPECIAL_PERMISSION_NOTIVIEW_DENY = 777;
+
+ // ACTION: "Premium SMS access" for an app - "ask user" option
+ APP_SPECIAL_PERMISSION_PREMIUM_SMS_ASK = 778;
+
+ // ACTION: "Premium SMS access" for an app - "never allow" option
+ APP_SPECIAL_PERMISSION_PREMIUM_SMS_DENY = 779;
+
+ // ACTION: "Premium SMS access" for an app - "always allow" option
+ APP_SPECIAL_PERMISSION_PREMIUM_SMS_ALWAYS_ALLOW = 780;
+
+ // ACTION: Allow "Unrestricted data access" for an app
+ APP_SPECIAL_PERMISSION_UNL_DATA_ALLOW = 781;
+
+ // ACTION: Deny "Unrestricted data access" for an app
+ APP_SPECIAL_PERMISSION_UNL_DATA_DENY = 782;
+
+ // ACTION: Allow "Usage access" for an app
+ APP_SPECIAL_PERMISSION_USAGE_VIEW_ALLOW = 783;
+
+ // ACTION: Deny "Usage access" for an app
+ APP_SPECIAL_PERMISSION_USAGE_VIEW_DENY = 784;
+
+ // ACTION: "Force stop" action on an app
+ ACTION_APP_FORCE_STOP = 807;
+
+ // ACTION: Allow "Enable picture-in-picture" for an app
+ APP_PICTURE_IN_PICTURE_ALLOW = 813;
+
+ // ACTION: Create a Settings shortcut item.
+ ACTION_SETTINGS_CREATE_SHORTCUT = 829;
+
+ // ACTION: Settings advanced button is expanded
+ ACTION_SETTINGS_ADVANCED_BUTTON_EXPAND = 834;
+
+ // ACTION: Deny "Enable picture-in-picture" for an app
+ APP_PICTURE_IN_PICTURE_DENY = 814;
+
+ // ACTION: Settings -> Display -> Theme
+ ACTION_THEME = 816;
+
+ // ACTION: Settings > About device > Build number
+ ACTION_SETTINGS_BUILD_NUMBER_PREF = 847;
+
+ // ACTION: Settings > Battery > Menu > Optimization
+ ACTION_SETTINGS_MENU_BATTERY_OPTIMIZATION = 851;
+
+ // ACTION: Settings > Battery > Menu > Apps Toggle
+ ACTION_SETTINGS_MENU_BATTERY_APPS_TOGGLE = 852;
+
// ACTION: Settings > Any preference is changed
ACTION_SETTINGS_PREFERENCE_CHANGE = 853;
+ // ACTION: Settings > Connected devices > Bluetooth -> Available devices
+ ACTION_SETTINGS_BLUETOOTH_PAIR = 866;
+
+ // ACTION: Settings > Connected devices > Bluetooth -> Paired devices
+ ACTION_SETTINGS_BLUETOOTH_CONNECT = 867;
+
+ // ACTION: Settings > Connected devices > Bluetooth -> Connected device
+ ACTION_SETTINGS_BLUETOOTH_DISCONNECT = 868;
+
+ // ACTION: Settings > Connected devices > Bluetooth -> Error dialog
+ ACTION_SETTINGS_BLUETOOTH_CONNECT_ERROR = 869;
+
+ // ACTION: Settings > Connected devices > Bluetooth master switch Toggle
+ ACTION_SETTINGS_MASTER_SWITCH_BLUETOOTH_TOGGLE = 870;
+
+ // ACTION: Settings > App detail > Uninstall
+ ACTION_SETTINGS_UNINSTALL_APP = 872;
+
+ // ACTION: Settings > App detail > Uninstall Device admin app
+ ACTION_SETTINGS_UNINSTALL_DEVICE_ADMIN = 873;
+
+ // ACTION: Settings > App detail > Disable app
+ ACTION_SETTINGS_DISABLE_APP = 874;
+
+ // ACTION: Settings > App detail > Enable app
+ ACTION_SETTINGS_ENABLE_APP = 875;
+
+ // ACTION: Settings > App detail > Clear data
+ ACTION_SETTINGS_CLEAR_APP_DATA = 876;
+
+ // ACTION: Settings > App detail > Clear cache
+ ACTION_SETTINGS_CLEAR_APP_CACHE = 877;
+
+ // ACTION: Logs pressing the "Clear app" button in the app info settings page for an instant
+ // app.
+ // VALUE: The package name of the app
+ ACTION_SETTINGS_CLEAR_INSTANT_APP = 923;
+
+ // OPEN: Assist Gesture training intro in Settings
+ // CATEGORY: SETTINGS
+ // OS: O DR
+ SETTINGS_ASSIST_GESTURE_TRAINING_INTRO = 991;
+
+ // OPEN: Assist Gesture training enrolling in Settings
+ // CATEGORY: SETTINGS
+ // OS: O DR
+ SETTINGS_ASSIST_GESTURE_TRAINING_ENROLLING = 992;
+
+ // OPEN: Assist Gesture training finished in Settings
+ // CATEGORY: SETTINGS
+ // OS: O DR
+ SETTINGS_ASSIST_GESTURE_TRAINING_FINISHED = 993;
+
+ // ACTION: Update default app from Settings
+ ACTION_SETTINGS_UPDATE_DEFAULT_APP = 1000;
+
+ // ACTION: Settings > Wi-Fi > [Long press network] > Sign in to network
+ // CATEGORY: SETTINGS
+ // OS: O DR
+ ACTION_WIFI_SIGNIN = 1008;
+
+ // ACTION: Settings > Notification Settings > Open application notification
+ // CATEGORY: SETTINGS
+ // OS: O DR
+ ACTION_OPEN_APP_NOTIFICATION_SETTING = 1016;
+
+ // ACTION: Settings > App Info > Open app settings
+ // CATEGORY: SETTINGS
+ // OS: O DR
+ ACTION_OPEN_APP_SETTING = 1017;
+
+ // ACTION: Collect PSD Signals
+ // CATEGORY: SETTINGS
+ // OS: O DR
+ ACTION_PSD_LOADER = 1019;
+
+ // OPEN: Settings > Trampoline Intent > Settings page
+ // CATEGORY: SETTINGS
+ // OS: O DR
+ TRAMPOLINE_SETTINGS_EVENT = 1033;
+
+ // ACTION: Logged when user tries to pair a Bluetooth device without name from Settings app
+ // CATEGORY: SETTINGS
+ // OS: O MR
+ ACTION_SETTINGS_BLUETOOTH_PAIR_DEVICES_WITHOUT_NAMES = 1096;
+
+ // ACTION: Settings > Network & Internet > Mobile network > Network
+ // CATEGORY: SETTINGS
+ ACTION_MOBILE_NETWORK_MANUAL_SELECT_NETWORK = 1210;
+
+ // ACTION: DND Settings > Priority only allows > Alarms toggle
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACTION_ZEN_ALLOW_ALARMS = 1226;
+
+ // ACTION: DND Settings > Priority only allows > Media toggle
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACTION_ZEN_ALLOW_MEDIA = 1227;
+
+ // ACTION: A private dns mode been selected by user
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACTION_PRIVATE_DNS_MODE = 1249;
+
+ // OPEN: Settings > Sound > Do Not Disturb > Turn on automatically > Select rule ("Event") > Rule name > OK
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACTION_ZEN_MODE_RULE_NAME_CHANGE_OK = 1267;
+
+ // OPEN: Settings > Sound > Do Not Disturb > TURN ON NOW/TURN OFF NOW
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACTION_ZEN_TOGGLE_DND_BUTTON = 1268;
+
+ // ACTION: DND Settings > What to block > full screen intents
+ // SUBTYPE: false is allowed, true is blocked
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ ACTION_ZEN_BLOCK_FULL_SCREEN_INTENTS = 1332;
+
+ // ACTION: DND Settings > What to block
+ // SUBTYPE: false is allowed, true is blocked
+ // OS: P
+ ACTION_ZEN_BLOCK_LIGHT = 1333;
+
+ // ACTION: DND Settings > What to block
+ // SUBTYPE: false is allowed, true is blocked
+ // OS: P
+ ACTION_ZEN_BLOCK_PEEK = 1334;
+
+ // ACTION: DND Settings > What to block
+ // SUBTYPE: false is allowed, true is blocked
+ // OS: P
+ ACTION_ZEN_BLOCK_STATUS = 1335;
+
+ // ACTION: DND Settings > What to block
+ // SUBTYPE: false is allowed, true is blocked
+ // OS: P
+ ACTION_ZEN_BLOCK_BADGE = 1336;
+
+ // ACTION: DND Settings > What to block
+ // SUBTYPE: false is allowed, true is blocked
+ // OS: P
+ ACTION_ZEN_BLOCK_AMBIENT = 1337;
+
+ // ACTION: DND Settings > What to block
+ // SUBTYPE: false is allowed, true is blocked
+ // OS: P
+ ACTION_ZEN_BLOCK_NOTIFICATION_LIST = 1338;
+
+ // ACTION: DND Settings > Priority only allows > System toggle
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACTION_ZEN_ALLOW_SYSTEM = 1340;
+
+ // ACTION: Settings > Battery settings > Battery tip > App restriction tip
+ // OS: P
+ ACTION_APP_RESTRICTION_TIP = 1347;
+
+ // ACTION: Settings > Battery settings > Battery tip > High usage tip
+ // OS: P
+ ACTION_HIGH_USAGE_TIP = 1348;
+
+ // ACTION: Settings > Battery settings > Battery tip > Summary tip
+ // OS: P
+ ACTION_SUMMARY_TIP = 1349;
+
+ // ACTION: Settings > Battery settings > Battery tip > Smart battery tip
+ // OS: P
+ ACTION_SMART_BATTERY_TIP = 1350;
+
+ // ACTION: Settings > Battery settings > Battery tip > Early warning tip
+ // OS: P
+ ACTION_EARLY_WARNING_TIP = 1351;
+
+ // ACTION: Settings > Battery settings > Battery tip > Low battery tip
+ // OS: P
+ ACTION_LOW_BATTERY_TIP = 1352;
+
+ // ACTION: Settings > Battery settings > Battery tip > App restriction list shown
+ // OS: P
+ ACTION_APP_RESTRICTION_TIP_LIST = 1353;
+
+ // ACTION: Settings > Battery settings > Battery tip > High usage list shown
+ // OS: P
+ ACTION_HIGH_USAGE_TIP_LIST = 1354;
+
+ // ACTION: Settings > Battery settings > Battery tip > Open app restriction page
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACTION_TIP_OPEN_APP_RESTRICTION_PAGE = 1361;
+
+ // ACTION: Settings > Battery settings > Battery tip > Restrict app
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACTION_TIP_RESTRICT_APP = 1362;
+
+ // ACTION: Settings > Battery settings > Battery tip > Unrestrict app
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACTION_TIP_UNRESTRICT_APP = 1363;
+
+ // ACTION: Settings > Battery settings > Battery tip > Open smart battery page
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACTION_TIP_OPEN_SMART_BATTERY = 1364;
+
+ // ACTION: Settings > Battery settings > Battery tip > Turn on battery saver
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACTION_TIP_TURN_ON_BATTERY_SAVER = 1365;
+
+ // ACTION: Settings > Anomaly receiver > Anomaly received
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACTION_ANOMALY_TRIGGERED = 1367;
+
+ // ACTION: A Settings Slice is requested
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACTION_SETTINGS_SLICE_REQUESTED = 1371;
+
+ // ACTION: A Settings Slice is updated with new value
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACTION_SETTINGS_SLICE_CHANGED = 1372;
+
+ // OPEN: DND onboarding activity > Ok button
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACTION_ZEN_ONBOARDING_OK = 1378;
+
+ // OPEN: DND onboarding activity > Settings link
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACTION_ZEN_ONBOARDING_SETTINGS = 1379;
+
+ // ACTION: Settings > Anomaly receiver > Anomaly ignored, don't show up in battery settings
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACTION_ANOMALY_IGNORED = 1387;
+
+ // ACTION: Settings > Battery settings > Battery tip > Open battery saver page
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACTION_TIP_OPEN_BATTERY_SAVER_PAGE = 1388;
+
+ // ACTION: DND Settings > What to block
+ // OS: P
+ ACTION_ZEN_SOUND_ONLY = 1396;
+
+ // ACTION: DND Settings > Notifications
+ // OS: P
+ ACTION_ZEN_SOUND_AND_VIS_EFFECTS = 1397;
+
+ // ACTION: DND Settings > Notifications
+ // OS: P
+ ACTION_ZEN_SHOW_CUSTOM = 1398;
+
+ // ACTION: DND Settings > Notifications
+ // OS: P
+ ACTION_ZEN_CUSTOM = 1399;
+
+ // OPEN: DND onboarding activity > don't update button
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACTION_ZEN_ONBOARDING_KEEP_CURRENT_SETTINGS = 1406;
+
+ // ACTION: Storage initialization wizard initialization choice of external/portable
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACTION_STORAGE_INIT_EXTERNAL = 1407;
+
+ // ACTION: Storage initialization wizard initialization choice of internal/adoptable
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACTION_STORAGE_INIT_INTERNAL = 1408;
+
+ // ACTION: Storage initialization wizard benchmark fast choice of continue
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACTION_STORAGE_BENCHMARK_FAST_CONTINUE = 1409;
+
+ // ACTION: Storage initialization wizard benchmark slow choice of continue
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACTION_STORAGE_BENCHMARK_SLOW_CONTINUE = 1410;
+
+ // ACTION: Storage initialization wizard benchmark slow choice of abort
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACTION_STORAGE_BENCHMARK_SLOW_ABORT = 1411;
+
+ // ACTION: Storage initialization wizard migration choice of now
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACTION_STORAGE_MIGRATE_NOW = 1412;
+
+ // ACTION: Storage initialization wizard migration choice of later
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACTION_STORAGE_MIGRATE_LATER = 1413;
+
+ // OPEN: Settings > Sound > Switch a2dp devices dialog
+ // CATEGORY: SETTINGS
+ // OS: P
+ DIALOG_SWITCH_A2DP_DEVICES = 1415;
+
+
+ // OPEN: Settings > Sound > Switch hfp devices dialog
+ // CATEGORY: SETTINGS
+ // OS: P
+ DIALOG_SWITCH_HFP_DEVICES = 1416;
+
// ACTION: Tap & Pay -> Default Application Setting -> Use Forground
ACTION_NFC_PAYMENT_FOREGROUND_SETTING = 1622;
@@ -44,15 +604,1454 @@ enum PageId {
// Unknown page. Should not be used in production code.
PAGE_UNKNOWN = 0;
+ // OPEN: Settings > Accessibility
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ ACCESSIBILITY = 2;
+
+ // OPEN: Settings > Accessibility > Captions
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ ACCESSIBILITY_CAPTION_PROPERTIES = 3;
+
+ // OPEN: Settings > Accessibility > [Service]
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ ACCESSIBILITY_SERVICE = 4;
+
+ // OPEN: Settings > Accessibility > Color correction
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ ACCESSIBILITY_TOGGLE_DALTONIZER = 5;
+
+ // OPEN: Settings > Accessibility > Accessibility shortcut
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ ACCESSIBILITY_TOGGLE_GLOBAL_GESTURE = 6;
+
+ // OPEN: Settings > Accessibility > Magnification gestures (Renamed in O)
+ // OPEN: Settings > Accessibility > Magnification > Magnify with triple-tap
+ // OPEN: Settings > Accessibility > Magnification > Magnify with button
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ ACCESSIBILITY_TOGGLE_SCREEN_MAGNIFICATION = 7;
+
+ // OPEN: Settings > Accounts
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ ACCOUNT = 8;
+
+ // OPEN: Settings > Accounts > [Single Account Sync Settings]
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ ACCOUNTS_ACCOUNT_SYNC = 9;
+
+ // OPEN: Settings > Accounts > Add an account
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ ACCOUNTS_CHOOSE_ACCOUNT_ACTIVITY = 10;
+
+ // OPEN: Settings > Cellular network settings > APNs
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ APN = 12;
+
+ // OPEN: Settings > More > Cellular network settings > APNs > [Edit APN]
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ APN_EDITOR = 13;
+
+ // OPEN: Settings > Apps > Configure apps > App links > [App]
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ APPLICATIONS_APP_LAUNCH = 17;
+
+ // OPEN: Settings > Internal storage > Apps storage > [App]
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ APPLICATIONS_APP_STORAGE = 19;
+
+ // OPEN: Settings > Apps > [App info]
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ APPLICATIONS_INSTALLED_APP_DETAILS = 20;
+
+ // OPEN: Settings > Memory > App usage > [App Memory usage]
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ APPLICATIONS_PROCESS_STATS_DETAIL = 21;
+
+ // OPEN: Settings > Memory > App usage
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ APPLICATIONS_PROCESS_STATS_UI = 23;
+
+ // OPEN: Choose Bluetooth device (ex: when sharing)
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ BLUETOOTH_DEVICE_PICKER = 25;
+
+ // OPEN: Settings > Security > Choose screen lock
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ CHOOSE_LOCK_GENERIC = 27;
+
+ // OPEN: Settings > Security > Choose screen lock > Choose your password
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ CHOOSE_LOCK_PASSWORD = 28;
+
+ // OPEN: Settings > Security > Choose screen lock > Choose your pattern
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ CHOOSE_LOCK_PATTERN = 29;
+
+ // OPEN: Settings > Security > Choose screen lock > Confirm your password
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ CONFIRM_LOCK_PASSWORD = 30;
+
+ // OPEN: Settings > Security > Choose screen lock > Confirm your pattern
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ CONFIRM_LOCK_PATTERN = 31;
+
+ // OPEN: Settings > Security > Encrypt phone
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ CRYPT_KEEPER = 32;
+
+ // OPEN: Settings > Security > Encrypt phone > Confirm
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ CRYPT_KEEPER_CONFIRM = 33;
+
+ // OPEN: Settings (Root page)
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ DASHBOARD_SUMMARY = 35;
+
+ // OPEN: Settings > Data usage
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ DATA_USAGE_SUMMARY = 37;
+
+ // OPEN: Settings > Date & time
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ DATE_TIME = 38;
+
+ // OPEN: Settings > Developer options
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ DEVELOPMENT = 39;
+
+ // OPEN: Settings > About phone
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ DEVICEINFO = 40;
+
+ // OPEN: Settings > Internal storage
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ DEVICEINFO_STORAGE = 42;
+
+ // OPEN: Settings > Display
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ DISPLAY = 46;
+
+ // OPEN: Settings > Display > Daydream
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ DREAM = 47;
+
+ // OPEN: Settings > Security > Screen lock > Secure start-up
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ ENCRYPTION = 48;
+
+ // OPEN: Settings > Security > Nexus Imprint
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ FINGERPRINT = 49;
+
+ // OPEN: Settings > Battery > History details
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ FUELGAUGE_BATTERY_HISTORY_DETAIL = 51;
+
+ // OPEN: Settings > Battery > Battery saver
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ FUELGAUGE_BATTERY_SAVER = 52;
+
+ // OPEN: Settings > Battery > [App Use details]
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ FUELGAUGE_POWER_USAGE_DETAIL = 53;
+
+ // OPEN: Settings > Security > SIM card lock settings
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ ICC_LOCK = 56;
+
+ // OPEN: Settings > Language & input > Physical keyboard
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ INPUTMETHOD_KEYBOARD = 58;
+
+ // OPEN: Settings > Language & input > Spell checker
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ INPUTMETHOD_SPELL_CHECKERS = 59;
+
+ // OBSOLETE
+ INPUTMETHOD_SUBTYPE_ENABLER = 60;
+
+ // OPEN: Settings > Language & input > Personal dictionary
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ INPUTMETHOD_USER_DICTIONARY = 61;
+
+ // OPEN: Settings > Language & input > Add word
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ INPUTMETHOD_USER_DICTIONARY_ADD_WORD = 62;
+
+ // OPEN: Settings > Location
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ LOCATION = 63;
+
+ // OPEN: Settings > Apps
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ MANAGE_APPLICATIONS = 65;
+
+ // OPEN: Settings > Backup & reset > Factory data reset
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ MASTER_CLEAR = 66;
+
+ // OPEN: Settings > Backup & reset > Factory data reset > Confirm
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ MASTER_CLEAR_CONFIRM = 67;
+
+ // OPEN: Settings > More > Android Beam
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ NFC_BEAM = 69;
+
+ // OPEN: Settings > Tap & pay
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ NFC_PAYMENT = 70;
+
+ // OPEN: Settings > Sound & notification > App notifications > [App]
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ NOTIFICATION_APP_NOTIFICATION = 72;
+
+ // OBSOLETE
+ NOTIFICATION_REDACTION = 74;
+
+ // OPEN: Settings Widget > Notification log
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ NOTIFICATION_STATION = 75;
+
+ // OPEN: Settings > Sound & notification > Do not disturb
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ NOTIFICATION_ZEN_MODE = 76;
+
+
+ // OPEN: Print job notification > Print job settings
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ PRINT_JOB_SETTINGS = 78;
+
+ // OPEN: Settings > Printing > [Print Service]
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ PRINT_SERVICE_SETTINGS = 79;
+
+ // OPEN: Settings > Printing
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ PRINT_SETTINGS = 80;
+
+ // OPEN: Settings > Backup & reset
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ PRIVACY = 81;
+
+ //OBSOLETE
+ PROXY_SELECTOR = 82;
+
+ // OPEN: Settings > Backup & reset > Network settings reset
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ RESET_NETWORK = 83;
+
+ // OPEN: Settings > Backup & reset > Network settings reset > Confirm
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ RESET_NETWORK_CONFIRM = 84;
+
+ // OPEN: Settings > Developer Options > Running Services
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ RUNNING_SERVICE_DETAILS = 85;
+
+ // OPEN: Settings > Security > Screen pinning
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ SCREEN_PINNING = 86;
+
+ // OPEN: Settings > Security
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ SECURITY = 87;
+
+ // OPEN: Settings > SIM cards
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ SIM = 88;
+
+ // OBSOLETE
+ TESTING = 89;
+
+ // OPEN: Settings > More > Tethering & portable hotspot
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ TETHER = 90;
+
+ // OPEN: Settings > Security > Trust agents
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ TRUST_AGENT = 91;
+
+ // OPEN: Settings > Security > Trusted credentials
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ TRUSTED_CREDENTIALS = 92;
+
+ // OPEN: Settings > Language & input > TTS output > [Engine] > Settings
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ TTS_ENGINE_SETTINGS = 93;
+
+ // OPEN: Settings > Language & input > Text-to-speech output
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ TTS_TEXT_TO_SPEECH = 94;
+
+ // OPEN: Settings > Security > Apps with usage access
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ USAGE_ACCESS = 95;
+
+ // OPEN: Settings > Users
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ USER = 96;
+
+ // OPEN: Settings > Users > [Restricted profile app & content access]
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ USERS_APP_RESTRICTIONS = 97;
+
+ // OPEN: Settings > Users > [User settings]
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ USER_DETAILS = 98;
+
+ // OPEN: Settings > More > VPN
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ VPN = 100;
+
+ // OPEN: Settings > Display > Choose wallpaper from
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ WALLPAPER_TYPE = 101;
+
+ // OPEN: Settings > Display > Cast
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ WFD_WIFI_DISPLAY = 102;
+
+ // OPEN: Settings > Wi-Fi
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ WIFI = 103;
+
+ // OPEN: Settings > More > Wi-Fi Calling
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ WIFI_CALLING = 105;
+
+ // OPEN: Settings > Wi-Fi > Saved networks
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ WIFI_SAVED_ACCESS_POINTS = 106;
+
+ // OPEN: Settings > Wi-Fi > Advanced Wi-Fi > Wi-Fi Direct
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ WIFI_P2P = 109;
+
+ // OPEN: Settings > Apps > Configure apps > App permissions
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ APPLICATIONS_ADVANCED = 130;
+
+ // OPEN: Settings > Location > Scanning
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ LOCATION_SCANNING = 131;
+
+ // OPEN: Settings > Sound & notification > App notifications
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ MANAGE_APPLICATIONS_NOTIFICATIONS = 133;
+
+ // OPEN: Settings > Sound & notification > DND > Priority only allows
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ NOTIFICATION_ZEN_MODE_PRIORITY = 141;
+
+ // OPEN: Settings > Sound & notification > DND > Automatic rules
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ NOTIFICATION_ZEN_MODE_AUTOMATION = 142;
+
+ // OPEN: Settings > Sound & notification > DND > [Time based rule]
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ NOTIFICATION_ZEN_MODE_SCHEDULE_RULE = 144;
+
+ // OPEN: Settings > Apps > Configure apps > App links
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ MANAGE_DOMAIN_URLS = 143;
+
+ // OPEN: Settings > Sound & notification > DND > [Event rule]
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ NOTIFICATION_ZEN_MODE_EVENT_RULE = 146;
+
+ // OPEN: Settings > Sound & notification > Notification access
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ NOTIFICATION_ACCESS = 179;
+
+ // OPEN: Settings > Sound & notification > Do Not Disturb access
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ NOTIFICATION_ZEN_MODE_ACCESS = 180;
+
+ // OPEN: Settings > Internal storage > Apps storage
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ APPLICATIONS_STORAGE_APPS = 182;
+
+ // OPEN: Settings > Security > Usage access
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ APPLICATIONS_USAGE_ACCESS_DETAIL = 183;
+
+ // OPEN: Settings > Battery > Battery optimization
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ APPLICATIONS_HIGH_POWER_APPS = 184;
+
+ // OPEN: Settings > Apps > Configure > Default apps > Assist & voice input
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ APPLICATIONS_MANAGE_ASSIST = 201;
+
+ // OPEN: Settings > Memory
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ PROCESS_STATS_SUMMARY = 202;
+
+ // OPEN: Settings > Apps > Configure Apps > Display over other apps
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ SYSTEM_ALERT_WINDOW_APPS = 221;
+
+ // OPEN: Settings > About phone > Legal information
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ ABOUT_LEGAL_SETTINGS = 225;
+
+
+ // OPEN: Settings > Developer options > Inactive apps
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ FUELGAUGE_INACTIVE_APPS = 238;
+
+ // OPEN: Settings > Security > Nexus Imprint > Add Fingerprint
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ FINGERPRINT_ENROLLING = 240;
+ // OPEN: Fingerprint Enroll > Find Sensor
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ FINGERPRINT_FIND_SENSOR = 241;
+
+ // OPEN: Fingerprint Enroll > Fingerprint Enrolled!
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ FINGERPRINT_ENROLL_FINISH = 242;
+
+ // OPEN: Fingerprint Enroll introduction
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ FINGERPRINT_ENROLL_INTRO = 243;
+
+ // OPEN: Fingerprint Enroll > Let's Start!
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ FINGERPRINT_ENROLL_SIDECAR = 245;
+
+ // OPEN: Fingerprint Enroll SUW > Let's Start!
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ FINGERPRINT_ENROLLING_SETUP = 246;
+
+ // OPEN: Fingerprint Enroll SUW > Find Sensor
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ FINGERPRINT_FIND_SENSOR_SETUP = 247;
+
+ // OPEN: Fingerprint Enroll SUW > Fingerprint Enrolled!
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ FINGERPRINT_ENROLL_FINISH_SETUP = 248;
+
+ // OPEN: Fingerprint Enroll SUW introduction
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ FINGERPRINT_ENROLL_INTRO_SETUP = 249;
+
+ // OPEN: Settings > Developer Options > Background Check
+ // CATEGORY: SETTINGS
+ // OS: N
+ BACKGROUND_CHECK_SUMMARY = 258;
+
+ // OPEN: Settings > Notifications > [App] > Channel Notifications
+ // CATEGORY: SETTINGS
+ // OS: N
+ NOTIFICATION_TOPIC_NOTIFICATION = 265;
+
+ // OPEN: Settings > Security > User credentials
+ // CATEGORY: Settings
+ // OS: N
+ USER_CREDENTIALS = 285;
+
+ // Logs that the user has edited the enabled VR listeners.
+ // CATEGORY: SETTINGS
+ // OS: N
+ VR_MANAGE_LISTENERS = 334;
+
+ // Settings -> Accessibility -> Click after pointer stops moving
+ // CATEGORY: SETTINGS
+ // OS: N
+ ACCESSIBILITY_TOGGLE_AUTOCLICK = 335;
+
+ // Settings -> Sound
+ // CATEGORY: SETTINGS
+ // OS: N
+ SOUND = 336;
+
+ // Settings -> Notifications -> Gear
+ // CATEGORY: SETTINGS
+ // OS: N
+ CONFIGURE_NOTIFICATION = 337;
+
+ // Settings -> Wi-Fi -> Gear
+ // CATEGORY: SETTINGS
+ // OS: N
+ CONFIGURE_WIFI = 338;
+
+ // Settings -> Display -> Display size
+ // OS: N
+ DISPLAY_SCREEN_ZOOM = 339;
+
+ // Settings -> Display -> Font size
+ // CATEGORY: SETTINGS
+ // OS: N
+ ACCESSIBILITY_FONT_SIZE = 340;
+
+ // Settings -> Data usage -> Cellular/Wi-Fi data usage
+ // CATEGORY: SETTINGS
+ // OS: N
+ DATA_USAGE_LIST = 341;
+
+ // Settings -> Data usage -> Billing cycle or DATA_USAGE_LIST -> Gear
+ // CATEGORY: SETTINGS
+ // OS: N
+ BILLING_CYCLE = 342;
+
+ // DATA_USAGE_LIST -> Any item or App info -> Data usage
+ // CATEGORY: SETTINGS
+ // OS: N
+ APP_DATA_USAGE = 343;
+
+ // Settings -> Language & input -> Language
+ // CATEGORY: SETTINGS
+ // OS: N
+ USER_LOCALE_LIST = 344;
+
+ // Settings -> Language & input -> Virtual keyboard
+ // CATEGORY: SETTINGS
+ // OS: N
+ VIRTUAL_KEYBOARDS = 345;
+
+ // Settings -> Language & input -> Physical keyboard
+ // CATEGORY: SETTINGS
+ // OS: N
+ PHYSICAL_KEYBOARDS = 346;
+
+ // Settings -> Language & input -> Virtual keyboard -> Add a virtual keyboard
+ // CATEGORY: SETTINGS
+ // OS: N
+ ENABLE_VIRTUAL_KEYBOARDS = 347;
+
+ // Settings -> Data usage -> Data Saver
+ // CATEGORY: SETTINGS
+ // OS: N
+ DATA_SAVER_SUMMARY = 348;
+
+ // Settings -> Data usage -> Data Saver -> Unrestricted data access
+ // CATEGORY: SETTINGS
+ // OS: N
+ DATA_USAGE_UNRESTRICTED_ACCESS = 349;
+
+ // Settings -> Apps -> Gear -> Special access
+ SPECIAL_ACCESS = 351;
+
+ // OPEN: SUW Welcome Screen -> Vision Settings
+ // CATEGORY: SETTINGS
+ // OS: N
+ SUW_ACCESSIBILITY = 367;
+
+ // OPEN: SUW Welcome Screen -> Vision Settings -> Magnification gestures (Renamed in O)
+ // OPEN: SUW Welcome Screen -> Vision Settings -> Magnification -> Magnify with triple-tap
+ // OPEN: SUW Welcome Screen -> Vision Settings -> Magnification -> Magnify with button
+ // ACTION: New magnification gesture configuration is chosen
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: SETTINGS
+ // OS: N
+ SUW_ACCESSIBILITY_TOGGLE_SCREEN_MAGNIFICATION = 368;
+
+ // OPEN: SUW Welcome Screen -> Vision Settings -> Font size
+ // ACTION: New font size is chosen
+ // SUBTYPE: 0 is small, 1 is default, 2 is large, 3 is largest
+ // CATEGORY: SETTINGS
+ // OS: N
+ SUW_ACCESSIBILITY_FONT_SIZE = 369;
+
+ // OPEN: SUW Welcome Screen -> Vision Settings -> Display size
+ // ACTION: New display size is chosen
+ // SUBTYPE: 0 is small, 1 is default, 2 is large, 3 is larger, 4 is largest
+ // CATEGORY: SETTINGS
+ // OS: N
+ SUW_ACCESSIBILITY_DISPLAY_SIZE = 370;
+
+ // OPEN: SUW Welcome Screen -> Vision Settings -> TalkBack
+ // ACTION: New screen reader configuration is chosen
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: SETTINGS
+ // OS: N
+ SUW_ACCESSIBILITY_TOGGLE_SCREEN_READER = 371;
+
+ // Airplane mode on
+ SETTINGS_CONDITION_AIRPLANE_MODE = 377;
+ // AKA Data saver on
+ SETTINGS_CONDITION_BACKGROUND_DATA = 378;
+ // Battery saver on
+ SETTINGS_CONDITION_BATTERY_SAVER = 379;
+ // Cellular data off
+ SETTINGS_CONDITION_CELLULAR_DATA = 380;
+ // Do not disturb on
+ SETTINGS_CONDITION_DND = 381;
+ // Hotspot on
+ SETTINGS_CONDITION_HOTSPOT = 382;
+ // Work profile off
+ SETTINGS_CONDITION_WORK_MODE = 383;
+
+ // Settings > Apps > Gear > Special Access > Premium SMS access
+ PREMIUM_SMS_ACCESS = 388;
+
+ // OPEN: Settings > Accounts > Work profile settings
+ // CATEGORY: SETTINGS
+ ACCOUNTS_WORK_PROFILE_SETTINGS = 401;
+
+ // Settings -> Dev options -> Convert to file encryption
+ CONVERT_FBE = 402;
+
+ // Settings -> Dev options -> Convert to file encryption -> WIPE AND CONVERT...
+ CONVERT_FBE_CONFIRM = 403;
+
+ // Settings -> Dev options -> Running services
+ RUNNING_SERVICES = 404;
+
+ // The dialog shown by 3P intent to change current webview implementation.
+ WEBVIEW_IMPLEMENTATION = 405;
+
+ // OPEN: Settings > Internal storage > Storage manager
+ // CATEGORY: SETTINGS
+ STORAGE_MANAGER_SETTINGS = 458;
+
+ // OPEN: Settings -> Gestures
+ // CATEGORY: SETTINGS
+ SETTINGS_GESTURES = 459;
+
+ // OPEN: Settings > Display > Night Light
+ // CATEGORY: SETTINGS
+ NIGHT_DISPLAY_SETTINGS = 488;
+
+ // Night Light on
+ SETTINGS_CONDITION_NIGHT_DISPLAY = 492;
+
+ // OPEN: Settings > Language & input > Personal dictionary (single locale)
+ USER_DICTIONARY_SETTINGS = 514;
+
+ // OPEN: Settings > Date & time > Select time zone
+ ZONE_PICKER = 515;
+
+ // OPEN: Settings > Security > Device administrators
+ DEVICE_ADMIN_SETTINGS = 516;
+
+ // OPEN: Settings > Security > Factory Reset Protection dialog
+ DIALOG_FRP = 528;
+
+ // OPEN: Settings > Custom list preference with confirmation message
+ DIALOG_CUSTOM_LIST_CONFIRMATION = 529;
+
+ // OPEN: Settings > APN Editor > Error dialog
+ DIALOG_APN_EDITOR_ERROR = 530;
+
+ // OPEN: Settings > Users > Edit owner info dialog
+ DIALOG_OWNER_INFO_SETTINGS = 531;
+
+ // OPEN: Settings > Security > Use one lock dialog
+ DIALOG_UNIFICATION_CONFIRMATION = 532;
+
+ // OPEN: Settings > Security > User Credential
+ DIALOG_USER_CREDENTIAL = 533;
+
+ // OPEN: Settings > Accounts > Remove account
+ DIALOG_REMOVE_USER = 534;
+
+ // OPEN: Settings > Accounts > Confirm auto sync dialog
+ DIALOG_CONFIRM_AUTO_SYNC_CHANGE = 535;
+
+ // OPEN: Settings > Apps > Dialog for running service details
+ DIALOG_RUNNIGN_SERVICE = 536;
+
+ // OPEN: Settings > Bluetooth > Rename this device
+ DIALOG_BLUETOOTH_RENAME = 538;
+
+ // OPEN: Settings > Battery optimization > details for app
+ DIALOG_HIGH_POWER_DETAILS = 540;
+
+ // OPEN: Settings > Keyboard > Show keyboard layout dialog
+ DIALOG_KEYBOARD_LAYOUT = 541;
+
+ // OPEN: Settings > WIFI Scan permission dialog
+ DIALOG_WIFI_SCAN_MODE = 543;
+
+ // OPEN: Settings > Wireless > VPN > Config dialog
+ DIALOG_LEGACY_VPN_CONFIG = 545;
+
+ // OPEN: Settings > Wireless > VPN > Config dialog for app
+ DIALOG_VPN_APP_CONFIG = 546;
+
+ // OPEN: Settings > Wireless > VPN > Cannot connect dialog
+ DIALOG_VPN_CANNOT_CONNECT = 547;
+
+ // OPEN: Settings > Wireless > VPN > Replace existing VPN dialog
+ DIALOG_VPN_REPLACE_EXISTING = 548;
+
+ // OPEN: Settings > Billing cycle > Edit billing cycle dates dialog
+ DIALOG_BILLING_CYCLE = 549;
+
+ // OPEN: Settings > Billing cycle > Edit data limit/warning dialog
+ DIALOG_BILLING_BYTE_LIMIT = 550;
+
+ // OPEN: Settings > Billing cycle > turn on data limit dialog
+ DIALOG_BILLING_CONFIRM_LIMIT = 551;
+
+ // OPEN: Settings > Service > Turn off notification access dialog
+ DIALOG_DISABLE_NOTIFICATION_ACCESS = 552;
+
+ // OPEN: Settings > Sound > Use personal sound for work profile dialog
+ DIALOG_UNIFY_SOUND_SETTINGS = 553;
+
+ // OPEN: Settings > Zen mode > Dialog warning about the zen access privileges being granted.
+ DIALOG_ZEN_ACCESS_GRANT = 554;
+
+ // OPEN: Settings > Zen mode > Dialog warning about the zen access privileges being revoked.
+ DIALOG_ZEN_ACCESS_REVOKE = 555;
+
+ // OPEN: Settings > Zen mode > Dialog that picks time for zen mode.
+ DIALOG_ZEN_TIMEPICKER = 556;
+
+ // OPEN: Settings > Apps > Dialog that informs user to allow service access for app.
+ DIALOG_SERVICE_ACCESS_WARNING = 557;
+
+ // OPEN: Settings > Apps > Dialog for app actions (such as force stop/clear data)
+ DIALOG_APP_INFO_ACTION = 558;
+
+ // OPEN: Settings > Storage > Dialog for forgetting a storage device
+ DIALOG_VOLUME_FORGET = 559;
+
+ // OPEN: Settings > Storage > Dialog for initializing a volume
+ DIALOG_VOLUME_INIT = 561;
+
+ // OPEN: Settings > Storage > Dialog for unmounting a volume
+ DIALOG_VOLUME_UNMOUNT = 562;
+
+ // OPEN: Settings > Storage > Dialog for renaming a volume
+ DIALOG_VOLUME_RENAME = 563;
+
+ // OPEN: Settings > Storage > Dialog for clear cache
+ DIALOG_STORAGE_CLEAR_CACHE = 564;
+
+ // OPEN: Settings > Storage > Dialog for system info
+ DIALOG_STORAGE_SYSTEM_INFO = 565;
+
+ // OPEN: Settings > Storage > Dialog for other info
+ DIALOG_STORAGE_OTHER_INFO = 566;
+
+ // OPEN: Settings > Storage > Dialog for user info
+ DIALOG_STORAGE_USER_INFO = 567;
+ // OPEN: Settings > Add fingerprint > Dialog when user touches fingerprint icon.
+ DIALOG_FINGERPRINT_ICON_TOUCH = 568;
+
+ // OPEN: Settings > Add fingerprint > Error dialog
+ DIALOG_FINGERPINT_ERROR = 569;
+
+ // OPEN: Settings > Fingerprint > Rename or delete dialog
+ DIALOG_FINGERPINT_EDIT = 570;
+
+ // OPEN: Settings > Fingerprint > Dialog for deleting last fingerprint
+ DIALOG_FINGERPINT_DELETE_LAST = 571;
+
+ // OPEN: SUW > Fingerprint > Dialog to confirm skip fingerprint setup entirely.
+ DIALOG_FINGERPRINT_SKIP_SETUP = 573;
+
+ // OPEN: Settings > Proxy Selector error dialog
+ DIALOG_PROXY_SELECTOR_ERROR = 574;
+
+ // OPEN: Settings > Wifi > P2P Settings > Disconnect dialog
+ DIALOG_WIFI_P2P_DISCONNECT = 575;
+
+ // OPEN: Settings > Wifi > P2P Settings > Cancel connection dialog
+ DIALOG_WIFI_P2P_CANCEL_CONNECT = 576;
+
+ // OPEN: Settings > Wifi > P2P Settings > Rename dialog
+ DIALOG_WIFI_P2P_RENAME = 577;
+
+ // OPEN: Settings > Wifi > P2P Settings > Forget group dialog
+ DIALOG_WIFI_P2P_DELETE_GROUP = 578;
+
+ // OPEN: Settings > APN > Restore default dialog
+ DIALOG_APN_RESTORE_DEFAULT = 579;
+
+ // OPEN: Settings > Encryption interstitial accessibility warning dialog
+ DIALOG_ENCRYPTION_INTERSTITIAL_ACCESSIBILITY = 581;
+
+ // OPEN: Settings > Acessibility > Enable accessiblity service dialog
+ DIALOG_ACCESSIBILITY_SERVICE_ENABLE = 583;
+
+ // OPEN: Settings > Acessibility > Disable accessiblity service dialog
+ DIALOG_ACCESSIBILITY_SERVICE_DISABLE = 584;
+
+ // OPEN: Settings > Account > Remove account dialog
+ DIALOG_ACCOUNT_SYNC_REMOVE = 585;
+
+ // OPEN: Settings > Account > Remove account failed dialog
+ DIALOG_ACCOUNT_SYNC_FAILED_REMOVAL = 586;
+
+ // OPEN: Settings > Account > Cannot do onetime sync dialog
+ DIALOG_ACCOUNT_SYNC_CANNOT_ONETIME_SYNC = 587;
+
+ // OPEN: Settings > Display > Night light > Set start time dialog
+ DIALOG_NIGHT_DISPLAY_SET_START_TIME = 588;
+
+ // OPEN: Settings > Display > Night light > Set end time dialog
+ DIALOG_NIGHT_DISPLAY_SET_END_TIME = 589;
+
+
+
+ // OPEN: Settings > User > Edit info dialog
+ DIALOG_USER_EDIT = 590;
+
+ // OPEN: Settings > User > Confirm remove dialog
+ DIALOG_USER_REMOVE = 591;
+
+ // OPEN: Settings > User > Enable calling dialog
+ DIALOG_USER_ENABLE_CALLING = 592;
+
+ // OPEN: Settings > User > Enable calling and sms dialog
+ DIALOG_USER_ENABLE_CALLING_AND_SMS = 593;
+
+ // OPEN: Settings > User > Cannot manage device message dialog
+ DIALOG_USER_CANNOT_MANAGE = 594;
+
+ // OPEN: Settings > User > Add user dialog
+ DIALOG_USER_ADD = 595;
+
+ // OPEN: Settings > User > Setup user dialog
+ DIALOG_USER_SETUP = 596;
+
+ // OPEN: Settings > User > Setup profile dialog
+ DIALOG_USER_SETUP_PROFILE = 597;
+
+ // OPEN: Settings > User > Choose user type dialog
+ DIALOG_USER_CHOOSE_TYPE = 598;
+
+ // OPEN: Settings > User > Need lockscreen dialog
+ DIALOG_USER_NEED_LOCKSCREEN = 599;
+
+ // OPEN: Settings > User > Confirm exit guest mode dialog
+ DIALOG_USER_CONFIRM_EXIT_GUEST = 600;
+
+ // OPEN: Settings > User > Edit user profile dialog
+ DIALOG_USER_EDIT_PROFILE = 601;
+
+
+ // OPEN: Settings > Wifi > Saved AP > Edit dialog
+ DIALOG_WIFI_SAVED_AP_EDIT = 602;
+
+ // OPEN: Settings > Wifi > Edit AP dialog
+ DIALOG_WIFI_AP_EDIT = 603;
+
+ // OPEN: Settings > Wifi > Write config to NFC dialog
+ DIALOG_WIFI_WRITE_NFC = 606;
+
+ // OPEN: Settings > Date > Date picker dialog
+ DIALOG_DATE_PICKER = 607;
+
+ // OPEN: Settings > Date > Time picker dialog
+ DIALOG_TIME_PICKER = 608;
+
+ // OPEN: Settings > Wireless > Manage wireless plan dialog
+ DIALOG_MANAGE_MOBILE_PLAN = 609;
+
+ // OPEN Settings > Bluetooth > Attempt to connect to device that shows dialog
+ BLUETOOTH_DIALOG_FRAGMENT = 613;
+
+ // OPEN: Settings > Security
+ // CATEGORY: SETTINGS
+ // OS: O
+ ENTERPRISE_PRIVACY_SETTINGS = 628;
+
+ // OPEN: Settings > System
+ SETTINGS_SYSTEM_CATEGORY = 744;
+
+ // OPEN: Settings > Storage
+ SETTINGS_STORAGE_CATEGORY = 745;
+
+ // OPEN: Settings > Network & Internet
+ SETTINGS_NETWORK_CATEGORY = 746;
+
+ // OPEN: Settings > Connected Device
+ SETTINGS_CONNECTED_DEVICE_CATEGORY = 747;
+
+ // OPEN: Settings > App & Notification
+ SETTINGS_APP_NOTIF_CATEGORY = 748;
+
+ // OPEN: Settings > System > Language & Region
+ SETTINGS_LANGUAGE_CATEGORY = 750;
+
+ // OPEN: Settings > System > Input & Gesture > Swipe to notification gesture
+ SETTINGS_GESTURE_SWIPE_TO_NOTIFICATION = 751;
+
+ // OPEN: Settings > System > Input & Gesture > Double tap power button gesture
+ SETTINGS_GESTURE_DOUBLE_TAP_POWER = 752;
+
+ // OPEN: Settings > System > Input & Gesture > Pick up gesture
+ SETTINGS_GESTURE_PICKUP = 753;
+
+ // OPEN: Settings > System > Input & Gesture > Double tap screen gesture
+ SETTINGS_GESTURE_DOUBLE_TAP_SCREEN = 754;
+
+ // OPEN: Settings > System > Input & Gesture > Double twist gesture
+ SETTINGS_GESTURE_DOUBLE_TWIST = 755;
+
+ // OPEN: Settings > Apps > Default Apps > Default browser
+ DEFAULT_BROWSER_PICKER = 785;
+ // OPEN: Settings > Apps > Default Apps > Default emergency app
+ DEFAULT_EMERGENCY_APP_PICKER = 786;
+
+ // OPEN: Settings > Apps > Default Apps > Default home
+ DEFAULT_HOME_PICKER = 787;
+
+ // OPEN: Settings > Apps > Default Apps > Default phone
+ DEFAULT_PHONE_PICKER = 788;
+
+ // OPEN: Settings > Apps > Default Apps > Default sms
+ DEFAULT_SMS_PICKER = 789;
+
+ // OPEN: Settings > Apps > Default Apps > Warning dialog to confirm selection
+ DEFAULT_APP_PICKER_CONFIRMATION_DIALOG = 791;
+
+ // OPEN: Settings > Apps > Default Apps > Default autofill app
+ DEFAULT_AUTOFILL_PICKER = 792;
+
+ // OPEN: Settings > Apps > Gear > Special Access > Install other apps
+ // CATEGORY: SETTINGS
+ // OS: 8.0
+ MANAGE_EXTERNAL_SOURCES = 808;
+
+ // Logs that the user has edited the picture-in-picture settings.
+ // CATEGORY: SETTINGS
+ SETTINGS_MANAGE_PICTURE_IN_PICTURE = 812;
+
+ // OPEN: SUW Welcome Screen -> Vision Settings -> Select to Speak
+ // ACTION: Select to Speak configuration is chosen
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: SETTINGS
+ // OS: N
+ SUW_ACCESSIBILITY_TOGGLE_SELECT_TO_SPEAK = 817;
+
+ // OPEN: Settings > System > Backup
+ // CATEGORY: SETTINGS
+ // OS: O
+ BACKUP_SETTINGS = 818;
+
+ // OPEN: Settings > Storage > Games
+ // CATEGORY: SETTINGS
+ // OS: O
+ APPLICATIONS_STORAGE_GAMES = 838;
+
+ // OPEN: Settings > Storage > Audio and Music
+ // CATEGORY: SETTINGS
+ // OS: O
+ APPLICATIONS_STORAGE_MUSIC = 839;
+
+ // ACTION: Settings > Storage > Free Up Space to launch Deletion Helper
+ // CATEGORY: SETTINGS
+ // OS: O
+ STORAGE_FREE_UP_SPACE_NOW = 840;
+
+ // ACTION: Settings > Storage > Files to open the File Manager
+ // CATEGORY: SETTINGS
+ // OS: O
+ STORAGE_FILES = 841;
+
+ // OPEN: Settings > Apps > Default Apps > Assist > Default assist
+ DEFAULT_ASSIST_PICKER = 843;
+
+ // OPEN: Settings > Apps > Default Apps > Assist > Default voice input
+ DEFAULT_VOICE_INPUT_PICKER = 844;
+
+ // OPEN: Settings > Storage > [Profile]
+ SETTINGS_STORAGE_PROFILE = 845;
+
+ // OPEN: Settings > Security & screen lock -> Encryption & crendentials
+ // CATEGORY: SETTINGS
+ // OS: O
+ ENCRYPTION_AND_CREDENTIAL = 846;
+
+ // OPEN: Settings > Wi-Fi > Network Details (click on Access Point)
+ // CATEGORY: SETTINGS
+ // OS: O
+ WIFI_NETWORK_DETAILS = 849;
+
+ // OPEN: Settings > Wi-Fi > Wifi Preferences -> Advanced -> Network Scorer
+ // CATEGORY: SETTINGS
+ // OS: O
+ SETTINGS_NETWORK_SCORER = 861;
+
+ // OPEN: Settings > About device > Model > Hardware info dialog
+ DIALOG_SETTINGS_HARDWARE_INFO = 862;
+
+ // OPEN: Settings > Security & screen lock -> Lock screen preferences
+ // CATEGORY: SETTINGS
+ SETTINGS_LOCK_SCREEN_PREFERENCES = 882;
+
+
+ // OPEN: Settings -> Display -> When in VR Mode
+ VR_DISPLAY_PREFERENCE = 921;
+
+ // OPEN: Settings > Accessibility > Magnification
+ // CATEGORY: SETTINGS
+ // OS: O
+ ACCESSIBILITY_SCREEN_MAGNIFICATION_SETTINGS = 922;
+
+ // OPEN: Settings -> System -> Reset options
+ RESET_DASHBOARD = 924;
+
+ // OPEN: Settings > Security > Nexus Imprint > [Fingerprint] > Delete
+ // CATEGORY: SETTINGS
+ // OS: O
+ FINGERPRINT_REMOVE_SIDECAR = 934;
+
+ // OPEN: Settings > Storage > Movies & TV
+ // CATEGORY: SETTINGS
+ // OS: O
+ APPLICATIONS_STORAGE_MOVIES = 935;
+
+ // OPEN: Settings > Security > Managed Device Info > Apps installed
+ // CATEGORY: SETTINGS
+ // OS: O
+ ENTERPRISE_PRIVACY_INSTALLED_APPS = 938;
+
+ // OPEN: Settings > Security > Managed Device Info > nnn permissions
+ // CATEGORY: SETTINGS
+ // OS: O
+ ENTERPRISE_PRIVACY_PERMISSIONS = 939;
+
+
+ // OPEN: Settings > Security > Managed Device Info > Default apps
+ // CATEGORY: SETTINGS
+ // OS: O
+ ENTERPRISE_PRIVACY_DEFAULT_APPS = 940;
+
+ // OPEN: Choose screen lock dialog in Settings
+ // CATEGORY: SETTINGS
+ // OS: O DR
+ SETTINGS_CHOOSE_LOCK_DIALOG = 990;
+
+ // OPEN: Settings > System > Languages & input > Assist gesture
+ // CATEGORY: SETTINGS
+ // OS: O DR
+ SETTINGS_ASSIST_GESTURE = 996;
+
// OPEN: Settings > Connected Devices > Bluetooth > (click on details link for a paired device)
BLUETOOTH_DEVICE_DETAILS = 1009;
+ // OPEN: Settings > credential pages - prompt for key guard configuration confirmation
+ CONFIGURE_KEYGUARD_DIALOG = 1010;
+
+ // OPEN: Settings > Network > Tether > Wi-Fi hotspot
+ WIFI_TETHER_SETTINGS = 1014;
+
+ // OPEN: Settings->Connected Devices->Bluetooth->(click on details link for a paired device)
+ // -> Edit name button.
+ // CATEGORY: SETTINGS
+ // OS: O DR
+ DIALOG_BLUETOOTH_PAIRED_DEVICE_RENAME = 1015;
+
// OPEN: Settings > Connected devices > Bluetooth > Pair new device
+ // CATEGORY: SETTINGS
+ // OS: O DR
BLUETOOTH_PAIRING = 1018;
+ // OPEN: Settings->Connected Devices->Bluetooth->(click on details link for a paired device)
+ // -> Forget button.
+ // CATEGORY: SETTINGS
+ // OS: O DR
+ DIALOG_BLUETOOTH_PAIRED_DEVICE_FORGET = 1031;
+
+ // OPEN: Settings > Storage > Photos & Videos
+ // CATEGORY: SETTINGS
+ // OS: O MR
+ APPLICATIONS_STORAGE_PHOTOS = 1092;
+
+ // OPEN: Settings > Display > Colors
+ // CATEGORY: SETTINGS
+ // OS: O MR
+ COLOR_MODE_SETTINGS = 1143;
+
+ // OPEN: Settings > Developer Options > Experiment dashboard
+ // CATEGORY: SETTINGS
+ SETTINGS_FEATURE_FLAGS_DASHBOARD = 1217;
+
+ // OPEN: Settings > Notifications > [App] > Topic Notifications
+ // CATEGORY: SETTINGS
+ // OS: P
+ NOTIFICATION_CHANNEL_GROUP = 1218;
+
+ // OPEN: Settings > Developer options > Enable > Info dialog
+ // CATEGORY: SETTINGS
+ // OS: P
+ DIALOG_ENABLE_DEVELOPMENT_OPTIONS = 1219;
+
+ // OPEN: Settings > Developer options > OEM unlocking > Info dialog
+ // CATEGORY: SETTINGS
+ // OS: P
+ DIALOG_ENABLE_OEM_UNLOCKING = 1220;
+
+ // OPEN: Settings > Developer options > USB debugging > Info dialog
+ // CATEGORY: SETTINGS
+ // OS: P
+ DIALOG_ENABLE_ADB = 1222;
+
+ // OPEN: Settings > Security > Nexus Imprint > [Fingerprint]
+ // CATEGORY: SETTINGS
+ // OS: P
+ FINGERPRINT_AUTHENTICATE_SIDECAR = 1221;
+
+ // OPEN: Settings > Developer options > Revoke USB debugging authorizations > Info dialog
+ // CATEGORY: SETTINGS
+ // OS: P
+ DIALOG_CLEAR_ADB_KEYS = 1223;
+
+ // Open: Settings > Developer options > Quick setting tile config
+ // CATEGORY: SETTINGS
+ // OS: P
+ DEVELOPMENT_QS_TILE_CONFIG = 1224;
+
+ // OPEN: Settings > Developer options > Store logger data persistently on device > Info dialog
+ // CATEGORY: SETTINGS
+ // OS: P
+ DIALOG_LOG_PERSIST = 1225;
+
+ // OPEN: Settings > Network & Internet > Mobile network > Wi-Fi calling
+ // CATEGORY: SETTINGS
+ // OS: P
+ WIFI_CALLING_FOR_SUB = 1230;
+
+ // Open: Settings > Dev options > Oem unlock > lock it > warning dialog.
+ // OS: P
+ DIALOG_OEM_LOCK_INFO = 1238;
+
+ // Open: Settings > System > About phone > IMEI
+ // CATEGORY: SETTINGS
+ // OS: P
+ DIALOG_IMEI_INFO = 1240;
+
+ // OPEN: Settings > System > About Phone > Sim status
+ // CATEGORY: SETTINGS
+ // OS: P
+ DIALOG_SIM_STATUS = 1246;
+
+ // OPEN: Settings > System > About Phone > Android Version
+ // CATEGORY: SETTINGS
+ // OS: P
+ DIALOG_FIRMWARE_VERSION = 1247;
+
+ // OPEN: Settings > Battery(version 2)
+ // CATEGORY: SETTINGS
+ // OS: P
+ FUELGAUGE_POWER_USAGE_SUMMARY_V2 = 1263;
+
+ // OPEN: Settings > Connected devices > Connection preferences
+ // CATEGORY: SETTINGS
+ // OS: P
+ CONNECTION_DEVICE_ADVANCED = 1264;
+
+ // OPEN: Settings > Security > Screen lock gear icon
+ // CATEGORY: SETTINGS
+ // OS: P
+ SCREEN_LOCK_SETTINGS = 1265;
+
+ // OPEN: Settings > Sound > Do Not Disturb > Turn on automatically > Delete rule (trash can icon)
+ // CATEGORY: SETTINGS
+ // OS: P
+ NOTIFICATION_ZEN_MODE_DELETE_RULE_DIALOG = 1266;
+
+ // OPEN: Settings > Sound > Do Not Disturb > Turn on automatically > Add rule > Event/Time
+ // OPEN: Settings > Sound > Do Not Disturb > Turn on automatically > Select rule ("Event") > Rule name
+ // CATEGORY: SETTINGS
+ // OS: P
+ NOTIFICATION_ZEN_MODE_RULE_NAME_DIALOG = 1269;
+
+ // OPEN: Settings > Sound > Do Not Disturb > Turn on automatically > Add rule
+ // CATEGORY: SETTINGS
+ // OS: P
+ NOTIFICATION_ZEN_MODE_RULE_SELECTION_DIALOG = 1270;
+
+ // OPEN: Settings > Battery > Smart Battery
+ // CATEGORY: SETTINGS
+ // OS: P
+ FUELGAUGE_SMART_BATTERY = 1281;
+
+ // OPEN: Settings > Battery > Smart Battery > Restricted apps
+ // CATEGORY: SETTINGS
+ // OS: P
+ FUELGAUGE_RESTRICTED_APP_DETAILS = 1285;
+
+ // OPEN: Settings > Sound & notification > Do Not Disturb > Turn on now
+ // CATEGORY: SETTINGS
+ // OS: P
+ NOTIFICATION_ZEN_MODE_ENABLE_DIALOG = 1286;
+
+ // OPEN: Settings->Connected Devices->USB->(click on details link)
+ // CATEGORY: SETTINGS
+ // OS: P
+ USB_DEVICE_DETAILS = 1291;
+
+ // OPEN: Settings > Accessibility > Vibration
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACCESSIBILITY_VIBRATION = 1292;
+
+ // OPEN: Settings > Accessibility > Vibration > Notification vibration
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACCESSIBILITY_VIBRATION_NOTIFICATION = 1293;
+
+ // OPEN: Settings > Accessibility > Vibration > Touch vibration
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACCESSIBILITY_VIBRATION_TOUCH = 1294;
+
+ // OPEN: Settings->Developer Options->Default USB
+ // CATEGORY: SETTINGS
+ // OS: P
+ USB_DEFAULT = 1312;
+
+ // OPEN: Settings > Battery > Battery tip > Battery tip Dialog
+ // CATEGORY: SETTINGS
+ // OS: P
+ FUELGAUGE_BATTERY_TIP_DIALOG = 1323;
+
+ // OPEN: DND Settings > What to block
+ // OS: P
+ ZEN_WHAT_TO_BLOCK = 1339;
+
+ // OPEN: Settings > Sounds > Do Not Disturb > Duration
+ // CATEGORY: SETTINGS
+ // OS: P
+ NOTIFICATION_ZEN_MODE_DURATION_DIALOG = 1341;
+
+ // OPEN: Settings > Date & time > Select time zone -> Region
+ // CATEGORY: SETTINGS
+ // OS: P
+ SETTINGS_ZONE_PICKER_REGION = 1355;
+
+ // OPEN: Settings > Date & time > Select time zone -> Time Zone
+ // CATEGORY: SETTINGS
+ // OS: P
+ SETTINGS_ZONE_PICKER_TIME_ZONE = 1356;
+ // OPEN: Settings > Date & time > Select time zone -> Select UTC Offset
+ // CATEGORY: SETTINGS
+ // OS: P
+ SETTINGS_ZONE_PICKER_FIXED_OFFSET = 1357;
+
+ // OPEN: Settings > Gestures > Prevent Ringing
+ // OS: P
+ SETTINGS_PREVENT_RINGING = 1360;
+
+ // Settings > Condition > Device muted
+ // CATEGORY: SETTINGS
+ // OS: P
+ SETTINGS_CONDITION_DEVICE_MUTED = 1368;
+
+ // Settings > Condition > Device vibrate
+ // CATEGORY: SETTINGS
+ // OS: P
+ SETTINGS_CONDITION_DEVICE_VIBRATE = 1369;
+
+ // OPEN: Settings > Connected devices > previously connected devices
+ // CATEGORY: SETTINGS
+ // OS: P
+ PREVIOUSLY_CONNECTED_DEVICES = 1370;
+
+ // OPEN: Settings > Network & Internet > Wi-Fi > Wi-Fi Preferences > Turn on Wi-Fi automatically
+ // note: Wifi Scanning must be off for this dialog to show
+ // CATEGORY: SETTINGS
+ // OS: P
+ WIFI_SCANNING_NEEDED_DIALOG = 1373;
+
+ // OPEN: Settings > System > Gestures > Swipe up gesture
+ // CATEGORY: SETTINGS
+ // OS: P
+ SETTINGS_GESTURE_SWIPE_UP = 1374;
+
+ // OPEN: Settings > Storage > Dialog to format a storage volume
+ // CATEGORY: SETTINGS
+ // OS: P
+ DIALOG_VOLUME_FORMAT = 1375;
+
+ // OPEN: DND onboarding activity
+ // CATEGORY: SETTINGS
+ // OS: P
+ SETTINGS_ZEN_ONBOARDING = 1380;
+
+ // OPEN: Settings > Display > Auto brightness
+ // CATEGORY: SETTINGS
+ // OS: P
+ SETTINGS_AUTO_BRIGHTNESS = 1381;
+
+ // OPEN: Settings > Connected Devices > Bluetooth
+ // CATEGORY: SETTINGS
+ // OS: P
+ BLUETOOTH_FRAGMENT = 1390;
+
+ // Screen: DND Settings > Notifications
+ // OS: P
+ SETTINGS_ZEN_NOTIFICATIONS = 1400;
+
+ // An event category for slices.
+ // OPEN: Slice became visible.
+ // CLOSE: Slice became invisible.
+ // ACTION: Slice was tapped.
+ SLICE = 1401;
+
+ // OPEN: Settings -> Developer Options -> Disable Bluetooth A2DP hardware
+ // offload
+ // CATEGORY: SETTINGS
+ // OS: P
+ DIALOG_BLUETOOTH_DISABLE_A2DP_HW_OFFLOAD = 1441;
+
// OPEN: Settings homepage
SETTINGS_HOMEPAGE = 1502;
+ // OPEN: Settings > Create shortcut(widget)
+ // CATEGORY: SETTINGS
+ // OS: Q
+ SETTINGS_CREATE_SHORTCUT = 1503;
+
+ // OPEN: Face Enroll introduction
+ // CATEGORY: SETTINGS
+ // OS: Q
+ FACE_ENROLL_INTRO = 1506;
+
+ // OPEN: Face Enroll introduction
+ // CATEGORY: SETTINGS
+ // OS: Q
+ FACE_ENROLL_ENROLLING = 1507;
+
+ // OPEN: Face Enroll introduction
+ // CATEGORY: SETTINGS
+ // OS: Q
+ FACE_ENROLL_FINISHED = 1508;
+
+ // OPEN: Face Enroll sidecar
+ // CATEGORY: SETTINGS
+ // OS: Q
+ FACE_ENROLL_SIDECAR = 1509;
+
+ // OPEN: Settings > Add face > Error dialog
+ // OS: Q
+ DIALOG_FACE_ERROR = 1510;
+
+ // OPEN: Settings > Security > Face
+ // CATEGORY: SETTINGS
+ // OS: Q
+ FACE = 1511;
+
+ // OPEN: Settings > Acessibility > HearingAid pairing instructions dialog
+ // CATEGORY: SETTINGS
+ // OS: Q
+ DIALOG_ACCESSIBILITY_HEARINGAID = 1512;
+
+ // OPEN: Settings > Add face
+ // OS: Q
+ FACE_ENROLL_PREVIEW = 1554;
+
+ // OPEN: Settings > Network & Internet > Wi-Fi > Add network
+ // CATEGORY: SETTINGS
+ // OS: Q
+ SETTINGS_WIFI_ADD_NETWORK = 1556;
+
+ // OPEN: Settings > System > Input & Gesture > Reach up gesture
+ // OS: Q
+ SETTINGS_GESTURE_WAKE_LOCK_SCREEN = 1557;
+
// OPEN: Settings > System > Input & Gesture > Wake screen
SETTINGS_GESTURE_WAKE_SCREEN = 1570;
@@ -80,6 +2079,19 @@ enum PageId {
// OPEN: Settings > Privacy
TOP_LEVEL_PRIVACY = 1587;
+ // OPEN: Settings > Sound & notification > Do Not Disturb > See all exceptions >
+ // Allow apps to override
+ // CATEGORY: SETTINGS
+ // OS: Q
+ NOTIFICATION_ZEN_MODE_OVERRIDING_APPS = 1588;
+
+
+ // OPEN: Settings > Sound & notification > Do Not Disturb > See all exceptions >
+ // Allow apps to override > Choose app
+ // CATEGORY: SETTINGS
+ // OS: Q
+ NOTIFICATION_ZEN_MODE_OVERRIDING_APP = 1589;
+
// OPEN: Settings > Developer options > Disable > Info dialog
DIALOG_DISABLE_DEVELOPMENT_OPTIONS = 1591;
@@ -92,6 +2104,69 @@ enum PageId {
// OPEN: Settings > Apps & Notifications -> Special app access -> Financial Apps Sms Access
SETTINGS_FINANCIAL_APPS_SMS_ACCESS = 1597;
+
+
+ // OPEN: Settings > Sound > Do Not Disturb > Schedules > (Click on system rule)
+ // > Do Not Disturb behavior
+ // CATEGORY: SETTINGS
+ // OS: Q
+ ZEN_CUSTOM_RULE_SETTINGS = 1604;
+
+ // OPEN: Settings > Sound > Do Not Disturb > Schedules > (Click on system rule)
+ // > Do Not Disturb behavior > Custom
+ // CATEGORY: SETTINGS
+ // OS: Q
+ ZEN_CUSTOM_RULE_SOUND_SETTINGS = 1605;
+
+ // OPEN: Settings > Sound > Do Not Disturb > Schedules > (Click on system rule)
+ // > Do Not Disturb behavior > Use default Do Not Disturb behavior
+ // CATEGORY: SETTINGS
+ // OS: Q
+ ZEN_CUSTOM_RULE_DEFAULT_SETTINGS = 1606;
+
+ // OPEN: Settings > Sound > Do Not Disturb > Schedules > (Click on system rule)
+ // > Do Not Disturb behavior > Use default Do Not Disturb behavior
+ // > Notification restriction
+ // CATEGORY: SETTINGS
+ // OS: Q
+ ZEN_CUSTOM_RULE_NOTIFICATION_RESTRICTIONS = 1608;
+
+ // OPEN: Settings > Sound > Do Not Disturb > Schedules > (Click on system rule)
+ // > Do Not Disturb behavior > Use default Do Not Disturb behavior
+ // > Notification restriction > Custom
+ // CATEGORY: SETTINGS
+ // OS: Q
+ ZEN_CUSTOM_RULE_VIS_EFFECTS = 1609;
+
+ // OPEN: Settings > Sound > Do Not Disturb > Schedules > (Click on system rule)
+ // > Do Not Disturb behavior > Use default Do Not Disturb behavior
+ // > Notification restriction > Custom > Allow messages
+ // CATEGORY: SETTINGS
+ // OS: Q
+ ZEN_CUSTOM_RULE_MESSAGES = 1610;
+
+ // OPEN: Settings > Sound > Do Not Disturb > Schedules > (Click on system rule)
+ // > Do Not Disturb behavior > Use default Do Not Disturb behavior
+ // > Notification restriction > Custom > Allow calls
+ // CATEGORY: SETTINGS
+ // OS: Q
+ ZEN_CUSTOM_RULE_CALLS = 1611;
+
+ // OPEN: Settings > Sound > Do Not Disturb > Click footer link if custom settings applied
+ // CATEGORY: SETTINGS
+ // OS: Q
+ ZEN_CUSTOM_SETTINGS_DIALOG = 1612;
+
+ // OPEN: Settings > Developer Options > Game Update Packages
+ // CATEGORY: SETTINGS
+ // OS: Q
+ SETTINGS_GUP_DASHBOARD = 1613;
+
+ // OPEN: Settings > Accessibility > Vibration > Ring vibration
+ // CATEGORY: SETTINGS
+ // OS: Q
+ ACCESSIBILITY_VIBRATION_RING = 1620;
+
// OPEN: Settings > System > Input & Gesture > Skip songs
SETTINGS_GESTURE_SKIP = 1624;
@@ -100,4 +2175,8 @@ enum PageId {
// OPEN: Settings > System > Input & Gesture > Tap to check
SETTINGS_GESTURE_TAP_SCREEN = 1626;
+
+ // OPEN: Settings > Network & internet > Click Mobile network to land on a page with a list of
+ // SIM/eSIM subscriptions.
+ MOBILE_NETWORK_LIST = 1627;
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index cf1f7bb2aac1..f3e32414ee26 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1186,6 +1186,7 @@
<!-- Used for permissions that are associated with activity recognition.
TODO(zezeozue). STOPSHIP: Add icon -->
<permission-group android:name="android.permission-group.ACTIVITY_RECOGNITION"
+ android:icon="@drawable/perm_group_activity_recognition"
android:label="@string/permgrouplab_activityRecognition"
android:description="@string/permgroupdesc_activityRecognition"
android:request="@string/permgrouprequest_activityRecognition"
diff --git a/core/res/res/drawable/perm_group_activity_recognition.xml b/core/res/res/drawable/perm_group_activity_recognition.xml
new file mode 100644
index 000000000000..0ade6c674171
--- /dev/null
+++ b/core/res/res/drawable/perm_group_activity_recognition.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:fillColor="#000000"
+ android:pathData="M13.49 5.48c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm-3.6 13.9l1-4.4 2.1
+2v6h2v-7.5l-2.1-2 .6-3c1.3 1.5 3.3 2.5 5.5 2.5v-2c-1.9
+0-3.5-1-4.3-2.4l-1-1.6c-.4-.6-1-1-1.7-1-.3 0-.5 .1 -.8 .1 l-5.2
+2.2v4.7h2v-3.4l1.8-.7-1.6 8.1-4.9-1-.4 2 7 1.4z" />
+</vector>
diff --git a/core/res/res/drawable/perm_group_sensors.xml b/core/res/res/drawable/perm_group_sensors.xml
index ce36c13e1690..e4663d7206fc 100644
--- a/core/res/res/drawable/perm_group_sensors.xml
+++ b/core/res/res/drawable/perm_group_sensors.xml
@@ -19,11 +19,11 @@
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
-
- <path
- android:fillColor="#000000"
- android:pathData="M13.49 5.48c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm-3.6 13.9l1-4.4 2.1
-2v6h2v-7.5l-2.1-2 .6-3c1.3 1.5 3.3 2.5 5.5 2.5v-2c-1.9
-0-3.5-1-4.3-2.4l-1-1.6c-.4-.6-1-1-1.7-1-.3 0-.5 .1 -.8 .1 l-5.2
-2.2v4.7h2v-3.4l1.8-.7-1.6 8.1-4.9-1-.4 2 7 1.4z" />
-</vector> \ No newline at end of file
+ <path
+ android:fillColor="#000000"
+ android:pathData="M16.5,3c-1.74,0 -3.41,0.81 -4.5,2.09C10.91,3.81 9.24,3 7.5,3C4.42,3 2,5.42 2,
+ 8.5c0,3.78 3.4,6.86 8.55,11.54L12,21.35l1.45,-1.32C18.6,15.36 22,12.28 22,8.5C22,
+ 5.42 19.58,3 16.5,3zM12.1,18.55l-0.1,0.1l-0.1,-0.1C7.14,14.24 4,11.39 4,8.5C4,6.5 5.5,
+ 5 7.5,5c1.54,0 3.04,0.99 3.57,2.36h1.87C13.46,5.99 14.96,5 16.5,5c2,0 3.5,1.5 3.5,3.5C20,
+ 11.39 16.86,14.24 12.1,18.55z"/>
+</vector>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index aa1364f4a24e..64fdc026cc68 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -618,15 +618,6 @@
<!-- Integer indicating wpa_supplicant scan interval when p2p is connected in milliseconds -->
<integer translatable="false" name="config_wifi_scan_interval_p2p_connected">60000</integer>
- <!-- Integer indicating the framework scan interval in milliseconds. This is used in the scenario
- where the chipset does not support background scanning (config_wifi_background_scan_suport
- is false) to set up a periodic wake up scan so that the device can connect to a new access
- point on the move. A value of 0 means no periodic scans will be used in the framework. -->
- <integer translatable="false" name="config_wifi_framework_scan_interval">300000</integer>
-
- <!-- Integer indicating the framework no networks periodic scan interval in milliseconds. -->
- <integer translatable="false" name="config_wifi_no_network_periodic_scan_interval">300000</integer>
-
<!-- Integer indicating disconnect mode short scan interval in milliseconds -->
<integer translatable="false" name="config_wifi_disconnected_short_scan_interval">15000</integer>
@@ -692,6 +683,11 @@
<!-- Wifi driver supports Automatic channel selection (ACS) for softap -->
<bool translatable="false" name="config_wifi_softap_acs_supported">false</bool>
+ <!-- Channel list restriction to Automatic channel selection (ACS) for softap. If the device
+ doesn't want to restrict channels this should be empty. Value is a comma separated channel
+ string and/or channel range string like '1-6,11' -->
+ <string translatable="false" name="config_wifi_softap_acs_supported_channel_list"></string>
+
<!-- Wifi driver supports IEEE80211AC for softap -->
<bool translatable="false" name="config_wifi_softap_ieee80211ac_supported">false</bool>
@@ -699,6 +695,9 @@
for automotive builds only (the one that have PackageManager#FEATURE_AUTOMOTIVE) -->
<bool translatable="false" name="config_wifi_local_only_hotspot_5ghz">false</bool>
+ <!-- Indicates that connected MAC randomization is supported on this device -->
+ <bool translatable="false" name="config_wifi_connected_mac_randomization_supported">false</bool>
+
<!-- Flag indicating whether we should enable the automatic brightness.
Software implementation will be used if config_hardware_auto_brightness_available is not set -->
<bool name="config_automatic_brightness_available">false</bool>
@@ -1892,6 +1891,8 @@
cell broadcasting sms, and MMS. -->
<bool name="config_sms_capable">true</bool>
+ <!-- TODO: STOPSHIP(b/110557011): Remove this from framework and overlays as we use
+ config_defaultRoleHolders now. -->
<!-- Default SMS Application. This will be the default SMS application when
the phone first boots. The user can then change the default app to one
of their choosing.
@@ -1910,6 +1911,12 @@
the behavior will be as though no app was named as an explicit default. -->
<string name="default_browser" translatable="false"></string>
+ <!-- Default role holders. This will be an array of roles and package names of their default
+ holders, with each item in the format of "ROLE_NAME: PACKAGE_NAME_1, PACKAGE_NAME_2". -->
+ <string-array name="config_defaultRoleHolders" translatable="false">
+ <item>android.app.role.SMS: com.android.messaging</item>
+ </string-array>
+
<!-- Enable/disable default bluetooth profiles:
HSP_AG, ObexObjectPush, Audio, NAP -->
<bool name="config_bluetooth_default_profiles">true</bool>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index b3b30e992302..777886a9911c 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2985,6 +2985,11 @@
<public name="system_notification_accent_color" />
</public-group>
+ <public-group type="array" first-id="0x01070006">
+ <!-- @hide @SystemApi -->
+ <public name="config_defaultRoleHolders" />
+ </public-group>
+
<!-- ===============================================================
DO NOT ADD UN-GROUPED ITEMS HERE
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index eb0a7a1d8b10..9317cff054ad 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -325,6 +325,7 @@
<java-symbol type="bool" name="config_forceDefaultOrientation" />
<java-symbol type="bool" name="config_wifi_batched_scan_supported" />
<java-symbol type="bool" name="config_wifi_softap_acs_supported" />
+ <java-symbol type="string" name="config_wifi_softap_acs_supported_channel_list" />
<java-symbol type="bool" name="config_wifi_softap_ieee80211ac_supported" />
<java-symbol type="bool" name="config_enableMultiUserUI"/>
<java-symbol type="bool" name="config_enableNewAutoSelectNetworkUI"/>
@@ -458,9 +459,7 @@
<java-symbol type="integer" name="config_toastDefaultGravity" />
<java-symbol type="integer" name="config_triplePressOnPowerBehavior" />
<java-symbol type="integer" name="config_shortPressOnSleepBehavior" />
- <java-symbol type="integer" name="config_wifi_framework_scan_interval" />
<java-symbol type="integer" name="config_wifi_supplicant_scan_interval" />
- <java-symbol type="integer" name="config_wifi_no_network_periodic_scan_interval" />
<java-symbol type="integer" name="config_wifi_scan_interval_p2p_connected" />
<java-symbol type="integer" name="config_windowOutsetBottom" />
<java-symbol type="integer" name="db_connection_pool_size" />
@@ -1880,6 +1879,7 @@
<java-symbol type="bool" name="config_wifi_dual_band_support" />
<java-symbol type="bool" name="config_wifi_convert_apband_5ghz_to_any" />
<java-symbol type="bool" name="config_wifi_local_only_hotspot_5ghz" />
+ <java-symbol type="bool" name="config_wifi_connected_mac_randomization_supported" />
<java-symbol type="bool" name="config_wifi_fast_bss_transition_enabled" />
<java-symbol type="bool" name="config_wimaxEnabled" />
<java-symbol type="bool" name="show_ongoing_ime_switcher" />
diff --git a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java
index a2f0eba0b831..05c0df7c9a5f 100644
--- a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java
+++ b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java
@@ -97,6 +97,22 @@ public class ContentCaptureSessionTest {
assertThat(structure.getAutofillId()).isEqualTo(childId);
}
+ @Test
+ public void testNotifyViewsDisappeared_invalid() {
+ // Null parent
+ assertThrows(NullPointerException.class,
+ () -> mSession1.notifyViewsDisappeared(null, new int[] {42}));
+ // Null child
+ assertThrows(IllegalArgumentException.class,
+ () -> mSession1.notifyViewsDisappeared(new AutofillId(42), null));
+ // Empty child
+ assertThrows(IllegalArgumentException.class,
+ () -> mSession1.notifyViewsDisappeared(new AutofillId(42), new int[] {}));
+ // Virtual parent
+ assertThrows(IllegalArgumentException.class,
+ () -> mSession1.notifyViewsDisappeared(new AutofillId(42, 108), new int[] {666}));
+ }
+
// Cannot use @Spy because we need to pass the session id on constructor
private class MyContentCaptureSession extends ContentCaptureSession {
@@ -115,7 +131,7 @@ public class ContentCaptureSessionTest {
}
@Override
- void flush() {
+ void flush(int reason) {
throw new UnsupportedOperationException("should not have been called");
}
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderEndToEndTest.java b/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderEndToEndTest.java
new file mode 100644
index 000000000000..c03d1f37ffa7
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderEndToEndTest.java
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import android.os.SystemClock;
+import android.support.test.filters.LargeTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.internal.os.KernelCpuThreadReader.ProcessCpuUsage;
+import com.android.internal.os.KernelCpuThreadReader.ThreadCpuUsage;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.time.Duration;
+import java.util.Arrays;
+import java.util.List;
+import java.util.OptionalDouble;
+import java.util.concurrent.CountDownLatch;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
+
+/**
+ * End to end test for {@link KernelCpuThreadReader} that checks the accuracy of the reported times
+ * by spawning threads that do a predictable amount of work
+ */
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class KernelCpuThreadReaderEndToEndTest {
+
+ private static final int TIMED_NUM_SAMPLES = 5;
+ private static final int TIMED_START_MILLIS = 500;
+ private static final int TIMED_END_MILLIS = 2000;
+ private static final int TIMED_INCREMENT_MILLIS = 500;
+ private static final int TIMED_COMPARISON_DELTA_MILLIS = 200;
+
+ private static final int ITERATIVE_NUM_SAMPLES = 100;
+ private static final long ITERATIVE_LOW_ITERATIONS = (long) 1e8;
+ private static final long ITERATIVE_HIGH_ITERATIONS = (long) 2e8;
+ private static final double ITERATIONS_COMPARISONS_DELTA = 0.25;
+
+ /**
+ * Test that when we busy-wait for the thread-local time to reach N seconds, the time reported
+ * is also N seconds. Takes ~10s.
+ */
+ @Test
+ public void testTimedWork() throws InterruptedException {
+ for (int millis = TIMED_START_MILLIS;
+ millis <= TIMED_END_MILLIS;
+ millis += TIMED_INCREMENT_MILLIS) {
+ final Duration targetDuration = Duration.ofMillis(millis);
+ final Runnable work = timedWork(targetDuration);
+ Duration resultDuration = getAverageWorkTime(
+ work, String.format("timed%dms", millis), TIMED_NUM_SAMPLES);
+ assertEquals(
+ "Time worked according to currentThreadTimeMillis doesn't match "
+ + "KernelCpuThreadReader",
+ targetDuration.toMillis(), resultDuration.toMillis(),
+ TIMED_COMPARISON_DELTA_MILLIS);
+ }
+ }
+
+ /**
+ * Test that when we scale up the amount of work by N, the time reported also scales by N. Takes
+ * ~15s.
+ */
+ @Test
+ public void testIterativeWork() throws InterruptedException {
+ final Runnable lowAmountWork = iterativeWork(ITERATIVE_LOW_ITERATIONS);
+ final Runnable highAmountWork = iterativeWork(ITERATIVE_HIGH_ITERATIONS);
+ final Duration lowResultDuration =
+ getAverageWorkTime(lowAmountWork, "iterlow", ITERATIVE_NUM_SAMPLES);
+ final Duration highResultDuration =
+ getAverageWorkTime(highAmountWork, "iterhigh", ITERATIVE_NUM_SAMPLES);
+ assertEquals(
+ "Work scale and CPU time scale do not match",
+ ((double) ITERATIVE_HIGH_ITERATIONS) / ((double) ITERATIVE_LOW_ITERATIONS),
+ ((double) highResultDuration.toMillis()) / ((double) lowResultDuration.toMillis()),
+ ITERATIONS_COMPARISONS_DELTA);
+ }
+
+ /**
+ * Run some work {@code numSamples} times, and take the average CPU duration used for that work
+ * according to {@link KernelCpuThreadReader}
+ */
+ private Duration getAverageWorkTime(
+ Runnable work, String tag, int numSamples) throws InterruptedException {
+ // Count down every time a thread finishes work, so that we can wait for work to complete
+ final CountDownLatch workFinishedLatch = new CountDownLatch(numSamples);
+ // Count down once when threads can terminate (after we get them from
+ // `KernelCpuThreadReader`)
+ final CountDownLatch threadFinishedLatch = new CountDownLatch(1);
+
+ // Start `NUM_SAMPLE` threads to do the work
+ for (int i = 0; i < numSamples; i++) {
+ final String threadName = String.format("%s%d", tag, i);
+ // Check the thread name, as we rely on it later to identify threads
+ assertTrue("Max name length for linux threads is 15", threadName.length() <= 15);
+ doWork(work, threadName, workFinishedLatch, threadFinishedLatch);
+ }
+
+ // Wait for threads to finish
+ workFinishedLatch.await();
+
+ // Get thread data from KernelCpuThreadReader
+ final KernelCpuThreadReader kernelCpuThreadReader = KernelCpuThreadReader.create();
+ assertNotNull(kernelCpuThreadReader);
+ final ProcessCpuUsage currentProcessCpuUsage =
+ kernelCpuThreadReader.getCurrentProcessCpuUsage();
+
+ // Threads can terminate, as we've finished crawling them from /proc
+ threadFinishedLatch.countDown();
+
+ // Check that we've got times for every thread we spawned
+ final List<ThreadCpuUsage> threadCpuUsages = currentProcessCpuUsage.threadCpuUsages
+ .stream()
+ .filter((thread) -> thread.threadName.startsWith(tag))
+ .collect(Collectors.toList());
+ assertEquals(
+ "Incorrect number of threads returned by KernelCpuThreadReader",
+ numSamples, threadCpuUsages.size());
+
+ // Calculate the average time spent working
+ final OptionalDouble averageWorkTimeMillis = threadCpuUsages.stream()
+ .mapToDouble((t) -> Arrays.stream(t.usageTimesMillis).sum())
+ .average();
+ assertTrue(averageWorkTimeMillis.isPresent());
+ return Duration.ofMillis((long) averageWorkTimeMillis.getAsDouble());
+ }
+
+ /**
+ * Work that lasts {@code duration} according to {@link SystemClock#currentThreadTimeMillis()}
+ */
+ private Runnable timedWork(Duration duration) {
+ return () -> {
+ // Busy loop until `duration` has elapsed for the thread timer
+ final long startTimeMillis = SystemClock.currentThreadTimeMillis();
+ final long durationMillis = duration.toMillis();
+ while (true) {
+ final long elapsedMillis = SystemClock.currentThreadTimeMillis() - startTimeMillis;
+ if (elapsedMillis >= durationMillis) {
+ break;
+ }
+ }
+ };
+ }
+
+ /**
+ * Work that iterates {@code iterations} times
+ */
+ private Runnable iterativeWork(long iterations) {
+ Consumer<Long> empty = (i) -> {
+ };
+ return () -> {
+ long count = 0;
+ for (long i = 0; i < iterations; i++) {
+ // Alternate branching to reduce effect of branch prediction
+ if (i % 2 == 0) {
+ count++;
+ }
+ }
+ // Call empty function with value to avoid loop getting optimized away
+ empty.accept(count);
+ };
+ }
+
+ /**
+ * Perform some work in another thread
+ *
+ * @param work the work to perform
+ * @param threadName the name of the spawned thread
+ * @param workFinishedLatch latch to register that the work has been completed
+ * @param threadFinishedLatch latch to pause termination of the thread until the latch is
+ * decremented
+ */
+ private void doWork(
+ Runnable work,
+ String threadName,
+ CountDownLatch workFinishedLatch,
+ CountDownLatch threadFinishedLatch) {
+ Runnable workWrapped = () -> {
+ // Do the work
+ work.run();
+ // Notify that the work is finished
+ workFinishedLatch.countDown();
+ // Wait until `threadFinishLatch` has been released in order to keep the thread alive so
+ // we can see it in `proc` filesystem
+ try {
+ threadFinishedLatch.await();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ };
+ new Thread(workWrapped, threadName).start();
+ }
+}
diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h
index 6b9ebd3e8d12..1655e89a9b97 100644
--- a/libs/androidfw/include/androidfw/ResourceTypes.h
+++ b/libs/androidfw/include/androidfw/ResourceTypes.h
@@ -1643,10 +1643,6 @@ struct ResTable_overlayable_policy_header
// The overlay must reside of the product partition or must have existed on the product
// partition before an upgrade to overlay these resources.
POLICY_PRODUCT_PARTITION = 0x00000008,
-
- // The overlay must reside of the product services partition or must have existed on the product
- // services partition before an upgrade to overlay these resources.
- POLICY_PRODUCT_SERVICES_PARTITION = 0x00000010,
};
uint32_t policy_flags;
diff --git a/libs/androidfw/tests/LoadedArsc_test.cpp b/libs/androidfw/tests/LoadedArsc_test.cpp
index 2e386a083185..b8d3c6bf92fb 100644
--- a/libs/androidfw/tests/LoadedArsc_test.cpp
+++ b/libs/androidfw/tests/LoadedArsc_test.cpp
@@ -312,7 +312,6 @@ TEST(LoadedArscTest, LoadOverlayable) {
EXPECT_THAT(info->actor, Eq("overlay://com.android.overlayable"));
EXPECT_THAT(info->policy_flags,
Eq(ResTable_overlayable_policy_header::POLICY_VENDOR_PARTITION
- | ResTable_overlayable_policy_header::POLICY_PRODUCT_SERVICES_PARTITION
| ResTable_overlayable_policy_header::POLICY_PRODUCT_PARTITION));
info = package->GetOverlayableInfo(overlayable::R::string::overlayable4);
diff --git a/libs/androidfw/tests/data/overlayable/overlayable.apk b/libs/androidfw/tests/data/overlayable/overlayable.apk
index 863474794d00..047e6afde86b 100644
--- a/libs/androidfw/tests/data/overlayable/overlayable.apk
+++ b/libs/androidfw/tests/data/overlayable/overlayable.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/overlayable/res/values/overlayable.xml b/libs/androidfw/tests/data/overlayable/res/values/overlayable.xml
index dba7b08628f1..fcdbe94466c1 100644
--- a/libs/androidfw/tests/data/overlayable/res/values/overlayable.xml
+++ b/libs/androidfw/tests/data/overlayable/res/values/overlayable.xml
@@ -32,9 +32,9 @@
</overlayable>
<overlayable name="OverlayableResources2" actor="overlay://com.android.overlayable">
- <!-- Any overlay on the product_services, vendor, or product partition can overlay the value of
+ <!-- Any overlay on the vendor or product partition can overlay the value of
@string/overlayable3 -->
- <policy type="product_services|vendor|product">
+ <policy type="vendor|product">
<item type="string" name="overlayable3" />
</policy>
</overlayable>
diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp
index b4f19c99c6fe..d742cc34b57e 100644
--- a/libs/input/PointerController.cpp
+++ b/libs/input/PointerController.cpp
@@ -255,7 +255,7 @@ void PointerController::setPresentation(Presentation presentation) {
if (presentation == PRESENTATION_POINTER && mLocked.additionalMouseResources.empty()) {
mPolicy->loadAdditionalMouseResources(&mLocked.additionalMouseResources,
- &mLocked.animationResources);
+ &mLocked.animationResources, mLocked.viewport.displayId);
}
if (mLocked.presentation != presentation) {
@@ -727,14 +727,14 @@ void PointerController::fadeOutAndReleaseAllSpotsLocked() {
}
void PointerController::loadResourcesLocked() REQUIRES(mLock) {
- mPolicy->loadPointerResources(&mResources);
+ mPolicy->loadPointerResources(&mResources, mLocked.viewport.displayId);
if (mLocked.presentation == PRESENTATION_POINTER) {
mLocked.additionalMouseResources.clear();
mLocked.animationResources.clear();
- mPolicy->loadPointerIcon(&mLocked.pointerIcon);
+ mPolicy->loadPointerIcon(&mLocked.pointerIcon, mLocked.viewport.displayId);
mPolicy->loadAdditionalMouseResources(&mLocked.additionalMouseResources,
- &mLocked.animationResources);
+ &mLocked.animationResources, mLocked.viewport.displayId);
}
mLocked.pointerIconChanged = true;
diff --git a/libs/input/PointerController.h b/libs/input/PointerController.h
index a32cc42a3342..be057867890d 100644
--- a/libs/input/PointerController.h
+++ b/libs/input/PointerController.h
@@ -62,10 +62,10 @@ protected:
virtual ~PointerControllerPolicyInterface() { }
public:
- virtual void loadPointerIcon(SpriteIcon* icon) = 0;
- virtual void loadPointerResources(PointerResources* outResources) = 0;
+ virtual void loadPointerIcon(SpriteIcon* icon, int32_t displayId) = 0;
+ virtual void loadPointerResources(PointerResources* outResources, int32_t displayId) = 0;
virtual void loadAdditionalMouseResources(std::map<int32_t, SpriteIcon>* outResources,
- std::map<int32_t, PointerAnimation>* outAnimationResources) = 0;
+ std::map<int32_t, PointerAnimation>* outAnimationResources, int32_t displayId) = 0;
virtual int32_t getDefaultPointerIconId() = 0;
virtual int32_t getCustomPointerIconId() = 0;
};
diff --git a/media/Android.bp b/media/Android.bp
index d5da6f266952..8ebc91a06f7a 100644
--- a/media/Android.bp
+++ b/media/Android.bp
@@ -1,4 +1,21 @@
java_library {
+ name: "media1",
+
+ srcs: [
+ ":media1-srcs",
+ ],
+
+ sdk_version: "system_current",
+}
+
+filegroup {
+ name: "media1-srcs",
+ srcs: [
+ "java/android/media/session/MediaSessionProviderService.java",
+ ],
+}
+
+java_library {
// TODO: include media2.jar in the media apex and add it to the bootclasspath.
name: "media2",
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index 33f81f1db69c..92afe7ede8f2 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -61,7 +61,8 @@ import java.util.concurrent.Executor;
* been read yet. Data should be read from the audio hardware in chunks of sizes inferior to
* the total recording buffer size.
*/
-public class AudioRecord implements AudioRouting, AudioRecordingMonitor, AudioRecordingMonitorClient
+public class AudioRecord implements AudioRouting, MicrophoneDirection,
+ AudioRecordingMonitor, AudioRecordingMonitorClient
{
//---------------------------------------------------------
// Constants
@@ -1657,7 +1658,6 @@ public class AudioRecord implements AudioRouting, AudioRecordingMonitor, AudioRe
return activeMicrophones;
}
-
//--------------------------------------------------------------------------
// Implementation of AudioRecordingMonitor interface
//--------------------
@@ -1707,6 +1707,33 @@ public class AudioRecord implements AudioRouting, AudioRecordingMonitor, AudioRe
return native_getPortId();
}
+ //--------------------------------------------------------------------------
+ // MicrophoneDirection
+ //--------------------
+ /**
+ * Specifies the logical microphone (for processing).
+ *
+ * @param direction Direction constant (MicrophoneDirection.MIC_DIRECTION_*)
+ * @return retval OK if the call is successful, an error code otherwise.
+ * @hide
+ */
+ public int setMicrophoneDirection(int direction) {
+ return native_set_microphone_direction(direction);
+ }
+
+ /**
+ * Specifies the zoom factor (i.e. the field dimension) for the selected microphone
+ * (for processing). The selected microphone is determined by the use-case for the stream.
+ *
+ * @param zoom the desired field dimension of microphone capture. Range is from -1 (wide angle),
+ * though 0 (no zoom) to 1 (maximum zoom).
+ * @return retval OK if the call is successful, an error code otherwise.
+ * @hide
+ */
+ public int setMicrophoneFieldDimension(float zoom) {
+ return native_set_microphone_field_dimension(zoom);
+ }
+
//---------------------------------------------------------
// Interface definitions
//--------------------
@@ -1860,6 +1887,9 @@ public class AudioRecord implements AudioRouting, AudioRecordingMonitor, AudioRe
private native int native_getPortId();
+ private native int native_set_microphone_direction(int direction);
+ private native int native_set_microphone_field_dimension(float zoom);
+
//---------------------------------------------------------
// Utility methods
//------------------
diff --git a/media/java/android/media/Controller2Link.java b/media/java/android/media/Controller2Link.java
index a62db5f1fb20..d11f7769ee5e 100644
--- a/media/java/android/media/Controller2Link.java
+++ b/media/java/android/media/Controller2Link.java
@@ -16,6 +16,7 @@
package android.media;
+import android.os.Binder;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -102,6 +103,15 @@ public final class Controller2Link implements Parcelable {
}
}
+ /** Interface method for IMediaController2.notifyPlaybackActiveChanged */
+ public void notifyPlaybackActiveChanged(int seq, boolean playbackActive) {
+ try {
+ mIController.notifyPlaybackActiveChanged(seq, playbackActive);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
/** Interface method for IMediaController2.sendSessionCommand */
public void sendSessionCommand(int seq, Session2Command command, Bundle args,
ResultReceiver resultReceiver) {
@@ -135,6 +145,11 @@ public final class Controller2Link implements Parcelable {
mController.onDisconnected(seq);
}
+ /** Stub implementation for IMediaController2.notifyPlaybackActiveChanged */
+ public void onPlaybackActiveChanged(int seq, boolean playbackActive) {
+ mController.onPlaybackActiveChanged(seq, playbackActive);
+ }
+
/** Stub implementation for IMediaController2.sendSessionCommand */
public void onSessionCommand(int seq, Session2Command command, Bundle args,
ResultReceiver resultReceiver) {
@@ -149,23 +164,53 @@ public final class Controller2Link implements Parcelable {
private class Controller2Stub extends IMediaController2.Stub {
@Override
public void notifyConnected(int seq, Bundle connectionResult) {
- Controller2Link.this.onConnected(seq, connectionResult);
+ final long token = Binder.clearCallingIdentity();
+ try {
+ Controller2Link.this.onConnected(seq, connectionResult);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
@Override
public void notifyDisconnected(int seq) {
- Controller2Link.this.onDisconnected(seq);
+ final long token = Binder.clearCallingIdentity();
+ try {
+ Controller2Link.this.onDisconnected(seq);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
+ public void notifyPlaybackActiveChanged(int seq, boolean playbackActive) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ Controller2Link.this.onPlaybackActiveChanged(seq, playbackActive);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
@Override
public void sendSessionCommand(int seq, Session2Command command, Bundle args,
ResultReceiver resultReceiver) {
- Controller2Link.this.onSessionCommand(seq, command, args, resultReceiver);
+ final long token = Binder.clearCallingIdentity();
+ try {
+ Controller2Link.this.onSessionCommand(seq, command, args, resultReceiver);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
@Override
public void cancelSessionCommand(int seq) {
- Controller2Link.this.onCancelCommand(seq);
+ final long token = Binder.clearCallingIdentity();
+ try {
+ Controller2Link.this.onCancelCommand(seq);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
}
}
diff --git a/media/java/android/media/IMediaController2.aidl b/media/java/android/media/IMediaController2.aidl
index ca5394f504cb..42c6e70529ec 100644
--- a/media/java/android/media/IMediaController2.aidl
+++ b/media/java/android/media/IMediaController2.aidl
@@ -31,8 +31,9 @@ import android.media.Session2Command;
oneway interface IMediaController2 {
void notifyConnected(int seq, in Bundle connectionResult) = 0;
void notifyDisconnected(int seq) = 1;
+ void notifyPlaybackActiveChanged(int seq, boolean playbackActive) = 2;
void sendSessionCommand(int seq, in Session2Command command, in Bundle args,
- in ResultReceiver resultReceiver) = 2;
- void cancelSessionCommand(int seq) = 3;
- // Next Id : 4
+ in ResultReceiver resultReceiver) = 3;
+ void cancelSessionCommand(int seq) = 4;
+ // Next Id : 5
}
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index bc9500ddb3b7..f756658b4fa8 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -1829,9 +1829,14 @@ final public class MediaCodec {
mBufferLock = new Object();
+ // save name used at creation
+ mNameAtCreation = nameIsType ? null : name;
+
native_setup(name, nameIsType, encoder);
}
+ private String mNameAtCreation;
+
@Override
protected void finalize() {
native_finalize();
@@ -3317,12 +3322,36 @@ final public class MediaCodec {
private native void native_setAudioPresentation(int presentationId, int programId);
/**
- * Get the component name. If the codec was created by createDecoderByType
- * or createEncoderByType, what component is chosen is not known beforehand.
+ * Retrieve the codec name.
+ *
+ * If the codec was created by createDecoderByType or createEncoderByType, what component is
+ * chosen is not known beforehand. This method returns the name of the codec that was
+ * selected by the platform.
+ *
+ * <strong>Note:</strong> Implementations may provide multiple aliases (codec
+ * names) for the same underlying codec, any of which can be used to instantiate the same
+ * underlying codec in {@link MediaCodec#createByCodecName}. This method returns the
+ * name used to create the codec in this case.
+ *
+ * @throws IllegalStateException if in the Released state.
+ */
+ @NonNull
+ public final String getName() {
+ // get canonical name to handle exception
+ String canonicalName = getCanonicalName();
+ return mNameAtCreation != null ? mNameAtCreation : canonicalName;
+ }
+
+ /**
+ * Retrieve the underlying codec name.
+ *
+ * This method is similar to {@link #getName}, except that it returns the underlying component
+ * name even if an alias was used to create this MediaCodec object by name,
+ *
* @throws IllegalStateException if in the Released state.
*/
@NonNull
- public native final String getName();
+ public native final String getCanonicalName();
/**
* Return Metrics data about the current codec instance.
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 10a1e3a72225..751d57bbdc81 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -32,8 +32,10 @@ import android.util.Size;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.Vector;
/**
* Provides information about a given media codec available on the device. You can
@@ -61,15 +63,25 @@ import java.util.Set;
*
*/
public final class MediaCodecInfo {
- private boolean mIsEncoder;
+ private static final String TAG = "MediaCodecInfo";
+
+ private static final int FLAG_IS_ENCODER = (1 << 0);
+ private static final int FLAG_IS_VENDOR = (1 << 1);
+ private static final int FLAG_IS_SOFTWARE_ONLY = (1 << 2);
+ private static final int FLAG_IS_HARDWARE_ACCELERATED = (1 << 3);
+
+ private int mFlags;
private String mName;
+ private String mCanonicalName;
private Map<String, CodecCapabilities> mCaps;
/* package private */ MediaCodecInfo(
- String name, boolean isEncoder, CodecCapabilities[] caps) {
+ String name, String canonicalName, int flags, CodecCapabilities[] caps) {
mName = name;
- mIsEncoder = isEncoder;
+ mCanonicalName = canonicalName;
+ mFlags = flags;
mCaps = new HashMap<String, CodecCapabilities>();
+
for (CodecCapabilities c: caps) {
mCaps.put(c.getMimeType(), c);
}
@@ -77,16 +89,69 @@ public final class MediaCodecInfo {
/**
* Retrieve the codec name.
+ *
+ * <strong>Note:</strong> Implementations may provide multiple aliases (codec
+ * names) for the same underlying codec, any of which can be used to instantiate the same
+ * underlying codec in {@link MediaCodec#createByCodecName}.
+ *
+ * Applications targeting SDK < {@link android.os.Build.VERSION_CODES#Q}, cannot determine if
+ * the multiple codec names listed in MediaCodecList are in-fact for the same codec.
*/
+ @NonNull
public final String getName() {
return mName;
}
/**
+ * Retrieve the underlying codec name.
+ *
+ * Device implementations may provide multiple aliases (codec names) for the same underlying
+ * codec to maintain backward app compatibility. This method returns the name of the underlying
+ * codec name, which must not be another alias. For non-aliases this is always the name of the
+ * codec.
+ */
+ @NonNull
+ public final String getCanonicalName() {
+ return mCanonicalName;
+ }
+
+ /**
+ * Query if the codec is an alias for another underlying codec.
+ */
+ public final boolean isAlias() {
+ return !mName.equals(mCanonicalName);
+ }
+
+ /**
* Query if the codec is an encoder.
*/
public final boolean isEncoder() {
- return mIsEncoder;
+ return (mFlags & FLAG_IS_ENCODER) != 0;
+ }
+
+ /**
+ * Query if the codec is provided by the Android platform (false) or the device manufacturer
+ * (true).
+ */
+ public final boolean isVendor() {
+ return (mFlags & FLAG_IS_VENDOR) != 0;
+ }
+
+ /**
+ * Query if the codec is software only. Software-only codecs are more secure as they run in
+ * a tighter security sandbox. On the other hand, software-only codecs do not provide any
+ * performance guarantees.
+ */
+ public final boolean isSoftwareOnly() {
+ return (mFlags & FLAG_IS_SOFTWARE_ONLY) != 0;
+ }
+
+ /**
+ * Query if the codec is hardware accelerated. This attribute is provided by the device
+ * manufacturer. Note that it cannot be tested for correctness.
+ */
+ public final boolean isHardwareAccelerated() {
+ return (mFlags & FLAG_IS_HARDWARE_ACCELERATED) != 0;
}
/**
@@ -163,7 +228,7 @@ public final class MediaCodecInfo {
// such as B-frame support, arithmetic coding...
public CodecProfileLevel[] profileLevels; // NOTE this array is modifiable by user
- // from OMX_COLOR_FORMATTYPE
+ // from MediaCodecConstants
/** @deprecated Use {@link #COLOR_Format24bitBGR888}. */
public static final int COLOR_FormatMonochrome = 1;
/** @deprecated Use {@link #COLOR_Format24bitBGR888}. */
@@ -344,7 +409,7 @@ public final class MediaCodecInfo {
/** @deprecated Use {@link #COLOR_FormatYUV420Flexible}. */
public static final int COLOR_TI_FormatYUV420PackedSemiPlanar = 0x7f000100;
// COLOR_FormatSurface indicates that the data will be a GraphicBuffer metadata reference.
- // In OMX this is called OMX_COLOR_FormatAndroidOpaque.
+ // Note: in OMX this is called OMX_COLOR_FormatAndroidOpaque.
public static final int COLOR_FormatSurface = 0x7F000789;
/**
@@ -435,8 +500,7 @@ public final class MediaCodecInfo {
public static final int COLOR_QCOM_FormatYUV420SemiPlanar = 0x7fa30c00;
/**
- * Defined in the OpenMAX IL specs, color format values are drawn from
- * OMX_COLOR_FORMATTYPE.
+ * The color format for the media. This is one of the color constants defined in this class.
*/
public int[] colorFormats; // NOTE this array is modifiable by user
@@ -462,6 +526,26 @@ public final class MediaCodecInfo {
public static final String FEATURE_TunneledPlayback = "tunneled-playback";
/**
+ * If true, the timestamp of each output buffer is derived from the timestamp of the input
+ * buffer that produced the output. If false, the timestamp of each output buffer is
+ * derived from the timestamp of the first input buffer.
+ */
+ public static final String FEATURE_DynamicTimestamp = "dynamic-timestamp";
+
+ /**
+ * <b>decoder only</b>If true, the codec supports partial (including multiple) access units
+ * per input buffer.
+ */
+ public static final String FEATURE_FrameParsing = "frame-parsing";
+
+ /**
+ * If true, the codec supports multiple access units (for decoding, or to output for
+ * encoders). If false, the codec only supports single access units. Producing multiple
+ * access units for output is an optional feature.
+ */
+ public static final String FEATURE_MultipleFrames = "multiple-frames";
+
+ /**
* <b>video decoder only</b>: codec supports queuing partial frames.
*/
public static final String FEATURE_PartialFrame = "partial-frame";
@@ -497,10 +581,15 @@ public final class MediaCodecInfo {
new Feature(FEATURE_SecurePlayback, (1 << 1), false),
new Feature(FEATURE_TunneledPlayback, (1 << 2), false),
new Feature(FEATURE_PartialFrame, (1 << 3), false),
+ new Feature(FEATURE_FrameParsing, (1 << 4), false),
+ new Feature(FEATURE_MultipleFrames, (1 << 5), false),
+ new Feature(FEATURE_DynamicTimestamp, (1 << 6), false),
};
private static final Feature[] encoderFeatures = {
new Feature(FEATURE_IntraRefresh, (1 << 0), false),
+ new Feature(FEATURE_MultipleFrames, (1 << 1), false),
+ new Feature(FEATURE_DynamicTimestamp, (1 << 2), false),
};
/** @hide */
@@ -869,7 +958,7 @@ public final class MediaCodecInfo {
CodecCapabilities ret = new CodecCapabilities(
new CodecProfileLevel[] { pl }, new int[0], true /* encoder */,
- 0 /* flags */, defaultFormat, new MediaFormat() /* info */);
+ defaultFormat, new MediaFormat() /* info */);
if (ret.mError != 0) {
return null;
}
@@ -878,10 +967,10 @@ public final class MediaCodecInfo {
/* package private */ CodecCapabilities(
CodecProfileLevel[] profLevs, int[] colFmts,
- boolean encoder, int flags,
+ boolean encoder,
Map<String, Object>defaultFormatMap,
Map<String, Object>capabilitiesMap) {
- this(profLevs, colFmts, encoder, flags,
+ this(profLevs, colFmts, encoder,
new MediaFormat(defaultFormatMap),
new MediaFormat(capabilitiesMap));
}
@@ -889,11 +978,11 @@ public final class MediaCodecInfo {
private MediaFormat mCapabilitiesInfo;
/* package private */ CodecCapabilities(
- CodecProfileLevel[] profLevs, int[] colFmts, boolean encoder, int flags,
+ CodecProfileLevel[] profLevs, int[] colFmts, boolean encoder,
MediaFormat defaultFormat, MediaFormat info) {
final Map<String, Object> map = info.getMap();
colorFormats = colFmts;
- mFlagsVerified = flags;
+ mFlagsVerified = 0; // TODO: remove as it is unused
mDefaultFormat = defaultFormat;
mCapabilitiesInfo = info;
mMime = mDefaultFormat.getString(MediaFormat.KEY_MIME);
@@ -1243,6 +1332,7 @@ public final class MediaCodecInfo {
private Range<Rational> mBlockAspectRatioRange;
private Range<Long> mBlocksPerSecondRange;
private Map<Size, Range<Long>> mMeasuredFrameRates;
+ private Vector<PerformancePoint> mPerformancePoints;
private Range<Integer> mFrameRateRange;
private int mBlockWidth;
@@ -1524,6 +1614,158 @@ public final class MediaCodecInfo {
}
/**
+ * Video performance points are a set of standard performance points defined by pixel rate.
+ */
+ public static final class PerformancePoint {
+ /**
+ * Frame width in pixels.
+ */
+ public final int width;
+
+ /**
+ * Frame height in pixels.
+ */
+ public final int height;
+
+ /**
+ * Frame rate in frames per second.
+ */
+ public final int frameRate;
+
+ /* package private */
+ PerformancePoint(int width_, int height_, int frameRate_) {
+ width = width_;
+ height = height_;
+ frameRate = frameRate_;
+ }
+
+ /**
+ * Checks whether the performance point covers a media format.
+ *
+ * @param format Stream format considered
+ *
+ * @return {@code true} if the performance point covers the format.
+ */
+ public boolean covers(@NonNull MediaFormat format) {
+ // for simplicity, this code assumes a 16x16 block size.
+ long macroBlocks = ((width + 15) / 16) * (long)((height + 15) / 16);
+ long mbps = macroBlocks * frameRate;
+
+ long formatMacroBlocks =
+ (long)((format.getInteger(MediaFormat.KEY_WIDTH, 0) + 15) / 16)
+ * ((format.getInteger(MediaFormat.KEY_HEIGHT, 0) + 15) / 16);
+ double formatMbps =
+ Math.ceil(formatMacroBlocks
+ * format.getNumber(MediaFormat.KEY_FRAME_RATE, 0).doubleValue());
+ return formatMacroBlocks > 0 && formatMacroBlocks <= macroBlocks
+ && formatMbps <= mbps;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof PerformancePoint) {
+ PerformancePoint other = (PerformancePoint)o;
+ return ((long)width * height) == ((long)other.width * other.height)
+ && frameRate == other.frameRate;
+ }
+ return false;
+ }
+
+ /** 480p 24fps */
+ public static final PerformancePoint SD_24 = new PerformancePoint(720, 480, 24);
+ /** 576p 25fps */
+ public static final PerformancePoint SD_25 = new PerformancePoint(720, 576, 25);
+ /** 480p 30fps */
+ public static final PerformancePoint SD_30 = new PerformancePoint(720, 480, 30);
+ /** 480p 48fps */
+ public static final PerformancePoint SD_48 = new PerformancePoint(720, 480, 48);
+ /** 576p 50fps */
+ public static final PerformancePoint SD_50 = new PerformancePoint(720, 576, 50);
+ /** 480p 60fps */
+ public static final PerformancePoint SD_60 = new PerformancePoint(720, 480, 60);
+
+ /** 720p 24fps */
+ public static final PerformancePoint HD_24 = new PerformancePoint(1280, 720, 24);
+ /** 720p 25fps */
+ public static final PerformancePoint HD_25 = new PerformancePoint(1280, 720, 25);
+ /** 720p 30fps */
+ public static final PerformancePoint HD_30 = new PerformancePoint(1280, 720, 30);
+ /** 720p 50fps */
+ public static final PerformancePoint HD_50 = new PerformancePoint(1280, 720, 50);
+ /** 720p 60fps */
+ public static final PerformancePoint HD_60 = new PerformancePoint(1280, 720, 60);
+ /** 720p 100fps */
+ public static final PerformancePoint HD_100 = new PerformancePoint(1280, 720, 100);
+ /** 720p 120fps */
+ public static final PerformancePoint HD_120 = new PerformancePoint(1280, 720, 120);
+ /** 720p 200fps */
+ public static final PerformancePoint HD_200 = new PerformancePoint(1280, 720, 200);
+ /** 720p 240fps */
+ public static final PerformancePoint HD_240 = new PerformancePoint(1280, 720, 240);
+
+ /** 1080p 24fps */
+ public static final PerformancePoint FHD_24 = new PerformancePoint(1920, 1080, 24);
+ /** 1080p 25fps */
+ public static final PerformancePoint FHD_25 = new PerformancePoint(1920, 1080, 25);
+ /** 1080p 30fps */
+ public static final PerformancePoint FHD_30 = new PerformancePoint(1920, 1080, 30);
+ /** 1080p 50fps */
+ public static final PerformancePoint FHD_50 = new PerformancePoint(1920, 1080, 50);
+ /** 1080p 60fps */
+ public static final PerformancePoint FHD_60 = new PerformancePoint(1920, 1080, 60);
+ /** 1080p 100fps */
+ public static final PerformancePoint FHD_100 = new PerformancePoint(1920, 1080, 100);
+ /** 1080p 120fps */
+ public static final PerformancePoint FHD_120 = new PerformancePoint(1920, 1080, 120);
+ /** 1080p 200fps */
+ public static final PerformancePoint FHD_200 = new PerformancePoint(1920, 1080, 200);
+ /** 1080p 240fps */
+ public static final PerformancePoint FHD_240 = new PerformancePoint(1920, 1080, 240);
+
+ /** 2160p 24fps */
+ public static final PerformancePoint UHD_24 = new PerformancePoint(3840, 2160, 24);
+ /** 2160p 25fps */
+ public static final PerformancePoint UHD_25 = new PerformancePoint(3840, 2160, 25);
+ /** 2160p 30fps */
+ public static final PerformancePoint UHD_30 = new PerformancePoint(3840, 2160, 30);
+ /** 2160p 50fps */
+ public static final PerformancePoint UHD_50 = new PerformancePoint(3840, 2160, 50);
+ /** 2160p 60fps */
+ public static final PerformancePoint UHD_60 = new PerformancePoint(3840, 2160, 60);
+ /** 2160p 100fps */
+ public static final PerformancePoint UHD_100 = new PerformancePoint(3840, 2160, 100);
+ /** 2160p 120fps */
+ public static final PerformancePoint UHD_120 = new PerformancePoint(3840, 2160, 120);
+ /** 2160p 200fps */
+ public static final PerformancePoint UHD_200 = new PerformancePoint(3840, 2160, 200);
+ /** 2160p 240fps */
+ public static final PerformancePoint UHD_240 = new PerformancePoint(3840, 2160, 240);
+ }
+
+ /**
+ * Returns the supported performance points. May return {@code null} if the codec did not
+ * publish any performance point information (e.g. the vendor codecs have not been updated
+ * to the latest android release). May return an empty list if the codec published that
+ * if does not guarantee any performance points.
+ * <p>
+ * This is a performance guarantee provided by the device manufacturer for hardware codecs
+ * based on hardware capabilities of the device.
+ * <p>
+ * The returned list is sorted first by decreasing number of pixels, then by decreasing
+ * width, and finally by decreasing frame rate.
+ * Performance points assume a single active codec. For use cases where multiple
+ * codecs are active, should use that highest pixel count, and add the frame rates of
+ * each individual codec.
+ */
+ @Nullable
+ public List<PerformancePoint> getSupportedPerformancePoints() {
+ if (mPerformancePoints == null) {
+ return null;
+ }
+ return new ArrayList<PerformancePoint>(mPerformancePoints);
+ }
+
+ /**
* Returns whether a given video size ({@code width} and
* {@code height}) and {@code frameRate} combination is supported.
*/
@@ -1659,6 +1901,50 @@ public final class MediaCodecInfo {
mSmallerDimensionUpperLimit = SIZE_RANGE.getUpper();
}
+ private @Nullable Vector<PerformancePoint> getPerformancePoints(Map<String, Object> map) {
+ Vector<PerformancePoint> ret = new Vector<>();
+ final String prefix = "performance-point-";
+ Set<String> keys = map.keySet();
+ for (String key : keys) {
+ // looking for: performance-point-WIDTHxHEIGHT-range
+ if (!key.startsWith(prefix)) {
+ continue;
+ }
+ String subKey = key.substring(prefix.length());
+ if (subKey.equals("none") && ret.size() == 0) {
+ // This means that component knowingly did not publish performance points.
+ // This is different from when the component forgot to publish performance
+ // points.
+ return ret;
+ }
+ String[] temp = key.split("-");
+ if (temp.length != 4) {
+ continue;
+ }
+ String sizeStr = temp[2];
+ Size size = Utils.parseSize(sizeStr, null);
+ if (size == null || size.getWidth() * size.getHeight() <= 0) {
+ continue;
+ }
+ Range<Long> range = Utils.parseLongRange(map.get(key), null);
+ if (range == null || range.getLower() < 0 || range.getUpper() < 0) {
+ continue;
+ }
+ ret.add(new PerformancePoint(
+ size.getWidth(), size.getHeight(), range.getLower().intValue()));
+ }
+ // check if the component specified no performance point indication
+ if (ret.size() == 0) {
+ return null;
+ }
+
+ // sort reversed by area first, then by frame rate
+ ret.sort((a, b) -> (a.width * a.height != b.width * b.height ?
+ (b.width * b.height - a.width * a.height) :
+ (b.frameRate - a.frameRate)));
+ return ret;
+ }
+
private Map<Size, Range<Long>> getMeasuredFrameRates(Map<String, Object> map) {
Map<Size, Range<Long>> ret = new HashMap<Size, Range<Long>>();
final String prefix = "measured-frame-rate-";
@@ -1770,6 +2056,7 @@ public final class MediaCodecInfo {
blockRates =
Utils.parseLongRange(map.get("blocks-per-second-range"), null);
mMeasuredFrameRates = getMeasuredFrameRates(map);
+ mPerformancePoints = getPerformancePoints(map);
Pair<Range<Integer>, Range<Integer>> sizeRanges =
parseWidthHeightRanges(map.get("size-range"));
if (sizeRanges != null) {
@@ -2879,7 +3166,9 @@ public final class MediaCodecInfo {
* {@link MediaCodecInfo.CodecCapabilities#profileLevels} field.
*/
public static final class CodecProfileLevel {
- // from OMX_VIDEO_AVCPROFILETYPE
+ // These constants were originally in-line with OMX values, but this
+ // correspondence is no longer maintained.
+
public static final int AVCProfileBaseline = 0x01;
public static final int AVCProfileMain = 0x02;
public static final int AVCProfileExtended = 0x04;
@@ -2890,7 +3179,6 @@ public final class MediaCodecInfo {
public static final int AVCProfileConstrainedBaseline = 0x10000;
public static final int AVCProfileConstrainedHigh = 0x80000;
- // from OMX_VIDEO_AVCLEVELTYPE
public static final int AVCLevel1 = 0x01;
public static final int AVCLevel1b = 0x02;
public static final int AVCLevel11 = 0x04;
@@ -2908,8 +3196,10 @@ public final class MediaCodecInfo {
public static final int AVCLevel5 = 0x4000;
public static final int AVCLevel51 = 0x8000;
public static final int AVCLevel52 = 0x10000;
+ public static final int AVCLevel6 = 0x20000;
+ public static final int AVCLevel61 = 0x40000;
+ public static final int AVCLevel62 = 0x80000;
- // from OMX_VIDEO_H263PROFILETYPE
public static final int H263ProfileBaseline = 0x01;
public static final int H263ProfileH320Coding = 0x02;
public static final int H263ProfileBackwardCompatible = 0x04;
@@ -2920,7 +3210,6 @@ public final class MediaCodecInfo {
public static final int H263ProfileInterlace = 0x80;
public static final int H263ProfileHighLatency = 0x100;
- // from OMX_VIDEO_H263LEVELTYPE
public static final int H263Level10 = 0x01;
public static final int H263Level20 = 0x02;
public static final int H263Level30 = 0x04;
@@ -2930,7 +3219,6 @@ public final class MediaCodecInfo {
public static final int H263Level60 = 0x40;
public static final int H263Level70 = 0x80;
- // from OMX_VIDEO_MPEG4PROFILETYPE
public static final int MPEG4ProfileSimple = 0x01;
public static final int MPEG4ProfileSimpleScalable = 0x02;
public static final int MPEG4ProfileCore = 0x04;
@@ -2948,7 +3236,6 @@ public final class MediaCodecInfo {
public static final int MPEG4ProfileAdvancedScalable = 0x4000;
public static final int MPEG4ProfileAdvancedSimple = 0x8000;
- // from OMX_VIDEO_MPEG4LEVELTYPE
public static final int MPEG4Level0 = 0x01;
public static final int MPEG4Level0b = 0x02;
public static final int MPEG4Level1 = 0x04;
@@ -2960,7 +3247,6 @@ public final class MediaCodecInfo {
public static final int MPEG4Level5 = 0x80;
public static final int MPEG4Level6 = 0x100;
- // from OMX_VIDEO_MPEG2PROFILETYPE
public static final int MPEG2ProfileSimple = 0x00;
public static final int MPEG2ProfileMain = 0x01;
public static final int MPEG2Profile422 = 0x02;
@@ -2968,14 +3254,12 @@ public final class MediaCodecInfo {
public static final int MPEG2ProfileSpatial = 0x04;
public static final int MPEG2ProfileHigh = 0x05;
- // from OMX_VIDEO_MPEG2LEVELTYPE
public static final int MPEG2LevelLL = 0x00;
public static final int MPEG2LevelML = 0x01;
public static final int MPEG2LevelH14 = 0x02;
public static final int MPEG2LevelHL = 0x03;
public static final int MPEG2LevelHP = 0x04;
- // from OMX_AUDIO_AACPROFILETYPE
public static final int AACObjectMain = 1;
public static final int AACObjectLC = 2;
public static final int AACObjectSSR = 3;
@@ -2990,16 +3274,13 @@ public final class MediaCodecInfo {
/** xHE-AAC (includes USAC) */
public static final int AACObjectXHE = 42;
- // from OMX_VIDEO_VP8LEVELTYPE
public static final int VP8Level_Version0 = 0x01;
public static final int VP8Level_Version1 = 0x02;
public static final int VP8Level_Version2 = 0x04;
public static final int VP8Level_Version3 = 0x08;
- // from OMX_VIDEO_VP8PROFILETYPE
public static final int VP8ProfileMain = 0x01;
- // from OMX_VIDEO_VP9PROFILETYPE
public static final int VP9Profile0 = 0x01;
public static final int VP9Profile1 = 0x02;
public static final int VP9Profile2 = 0x04;
@@ -3010,7 +3291,6 @@ public final class MediaCodecInfo {
public static final int VP9Profile2HDR10Plus = 0x4000;
public static final int VP9Profile3HDR10Plus = 0x8000;
- // from OMX_VIDEO_VP9LEVELTYPE
public static final int VP9Level1 = 0x1;
public static final int VP9Level11 = 0x2;
public static final int VP9Level2 = 0x4;
@@ -3026,14 +3306,12 @@ public final class MediaCodecInfo {
public static final int VP9Level61 = 0x1000;
public static final int VP9Level62 = 0x2000;
- // from OMX_VIDEO_HEVCPROFILETYPE
public static final int HEVCProfileMain = 0x01;
public static final int HEVCProfileMain10 = 0x02;
public static final int HEVCProfileMainStill = 0x04;
public static final int HEVCProfileMain10HDR10 = 0x1000;
public static final int HEVCProfileMain10HDR10Plus = 0x2000;
- // from OMX_VIDEO_HEVCLEVELTYPE
public static final int HEVCMainTierLevel1 = 0x1;
public static final int HEVCHighTierLevel1 = 0x2;
public static final int HEVCMainTierLevel2 = 0x4;
@@ -3067,7 +3345,6 @@ public final class MediaCodecInfo {
HEVCHighTierLevel51 | HEVCHighTierLevel52 | HEVCHighTierLevel6 | HEVCHighTierLevel61 |
HEVCHighTierLevel62;
- // from OMX_VIDEO_DOLBYVISIONPROFILETYPE
public static final int DolbyVisionProfileDvavPer = 0x1;
public static final int DolbyVisionProfileDvavPen = 0x2;
public static final int DolbyVisionProfileDvheDer = 0x4;
@@ -3079,7 +3356,6 @@ public final class MediaCodecInfo {
public static final int DolbyVisionProfileDvheSt = 0x100;
public static final int DolbyVisionProfileDvavSe = 0x200;
- // from OMX_VIDEO_DOLBYVISIONLEVELTYPE
public static final int DolbyVisionLevelHd24 = 0x1;
public static final int DolbyVisionLevelHd30 = 0x2;
public static final int DolbyVisionLevelFhd24 = 0x4;
@@ -3090,17 +3366,44 @@ public final class MediaCodecInfo {
public static final int DolbyVisionLevelUhd48 = 0x80;
public static final int DolbyVisionLevelUhd60 = 0x100;
+ public static final int AV1Profile0 = 0x1;
+ public static final int AV1Profile1 = 0x2;
+ public static final int AV1Profile2 = 0x4;
+
+ public static final int AV1Level2 = 0x1;
+ public static final int AV1Level21 = 0x2;
+ public static final int AV1Level22 = 0x4;
+ public static final int AV1Level23 = 0x8;
+ public static final int AV1Level3 = 0x10;
+ public static final int AV1Level31 = 0x20;
+ public static final int AV1Level32 = 0x40;
+ public static final int AV1Level33 = 0x80;
+ public static final int AV1Level4 = 0x100;
+ public static final int AV1Level41 = 0x200;
+ public static final int AV1Level42 = 0x400;
+ public static final int AV1Level43 = 0x800;
+ public static final int AV1Level5 = 0x1000;
+ public static final int AV1Level51 = 0x2000;
+ public static final int AV1Level52 = 0x4000;
+ public static final int AV1Level53 = 0x8000;
+ public static final int AV1Level6 = 0x10000;
+ public static final int AV1Level61 = 0x20000;
+ public static final int AV1Level62 = 0x40000;
+ public static final int AV1Level63 = 0x80000;
+ public static final int AV1Level7 = 0x100000;
+ public static final int AV1Level71 = 0x200000;
+ public static final int AV1Level72 = 0x400000;
+ public static final int AV1Level73 = 0x800000;
+
/**
- * Defined in the OpenMAX IL specs, depending on the type of media
- * this can be OMX_VIDEO_AVCPROFILETYPE, OMX_VIDEO_H263PROFILETYPE,
- * OMX_VIDEO_MPEG4PROFILETYPE, OMX_VIDEO_VP8PROFILETYPE or OMX_VIDEO_VP9PROFILETYPE.
+ * The profile of the media content. Depending on the type of media this can be
+ * one of the profile values defined in this class.
*/
public int profile;
/**
- * Defined in the OpenMAX IL specs, depending on the type of media
- * this can be OMX_VIDEO_AVCLEVELTYPE, OMX_VIDEO_H263LEVELTYPE
- * OMX_VIDEO_MPEG4LEVELTYPE, OMX_VIDEO_VP8LEVELTYPE or OMX_VIDEO_VP9LEVELTYPE.
+ * The level of the media content. Depending on the type of media this can be
+ * one of the level values defined in this class.
*
* Note that VP9 decoder on platforms before {@link android.os.Build.VERSION_CODES#N} may
* not advertise a profile level support. For those VP9 decoders, please use
@@ -3157,7 +3460,7 @@ public final class MediaCodecInfo {
}
return new MediaCodecInfo(
- mName, mIsEncoder,
+ mName, mCanonicalName, mFlags,
caps.toArray(new CodecCapabilities[caps.size()]));
}
}
diff --git a/media/java/android/media/MediaCodecList.java b/media/java/android/media/MediaCodecList.java
index 2e4786579d97..a46095484fe7 100644
--- a/media/java/android/media/MediaCodecList.java
+++ b/media/java/android/media/MediaCodecList.java
@@ -111,12 +111,14 @@ final public class MediaCodecList {
caps[typeIx++] = getCodecCapabilities(index, type);
}
return new MediaCodecInfo(
- getCodecName(index), isEncoder(index), caps);
+ getCodecName(index), getCanonicalName(index), getAttributes(index), caps);
}
/* package private */ static native final String getCodecName(int index);
- /* package private */ static native final boolean isEncoder(int index);
+ /* package private */ static native final String getCanonicalName(int index);
+
+ /* package private */ static native final int getAttributes(int index);
/* package private */ static native final String[] getSupportedTypes(int index);
diff --git a/media/java/android/media/MediaConstants.java b/media/java/android/media/MediaConstants.java
index 5a5747ae4bab..65b6f55a068a 100644
--- a/media/java/android/media/MediaConstants.java
+++ b/media/java/android/media/MediaConstants.java
@@ -26,6 +26,7 @@ class MediaConstants {
// Bundle key for Parcelable
static final String KEY_SESSION2LINK = "android.media.key.SESSION2LINK";
static final String KEY_ALLOWED_COMMANDS = "android.media.key.ALLOWED_COMMANDS";
+ static final String KEY_PLAYBACK_ACTIVE = "android.media.key.PLAYBACK_ACTIVE";
private MediaConstants() {
}
diff --git a/media/java/android/media/MediaController2.java b/media/java/android/media/MediaController2.java
index 165ea412333e..7c5335b71627 100644
--- a/media/java/android/media/MediaController2.java
+++ b/media/java/android/media/MediaController2.java
@@ -19,6 +19,7 @@ package android.media;
import static android.media.MediaConstants.KEY_ALLOWED_COMMANDS;
import static android.media.MediaConstants.KEY_PACKAGE_NAME;
import static android.media.MediaConstants.KEY_PID;
+import static android.media.MediaConstants.KEY_PLAYBACK_ACTIVE;
import static android.media.MediaConstants.KEY_SESSION2LINK;
import static android.media.Session2Command.RESULT_ERROR_UNKNOWN_ERROR;
import static android.media.Session2Command.RESULT_INFO_SKIPPED;
@@ -30,7 +31,6 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
-import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
@@ -82,6 +82,8 @@ public class MediaController2 implements AutoCloseable {
private ArrayMap<ResultReceiver, Integer> mPendingCommands;
//@GuardedBy("mLock")
private ArraySet<Integer> mRequestedCommandSeqNumbers;
+ //@GuardedBy("mLock")
+ private boolean mPlaybackActive;
/**
* Create a {@link MediaController2} from the {@link Session2Token}.
@@ -160,6 +162,18 @@ public class MediaController2 implements AutoCloseable {
}
/**
+ * Returns whether the session's playback is active.
+ *
+ * @return {@code true} if playback active. {@code false} otherwise.
+ * @see ControllerCallback#onPlaybackActiveChanged(MediaController2, boolean)
+ */
+ public boolean isPlaybackActive() {
+ synchronized (mLock) {
+ return mPlaybackActive;
+ }
+ }
+
+ /**
* Sends a session command to the session
* <p>
* @param command the session command
@@ -221,89 +235,82 @@ public class MediaController2 implements AutoCloseable {
// Called by Controller2Link.onConnected
void onConnected(int seq, Bundle connectionResult) {
- final long token = Binder.clearCallingIdentity();
- try {
- Session2Link sessionBinder = connectionResult.getParcelable(KEY_SESSION2LINK);
- Session2CommandGroup allowedCommands =
- connectionResult.getParcelable(KEY_ALLOWED_COMMANDS);
- if (DEBUG) {
- Log.d(TAG, "notifyConnected sessionBinder=" + sessionBinder
- + ", allowedCommands=" + allowedCommands);
- }
- if (sessionBinder == null || allowedCommands == null) {
- // Connection rejected.
- close();
- return;
- }
- synchronized (mLock) {
- mSessionBinder = sessionBinder;
- mAllowedCommands = allowedCommands;
- // Implementation for the local binder is no-op,
- // so can be used without worrying about deadlock.
- sessionBinder.linkToDeath(mDeathRecipient, 0);
- mConnectedToken = new Session2Token(mSessionToken.getUid(), TYPE_SESSION,
- mSessionToken.getPackageName(), sessionBinder);
- }
- mCallbackExecutor.execute(() -> {
- mCallback.onConnected(MediaController2.this, allowedCommands);
- });
- } finally {
- Binder.restoreCallingIdentity(token);
+ Session2Link sessionBinder = connectionResult.getParcelable(KEY_SESSION2LINK);
+ Session2CommandGroup allowedCommands =
+ connectionResult.getParcelable(KEY_ALLOWED_COMMANDS);
+ boolean playbackActive = connectionResult.getBoolean(KEY_PLAYBACK_ACTIVE);
+ if (DEBUG) {
+ Log.d(TAG, "notifyConnected sessionBinder=" + sessionBinder
+ + ", allowedCommands=" + allowedCommands);
+ }
+ if (sessionBinder == null || allowedCommands == null) {
+ // Connection rejected.
+ close();
+ return;
+ }
+ synchronized (mLock) {
+ mSessionBinder = sessionBinder;
+ mAllowedCommands = allowedCommands;
+ mPlaybackActive = playbackActive;
+
+ // Implementation for the local binder is no-op,
+ // so can be used without worrying about deadlock.
+ sessionBinder.linkToDeath(mDeathRecipient, 0);
+ mConnectedToken = new Session2Token(mSessionToken.getUid(), TYPE_SESSION,
+ mSessionToken.getPackageName(), sessionBinder);
}
+ mCallbackExecutor.execute(() -> {
+ mCallback.onConnected(MediaController2.this, allowedCommands);
+ });
}
// Called by Controller2Link.onDisconnected
void onDisconnected(int seq) {
- final long token = Binder.clearCallingIdentity();
- try {
- // close() will call mCallback.onDisconnected
- close();
- } finally {
- Binder.restoreCallingIdentity(token);
+ // close() will call mCallback.onDisconnected
+ close();
+ }
+
+ // Called by Controller2Link.onPlaybackActiveChanged
+ void onPlaybackActiveChanged(int seq, boolean playbackActive) {
+ synchronized (mLock) {
+ mPlaybackActive = playbackActive;
}
+ mCallbackExecutor.execute(() -> {
+ mCallback.onPlaybackActiveChanged(MediaController2.this, playbackActive);
+ });
}
// Called by Controller2Link.onSessionCommand
void onSessionCommand(int seq, Session2Command command, Bundle args,
@Nullable ResultReceiver resultReceiver) {
- final long token = Binder.clearCallingIdentity();
- try {
+ synchronized (mLock) {
+ mRequestedCommandSeqNumbers.add(seq);
+ }
+ mCallbackExecutor.execute(() -> {
+ boolean isCanceled;
synchronized (mLock) {
- mRequestedCommandSeqNumbers.add(seq);
+ isCanceled = !mRequestedCommandSeqNumbers.remove(seq);
}
- mCallbackExecutor.execute(() -> {
- boolean isCanceled;
- synchronized (mLock) {
- isCanceled = !mRequestedCommandSeqNumbers.remove(seq);
- }
- if (isCanceled) {
- resultReceiver.send(RESULT_INFO_SKIPPED, null);
- return;
- }
- Session2Command.Result result = mCallback.onSessionCommand(
- MediaController2.this, command, args);
- if (resultReceiver != null) {
- if (result == null) {
- throw new RuntimeException("onSessionCommand shouldn't return null");
- } else {
- resultReceiver.send(result.getResultCode(), result.getResultData());
- }
+ if (isCanceled) {
+ resultReceiver.send(RESULT_INFO_SKIPPED, null);
+ return;
+ }
+ Session2Command.Result result = mCallback.onSessionCommand(
+ MediaController2.this, command, args);
+ if (resultReceiver != null) {
+ if (result == null) {
+ throw new RuntimeException("onSessionCommand shouldn't return null");
+ } else {
+ resultReceiver.send(result.getResultCode(), result.getResultData());
}
- });
- } finally {
- Binder.restoreCallingIdentity(token);
- }
+ }
+ });
}
// Called by Controller2Link.onSessionCommand
void onCancelCommand(int seq) {
- final long token = Binder.clearCallingIdentity();
- try {
- synchronized (mLock) {
- mRequestedCommandSeqNumbers.remove(seq);
- }
- } finally {
- Binder.restoreCallingIdentity(token);
+ synchronized (mLock) {
+ mRequestedCommandSeqNumbers.remove(seq);
}
}
@@ -393,6 +400,17 @@ public class MediaController2 implements AutoCloseable {
public void onDisconnected(@NonNull MediaController2 controller) {}
/**
+ * Called when the playback of the session's playback activeness is changed.
+ *
+ * @param controller the controller for this event
+ * @param playbackActive {@code true} if the session's playback is active.
+ * {@code false} otherwise.
+ * @see MediaController2#isPlaybackActive()
+ */
+ public void onPlaybackActiveChanged(@NonNull MediaController2 controller,
+ boolean playbackActive) {}
+
+ /**
* Called when the connected session sent a session command.
*
* @param controller the controller for this event
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index 594a22457cc3..c82b5f6f12a1 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -124,6 +124,7 @@ import java.util.stream.Collectors;
public final class MediaFormat {
public static final String MIMETYPE_VIDEO_VP8 = "video/x-vnd.on2.vp8";
public static final String MIMETYPE_VIDEO_VP9 = "video/x-vnd.on2.vp9";
+ public static final String MIMETYPE_VIDEO_AV1 = "video/av01";
public static final String MIMETYPE_VIDEO_AVC = "video/avc";
public static final String MIMETYPE_VIDEO_HEVC = "video/hevc";
public static final String MIMETYPE_VIDEO_MPEG4 = "video/mp4v-es";
diff --git a/media/java/android/media/MediaSession2.java b/media/java/android/media/MediaSession2.java
index dceef34596b7..3adac7295fff 100644
--- a/media/java/android/media/MediaSession2.java
+++ b/media/java/android/media/MediaSession2.java
@@ -19,6 +19,7 @@ package android.media;
import static android.media.MediaConstants.KEY_ALLOWED_COMMANDS;
import static android.media.MediaConstants.KEY_PACKAGE_NAME;
import static android.media.MediaConstants.KEY_PID;
+import static android.media.MediaConstants.KEY_PLAYBACK_ACTIVE;
import static android.media.MediaConstants.KEY_SESSION2LINK;
import static android.media.Session2Command.RESULT_ERROR_UNKNOWN_ERROR;
import static android.media.Session2Command.RESULT_INFO_SKIPPED;
@@ -87,6 +88,8 @@ public class MediaSession2 implements AutoCloseable {
//@GuardedBy("mLock")
private boolean mClosed;
+ //@GuardedBy("mLock")
+ private boolean mPlaybackActive;
MediaSession2(@NonNull Context context, @NonNull String id, PendingIntent sessionActivity,
@NonNull Executor callbackExecutor, @NonNull SessionCallback callback) {
@@ -215,6 +218,35 @@ public class MediaSession2 implements AutoCloseable {
controller.cancelSessionCommand(token);
}
+ /**
+ * Sets whether the playback is active (i.e. playing something)
+ *
+ * @param playbackActive {@code true} if the playback active, {@code false} otherwise.
+ **/
+ public void setPlaybackActive(boolean playbackActive) {
+ synchronized (mLock) {
+ if (mPlaybackActive == playbackActive) {
+ return;
+ }
+ mPlaybackActive = playbackActive;
+ }
+ List<ControllerInfo> controllerInfos = getConnectedControllers();
+ for (ControllerInfo controller : controllerInfos) {
+ controller.notifyPlaybackActiveChanged(playbackActive);
+ }
+ }
+
+ /**
+ * Returns whehther the playback is active (i.e. playing something)
+ *
+ * @return {@code true} if the playback active, {@code false} otherwise.
+ */
+ public boolean isPlaybackActive() {
+ synchronized (mLock) {
+ return mPlaybackActive;
+ }
+ }
+
boolean isClosed() {
synchronized (mLock) {
return mClosed;
@@ -239,7 +271,7 @@ public class MediaSession2 implements AutoCloseable {
final ControllerInfo controllerInfo = new ControllerInfo(remoteUserInfo,
mSessionManager.isTrustedForMediaControl(remoteUserInfo), controller);
mCallbackExecutor.execute(() -> {
- boolean accept = false;
+ boolean connected = false;
try {
if (isClosed()) {
return;
@@ -249,8 +281,7 @@ public class MediaSession2 implements AutoCloseable {
// Don't reject connection for the request from trusted app.
// Otherwise server will fail to retrieve session's information to dispatch
// media keys to.
- accept = controllerInfo.mAllowedCommands != null || controllerInfo.isTrusted();
- if (!accept) {
+ if (controllerInfo.mAllowedCommands == null && !controllerInfo.isTrusted()) {
return;
}
if (controllerInfo.mAllowedCommands == null) {
@@ -276,6 +307,7 @@ public class MediaSession2 implements AutoCloseable {
connectionResult.putParcelable(KEY_SESSION2LINK, mSessionStub);
connectionResult.putParcelable(KEY_ALLOWED_COMMANDS,
controllerInfo.mAllowedCommands);
+ connectionResult.putBoolean(KEY_PLAYBACK_ACTIVE, isPlaybackActive());
// Double check if session is still there, because close() can be called in
// another thread.
@@ -283,13 +315,18 @@ public class MediaSession2 implements AutoCloseable {
return;
}
controllerInfo.notifyConnected(connectionResult);
+ connected = true;
} finally {
- if (!accept) {
+ if (!connected) {
if (DEBUG) {
- Log.d(TAG, "Rejecting connection, controllerInfo=" + controllerInfo);
+ Log.d(TAG, "Rejecting connection or notifying that session is closed"
+ + ", controllerInfo=" + controllerInfo);
+ }
+ synchronized (mLock) {
+ mConnectedControllers.remove(controller);
}
+ controllerInfo.notifyDisconnected();
}
- controllerInfo.notifyDisconnected();
}
});
}
@@ -587,6 +624,16 @@ public class MediaSession2 implements AutoCloseable {
}
}
+ void notifyPlaybackActiveChanged(boolean playbackActive) {
+ if (mControllerBinder == null) return;
+
+ try {
+ mControllerBinder.notifyPlaybackActiveChanged(getNextSeqNumber(), playbackActive);
+ } catch (RuntimeException e) {
+ // Controller may be died prematurely.
+ }
+ }
+
void sendSessionCommand(Session2Command command, Bundle args,
ResultReceiver resultReceiver) {
if (mControllerBinder == null) return;
diff --git a/media/java/android/media/MicrophoneDirection.java b/media/java/android/media/MicrophoneDirection.java
new file mode 100644
index 000000000000..99201c0279bf
--- /dev/null
+++ b/media/java/android/media/MicrophoneDirection.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+/**
+ * @hide
+ */
+public interface MicrophoneDirection {
+ /**
+ * @hide
+ */
+ int MIC_DIRECTION_UNSPECIFIED = 0;
+
+ /**
+ * @hide
+ */
+ int MIC_DIRECTION_FRONT = 1;
+
+ /**
+ * @hide
+ */
+ int MIC_DIRECTION_BACK = 2;
+
+ /**
+ * @hide
+ */
+ int MIC_DIRECTION_EXTERNAL = 3;
+
+ /**
+ * Specifies the logical microphone (for processing).
+ *
+ * @param direction Direction constant (MicrophoneDirection.MIC_DIRECTION_*)
+ * @return retval OK if the call is successful, an error code otherwise.
+ * @hide
+ */
+ int setMicrophoneDirection(int direction);
+
+ /**
+ * Specifies the zoom factor (i.e. the field dimension) for the selected microphone
+ * (for processing). The selected microphone is determined by the use-case for the stream.
+ *
+ * @param zoom the desired field dimension of microphone capture. Range is from -1 (wide angle),
+ * though 0 (no zoom) to 1 (maximum zoom).
+ * @return retval OK if the call is successful, an error code otherwise.
+ * @hide
+ */
+ int setMicrophoneFieldDimension(float zoom);
+}
diff --git a/media/java/android/media/session/MediaSessionProviderService.java b/media/java/android/media/session/MediaSessionProviderService.java
new file mode 100644
index 000000000000..9a346ff4a12e
--- /dev/null
+++ b/media/java/android/media/session/MediaSessionProviderService.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.session;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+
+/**
+ * Abstract class for mainline module services.
+ *
+ * @hide // TODO: Make it as a @SystemApi
+ */
+public abstract class MediaSessionProviderService extends Service {
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ // TODO: Return IMediaSessionProviderService.Stub()
+ return null;
+ }
+}
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index 7b07bea3cf1a..406f9dd94bb4 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -648,7 +648,6 @@ static jobject getCodecCapabilitiesObject(
capabilities->getSupportedColorFormats(&colorFormats);
capabilities->getSupportedProfileLevels(&profileLevels);
- uint32_t flags = capabilities->getFlags();
sp<AMessage> details = capabilities->getDetails();
jobject defaultFormatObj = NULL;
@@ -687,7 +686,7 @@ static jobject getCodecCapabilitiesObject(
return env->NewObject(
gCodecInfo.capsClazz, gCodecInfo.capsCtorId,
- profileLevelArray.get(), colorFormatsArray.get(), isEncoder, flags,
+ profileLevelArray.get(), colorFormatsArray.get(), isEncoder,
defaultFormatRef.get(), detailsRef.get());
}
@@ -700,23 +699,28 @@ status_t JMediaCodec::getCodecInfo(JNIEnv *env, jobject *codecInfoObject) const
return err;
}
+ // TODO: get alias
ScopedLocalRef<jstring> nameObject(env,
env->NewStringUTF(codecInfo->getCodecName()));
+ ScopedLocalRef<jstring> canonicalNameObject(env,
+ env->NewStringUTF(codecInfo->getCodecName()));
+
+ MediaCodecInfo::Attributes attributes = codecInfo->getAttributes();
bool isEncoder = codecInfo->isEncoder();
- Vector<AString> mimes;
- codecInfo->getSupportedMimes(&mimes);
+ Vector<AString> mediaTypes;
+ codecInfo->getSupportedMediaTypes(&mediaTypes);
ScopedLocalRef<jobjectArray> capsArrayObj(env,
- env->NewObjectArray(mimes.size(), gCodecInfo.capsClazz, NULL));
+ env->NewObjectArray(mediaTypes.size(), gCodecInfo.capsClazz, NULL));
- for (size_t i = 0; i < mimes.size(); i++) {
+ for (size_t i = 0; i < mediaTypes.size(); i++) {
const sp<MediaCodecInfo::Capabilities> caps =
- codecInfo->getCapabilitiesFor(mimes[i].c_str());
+ codecInfo->getCapabilitiesFor(mediaTypes[i].c_str());
ScopedLocalRef<jobject> capsObj(env, getCodecCapabilitiesObject(
- env, mimes[i].c_str(), isEncoder, caps));
+ env, mediaTypes[i].c_str(), isEncoder, caps));
env->SetObjectArrayElement(capsArrayObj.get(), i, capsObj.get());
}
@@ -726,10 +730,10 @@ status_t JMediaCodec::getCodecInfo(JNIEnv *env, jobject *codecInfoObject) const
CHECK(codecInfoClazz.get() != NULL);
jmethodID codecInfoCtorID = env->GetMethodID(codecInfoClazz.get(), "<init>",
- "(Ljava/lang/String;Z[Landroid/media/MediaCodecInfo$CodecCapabilities;)V");
+ "(Ljava/lang/String;Ljava/lang/String;I[Landroid/media/MediaCodecInfo$CodecCapabilities;)V");
*codecInfoObject = env->NewObject(codecInfoClazz.get(), codecInfoCtorID,
- nameObject.get(), isEncoder, capsArrayObj.get());
+ nameObject.get(), canonicalNameObject.get(), attributes, capsArrayObj.get());
return OK;
}
@@ -2079,7 +2083,7 @@ static void android_media_MediaCodec_native_init(JNIEnv *env) {
gCodecInfo.capsClazz = (jclass)env->NewGlobalRef(clazz.get());
method = env->GetMethodID(clazz.get(), "<init>",
- "([Landroid/media/MediaCodecInfo$CodecProfileLevel;[IZI"
+ "([Landroid/media/MediaCodecInfo$CodecProfileLevel;[IZ"
"Ljava/util/Map;Ljava/util/Map;)V");
CHECK(method != NULL);
gCodecInfo.capsCtorId = method;
@@ -2217,7 +2221,7 @@ static const JNINativeMethod gMethods[] = {
{ "getImage", "(ZI)Landroid/media/Image;",
(void *)android_media_MediaCodec_getImage },
- { "getName", "()Ljava/lang/String;",
+ { "getCanonicalName", "()Ljava/lang/String;",
(void *)android_media_MediaCodec_getName },
{ "getOwnCodecInfo", "()Landroid/media/MediaCodecInfo;",
diff --git a/media/jni/android_media_MediaCodecList.cpp b/media/jni/android_media_MediaCodecList.cpp
index 8de11caf7d7a..cf1494296756 100644
--- a/media/jni/android_media_MediaCodecList.cpp
+++ b/media/jni/android_media_MediaCodecList.cpp
@@ -41,6 +41,21 @@ static sp<IMediaCodecList> getCodecList(JNIEnv *env) {
return mcl;
}
+static sp<MediaCodecInfo> getCodecInfo(JNIEnv *env, jint index) {
+ sp<IMediaCodecList> mcl = getCodecList(env);
+ if (mcl == NULL) {
+ // Runtime exception already pending.
+ return NULL;
+ }
+
+ sp<MediaCodecInfo> info = mcl->getCodecInfo(index);
+ if (info == NULL) {
+ jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
+ }
+
+ return info;
+}
+
static jint android_media_MediaCodecList_getCodecCount(
JNIEnv *env, jobject /* thiz */) {
sp<IMediaCodecList> mcl = getCodecList(env);
@@ -53,15 +68,22 @@ static jint android_media_MediaCodecList_getCodecCount(
static jstring android_media_MediaCodecList_getCodecName(
JNIEnv *env, jobject /* thiz */, jint index) {
- sp<IMediaCodecList> mcl = getCodecList(env);
- if (mcl == NULL) {
+ sp<MediaCodecInfo> info = getCodecInfo(env, index);
+ if (info == NULL) {
// Runtime exception already pending.
return NULL;
}
- const sp<MediaCodecInfo> &info = mcl->getCodecInfo(index);
+ // TODO: support aliases
+ const char *name = info->getCodecName();
+ return env->NewStringUTF(name);
+}
+
+static jstring android_media_MediaCodecList_getCanonicalName(
+ JNIEnv *env, jobject /* thiz */, jint index) {
+ sp<MediaCodecInfo> info = getCodecInfo(env, index);
if (info == NULL) {
- jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
+ // Runtime exception already pending.
return NULL;
}
@@ -94,39 +116,27 @@ static jint android_media_MediaCodecList_findCodecByName(
return ret;
}
-static jboolean android_media_MediaCodecList_isEncoder(
+static jboolean android_media_MediaCodecList_getAttributes(
JNIEnv *env, jobject /* thiz */, jint index) {
- sp<IMediaCodecList> mcl = getCodecList(env);
- if (mcl == NULL) {
- // Runtime exception already pending.
- return false;
- }
-
- const sp<MediaCodecInfo> &info = mcl->getCodecInfo(index);
+ sp<MediaCodecInfo> info = getCodecInfo(env, index);
if (info == NULL) {
- jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
- return false;
+ // Runtime exception already pending.
+ return 0;
}
- return info->isEncoder();
+ return info->getAttributes();
}
static jarray android_media_MediaCodecList_getSupportedTypes(
JNIEnv *env, jobject /* thiz */, jint index) {
- sp<IMediaCodecList> mcl = getCodecList(env);
- if (mcl == NULL) {
- // Runtime exception already pending.
- return NULL;
- }
-
- const sp<MediaCodecInfo> &info = mcl->getCodecInfo(index);
+ sp<MediaCodecInfo> info = getCodecInfo(env, index);
if (info == NULL) {
- jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
+ // Runtime exception already pending.
return NULL;
}
Vector<AString> types;
- info->getSupportedMimes(&types);
+ info->getSupportedMediaTypes(&types);
jclass clazz = env->FindClass("java/lang/String");
CHECK(clazz != NULL);
@@ -150,17 +160,12 @@ static jobject android_media_MediaCodecList_getCodecCapabilities(
return NULL;
}
- sp<IMediaCodecList> mcl = getCodecList(env);
- if (mcl == NULL) {
+ sp<MediaCodecInfo> info = getCodecInfo(env, index);
+ if (info == NULL) {
// Runtime exception already pending.
return NULL;
}
- const sp<MediaCodecInfo> &info = mcl->getCodecInfo(index);
- if (info == NULL) {
- jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
- return NULL;
- }
const char *typeStr = env->GetStringUTFChars(type, NULL);
if (typeStr == NULL) {
@@ -186,7 +191,6 @@ static jobject android_media_MediaCodecList_getCodecCapabilities(
capabilities->getSupportedColorFormats(&colorFormats);
capabilities->getSupportedProfileLevels(&profileLevels);
- uint32_t flags = capabilities->getFlags();
sp<AMessage> details = capabilities->getDetails();
bool isEncoder = info->isEncoder();
@@ -240,11 +244,11 @@ static jobject android_media_MediaCodecList_getCodecCapabilities(
}
jmethodID capsConstructID = env->GetMethodID(capsClazz, "<init>",
- "([Landroid/media/MediaCodecInfo$CodecProfileLevel;[IZI"
+ "([Landroid/media/MediaCodecInfo$CodecProfileLevel;[IZ"
"Ljava/util/Map;Ljava/util/Map;)V");
jobject caps = env->NewObject(capsClazz, capsConstructID,
- profileLevelArray, colorFormatsArray, isEncoder, flags,
+ profileLevelArray, colorFormatsArray, isEncoder,
defaultFormatObj, infoObj);
env->DeleteLocalRef(profileLevelArray);
@@ -288,9 +292,15 @@ static void android_media_MediaCodecList_native_init(JNIEnv* /* env */) {
static const JNINativeMethod gMethods[] = {
{ "native_getCodecCount", "()I", (void *)android_media_MediaCodecList_getCodecCount },
+
+ { "getCanonicalName", "(I)Ljava/lang/String;",
+ (void *)android_media_MediaCodecList_getCanonicalName },
+
{ "getCodecName", "(I)Ljava/lang/String;",
(void *)android_media_MediaCodecList_getCodecName },
- { "isEncoder", "(I)Z", (void *)android_media_MediaCodecList_isEncoder },
+
+ { "getAttributes", "(I)I", (void *)android_media_MediaCodecList_getAttributes },
+
{ "getSupportedTypes", "(I)[Ljava/lang/String;",
(void *)android_media_MediaCodecList_getSupportedTypes },
diff --git a/media/packages/MediaCore/Android.bp b/media/packages/MediaCore/Android.bp
new file mode 100644
index 000000000000..c7fd58bf933a
--- /dev/null
+++ b/media/packages/MediaCore/Android.bp
@@ -0,0 +1,21 @@
+android_app {
+ name: "MediaCore",
+
+ srcs: [
+ "src/**/*.java",
+ ],
+
+ static_libs: [
+ // TODO: Temporarily statically linked. Should go into "libs"
+ "media1",
+ ],
+
+ // System app
+ platform_apis: true,
+
+ // Privileged app
+ privileged: true,
+
+ // Make sure that the implementation only relies on SDK or system APIs.
+ sdk_version: "system_current",
+}
diff --git a/media/packages/MediaCore/AndroidManifest.xml b/media/packages/MediaCore/AndroidManifest.xml
new file mode 100644
index 000000000000..4e2b274511e8
--- /dev/null
+++ b/media/packages/MediaCore/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/AndroidManifest.xml
+**
+** 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.
+*/
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.media" coreApp="true" android:sharedUserId="android.uid.system"
+ android:sharedUserLabel="@string/android_system_label">
+ <application android:process="system"
+ android:persistent="true"
+ android:directBootAware="true">
+ <service android:name="AmlMediaSessionProviderService" android:singleUser="true">
+ <intent-filter>
+ <action android:name="android.media.session.MediaSessionProviderService"/>
+ </intent-filter>
+ </service>
+ </application>
+</manifest>
diff --git a/media/packages/MediaCore/res/values/strings.xml b/media/packages/MediaCore/res/values/strings.xml
new file mode 100644
index 000000000000..59fd635b905f
--- /dev/null
+++ b/media/packages/MediaCore/res/values/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resources>
+ <!-- Label for the Android system components when they are shown to the user. -->
+ <string name="android_system_label" translatable="false">Android System</string>
+</resources>
+
diff --git a/media/packages/MediaCore/src/com/android/media/AmlMediaSessionProviderService.java b/media/packages/MediaCore/src/com/android/media/AmlMediaSessionProviderService.java
new file mode 100644
index 000000000000..43b95ab7ebdb
--- /dev/null
+++ b/media/packages/MediaCore/src/com/android/media/AmlMediaSessionProviderService.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.media;
+
+import android.content.Context;
+import android.media.session.MediaSessionProviderService;
+import android.os.PowerManager;
+import android.util.Log;
+
+/**
+ * System implementation of MediaSessionProviderService
+ */
+public class AmlMediaSessionProviderService extends MediaSessionProviderService {
+ private static final String TAG = "AmlMediaSessionProviderS";
+ static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+ private Context mContext;
+
+ public AmlMediaSessionProviderService(Context context) {
+ mContext = context;
+ PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+ }
+}
diff --git a/native/android/sensor.cpp b/native/android/sensor.cpp
index 8e5821024cee..c3b2e2526ea8 100644
--- a/native/android/sensor.cpp
+++ b/native/android/sensor.cpp
@@ -342,3 +342,8 @@ int ASensor_getHighestDirectReportRateLevel(ASensor const *sensor) {
RETURN_IF_SENSOR_IS_NULL(ASENSOR_DIRECT_RATE_STOP);
return static_cast<Sensor const *>(sensor)->getHighestDirectReportRateLevel();
}
+
+int ASensor_getHandle(ASensor const* sensor) {
+ RETURN_IF_SENSOR_IS_NULL(ASENSOR_INVALID);
+ return static_cast<Sensor const*>(sensor)->getHandle();
+}
diff --git a/packages/SystemUI/res-keyguard/layout/bubble_clock.xml b/packages/SystemUI/res-keyguard/layout/bubble_clock.xml
index 0d72657bb2df..6f7f39810608 100644
--- a/packages/SystemUI/res-keyguard/layout/bubble_clock.xml
+++ b/packages/SystemUI/res-keyguard/layout/bubble_clock.xml
@@ -19,15 +19,9 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
>
- <TextClock
+ <include
android:id="@+id/digital_clock"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:letterSpacing="0.03"
- android:singleLine="true"
- style="@style/widget_big"
- android:format12Hour="@string/keyguard_widget_12_hours_format"
- android:format24Hour="@string/keyguard_widget_24_hours_format"
+ layout="@layout/text_clock"
/>
<com.android.keyguard.clock.ImageClock
android:id="@+id/analog_clock"
diff --git a/packages/SystemUI/res-keyguard/layout/digital_clock.xml b/packages/SystemUI/res-keyguard/layout/digital_clock.xml
index cf4a573834dd..e88e2c94e74f 100644
--- a/packages/SystemUI/res-keyguard/layout/digital_clock.xml
+++ b/packages/SystemUI/res-keyguard/layout/digital_clock.xml
@@ -20,16 +20,9 @@
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_alignParentTop="true">
- <TextClock
+ <include
android:id="@+id/lock_screen_clock"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal"
- android:letterSpacing="0.03"
- android:singleLine="true"
- style="@style/widget_big"
- android:format12Hour="@string/keyguard_widget_12_hours_format"
- android:format24Hour="@string/keyguard_widget_24_hours_format" />
+ layout="@layout/text_clock"
/>
</FrameLayout>
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
index d52866fbd444..463367b2c600 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
@@ -30,17 +30,9 @@
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_alignParentTop="true">
- <TextClock
+ <include
android:id="@+id/default_clock_view"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal"
- android:letterSpacing="0.03"
- android:textColor="?attr/wallpaperTextColor"
- android:singleLine="true"
- style="@style/widget_big"
- android:format12Hour="@string/keyguard_widget_12_hours_format"
- android:format24Hour="@string/keyguard_widget_24_hours_format" />
+ layout="@layout/text_clock" />
</FrameLayout>
<include layout="@layout/keyguard_status_area"
android:id="@+id/keyguard_status_area"
diff --git a/packages/SystemUI/res-keyguard/layout/stretchanalog_clock.xml b/packages/SystemUI/res-keyguard/layout/stretchanalog_clock.xml
index 9033fce881c4..64b676f55fd6 100644
--- a/packages/SystemUI/res-keyguard/layout/stretchanalog_clock.xml
+++ b/packages/SystemUI/res-keyguard/layout/stretchanalog_clock.xml
@@ -19,15 +19,9 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
>
- <TextClock
+ <include
android:id="@+id/digital_clock"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:letterSpacing="0.03"
- android:singleLine="true"
- style="@style/widget_big"
- android:format12Hour="@string/keyguard_widget_12_hours_format"
- android:format24Hour="@string/keyguard_widget_24_hours_format"
+ layout="@layout/text_clock"
/>
<com.android.keyguard.clock.StretchAnalogClock
android:id="@+id/analog_clock"
diff --git a/packages/SystemUI/res-keyguard/layout/text_clock.xml b/packages/SystemUI/res-keyguard/layout/text_clock.xml
new file mode 100644
index 000000000000..b61ad9c4fc11
--- /dev/null
+++ b/packages/SystemUI/res-keyguard/layout/text_clock.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<TextClock
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:letterSpacing="0.03"
+ android:textColor="?attr/wallpaperTextColor"
+ android:singleLine="true"
+ style="@style/widget_big"
+ android:format12Hour="@string/keyguard_widget_12_hours_format"
+ android:format24Hour="@string/keyguard_widget_24_hours_format"
+ android:elegantTextHeight="false"
+/>
diff --git a/packages/SystemUI/res-keyguard/layout/type_clock.xml b/packages/SystemUI/res-keyguard/layout/type_clock.xml
new file mode 100644
index 000000000000..21c64e9c7dbe
--- /dev/null
+++ b/packages/SystemUI/res-keyguard/layout/type_clock.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<com.android.keyguard.clock.ClockLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ >
+ <com.android.keyguard.clock.TypographicClock
+ android:id="@+id/type_clock"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ >
+ <TextView
+ android:id="@+id/header"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="50dp"
+ style="@style/widget_big"
+ android:textColor="@color/typeClockAccentColor"
+ android:text="@string/type_clock_header"
+ android:textSize="40dp"
+ />
+ <TextView
+ android:id="@+id/hour"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="50dp"
+ style="@style/widget_big"
+ android:textSize="40dp"
+ />
+ <TextView
+ android:id="@+id/minute"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="50dp"
+ style="@style/widget_big"
+ android:textSize="40dp"
+ />
+ </com.android.keyguard.clock.TypographicClock>
+</com.android.keyguard.clock.ClockLayout>
diff --git a/packages/SystemUI/res-keyguard/values/colors.xml b/packages/SystemUI/res-keyguard/values/colors.xml
index 7a849ebd481d..74ee7ffad3f6 100644
--- a/packages/SystemUI/res-keyguard/values/colors.xml
+++ b/packages/SystemUI/res-keyguard/values/colors.xml
@@ -19,4 +19,6 @@
<color name="bubbleHourHandColor">#C97343</color>
<!-- Default color for minute hand of Bubble clock. -->
<color name="bubbleMinuteHandColor">#F5C983</color>
+ <!-- Accent color for Typographic clock. -->
+ <color name="typeClockAccentColor">#F5C983</color>
</resources>
diff --git a/packages/SystemUI/res-keyguard/values/strings.xml b/packages/SystemUI/res-keyguard/values/strings.xml
index 1d5aa6d76991..7432f9cde639 100644
--- a/packages/SystemUI/res-keyguard/values/strings.xml
+++ b/packages/SystemUI/res-keyguard/values/strings.xml
@@ -402,4 +402,87 @@ number">%d</xliff:g> remaining attempt before SIM becomes permanently unusable.
number">%d</xliff:g> remaining attempts before SIM becomes permanently unusable. Contact carrier for details.</item>
</plurals>
+ <!-- Header for typographic clock face. [CHAR LIMIT=8] -->
+ <string name="type_clock_header">It\u2019s</string>
+
+ <!-- Hour displayed in words on the typographic clock face. [CHAR LIMIT=8] -->
+ <string-array name="type_clock_hours">
+ <item>Twelve</item>
+ <item>One</item>
+ <item>Two</item>
+ <item>Three</item>
+ <item>Four</item>
+ <item>Five</item>
+ <item>Six</item>
+ <item>Seven</item>
+ <item>Eight</item>
+ <item>Nine</item>
+ <item>Ten</item>
+ <item>Eleven</item>
+ </string-array>
+
+ <!-- Minutes displayed in words on the typographic clock face. [CHAR LIMIT=16] -->
+ <string-array name="type_clock_minutes">
+ <item>O\u2019Clock</item>
+ <item>O\u2019One</item>
+ <item>O\u2019Two</item>
+ <item>O\u2019Three</item>
+ <item>O\u2019Four</item>
+ <item>O\u2019Five</item>
+ <item>O\u2019Six</item>
+ <item>O\u2019Seven</item>
+ <item>O\u2019Eight</item>
+ <item>O\u2019Nine</item>
+ <item>Ten</item>
+ <item>Eleven</item>
+ <item>Twelve</item>
+ <item>Thirteen</item>
+ <item>Fourteen</item>
+ <item>Fifteen</item>
+ <item>Sixteen</item>
+ <item>Seventeen</item>
+ <item>Eighteen</item>
+ <item>Nineteen</item>
+ <item>Twenty</item>
+ <item>Twenty\nOne</item>
+ <item>Twenty\nTwo</item>
+ <item>Twenty\nThree</item>
+ <item>Twenty\nFour</item>
+ <item>Twenty\nFive</item>
+ <item>Twenty\nSix</item>
+ <item>Twenty\nSeven</item>
+ <item>Twenty\nEight</item>
+ <item>Twenty\nNine</item>
+ <item>Thirty</item>
+ <item>Thirty\nOne</item>
+ <item>Thirty\nTwo</item>
+ <item>Thirty\nThree</item>
+ <item>Thirty\nFour</item>
+ <item>Thirty\nFive</item>
+ <item>Thirty\nSix</item>
+ <item>Thirty\nSeven</item>
+ <item>Thirty\nEight</item>
+ <item>Thirty\nNine</item>
+ <item>Forty</item>
+ <item>Forty\nOne</item>
+ <item>Forty\nTwo</item>
+ <item>Forty\nThree</item>
+ <item>Forty\nFour</item>
+ <item>Forty\nFive</item>
+ <item>Forty\nSix</item>
+ <item>Forty\nSeven</item>
+ <item>Forty\nEight</item>
+ <item>Forty\nNine</item>
+ <item>Fifty</item>
+ <item>Fifty\nOne</item>
+ <item>Fifty\nTwo</item>
+ <item>Fifty\nThree</item>
+ <item>Fifty\nFour</item>
+ <item>Fifty\nFive</item>
+ <item>Fifty\nSix</item>
+ <item>Fifty\nSeven</item>
+ <item>Fifty\nEight</item>
+ <item>Fifty\nNine</item>
+ </string-array>
+
</resources>
diff --git a/packages/SystemUI/res/layout/global_actions_wrapped.xml b/packages/SystemUI/res/layout/global_actions_wrapped.xml
index 7f4e0d21078f..f932303473bd 100644
--- a/packages/SystemUI/res/layout/global_actions_wrapped.xml
+++ b/packages/SystemUI/res/layout/global_actions_wrapped.xml
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<com.android.systemui.HardwareUiLayout
xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@id/global_actions_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="top|right"
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 476089aa3aac..98f0cbe29110 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -106,7 +106,7 @@
<!-- The default tiles to display in QuickSettings -->
<string name="quick_settings_tiles_default" translatable="false">
- wifi,bt,dnd,flashlight,rotation,battery,cell,airplane,cast
+ wifi,bt,dnd,flashlight,rotation,battery,cell,airplane,cast,sensorprivacy
</string>
<!-- Tiles native to System UI. Order should match "quick_settings_tiles_default" -->
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index 633f8686b804..bd34beac7fd6 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -114,5 +114,8 @@
<item type="id" name="aod_mask_transition_progress_tag" />
<item type="id" name="aod_mask_transition_progress_end_tag" />
<item type="id" name="aod_mask_transition_progress_start_tag" />
+
+ <!-- Global Actions Menu -->
+ <item type="id" name="global_actions_view" />
</resources>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
index a8094d20d5a2..1aff3949a74b 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -20,6 +20,7 @@ import androidx.annotation.VisibleForTesting;
import com.android.keyguard.clock.BubbleClockController;
import com.android.keyguard.clock.StretchAnalogClockController;
+import com.android.keyguard.clock.TypeClockController;
import com.android.systemui.Dependency;
import com.android.systemui.plugins.ClockPlugin;
import com.android.systemui.statusbar.StatusBarState;
@@ -153,6 +154,12 @@ public class KeyguardClockSwitch extends RelativeLayout {
Settings.Secure.LOCK_SCREEN_CUSTOM_CLOCK_FACE,
StretchAnalogClockController.class.getName(),
() -> StretchAnalogClockController.build(mLayoutInflater)))
+ .withDefault(
+ new SettingsGattedSupplier(
+ mContentResolver,
+ Settings.Secure.LOCK_SCREEN_CUSTOM_CLOCK_FACE,
+ TypeClockController.class.getName(),
+ () -> TypeClockController.build(mLayoutInflater)))
.build();
mContentResolver.registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_CUSTOM_CLOCK_FACE),
@@ -248,10 +255,6 @@ public class KeyguardClockSwitch extends RelativeLayout {
mClockView.setShowCurrentUserTime(showCurrentUserTime);
}
- public void setElegantTextHeight(boolean elegant) {
- mClockView.setElegantTextHeight(elegant);
- }
-
public void setTextSize(int unit, float size) {
mClockView.setTextSize(unit, size);
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index f0cdc890306f..7ae4c41d318f 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -202,10 +202,6 @@ public class KeyguardStatusView extends GridLayout implements
updateOwnerInfo();
updateLogoutView();
updateDark();
-
- // Disable elegant text height because our fancy colon makes the ymin value huge for no
- // reason.
- mClockView.setElegantTextHeight(false);
}
/**
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ClockLayout.java b/packages/SystemUI/src/com/android/keyguard/clock/ClockLayout.java
index 5aa566848732..3591dc82c8ec 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/ClockLayout.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/ClockLayout.java
@@ -36,6 +36,7 @@ public class ClockLayout extends FrameLayout {
*/
private View mDigitalClock;
private View mAnalogClock;
+ private View mTypeClock;
/**
* Pixel shifting amplitidues used to prevent screen burn-in.
@@ -60,6 +61,7 @@ public class ClockLayout extends FrameLayout {
super.onFinishInflate();
mDigitalClock = findViewById(R.id.digital_clock);
mAnalogClock = findViewById(R.id.analog_clock);
+ mTypeClock = findViewById(R.id.type_clock);
// Get pixel shifting X, Y amplitudes from resources.
Resources resources = getResources();
@@ -89,5 +91,11 @@ public class ClockLayout extends FrameLayout {
mAnalogClock.setY(Math.max(0f, 0.5f * (getHeight() - mAnalogClock.getHeight()))
+ offsetY);
}
+
+ // Put the typographic clock part way down the screen.
+ if (mTypeClock != null) {
+ mTypeClock.setX(offsetX);
+ mTypeClock.setY(0.2f * getHeight() + offsetY);
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClock.java b/packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClock.java
index 91cec86392d6..8734754541a6 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClock.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClock.java
@@ -80,6 +80,7 @@ public class StretchAnalogClock extends View {
*/
public void setMinuteHandColor(int color) {
mMinutePaint.setColor(color);
+ invalidate();
}
private void init() {
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/TypeClockController.java b/packages/SystemUI/src/com/android/keyguard/clock/TypeClockController.java
new file mode 100644
index 000000000000..17d929dc8a3b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/clock/TypeClockController.java
@@ -0,0 +1,106 @@
+/*
+ * 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.keyguard.clock;
+
+import android.graphics.Paint.Style;
+import android.view.LayoutInflater;
+import android.view.View;
+
+import com.android.keyguard.R;
+import com.android.systemui.plugins.ClockPlugin;
+
+import java.util.TimeZone;
+
+/**
+ * Plugin for a custom Typographic clock face that displays the time in words.
+ */
+public class TypeClockController implements ClockPlugin {
+
+ /**
+ * Custom clock shown on AOD screen and behind stack scroller on lock.
+ */
+ private View mView;
+ private TypographicClock mTypeClock;
+
+ /**
+ * Small clock shown on lock screen above stack scroller.
+ */
+ private View mLockClockContainer;
+
+ /**
+ * Controller for transition into dark state.
+ */
+ private CrossFadeDarkController mDarkController;
+
+ private TypeClockController() {}
+
+ /**
+ * Create a TypeClockController instance.
+ *
+ * @param inflater Inflater used to inflate custom clock views.
+ */
+ public static TypeClockController build(LayoutInflater inflater) {
+ TypeClockController controller = new TypeClockController();
+ controller.createViews(inflater);
+ return controller;
+ }
+
+ private void createViews(LayoutInflater inflater) {
+ mView = inflater.inflate(R.layout.type_clock, null);
+ mTypeClock = mView.findViewById(R.id.type_clock);
+
+ // For now, this view is used to hide the default digital clock.
+ // Need better transition to lock screen.
+ mLockClockContainer = inflater.inflate(R.layout.digital_clock, null);
+ mLockClockContainer.setVisibility(View.GONE);
+ }
+
+ @Override
+ public View getView() {
+ return mLockClockContainer;
+ }
+
+ @Override
+ public View getBigClockView() {
+ return mView;
+ }
+
+ @Override
+ public void setStyle(Style style) {}
+
+ @Override
+ public void setTextColor(int color) {
+ mTypeClock.setTextColor(color);
+ }
+
+ @Override
+ public void dozeTimeTick() {
+ mTypeClock.onTimeChanged();
+ }
+
+ @Override
+ public void setDarkAmount(float darkAmount) {}
+
+ @Override
+ public void onTimeZoneChanged(TimeZone timeZone) {
+ mTypeClock.onTimeZoneChanged(timeZone);
+ }
+
+ @Override
+ public boolean shouldShowStatusArea() {
+ return false;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/TypographicClock.java b/packages/SystemUI/src/com/android/keyguard/clock/TypographicClock.java
new file mode 100644
index 000000000000..5f9da3ee33bb
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/clock/TypographicClock.java
@@ -0,0 +1,110 @@
+/*
+ * 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.keyguard.clock;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.text.format.DateFormat;
+import android.util.AttributeSet;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.keyguard.R;
+
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.TimeZone;
+
+/**
+ * Clock that presents the time in words.
+ */
+public class TypographicClock extends LinearLayout {
+
+ private final String[] mHours;
+ private final String[] mMinutes;
+ private TextView mHeaderText;
+ private TextView mHourText;
+ private TextView mMinuteText;
+ private Calendar mTime;
+ private String mDescFormat;
+ private TimeZone mTimeZone;
+
+ public TypographicClock(Context context) {
+ this(context, null);
+ }
+
+ public TypographicClock(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public TypographicClock(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ mTime = Calendar.getInstance();
+ mDescFormat = ((SimpleDateFormat) DateFormat.getTimeFormat(context)).toLocalizedPattern();
+ Resources res = context.getResources();
+ mHours = res.getStringArray(R.array.type_clock_hours);
+ mMinutes = res.getStringArray(R.array.type_clock_minutes);
+ }
+
+ /**
+ * Call when the time changes to update the text of the time.
+ */
+ public void onTimeChanged() {
+ mTime.setTimeInMillis(System.currentTimeMillis());
+ setContentDescription(DateFormat.format(mDescFormat, mTime));
+ final int hour = mTime.get(Calendar.HOUR);
+ mHourText.setText(mHours[hour % 12]);
+ final int minute = mTime.get(Calendar.MINUTE);
+ mMinuteText.setText(mMinutes[minute % 60]);
+ invalidate();
+ }
+
+ /**
+ * Call when the time zone has changed to update clock time.
+ *
+ * @param timeZone The updated time zone that will be used.
+ */
+ public void onTimeZoneChanged(TimeZone timeZone) {
+ mTimeZone = timeZone;
+ mTime.setTimeZone(timeZone);
+ }
+
+ /**
+ * Set the color of the text used to display the time.
+ *
+ * This is necessary when the wallpaper shown behind the clock on the
+ * lock screen changes.
+ */
+ public void setTextColor(int color) {
+ mHourText.setTextColor(color);
+ mMinuteText.setTextColor(color);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mHeaderText = findViewById(R.id.header);
+ mHourText = findViewById(R.id.hour);
+ mMinuteText = findViewById(R.id.minute);
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ mTime = Calendar.getInstance(mTimeZone != null ? mTimeZone : TimeZone.getDefault());
+ onTimeChanged();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java b/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
index 16e869e9d317..e28aa9d369cb 100644
--- a/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
@@ -37,23 +37,25 @@ import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
import com.android.systemui.util.leak.RotationUtils;
-public class HardwareUiLayout extends LinearLayout implements Tunable {
+/**
+ * Layout for placing two containers at a specific physical position on the device, relative to the
+ * device's hardware, regardless of screen rotation.
+ */
+public class HardwareUiLayout extends MultiListLayout implements Tunable {
private static final String EDGE_BLEED = "sysui_hwui_edge_bleed";
private static final String ROUNDED_DIVIDER = "sysui_hwui_rounded_divider";
private final int[] mTmp2 = new int[2];
- private View mList;
- private View mSeparatedView;
+ private ViewGroup mList;
+ private ViewGroup mSeparatedView;
private int mOldHeight;
private boolean mAnimating;
private AnimatorSet mAnimation;
private View mDivision;
- private boolean mHasOutsideTouch;
private HardwareBgDrawable mListBackground;
private HardwareBgDrawable mSeparatedViewBackground;
private Animator mAnimator;
private boolean mCollapse;
- private boolean mHasSeparatedButton;
private int mEndPoint;
private boolean mEdgeBleed;
private boolean mRoundedDivider;
@@ -67,6 +69,35 @@ public class HardwareUiLayout extends LinearLayout implements Tunable {
}
@Override
+ protected ViewGroup getSeparatedView() {
+ return findViewById(com.android.systemui.R.id.separated_button);
+ }
+
+ @Override
+ protected ViewGroup getListView() {
+ return findViewById(android.R.id.list);
+ }
+
+ @Override
+ public void removeAllItems() {
+ if (mList != null) {
+ mList.removeAllViews();
+ }
+ if (mSeparatedView != null) {
+ mSeparatedView.removeAllViews();
+ }
+ }
+
+ @Override
+ public ViewGroup getParentView(boolean separated, int index) {
+ if (separated) {
+ return getSeparatedView();
+ } else {
+ return getListView();
+ }
+ }
+
+ @Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
updateSettings();
@@ -137,9 +168,9 @@ public class HardwareUiLayout extends LinearLayout implements Tunable {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (mList == null) {
if (getChildCount() != 0) {
- mList = getChildAt(0);
+ mList = getListView();
mList.setBackground(mListBackground);
- mSeparatedView = getChildAt(1);
+ mSeparatedView = getSeparatedView();
mSeparatedView.setBackground(mSeparatedViewBackground);
updateEdgeMargin(mEdgeBleed ? 0 : getEdgePadding());
mOldHeight = mList.getMeasuredHeight();
@@ -187,7 +218,7 @@ public class HardwareUiLayout extends LinearLayout implements Tunable {
} else {
rotateLeft();
}
- if (mHasSeparatedButton) {
+ if (mHasSeparatedView) {
if (from == ROTATION_SEASCAPE || to == ROTATION_SEASCAPE) {
// Separated view has top margin, so seascape separated view need special rotation,
// not a full left or right rotation.
@@ -408,8 +439,8 @@ public class HardwareUiLayout extends LinearLayout implements Tunable {
if (mList == null) return;
// If got separated button, setRotatedBackground to false,
// all items won't get white background.
- mListBackground.setRotatedBackground(mHasSeparatedButton);
- mSeparatedViewBackground.setRotatedBackground(mHasSeparatedButton);
+ mListBackground.setRotatedBackground(mHasSeparatedView);
+ mSeparatedViewBackground.setRotatedBackground(mHasSeparatedView);
if (mDivision != null && mDivision.getVisibility() == VISIBLE) {
int index = mRotatedBackground ? 0 : 1;
mDivision.getLocationOnScreen(mTmp2);
@@ -460,21 +491,21 @@ public class HardwareUiLayout extends LinearLayout implements Tunable {
case RotationUtils.ROTATION_LANDSCAPE:
defaultTopPadding = getPaddingLeft();
viewsTotalHeight = mList.getMeasuredWidth() + mSeparatedView.getMeasuredWidth();
- separatedViewTopMargin = mHasSeparatedButton ? params.leftMargin : 0;
+ separatedViewTopMargin = mHasSeparatedView ? params.leftMargin : 0;
screenHeight = getMeasuredWidth();
targetGravity = Gravity.CENTER_HORIZONTAL|Gravity.TOP;
break;
case RotationUtils.ROTATION_SEASCAPE:
defaultTopPadding = getPaddingRight();
viewsTotalHeight = mList.getMeasuredWidth() + mSeparatedView.getMeasuredWidth();
- separatedViewTopMargin = mHasSeparatedButton ? params.leftMargin : 0;
+ separatedViewTopMargin = mHasSeparatedView ? params.leftMargin : 0;
screenHeight = getMeasuredWidth();
targetGravity = Gravity.CENTER_HORIZONTAL|Gravity.BOTTOM;
break;
default: // Portrait
defaultTopPadding = getPaddingTop();
viewsTotalHeight = mList.getMeasuredHeight() + mSeparatedView.getMeasuredHeight();
- separatedViewTopMargin = mHasSeparatedButton ? params.topMargin : 0;
+ separatedViewTopMargin = mHasSeparatedView ? params.topMargin : 0;
screenHeight = getMeasuredHeight();
targetGravity = Gravity.CENTER_VERTICAL|Gravity.RIGHT;
break;
@@ -491,30 +522,10 @@ public class HardwareUiLayout extends LinearLayout implements Tunable {
return super.getOutlineProvider();
}
- public void setOutsideTouchListener(OnClickListener onClickListener) {
- mHasOutsideTouch = true;
- requestLayout();
- setOnClickListener(onClickListener);
- setClickable(true);
- setFocusable(true);
- }
-
public void setCollapse() {
mCollapse = true;
}
- public void setHasSeparatedButton(boolean hasSeparatedButton) {
- mHasSeparatedButton = hasSeparatedButton;
- }
-
- public static HardwareUiLayout get(View v) {
- if (v instanceof HardwareUiLayout) return (HardwareUiLayout) v;
- if (v.getParent() instanceof View) {
- return get((View) v.getParent());
- }
- return null;
- }
-
private final ViewTreeObserver.OnComputeInternalInsetsListener mInsetsListener = inoutInfo -> {
if (mHasOutsideTouch || (mList == null)) {
inoutInfo.setTouchableInsets(
diff --git a/packages/SystemUI/src/com/android/systemui/MultiListLayout.java b/packages/SystemUI/src/com/android/systemui/MultiListLayout.java
new file mode 100644
index 000000000000..0c7a9a9fffd2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/MultiListLayout.java
@@ -0,0 +1,124 @@
+/*
+ * 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;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+
+/**
+ * Layout class representing the Global Actions menu which appears when the power button is held.
+ */
+public abstract class MultiListLayout extends LinearLayout {
+ boolean mHasOutsideTouch;
+ boolean mHasSeparatedView;
+
+ int mExpectedSeparatedItemCount;
+ int mExpectedListItemCount;
+
+ public MultiListLayout(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ protected abstract ViewGroup getSeparatedView();
+
+ protected abstract ViewGroup getListView();
+
+ /**
+ * Removes all child items from the separated and list views, if they exist.
+ */
+ public abstract void removeAllItems();
+
+ /**
+ * Get the parent view which will be used to contain the item at the specified index.
+ * @param separated Whether or not this index refers to a position in the separated or list
+ * container.
+ * @param index The index of the item within the container.
+ * @return The parent ViewGroup which will be used to contain the specified item
+ * after it has been added to the layout.
+ */
+ public abstract ViewGroup getParentView(boolean separated, int index);
+
+ /**
+ * Sets the divided view, which may have a differently-colored background.
+ */
+ public abstract void setDivisionView(View v);
+
+ /**
+ * Set the view accessibility delegate for the list view container.
+ */
+ public void setListViewAccessibilityDelegate(View.AccessibilityDelegate delegate) {
+ getListView().setAccessibilityDelegate(delegate);
+ }
+
+ protected void setSeparatedViewVisibility(boolean visible) {
+ getSeparatedView().setVisibility(visible ? View.VISIBLE : View.GONE);
+ }
+
+ /**
+ * Sets the number of items expected to be rendered in the separated container. This allows the
+ * layout to correctly determine which parent containers will be used for items before they have
+ * beenadded to the layout.
+ * @param count The number of items expected.
+ */
+ public void setExpectedSeparatedItemCount(int count) {
+ mExpectedSeparatedItemCount = count;
+ }
+
+ /**
+ * Sets the number of items expected to be rendered in the list container. This allows the
+ * layout to correctly determine which parent containers will be used for items before they have
+ * beenadded to the layout.
+ * @param count The number of items expected.
+ */
+ public void setExpectedListItemCount(int count) {
+ mExpectedListItemCount = count;
+ }
+
+ /**
+ * Sets whether the separated view should be shown, and handles updating visibility on
+ * that view.
+ */
+ public void setHasSeparatedView(boolean hasSeparatedView) {
+ mHasSeparatedView = hasSeparatedView;
+ setSeparatedViewVisibility(hasSeparatedView);
+ }
+
+ /**
+ * Sets this layout to respond to an outside touch listener.
+ */
+ public void setOutsideTouchListener(OnClickListener onClickListener) {
+ mHasOutsideTouch = true;
+ requestLayout();
+ setOnClickListener(onClickListener);
+ setClickable(true);
+ setFocusable(true);
+ }
+
+ /**
+ * Retrieve the MultiListLayout associated with the given view.
+ */
+ public static MultiListLayout get(View v) {
+ if (v instanceof MultiListLayout) return (MultiListLayout) v;
+ if (v.getParent() instanceof View) {
+ return get((View) v.getParent());
+ }
+ return null;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 268245bd4acd..7b18fad0e105 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -67,10 +67,8 @@ import android.view.WindowManagerGlobal;
import android.view.accessibility.AccessibilityEvent;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.BaseAdapter;
-import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
-import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.internal.R;
@@ -86,8 +84,8 @@ import com.android.internal.util.ScreenRecordHelper;
import com.android.internal.util.ScreenshotHelper;
import com.android.internal.widget.LockPatternUtils;
import com.android.systemui.Dependency;
-import com.android.systemui.HardwareUiLayout;
import com.android.systemui.Interpolators;
+import com.android.systemui.MultiListLayout;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.plugins.GlobalActions.GlobalActionsManager;
import com.android.systemui.statusbar.phone.ScrimController;
@@ -490,6 +488,11 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener,
public boolean showBeforeProvisioning() {
return true;
}
+
+ @Override
+ public boolean shouldBeSeparated() {
+ return true;
+ }
}
private final class RestartAction extends SinglePressAction implements LongPressAction {
@@ -926,6 +929,34 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener,
return getItem(position).isEnabled();
}
+ public ArrayList<Action> getSeparatedActions(boolean shouldUseSeparatedView) {
+ ArrayList<Action> separatedActions = new ArrayList<Action>();
+ if (!shouldUseSeparatedView) {
+ return separatedActions;
+ }
+ for (int i = 0; i < mItems.size(); i++) {
+ final Action action = mItems.get(i);
+ if (action.shouldBeSeparated()) {
+ separatedActions.add(action);
+ }
+ }
+ return separatedActions;
+ }
+
+ public ArrayList<Action> getListActions(boolean shouldUseSeparatedView) {
+ if (!shouldUseSeparatedView) {
+ return new ArrayList<Action>(mItems);
+ }
+ ArrayList<Action> listActions = new ArrayList<Action>();
+ for (int i = 0; i < mItems.size(); i++) {
+ final Action action = mItems.get(i);
+ if (!action.shouldBeSeparated()) {
+ listActions.add(action);
+ }
+ }
+ return listActions;
+ }
+
@Override
public boolean areAllItemsEnabled() {
return false;
@@ -965,7 +996,7 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener,
View view = action.create(mContext, convertView, parent, LayoutInflater.from(mContext));
// Everything but screenshot, the last item, gets white background.
if (position == getCount() - 1) {
- HardwareUiLayout.get(parent).setDivisionView(view);
+ MultiListLayout.get(parent).setDivisionView(view);
}
return view;
}
@@ -1004,6 +1035,10 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener,
boolean showBeforeProvisioning();
boolean isEnabled();
+
+ default boolean shouldBeSeparated() {
+ return false;
+ }
}
/**
@@ -1423,9 +1458,7 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener,
private final Context mContext;
private final MyAdapter mAdapter;
- private final LinearLayout mListView;
- private final FrameLayout mSeparatedView;
- private final HardwareUiLayout mHardwareLayout;
+ private final MultiListLayout mGlobalActionsLayout;
private final OnClickListener mClickListener;
private final OnItemLongClickListener mLongClickListener;
private final GradientDrawable mGradientDrawable;
@@ -1466,16 +1499,11 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener,
window.setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY);
setContentView(com.android.systemui.R.layout.global_actions_wrapped);
- mListView = findViewById(android.R.id.list);
- mSeparatedView = findViewById(com.android.systemui.R.id.separated_button);
- if (!mShouldDisplaySeparatedButton) {
- mSeparatedView.setVisibility(View.GONE);
- }
- mHardwareLayout = HardwareUiLayout.get(mListView);
- mHardwareLayout.setOutsideTouchListener(view -> dismiss());
- mHardwareLayout.setHasSeparatedButton(mShouldDisplaySeparatedButton);
- setTitle(R.string.global_actions);
- mListView.setAccessibilityDelegate(new View.AccessibilityDelegate() {
+ mGlobalActionsLayout = (MultiListLayout)
+ findViewById(com.android.systemui.R.id.global_actions_view);
+ mGlobalActionsLayout.setOutsideTouchListener(view -> dismiss());
+ mGlobalActionsLayout.setHasSeparatedView(mShouldDisplaySeparatedButton);
+ mGlobalActionsLayout.setListViewAccessibilityDelegate(new View.AccessibilityDelegate() {
@Override
public boolean dispatchPopulateAccessibilityEvent(
View host, AccessibilityEvent event) {
@@ -1484,20 +1512,33 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener,
return true;
}
});
+ setTitle(R.string.global_actions);
}
private void updateList() {
- mListView.removeAllViews();
- mSeparatedView.removeAllViews();
+ mGlobalActionsLayout.removeAllItems();
+ ArrayList<Action> separatedActions =
+ mAdapter.getSeparatedActions(mShouldDisplaySeparatedButton);
+ ArrayList<Action> listActions = mAdapter.getListActions(mShouldDisplaySeparatedButton);
+ mGlobalActionsLayout.setExpectedListItemCount(listActions.size());
+ mGlobalActionsLayout.setExpectedSeparatedItemCount(separatedActions.size());
+
for (int i = 0; i < mAdapter.getCount(); i++) {
- ViewGroup parentView = mShouldDisplaySeparatedButton && i == mAdapter.getCount() - 1
- ? mSeparatedView : mListView;
- View v = mAdapter.getView(i, null, parentView);
+ Action action = mAdapter.getItem(i);
+ int separatedIndex = separatedActions.indexOf(action);
+ ViewGroup parent;
+ if (separatedIndex != -1) {
+ parent = mGlobalActionsLayout.getParentView(true, separatedIndex);
+ } else {
+ int listIndex = listActions.indexOf(action);
+ parent = mGlobalActionsLayout.getParentView(false, listIndex);
+ }
+ View v = mAdapter.getView(i, null, parent);
final int pos = i;
v.setOnClickListener(view -> mClickListener.onClick(this, pos));
v.setOnLongClickListener(view ->
mLongClickListener.onItemLongClick(null, v, pos, 0));
- parentView.addView(v);
+ parent.addView(v);
}
}
@@ -1543,9 +1584,9 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener,
super.show();
mShowing = true;
mGradientDrawable.setAlpha(0);
- mHardwareLayout.setTranslationX(getAnimTranslation());
- mHardwareLayout.setAlpha(0);
- mHardwareLayout.animate()
+ mGlobalActionsLayout.setTranslationX(getAnimTranslation());
+ mGlobalActionsLayout.setAlpha(0);
+ mGlobalActionsLayout.animate()
.alpha(1)
.translationX(0)
.setDuration(300)
@@ -1564,9 +1605,9 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener,
return;
}
mShowing = false;
- mHardwareLayout.setTranslationX(0);
- mHardwareLayout.setAlpha(1);
- mHardwareLayout.animate()
+ mGlobalActionsLayout.setTranslationX(0);
+ mGlobalActionsLayout.setAlpha(1);
+ mGlobalActionsLayout.animate()
.alpha(0)
.translationX(getAnimTranslation())
.setDuration(300)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyTile.java
index 5230cea88e8e..7ee37d567a55 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyTile.java
@@ -84,7 +84,7 @@ public class SensorPrivacyTile extends QSTileImpl<BooleanState> implements
@Override
public Intent getLongClickIntent() {
- return null;
+ return new Intent();
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java
index eea44906029d..839b06cec496 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java
@@ -33,6 +33,13 @@ public interface NotificationEntryListener {
default void onPendingEntryAdded(NotificationEntry entry) {
}
+ // TODO: Combine this with onPreEntryUpdated into "onBeforeEntryFiltered" or similar
+ /**
+ * Called when a new entry is created but before it has been filtered or displayed to the user.
+ */
+ default void onBeforeNotificationAdded(NotificationEntry entry) {
+ }
+
/**
* Called when a new entry is created.
*/
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 45db00210a2e..989e781ab5ba 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
@@ -18,11 +18,9 @@ package com.android.systemui.statusbar.notification;
import android.annotation.Nullable;
import android.app.Notification;
import android.content.Context;
-import android.os.UserHandle;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.util.ArrayMap;
-import android.util.ArraySet;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
@@ -41,7 +39,6 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.row.NotificationInflater;
import com.android.systemui.statusbar.notification.row.NotificationInflater.InflationFlag;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
-import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.util.leak.LeakDetector;
@@ -68,8 +65,6 @@ public class NotificationEntryManager implements
@VisibleForTesting
protected final HashMap<String, NotificationEntry> mPendingNotifications = new HashMap<>();
- private final DeviceProvisionedController mDeviceProvisionedController =
- Dependency.get(DeviceProvisionedController.class);
private final ForegroundServiceController mForegroundServiceController =
Dependency.get(ForegroundServiceController.class);
@@ -81,25 +76,12 @@ public class NotificationEntryManager implements
private NotificationListenerService.RankingMap mLatestRankingMap;
@VisibleForTesting
protected NotificationData mNotificationData;
- private NotificationListContainer mListContainer;
+
@VisibleForTesting
final ArrayList<NotificationLifetimeExtender> mNotificationLifetimeExtenders
= new ArrayList<>();
private final List<NotificationEntryListener> mNotificationEntryListeners = new ArrayList<>();
- private final DeviceProvisionedController.DeviceProvisionedListener
- mDeviceProvisionedListener =
- new DeviceProvisionedController.DeviceProvisionedListener() {
- @Override
- public void onDeviceProvisionedChanged() {
- updateNotifications();
- }
- };
-
- public void destroy() {
- mDeviceProvisionedController.removeCallback(mDeviceProvisionedListener);
- }
-
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("NotificationEntryManager state:");
@@ -151,9 +133,6 @@ public class NotificationEntryManager implements
HeadsUpManager headsUpManager) {
mPresenter = presenter;
mNotificationData.setHeadsUpManager(headsUpManager);
- mListContainer = listContainer;
-
- mDeviceProvisionedController.addCallback(mDeviceProvisionedListener);
}
/** Adds multiple {@link NotificationLifetimeExtender}s. */
@@ -227,7 +206,9 @@ public class NotificationEntryManager implements
listener.onEntryInflated(entry, inflatedFlags);
}
mNotificationData.add(entry);
- tagForeground(entry.notification);
+ for (NotificationEntryListener listener : mNotificationEntryListeners) {
+ listener.onBeforeNotificationAdded(entry);
+ }
updateNotifications();
for (NotificationEntryListener listener : mNotificationEntryListeners) {
listener.onNotificationAdded(entry);
@@ -283,7 +264,6 @@ public class NotificationEntryManager implements
if (entry.rowExists()) {
entry.removeRow();
- mListContainer.cleanUpViewStateForEntry(entry);
}
// Let's remove the children if this was a summary
@@ -368,19 +348,6 @@ public class NotificationEntryManager implements
}
}
- @VisibleForTesting
- void tagForeground(StatusBarNotification notification) {
- ArraySet<Integer> activeOps = mForegroundServiceController.getAppOps(
- notification.getUserId(), notification.getPackageName());
- if (activeOps != null) {
- int N = activeOps.size();
- for (int i = 0; i < N; i++) {
- updateNotificationsForAppOp(activeOps.valueAt(i), notification.getUid(),
- notification.getPackageName(), true);
- }
- }
- }
-
@Override
public void addNotification(StatusBarNotification notification,
NotificationListenerService.RankingMap ranking) {
@@ -391,15 +358,6 @@ public class NotificationEntryManager implements
}
}
- public void updateNotificationsForAppOp(int appOp, int uid, String pkg, boolean showIcon) {
- String foregroundKey = mForegroundServiceController.getStandardLayoutKey(
- UserHandle.getUserId(uid), pkg);
- if (foregroundKey != null) {
- mNotificationData.updateAppOp(appOp, uid, pkg, foregroundKey, showIcon);
- updateNotifications();
- }
- }
-
private void updateNotificationInternal(StatusBarNotification notification,
NotificationListenerService.RankingMap ranking) throws InflationException {
if (DEBUG) Log.d(TAG, "updateNotification(" + notification + ")");
@@ -452,8 +410,9 @@ public class NotificationEntryManager implements
public void updateNotifications() {
mNotificationData.filterAndSort();
-
- mPresenter.updateNotificationViews();
+ if (mPresenter != null) {
+ mPresenter.updateNotificationViews();
+ }
}
public void updateNotificationRanking(NotificationListenerService.RankingMap rankingMap) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationListController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationListController.java
new file mode 100644
index 000000000000..88f4ca239af4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationListController.java
@@ -0,0 +1,117 @@
+/*
+ * 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;
+
+import static com.android.internal.util.Preconditions.checkNotNull;
+
+import android.os.UserHandle;
+import android.service.notification.StatusBarNotification;
+import android.util.ArraySet;
+
+import com.android.internal.statusbar.NotificationVisibility;
+import com.android.systemui.ForegroundServiceController;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
+
+/**
+ * Root controller for the list of notifications in the shade.
+ *
+ * TODO: Much of the code in NotificationPresenter should eventually move in here. It will proxy
+ * domain-specific behavior (ARC, etc) to subcontrollers.
+ */
+public class NotificationListController {
+ private final NotificationEntryManager mEntryManager;
+ private final NotificationListContainer mListContainer;
+ private final ForegroundServiceController mForegroundServiceController;
+ private final DeviceProvisionedController mDeviceProvisionedController;
+
+ public NotificationListController(
+ NotificationEntryManager entryManager,
+ NotificationListContainer listContainer,
+ ForegroundServiceController foregroundServiceController,
+ DeviceProvisionedController deviceProvisionedController) {
+ mEntryManager = checkNotNull(entryManager);
+ mListContainer = checkNotNull(listContainer);
+ mForegroundServiceController = checkNotNull(foregroundServiceController);
+ mDeviceProvisionedController = checkNotNull(deviceProvisionedController);
+ }
+
+ /**
+ * Causes the controller to register listeners on its dependencies. This method must be called
+ * before the controller is ready to perform its duties.
+ */
+ public void bind() {
+ mEntryManager.addNotificationEntryListener(mEntryListener);
+ mDeviceProvisionedController.addCallback(mDeviceProvisionedListener);
+ }
+
+ /** Should be called when the list controller is being destroyed. */
+ public void destroy() {
+ mDeviceProvisionedController.removeCallback(mDeviceProvisionedListener);
+ }
+
+ @SuppressWarnings("FieldCanBeLocal")
+ private final NotificationEntryListener mEntryListener = new NotificationEntryListener() {
+ @Override
+ public void onEntryRemoved(
+ NotificationEntry entry,
+ NotificationVisibility visibility,
+ boolean removedByUser) {
+ mListContainer.cleanUpViewStateForEntry(entry);
+ }
+
+ @Override
+ public void onBeforeNotificationAdded(NotificationEntry entry) {
+ tagForeground(entry.notification);
+ }
+ };
+
+ private final DeviceProvisionedListener mDeviceProvisionedListener =
+ new DeviceProvisionedListener() {
+ @Override
+ public void onDeviceProvisionedChanged() {
+ mEntryManager.updateNotifications();
+ }
+ };
+
+ // TODO: This method is horrifically inefficient
+ private void tagForeground(StatusBarNotification notification) {
+ ArraySet<Integer> activeOps =
+ mForegroundServiceController.getAppOps(
+ notification.getUserId(), notification.getPackageName());
+ if (activeOps != null) {
+ int len = activeOps.size();
+ for (int i = 0; i < len; i++) {
+ updateNotificationsForAppOp(activeOps.valueAt(i), notification.getUid(),
+ notification.getPackageName(), true);
+ }
+ }
+ }
+
+ /** When an app op changes, propagate that change to notifications. */
+ public void updateNotificationsForAppOp(int appOp, int uid, String pkg, boolean showIcon) {
+ String foregroundKey =
+ mForegroundServiceController.getStandardLayoutKey(UserHandle.getUserId(uid), pkg);
+ if (foregroundKey != null) {
+ mEntryManager
+ .getNotificationData().updateAppOp(appOp, uid, pkg, foregroundKey, showIcon);
+ mEntryManager.updateNotifications();
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationAssistantAction.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationAssistantAction.java
index ebcd39b99778..323e7761b475 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationAssistantAction.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationAssistantAction.java
@@ -43,6 +43,11 @@ public class NavigationAssistantAction extends NavigationGestureAction {
}
@Override
+ public boolean disableProxyEvents() {
+ return true;
+ }
+
+ @Override
public void onGestureStart(MotionEvent event) {
mAssistManager.startAssist(new Bundle());
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBackAction.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBackAction.java
index 93605adf4589..7a42b03947ae 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBackAction.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBackAction.java
@@ -95,6 +95,11 @@ public class NavigationBackAction extends NavigationGestureAction {
}
}
+ @Override
+ public boolean disableProxyEvents() {
+ return true;
+ }
+
private void performBack() {
sendEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK);
sendEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 31310f5f2043..32cc0e6d303a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -141,6 +141,7 @@ public class NotificationPanelView extends PanelView implements
private KeyguardAffordanceHelper mAffordanceHelper;
private KeyguardUserSwitcher mKeyguardUserSwitcher;
private KeyguardStatusBarView mKeyguardStatusBar;
+ private ViewGroup mBigClockContainer;
private QS mQs;
private FrameLayout mQsFrame;
@VisibleForTesting
@@ -348,8 +349,8 @@ public class NotificationPanelView extends PanelView implements
mKeyguardStatusView = findViewById(R.id.keyguard_status_view);
KeyguardClockSwitch keyguardClockSwitch = findViewById(R.id.keyguard_clock_container);
- ViewGroup bigClockContainer = findViewById(R.id.big_clock_container);
- keyguardClockSwitch.setBigClockContainer(bigClockContainer);
+ mBigClockContainer = findViewById(R.id.big_clock_container);
+ keyguardClockSwitch.setBigClockContainer(mBigClockContainer);
mNotificationContainerParent = findViewById(R.id.notification_container_parent);
mNotificationStackScroller = findViewById(R.id.notification_stack_scroller);
@@ -585,6 +586,11 @@ public class NotificationPanelView extends PanelView implements
mClockPositionResult.clockX, CLOCK_ANIMATION_PROPERTIES, animateClock);
PropertyAnimator.setProperty(mKeyguardStatusView, AnimatableProperty.Y,
mClockPositionResult.clockY, CLOCK_ANIMATION_PROPERTIES, animateClock);
+ // Move big clock up while pulling up the bouncer
+ PropertyAnimator.setProperty(mBigClockContainer, AnimatableProperty.Y,
+ MathUtils.lerp(-mBigClockContainer.getHeight(), 0,
+ Interpolators.FAST_OUT_LINEAR_IN.getInterpolation(getExpandedFraction())),
+ CLOCK_ANIMATION_PROPERTIES, animateClock);
updateClock();
stackScrollerPadding = mClockPositionResult.stackScrollerPadding;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 853d7ab9a76d..3568f2846a51 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -612,9 +612,11 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
anim.setStartDelay(mAnimationDelay);
anim.setDuration(mAnimationDuration);
anim.addListener(new AnimatorListenerAdapter() {
+ private Callback lastCallback = mCallback;
+
@Override
public void onAnimationEnd(Animator animation) {
- onFinished();
+ onFinished(lastCallback);
scrim.setTag(TAG_KEY_ANIM, null);
dispatchScrimsVisible();
@@ -672,14 +674,23 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
}
private void onFinished() {
+ onFinished(mCallback);
+ }
+
+ private void onFinished(Callback callback) {
if (mWakeLockHeld) {
mWakeLock.release();
mWakeLockHeld = false;
}
- if (mCallback != null) {
- mCallback.onFinished();
- mCallback = null;
+
+ if (callback != null) {
+ callback.onFinished();
+
+ if (callback == mCallback) {
+ mCallback = null;
+ }
}
+
// When unlocking with fingerprint, we'll fade the scrims from black to transparent.
// At the end of the animation we need to remove the tint.
if (mState == ScrimState.UNLOCKED) {
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 7569a50a8c54..ed71598e22ce 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -196,6 +196,7 @@ import com.android.systemui.statusbar.notification.NotificationAlertingManager;
import com.android.systemui.statusbar.notification.NotificationClicker;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
+import com.android.systemui.statusbar.notification.NotificationListController;
import com.android.systemui.statusbar.notification.NotificationRowBinder;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -387,6 +388,7 @@ public class StatusBar extends SystemUI implements DemoMode,
private NotificationGutsManager mGutsManager;
protected NotificationLogger mNotificationLogger;
protected NotificationEntryManager mEntryManager;
+ private NotificationListController mNotificationListController;
private NotificationInterruptionStateProvider mNotificationInterruptionStateProvider;
private NotificationRowBinder mNotificationRowBinder;
protected NotificationViewHierarchyManager mViewHierarchyManager;
@@ -593,7 +595,7 @@ public class StatusBar extends SystemUI implements DemoMode,
public void onActiveStateChanged(int code, int uid, String packageName, boolean active) {
mForegroundServiceController.onAppOpChanged(code, uid, packageName, active);
Dependency.get(Dependency.MAIN_HANDLER).post(() -> {
- mEntryManager.updateNotificationsForAppOp(code, uid, packageName, active);
+ mNotificationListController.updateNotificationsForAppOp(code, uid, packageName, active);
});
}
@@ -1044,6 +1046,13 @@ public class StatusBar extends SystemUI implements DemoMode,
mScrimController, mActivityLaunchAnimator, mStatusBarKeyguardViewManager,
mNotificationAlertingManager);
+ mNotificationListController =
+ new NotificationListController(
+ mEntryManager,
+ (NotificationListContainer) mStackScroller,
+ mForegroundServiceController,
+ mDeviceProvisionedController);
+
mAppOpsController.addCallback(APP_OPS, this);
mNotificationListener.setUpWithPresenter(mPresenter);
mNotificationShelf.setOnActivatedListener(mPresenter);
@@ -1056,6 +1065,7 @@ public class StatusBar extends SystemUI implements DemoMode,
this, Dependency.get(BubbleController.class), mNotificationActivityStarter));
mGroupAlertTransferHelper.bind(mEntryManager, mGroupManager);
+ mNotificationListController.bind();
}
/**
@@ -2831,7 +2841,7 @@ public class StatusBar extends SystemUI implements DemoMode,
} catch (RemoteException e) {
// Ignore.
}
- mEntryManager.destroy();
+ mNotificationListController.destroy();
// End old BaseStatusBar.destroy().
if (mStatusBarWindow != null) {
mWindowManager.removeViewImmediate(mStatusBarWindow);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
index 04d24dc18f05..4f61009095c7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -346,7 +346,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
}
private void handleFullScreenIntent(NotificationEntry entry) {
- boolean isHeadsUped = mNotificationInterruptionStateProvider.canHeadsUpCommon(entry);
+ boolean isHeadsUped = mNotificationInterruptionStateProvider.shouldHeadsUp(entry);
if (!isHeadsUped && entry.notification.getNotification().fullScreenIntent != null) {
if (shouldSuppressFullScreenIntent(entry)) {
if (DEBUG) {
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 d937f93482d5..9ce6ae139998 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
@@ -22,19 +22,15 @@ import static junit.framework.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.ActivityManager;
-import android.app.AppOpsManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
@@ -49,7 +45,6 @@ import android.service.notification.StatusBarNotification;
import android.support.test.filters.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
-import android.util.ArraySet;
import android.widget.FrameLayout;
import com.android.internal.logging.MetricsLogger;
@@ -79,8 +74,6 @@ import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
-import junit.framework.Assert;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -346,7 +339,6 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
verify(mEntryListener, never()).onInflationError(any(), any());
- verify(mListContainer).cleanUpViewStateForEntry(mEntry);
verify(mPresenter).updateNotificationViews();
verify(mEntryListener).onEntryRemoved(
mEntry, null, false /* removedByUser */);
@@ -401,90 +393,6 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
}
@Test
- public void testUpdateAppOps_foregroundNoti() {
- com.android.systemui.util.Assert.isNotMainThread();
-
- when(mForegroundServiceController.getStandardLayoutKey(anyInt(), anyString()))
- .thenReturn(mEntry.key);
- mEntry.setRow(mRow);
- mEntryManager.getNotificationData().add(mEntry);
-
- mEntryManager.updateNotificationsForAppOp(
- AppOpsManager.OP_CAMERA, mEntry.notification.getUid(),
- mEntry.notification.getPackageName(), true);
-
- verify(mPresenter, times(1)).updateNotificationViews();
- assertTrue(mEntryManager.getNotificationData().get(mEntry.key).mActiveAppOps.contains(
- AppOpsManager.OP_CAMERA));
- }
-
- @Test
- public void testUpdateAppOps_otherNoti() {
- com.android.systemui.util.Assert.isNotMainThread();
-
- when(mForegroundServiceController.getStandardLayoutKey(anyInt(), anyString()))
- .thenReturn(null);
- mEntryManager.updateNotificationsForAppOp(AppOpsManager.OP_CAMERA, 1000, "pkg", true);
-
- verify(mPresenter, never()).updateNotificationViews();
- }
-
- @Test
- public void testAddNotificationExistingAppOps() {
- mEntry.setRow(mRow);
- mEntryManager.getNotificationData().add(mEntry);
- ArraySet<Integer> expected = new ArraySet<>();
- expected.add(3);
- expected.add(235);
- expected.add(1);
-
- when(mForegroundServiceController.getAppOps(mEntry.notification.getUserId(),
- mEntry.notification.getPackageName())).thenReturn(expected);
- when(mForegroundServiceController.getStandardLayoutKey(
- mEntry.notification.getUserId(),
- mEntry.notification.getPackageName())).thenReturn(mEntry.key);
-
- mEntryManager.tagForeground(mEntry.notification);
-
- Assert.assertEquals(expected.size(), mEntry.mActiveAppOps.size());
- for (int op : expected) {
- assertTrue("Entry missing op " + op, mEntry.mActiveAppOps.contains(op));
- }
- }
-
- @Test
- public void testAdd_noExistingAppOps() {
- mEntry.setRow(mRow);
- mEntryManager.getNotificationData().add(mEntry);
- when(mForegroundServiceController.getStandardLayoutKey(
- mEntry.notification.getUserId(),
- mEntry.notification.getPackageName())).thenReturn(mEntry.key);
- when(mForegroundServiceController.getAppOps(mEntry.notification.getUserId(),
- mEntry.notification.getPackageName())).thenReturn(null);
-
- mEntryManager.tagForeground(mEntry.notification);
- Assert.assertEquals(0, mEntry.mActiveAppOps.size());
- }
-
- @Test
- public void testAdd_existingAppOpsNotForegroundNoti() {
- mEntry.setRow(mRow);
- mEntryManager.getNotificationData().add(mEntry);
- ArraySet<Integer> ops = new ArraySet<>();
- ops.add(3);
- ops.add(235);
- ops.add(1);
- when(mForegroundServiceController.getAppOps(mEntry.notification.getUserId(),
- mEntry.notification.getPackageName())).thenReturn(ops);
- when(mForegroundServiceController.getStandardLayoutKey(
- mEntry.notification.getUserId(),
- mEntry.notification.getPackageName())).thenReturn("something else");
-
- mEntryManager.tagForeground(mEntry.notification);
- Assert.assertEquals(0, mEntry.mActiveAppOps.size());
- }
-
- @Test
public void testUpdateNotificationRanking() {
when(mDeviceProvisionedController.isDeviceProvisioned()).thenReturn(true);
when(mEnvironment.isDeviceProvisioned()).thenReturn(true);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java
new file mode 100644
index 000000000000..4b5037bb3f64
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java
@@ -0,0 +1,241 @@
+/*
+ * 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;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertTrue;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.ActivityManager;
+import android.app.AppOpsManager;
+import android.app.Notification;
+import android.os.UserHandle;
+import android.service.notification.StatusBarNotification;
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.util.ArraySet;
+
+import com.android.internal.statusbar.NotificationVisibility;
+import com.android.systemui.ForegroundServiceController;
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.notification.collection.NotificationData;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class NotificationListControllerTest extends SysuiTestCase {
+ private NotificationListController mController;
+
+ @Mock private NotificationEntryManager mEntryManager;
+ @Mock private NotificationListContainer mListContainer;
+ @Mock private ForegroundServiceController mForegroundServiceController;
+ @Mock private DeviceProvisionedController mDeviceProvisionedController;
+
+ @Captor private ArgumentCaptor<NotificationEntryListener> mEntryListenerCaptor;
+ @Captor private ArgumentCaptor<DeviceProvisionedListener> mProvisionedCaptor;
+
+ private NotificationEntryListener mEntryListener;
+ private DeviceProvisionedListener mProvisionedListener;
+
+ // TODO: Remove this once EntryManager no longer needs to be mocked
+ private NotificationData mNotificationData = new NotificationData();
+
+ private int mNextNotifId = 0;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ when(mEntryManager.getNotificationData()).thenReturn(mNotificationData);
+
+ mController = new NotificationListController(
+ mEntryManager,
+ mListContainer,
+ mForegroundServiceController,
+ mDeviceProvisionedController);
+ mController.bind();
+
+ // Capture callbacks passed to mocks
+ verify(mEntryManager).addNotificationEntryListener(mEntryListenerCaptor.capture());
+ mEntryListener = mEntryListenerCaptor.getValue();
+ verify(mDeviceProvisionedController).addCallback(mProvisionedCaptor.capture());
+ mProvisionedListener = mProvisionedCaptor.getValue();
+ }
+
+ @Test
+ public void testCleanUpViewStateOnEntryRemoved() {
+ final NotificationEntry entry = buildEntry();
+ mEntryListener.onEntryRemoved(
+ entry,
+ NotificationVisibility.obtain(entry.key, 0, 0, true),
+ false);
+ verify(mListContainer).cleanUpViewStateForEntry(entry);
+ }
+
+ @Test
+ public void testCallUpdateNotificationsOnDeviceProvisionedChange() {
+ mProvisionedListener.onDeviceProvisionedChanged();
+ verify(mEntryManager).updateNotifications();
+ }
+
+ @Test
+ public void testAppOps_appOpAddedToForegroundNotif() {
+ // GIVEN a notification associated with a foreground service
+ final NotificationEntry entry = buildEntry();
+ mNotificationData.add(entry);
+ when(mForegroundServiceController.getStandardLayoutKey(anyInt(), anyString()))
+ .thenReturn(entry.key);
+
+ // WHEN we are notified of a new app op
+ mController.updateNotificationsForAppOp(
+ AppOpsManager.OP_CAMERA,
+ entry.notification.getUid(),
+ entry.notification.getPackageName(),
+ true);
+
+ // THEN the app op is added to the entry
+ assertTrue(entry.mActiveAppOps.contains(AppOpsManager.OP_CAMERA));
+ // THEN updateNotifications() is called
+ verify(mEntryManager, times(1)).updateNotifications();
+ }
+
+ @Test
+ public void testAppOps_appOpAddedToUnrelatedNotif() {
+ // GIVEN No current foreground notifs
+ when(mForegroundServiceController.getStandardLayoutKey(anyInt(), anyString()))
+ .thenReturn(null);
+
+ // WHEN An unrelated notification gets a new app op
+ mController.updateNotificationsForAppOp(AppOpsManager.OP_CAMERA, 1000, "pkg", true);
+
+ // THEN We never call updateNotifications()
+ verify(mEntryManager, never()).updateNotifications();
+ }
+
+ @Test
+ public void testAppOps_addNotificationWithExistingAppOps() {
+ // GIVEN a notification with three associated app ops that is associated with a foreground
+ // service
+ final NotificationEntry entry = buildEntry();
+ mNotificationData.add(entry);
+ ArraySet<Integer> expected = new ArraySet<>();
+ expected.add(3);
+ expected.add(235);
+ expected.add(1);
+ when(mForegroundServiceController.getStandardLayoutKey(
+ entry.notification.getUserId(),
+ entry.notification.getPackageName())).thenReturn(entry.key);
+ when(mForegroundServiceController.getAppOps(entry.notification.getUserId(),
+ entry.notification.getPackageName())).thenReturn(expected);
+
+ // WHEN the notification is added
+ mEntryListener.onBeforeNotificationAdded(entry);
+
+ // THEN the entry is tagged with all three app ops
+ assertEquals(expected.size(), entry.mActiveAppOps.size());
+ for (int op : expected) {
+ assertTrue("Entry missing op " + op, entry.mActiveAppOps.contains(op));
+ }
+ }
+
+ @Test
+ public void testAdd_addNotificationWithNoExistingAppOps() {
+ // GIVEN a notification with NO associated app ops
+ final NotificationEntry entry = buildEntry();
+
+ mNotificationData.add(entry);
+ when(mForegroundServiceController.getStandardLayoutKey(
+ entry.notification.getUserId(),
+ entry.notification.getPackageName())).thenReturn(entry.key);
+ when(mForegroundServiceController.getAppOps(entry.notification.getUserId(),
+ entry.notification.getPackageName())).thenReturn(null);
+
+ // WHEN the notification is added
+ mEntryListener.onBeforeNotificationAdded(entry);
+
+ // THEN the entry doesn't have any app ops associated with it
+ assertEquals(0, entry.mActiveAppOps.size());
+ }
+
+ @Test
+ public void testAdd_addNonForegroundNotificationWithExistingAppOps() {
+ // GIVEN a notification with app ops that isn't associated with a foreground service
+ final NotificationEntry entry = buildEntry();
+ mNotificationData.add(entry);
+ ArraySet<Integer> ops = new ArraySet<>();
+ ops.add(3);
+ ops.add(235);
+ ops.add(1);
+ when(mForegroundServiceController.getAppOps(entry.notification.getUserId(),
+ entry.notification.getPackageName())).thenReturn(ops);
+ when(mForegroundServiceController.getStandardLayoutKey(
+ entry.notification.getUserId(),
+ entry.notification.getPackageName())).thenReturn("something else");
+
+ // WHEN the notification is added
+ mEntryListener.onBeforeNotificationAdded(entry);
+
+ // THEN the entry doesn't have any app ops associated with it
+ assertEquals(0, entry.mActiveAppOps.size());
+ }
+
+ private NotificationEntry buildEntry() {
+ mNextNotifId++;
+
+ Notification.Builder n = new Notification.Builder(mContext, "")
+ .setSmallIcon(R.drawable.ic_person)
+ .setContentTitle("Title")
+ .setContentText("Text");
+
+ StatusBarNotification notification =
+ new StatusBarNotification(
+ TEST_PACKAGE_NAME,
+ TEST_PACKAGE_NAME,
+ mNextNotifId,
+ null,
+ TEST_UID,
+ 0,
+ n.build(),
+ new UserHandle(ActivityManager.getCurrentUser()),
+ null,
+ 0);
+ return new NotificationEntry(notification);
+ }
+
+ private static final String TEST_PACKAGE_NAME = "test";
+ private static final int TEST_UID = 0;
+}
diff --git a/proto/src/metrics_constants/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto
index a07411d0afaf..8261fe89f778 100644
--- a/proto/src/metrics_constants/metrics_constants.proto
+++ b/proto/src/metrics_constants/metrics_constants.proto
@@ -6814,6 +6814,12 @@ message MetricsEvent {
// OS: Q
SETTINGS_GESTURE_TAP_SCREEN = 1626;
+ // OPEN: Settings > Network & internet > Click Mobile network to land on a page with a list of
+ // SIM/eSIM subscriptions.
+ // CATEGORY: SETTINGS
+ // OS: Q
+ MOBILE_NETWORK_LIST = 1627;
+
// ---- End Q Constants, all Q constants go above this line ----
// Add new aosp constants above this line.
// END OF AOSP CONSTANTS
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index ec6d20dd5c6a..c992da43fc07 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -252,9 +252,8 @@ public final class AutofillManagerService
@Override // from AbstractMasterSystemService
protected AutofillManagerServiceImpl newServiceLocked(@UserIdInt int resolvedUserId,
boolean disabled) {
- return new AutofillManagerServiceImpl(this, mLock, mRequestsHistory,
- mUiLatencyHistory, mWtfHistory, resolvedUserId, mUi, mAutofillCompatState,
- disabled);
+ return new AutofillManagerServiceImpl(this, mLock, mUiLatencyHistory,
+ mWtfHistory, resolvedUserId, mUi, mAutofillCompatState, disabled);
}
@Override // AbstractMasterSystemService
@@ -291,6 +290,13 @@ public final class AutofillManagerService
return mSupportedSmartSuggestionModes;
}
+ /**
+ * Logs a request so it's dumped later...
+ */
+ void logRequestLocked(@NonNull String historyItem) {
+ mRequestsHistory.log(historyItem);
+ }
+
// Called by AutofillManagerServiceImpl, doesn't need to check permission
boolean isInstantServiceAllowed() {
return mAllowInstantService;
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index d037b081cd4d..954b67e4e2dc 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -108,7 +108,6 @@ final class AutofillManagerServiceImpl
private static final Random sRandom = new Random();
- private final LocalLog mRequestsHistory;
private final LocalLog mUiLatencyHistory;
private final LocalLog mWtfHistory;
private final FieldClassificationStrategy mFieldClassificationStrategy;
@@ -166,12 +165,12 @@ final class AutofillManagerServiceImpl
@Nullable
private RemoteAugmentedAutofillService mRemoteAugmentedAutofillService;
- AutofillManagerServiceImpl(AutofillManagerService master, Object lock, LocalLog requestsHistory,
+ AutofillManagerServiceImpl(AutofillManagerService master, Object lock,
LocalLog uiLatencyHistory, LocalLog wtfHistory, int userId, AutoFillUI ui,
- AutofillCompatState autofillCompatState, boolean disabled) {
+ AutofillCompatState autofillCompatState,
+ boolean disabled) {
super(master, lock, userId);
- mRequestsHistory = requestsHistory;
mUiLatencyHistory = uiLatencyHistory;
mWtfHistory = wtfHistory;
mUi = ui;
@@ -310,7 +309,7 @@ final class AutofillManagerServiceImpl
+ " s=" + mInfo.getServiceInfo().packageName
+ " u=" + mUserId + " i=" + autofillId + " b=" + virtualBounds
+ " hc=" + hasCallback + " f=" + flags;
- mRequestsHistory.log(historyItem);
+ mMaster.logRequestLocked(historyItem);
newSession.updateLocked(autofillId, virtualBounds, value, ACTION_START_SESSION, flags);
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index a5ef21afc23e..7dfd8fef13c2 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -2610,6 +2610,13 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
+ " when server returned null for session " + this.id);
}
+ final String historyItem =
+ "aug:id=" + id + " u=" + uid + " m=" + mode
+ + " a=" + ComponentName.flattenToShortString(mComponentName)
+ + " f=" + mCurrentViewId
+ + " s=" + remoteService.getComponentName();
+ mService.getMaster().logRequestLocked(historyItem);
+
final AutofillValue currentValue = mViewStates.get(mCurrentViewId).getCurrentValue();
// TODO(b/111330312): we might need to add a new state in the AutofillManager to optimize
diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
index e0e81ffb6b48..79f8a7e4e9ae 100644
--- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
@@ -494,20 +494,18 @@ public class UserBackupManagerService {
mUserId);
mBaseStateDir = checkNotNull(baseStateDir, "baseStateDir cannot be null");
- mBaseStateDir.mkdirs();
- if (!SELinux.restoreconRecursive(mBaseStateDir)) {
- Slog.w(TAG, "SELinux restorecon failed on " + mBaseStateDir);
+ // TODO (b/120424138): Remove once the system user is migrated to use the per-user CE
+ // directory. Per-user CE directories are managed by vold.
+ if (userId == UserHandle.USER_SYSTEM) {
+ mBaseStateDir.mkdirs();
+ if (!SELinux.restorecon(mBaseStateDir)) {
+ Slog.w(TAG, "SELinux restorecon failed on " + mBaseStateDir);
+ }
}
+ // TODO (b/120424138): The system user currently uses the cache which is managed by init.rc
+ // Initialization and restorecon is managed by vold for per-user CE directories.
mDataDir = checkNotNull(dataDir, "dataDir cannot be null");
- // TODO(b/120424138): Remove when the system user moves out of the cache dir. The cache dir
- // is managed by init.rc so we don't have to create it below.
- if (userId != UserHandle.USER_SYSTEM) {
- mDataDir.mkdirs();
- if (!SELinux.restoreconRecursive(mDataDir)) {
- Slog.w(TAG, "SELinux restorecon failed on " + mDataDir);
- }
- }
mBackupPasswordManager = new BackupPasswordManager(mContext, mBaseStateDir, mRng);
// Receivers for scheduled backups and transport initialization operations.
diff --git a/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
index 862ca711e694..cfc129e11c6e 100644
--- a/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
+++ b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
@@ -45,6 +45,7 @@ import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
import android.os.SELinux;
+import android.os.UserHandle;
import android.os.WorkSource;
import com.android.internal.annotations.GuardedBy;
@@ -686,8 +687,12 @@ public class KeyValueBackupTask implements BackupRestoreTask, Runnable {
ParcelFileDescriptor.open(
mNewStateFile, MODE_READ_WRITE | MODE_CREATE | MODE_TRUNCATE);
- if (!SELinux.restorecon(mBackupDataFile)) {
- mReporter.onRestoreconFailed(mBackupDataFile);
+ // TODO (b/120424138): Remove once the system user is migrated to use the per-user CE
+ // directory. Per-user CE directories are managed by vold.
+ if (mUserId == UserHandle.USER_SYSTEM) {
+ if (!SELinux.restorecon(mBackupDataFile)) {
+ mReporter.onRestoreconFailed(mBackupDataFile);
+ }
}
IBackupTransport transport = mTransportClient.connectOrThrow("KVBT.extractAgentData()");
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
index dc0f6028b0f8..e4bbcd67d4df 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
@@ -32,6 +32,7 @@ import android.os.ResultReceiver;
import android.os.ShellCallback;
import android.os.UserHandle;
import android.os.UserManager;
+import android.util.LocalLog;
import android.util.Slog;
import android.view.contentcapture.IContentCaptureManager;
@@ -69,6 +70,8 @@ public final class ContentCaptureManagerService extends
private final LocalService mLocalService = new LocalService();
+ private final LocalLog mRequestsHistory = new LocalLog(20);
+
public ContentCaptureManagerService(@NonNull Context context) {
super(context, new FrameworkResourcesServiceNameResolver(context,
com.android.internal.R.string.config_defaultContentCaptureService),
@@ -154,6 +157,13 @@ public final class ContentCaptureManagerService extends
}
}
+ /**
+ * Logs a request so it's dumped later...
+ */
+ void logRequestLocked(@NonNull String historyItem) {
+ mRequestsHistory.log(historyItem);
+ }
+
private ActivityManagerInternal getAmInternal() {
synchronized (mLock) {
if (mAm == null) {
@@ -217,9 +227,29 @@ public final class ContentCaptureManagerService extends
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) return;
+ boolean showHistory = true;
+ if (args != null) {
+ for (String arg : args) {
+ switch(arg) {
+ case "--no-history":
+ showHistory = false;
+ break;
+ case "--help":
+ pw.println("Usage: dumpsys content_capture [--no-history]");
+ return;
+ default:
+ Slog.w(TAG, "Ignoring invalid dump arg: " + arg);
+ }
+ }
+ }
+
synchronized (mLock) {
dumpLocked("", pw);
}
+ if (showHistory) {
+ pw.println(); pw.println("Requests history:"); pw.println();
+ mRequestsHistory.reverseDump(fd, pw, args);
+ }
}
@Override
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
index 1dae2ceae7d9..8d2c79bd9923 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
@@ -85,7 +85,6 @@ final class ContentCapturePerUserService
ContentCapturePerUserService(@NonNull ContentCaptureManagerService master,
@NonNull Object lock, boolean disabled, @UserIdInt int userId) {
super(master, lock, userId);
-
updateRemoteServiceLocked(disabled);
}
@@ -170,14 +169,24 @@ final class ContentCapturePerUserService
@NonNull ComponentName componentName, int taskId, int displayId,
@NonNull String sessionId, int uid, int flags,
@NonNull IResultReceiver clientReceiver) {
- if (!isEnabledLocked()) {
+
+ final ComponentName serviceComponentName = getServiceComponentName();
+ final boolean enabled = isEnabledLocked();
+ final String historyItem =
+ "id=" + sessionId + " uid=" + uid
+ + " a=" + ComponentName.flattenToShortString(componentName)
+ + " t=" + taskId + " d=" + displayId
+ + " s=" + ComponentName.flattenToShortString(serviceComponentName)
+ + " u=" + mUserId + " f=" + flags + (enabled ? "" : " (disabled)");
+ mMaster.logRequestLocked(historyItem);
+
+ if (!enabled) {
// TODO: it would be better to split in differet reasons, like
// STATE_DISABLED_NO_SERVICE and STATE_DISABLED_BY_DEVICE_POLICY
setClientState(clientReceiver, STATE_DISABLED | STATE_NO_SERVICE,
/* binder= */ null);
return;
}
- final ComponentName serviceComponentName = getServiceComponentName();
if (serviceComponentName == null) {
// TODO(b/111276913): this happens when the system service is starting, we should
// probably handle it in a more elegant way (like waiting for boot_complete or
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java
index ebe0083b398e..3c52e17ce1e8 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java
@@ -83,6 +83,8 @@ final class ContentCaptureServerSession {
*/
@GuardedBy("mLock")
public void sendActivitySnapshotLocked(@NonNull SnapshotData snapshotData) {
+ mService.getMaster().logRequestLocked("snapshot: id=" + mId);
+
mRemoteService.onActivitySnapshotRequest(mId, snapshotData);
}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index d6f3e2ba4835..00550d9c660e 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -1494,6 +1494,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
newNc.setUids(null);
newNc.setSSID(null);
}
+ if (newNc.getNetworkSpecifier() != null) {
+ newNc.setNetworkSpecifier(newNc.getNetworkSpecifier().redact());
+ }
return newNc;
}
@@ -5358,7 +5361,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
switch (notificationType) {
case ConnectivityManager.CALLBACK_AVAILABLE: {
- putParcelable(bundle, new NetworkCapabilities(networkAgent.networkCapabilities));
+ putParcelable(bundle, networkCapabilitiesRestrictedForCallerPermissions(
+ networkAgent.networkCapabilities, nri.mPid, nri.mUid));
putParcelable(bundle, new LinkProperties(networkAgent.linkProperties));
// For this notification, arg1 contains the blocked status.
msg.arg1 = arg1;
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 1f9362e246b7..dc033691eea5 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -132,8 +132,11 @@ public final class OomAdjuster {
mActiveUids = activeUids;
mLocalPowerManager = LocalServices.getService(PowerManagerInternal.class);
- mAppCompact = new AppCompactor(mService);
mConstants = mService.mConstants;
+ // mConstants can be null under test, which causes AppCompactor to crash
+ if (mConstants != null) {
+ mAppCompact = new AppCompactor(mService);
+ }
}
/**
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 979de66f1dc8..669ff2b7bad5 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -138,6 +138,9 @@ public class InputManagerService extends IInputManager.Stub
private final Context mContext;
private final InputManagerHandler mHandler;
+ // Context cache used for loading pointer resources.
+ private Context mDisplayContext;
+
private final File mDoubleTouchGestureEnableFile;
private WindowManagerCallbacks mWindowManagerCallbacks;
@@ -1923,8 +1926,25 @@ public class InputManagerService extends IInputManager.Stub
}
// Native callback.
- private PointerIcon getPointerIcon() {
- return PointerIcon.getDefaultIcon(mContext);
+ private PointerIcon getPointerIcon(int displayId) {
+ return PointerIcon.getDefaultIcon(getContextForDisplay(displayId));
+ }
+
+ private Context getContextForDisplay(int displayId) {
+ if (mDisplayContext != null && mDisplayContext.getDisplay().getDisplayId() == displayId) {
+ return mDisplayContext;
+ }
+
+ if (mContext.getDisplay().getDisplayId() == displayId) {
+ mDisplayContext = mContext;
+ return mDisplayContext;
+ }
+
+ // Create and cache context for non-default display.
+ final DisplayManager displayManager = mContext.getSystemService(DisplayManager.class);
+ final Display display = displayManager.getDisplay(displayId);
+ mDisplayContext = mContext.createDisplayContext(display);
+ return mDisplayContext;
}
// Native callback.
diff --git a/services/core/java/com/android/server/om/IdmapManager.java b/services/core/java/com/android/server/om/IdmapManager.java
index 16143d3ae9e0..74fbea1544bd 100644
--- a/services/core/java/com/android/server/om/IdmapManager.java
+++ b/services/core/java/com/android/server/om/IdmapManager.java
@@ -24,11 +24,14 @@ import static com.android.server.om.OverlayManagerService.TAG;
import android.annotation.NonNull;
import android.content.om.OverlayInfo;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
+import android.os.Build.VERSION_CODES;
import android.os.IBinder;
import android.os.IIdmap2;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.SystemProperties;
import android.os.UserHandle;
import android.util.Slog;
@@ -51,6 +54,13 @@ class IdmapManager {
private final Installer mInstaller;
private IIdmap2 mIdmap2Service;
+ private static final boolean VENDOR_IS_Q_OR_LATER;
+ static {
+ // STOPSHIP(b/119390857): Check api version once Q sdk version is finalized
+ final String value = SystemProperties.get("ro.vndk.version", "Q");
+ VENDOR_IS_Q_OR_LATER = value.equals("Q") || value.equals("q");
+ }
+
IdmapManager(final Installer installer) {
mInstaller = installer;
if (FEATURE_FLAG_IDMAP2) {
@@ -69,10 +79,13 @@ class IdmapManager {
final String overlayPath = overlayPackage.applicationInfo.getBaseCodePath();
try {
if (FEATURE_FLAG_IDMAP2) {
- if (mIdmap2Service.verifyIdmap(overlayPath, userId)) {
+ int policies = determineFulfilledPolicies(overlayPackage);
+ boolean enforce = enforceOverlayable(overlayPackage);
+ if (mIdmap2Service.verifyIdmap(overlayPath, policies, enforce, userId)) {
return true;
}
- return mIdmap2Service.createIdmap(targetPath, overlayPath, userId) != null;
+ return mIdmap2Service.createIdmap(targetPath, overlayPath, policies, enforce,
+ userId) != null;
} else {
mInstaller.idmap(targetPath, overlayPath, sharedGid);
return true;
@@ -156,4 +169,71 @@ class IdmapManager {
}, SECOND_IN_MILLIS);
}
}
+
+ /**
+ * Checks if overlayable and policies should be enforced on the specified overlay for backwards
+ * compatibility with pre-Q overlays.
+ */
+ private boolean enforceOverlayable(@NonNull final PackageInfo overlayPackage) {
+ final ApplicationInfo ai = overlayPackage.applicationInfo;
+ if (ai.targetSdkVersion >= VERSION_CODES.Q) {
+ // Always enforce policies for overlays targeting Q+.
+ return true;
+ }
+
+ if (ai.isVendor() && !VENDOR_IS_Q_OR_LATER) {
+ // If the overlay is on a pre-Q vendor partition, do not enforce overlayable
+ // restrictions on this overlay because the pre-Q platform has no understanding of
+ // overlayable.
+ return false;
+ }
+
+ // Do not enforce overlayable restrictions on pre-Q overlays signed with the
+ // platform signature.
+ return !ai.isSignedWithPlatformKey();
+ }
+
+ /**
+ * Retrieves a bitmask for idmap2 that represents the policies the specified overlay fulfills.
+ * @throws SecurityException if the overlay is not allowed to overlay any resource
+ */
+ private int determineFulfilledPolicies(@NonNull final PackageInfo overlayPackage)
+ throws SecurityException {
+ final ApplicationInfo ai = overlayPackage.applicationInfo;
+ final boolean overlayIsQOrLater = ai.targetSdkVersion >= VERSION_CODES.Q;
+
+ int fulfilledPolicies = 0;
+
+ // TODO(b/119402606) : Add signature policy
+
+ // Vendor partition (/vendor)
+ if (ai.isVendor()) {
+ if (overlayIsQOrLater) {
+ fulfilledPolicies |= IIdmap2.POLICY_VENDOR_PARTITION;
+ } else if (VENDOR_IS_Q_OR_LATER) {
+ throw new SecurityException("Overlay must target Q sdk or higher");
+ }
+ }
+
+ // Product partition (/product)
+ if (ai.isProduct()) {
+ if (overlayIsQOrLater) {
+ fulfilledPolicies |= IIdmap2.POLICY_PRODUCT_PARTITION;
+ } else {
+ throw new SecurityException("Overlay must target Q sdk or higher");
+ }
+ }
+
+ // System partition (/system)
+ if (ai.isSystemApp()) {
+ if (overlayIsQOrLater) {
+ fulfilledPolicies |= IIdmap2.POLICY_SYSTEM_PARTITION;
+ } else {
+ throw new SecurityException("Overlay must target Q sdk or higher");
+ }
+ }
+
+ // All overlays can overlay resources with the public policy
+ return fulfilledPolicies | IIdmap2.POLICY_PUBLIC;
+ }
}
diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
index b0d2704196a6..1cbf0bfac05c 100644
--- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
+++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
@@ -270,7 +270,9 @@ final class OverlayManagerServiceImpl {
Slog.d(TAG, "onTargetPackageUpgraded packageName=" + packageName + " userId=" + userId);
}
- updateAllOverlaysForTarget(packageName, userId, 0);
+ if (updateAllOverlaysForTarget(packageName, userId, 0)) {
+ mListener.onOverlaysChanged(packageName, userId);
+ }
}
void onTargetPackageRemoved(@NonNull final String packageName, final int userId) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 70ead41853d0..6fe32c5677d4 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -1343,6 +1343,7 @@ public class PackageManagerService extends IPackageManager.Stub
final @Nullable String mWellbeingPackage;
final @Nullable String mDocumenterPackage;
final @Nullable String mConfiguratorPackage;
+ final @Nullable String mAppPredictionServicePackage;
final @NonNull String mServicesSystemSharedLibraryPackageName;
final @NonNull String mSharedSystemSharedLibraryPackageName;
@@ -2868,6 +2869,7 @@ public class PackageManagerService extends IPackageManager.Stub
mDocumenterPackage = getDocumenterPackageName();
mConfiguratorPackage =
mContext.getString(R.string.config_deviceConfiguratorPackageName);
+ mAppPredictionServicePackage = getAppPredictionServicePackageName();
// Now that we know all of the shared libraries, update all clients to have
// the correct library paths.
@@ -3750,7 +3752,7 @@ public class PackageManagerService extends IPackageManager.Stub
/**
* Returns whether or not a full application can see an instant application.
* <p>
- * Currently, there are three cases in which this can occur:
+ * Currently, there are four cases in which this can occur:
* <ol>
* <li>The calling application is a "special" process. Special processes
* are those with a UID < {@link Process#FIRST_APPLICATION_UID}.</li>
@@ -3758,6 +3760,7 @@ public class PackageManagerService extends IPackageManager.Stub
* {@link android.Manifest.permission#ACCESS_INSTANT_APPS}.</li>
* <li>The calling application is the default launcher on the
* system partition.</li>
+ * <li>The calling application is the default app prediction service.</li>
* </ol>
*/
private boolean canViewInstantApps(int callingUid, int userId) {
@@ -3775,6 +3778,11 @@ public class PackageManagerService extends IPackageManager.Stub
&& isCallerSameApp(homeComponent.getPackageName(), callingUid)) {
return true;
}
+ // TODO(b/122900055) Change/Remove this and replace with new permission role.
+ if (mAppPredictionServicePackage != null
+ && isCallerSameApp(mAppPredictionServicePackage, callingUid)) {
+ return true;
+ }
}
return false;
}
@@ -5490,13 +5498,13 @@ public class PackageManagerService extends IPackageManager.Stub
final int callingUserId = UserHandle.getUserId(callingUid);
final boolean isCallerInstantApp = getInstantAppPackageName(callingUid) != null;
// Map to base uids.
- uid1 = UserHandle.getAppId(uid1);
- uid2 = UserHandle.getAppId(uid2);
+ final int appId1 = UserHandle.getAppId(uid1);
+ final int appId2 = UserHandle.getAppId(uid2);
// reader
synchronized (mPackages) {
Signature[] s1;
Signature[] s2;
- Object obj = mSettings.getSettingLPr(uid1);
+ Object obj = mSettings.getSettingLPr(appId1);
if (obj != null) {
if (obj instanceof SharedUserSetting) {
if (isCallerInstantApp) {
@@ -5515,7 +5523,7 @@ public class PackageManagerService extends IPackageManager.Stub
} else {
return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
}
- obj = mSettings.getSettingLPr(uid2);
+ obj = mSettings.getSettingLPr(appId2);
if (obj != null) {
if (obj instanceof SharedUserSetting) {
if (isCallerInstantApp) {
@@ -5570,11 +5578,11 @@ public class PackageManagerService extends IPackageManager.Stub
final int callingUid = Binder.getCallingUid();
final int callingUserId = UserHandle.getUserId(callingUid);
// Map to base uids.
- uid = UserHandle.getAppId(uid);
+ final int appId = UserHandle.getAppId(uid);
// reader
synchronized (mPackages) {
final PackageParser.SigningDetails signingDetails;
- final Object obj = mSettings.getSettingLPr(uid);
+ final Object obj = mSettings.getSettingLPr(appId);
if (obj != null) {
if (obj instanceof SharedUserSetting) {
final boolean isCallerInstantApp = getInstantAppPackageName(callingUid) != null;
@@ -5690,10 +5698,10 @@ public class PackageManagerService extends IPackageManager.Stub
final int callingUid = Binder.getCallingUid();
final boolean isCallerInstantApp = getInstantAppPackageName(callingUid) != null;
final int userId = UserHandle.getUserId(uid);
- uid = UserHandle.getAppId(uid);
+ final int appId = UserHandle.getAppId(uid);
// reader
synchronized (mPackages) {
- Object obj = mSettings.getSettingLPr(uid);
+ final Object obj = mSettings.getSettingLPr(appId);
if (obj instanceof SharedUserSetting) {
if (isCallerInstantApp) {
return null;
@@ -5728,8 +5736,9 @@ public class PackageManagerService extends IPackageManager.Stub
if (getInstantAppPackageName(callingUid) != null) {
return null;
}
+ final int appId = UserHandle.getAppId(uid);
synchronized (mPackages) {
- Object obj = mSettings.getSettingLPr(UserHandle.getAppId(uid));
+ final Object obj = mSettings.getSettingLPr(appId);
if (obj instanceof SharedUserSetting) {
final SharedUserSetting sus = (SharedUserSetting) obj;
return sus.name + ":" + sus.userId;
@@ -5756,8 +5765,8 @@ public class PackageManagerService extends IPackageManager.Stub
final String[] names = new String[uids.length];
synchronized (mPackages) {
for (int i = uids.length - 1; i >= 0; i--) {
- final int uid = uids[i];
- Object obj = mSettings.getSettingLPr(UserHandle.getAppId(uid));
+ final int appId = UserHandle.getAppId(uids[i]);
+ final Object obj = mSettings.getSettingLPr(appId);
if (obj instanceof SharedUserSetting) {
final SharedUserSetting sus = (SharedUserSetting) obj;
names[i] = "shared:" + sus.name;
@@ -5805,8 +5814,9 @@ public class PackageManagerService extends IPackageManager.Stub
if (getInstantAppPackageName(callingUid) != null) {
return 0;
}
+ final int appId = UserHandle.getAppId(uid);
synchronized (mPackages) {
- Object obj = mSettings.getSettingLPr(UserHandle.getAppId(uid));
+ final Object obj = mSettings.getSettingLPr(appId);
if (obj instanceof SharedUserSetting) {
final SharedUserSetting sus = (SharedUserSetting) obj;
return sus.pkgFlags;
@@ -5827,8 +5837,9 @@ public class PackageManagerService extends IPackageManager.Stub
if (getInstantAppPackageName(callingUid) != null) {
return 0;
}
+ final int appId = UserHandle.getAppId(uid);
synchronized (mPackages) {
- Object obj = mSettings.getSettingLPr(UserHandle.getAppId(uid));
+ final Object obj = mSettings.getSettingLPr(appId);
if (obj instanceof SharedUserSetting) {
final SharedUserSetting sus = (SharedUserSetting) obj;
return sus.pkgPrivateFlags;
@@ -5848,10 +5859,10 @@ public class PackageManagerService extends IPackageManager.Stub
if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
return false;
}
- uid = UserHandle.getAppId(uid);
+ final int appId = UserHandle.getAppId(uid);
// reader
synchronized (mPackages) {
- Object obj = mSettings.getSettingLPr(uid);
+ final Object obj = mSettings.getSettingLPr(appId);
if (obj instanceof SharedUserSetting) {
final SharedUserSetting sus = (SharedUserSetting) obj;
final Iterator<PackageSetting> it = sus.packages.iterator();
@@ -13781,6 +13792,11 @@ public class PackageManagerService extends IPackageManager.Stub
ServiceManager.getService(Context.BACKUP_SERVICE));
if (bm != null) {
int userId = args.user.getIdentifier();
+ // For backwards compatibility as USER_ALL previously routed directly to USER_SYSTEM
+ // in the BackupManager. USER_ALL is used in compatibility tests.
+ if (userId == UserHandle.USER_ALL) {
+ userId = UserHandle.USER_SYSTEM;
+ }
if (DEBUG_INSTALL) {
Log.v(TAG, "token " + token + " to BM for possible restore for user " + userId);
}
@@ -18947,7 +18963,8 @@ public class PackageManagerService extends IPackageManager.Stub
@GuardedBy("mPackages")
private int getUidTargetSdkVersionLockedLPr(int uid) {
- Object obj = mSettings.getSettingLPr(uid);
+ final int appId = UserHandle.getAppId(uid);
+ final Object obj = mSettings.getSettingLPr(appId);
if (obj instanceof SharedUserSetting) {
final SharedUserSetting sus = (SharedUserSetting) obj;
int vers = Build.VERSION_CODES.CUR_DEVELOPMENT;
@@ -19138,7 +19155,7 @@ public class PackageManagerService extends IPackageManager.Stub
// writer
synchronized (mPackages) {
PackageParser.Package pkg = mPackages.get(packageName);
- if (pkg == null || pkg.applicationInfo.uid != callingUid) {
+ if (pkg == null || !isCallerSameApp(packageName, callingUid)) {
if (mContext.checkCallingOrSelfPermission(
android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
!= PackageManager.PERMISSION_GRANTED) {
@@ -19811,6 +19828,14 @@ public class PackageManagerService extends IPackageManager.Stub
.setPackage(launcherComponent.getPackageName());
mContext.sendBroadcastAsUser(launcherIntent, UserHandle.of(launcherUid));
}
+ // TODO(b/122900055) Change/Remove this and replace with new permission role.
+ if (mAppPredictionServicePackage != null) {
+ Intent predictorIntent = new Intent(PackageInstaller.ACTION_SESSION_COMMITTED)
+ .putExtra(PackageInstaller.EXTRA_SESSION, sessionInfo)
+ .putExtra(Intent.EXTRA_USER, UserHandle.of(userId))
+ .setPackage(mAppPredictionServicePackage);
+ mContext.sendBroadcastAsUser(predictorIntent, UserHandle.of(launcherUid));
+ }
}
}
@@ -19963,6 +19988,20 @@ public class PackageManagerService extends IPackageManager.Stub
return mContext.getString(R.string.config_defaultWellbeingPackage);
}
+ private String getAppPredictionServicePackageName() {
+ String flattenedAppPredictionServiceComponentName =
+ mContext.getString(R.string.config_defaultAppPredictionService);
+ if (flattenedAppPredictionServiceComponentName == null) {
+ return null;
+ }
+ ComponentName appPredictionServiceComponentName =
+ ComponentName.unflattenFromString(flattenedAppPredictionServiceComponentName);
+ if (appPredictionServiceComponentName == null) {
+ return null;
+ }
+ return appPredictionServiceComponentName.getPackageName();
+ }
+
@Override
public void setApplicationEnabledSetting(String appPackageName,
int newState, int flags, int userId, String callingPackage) {
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 95da2091828d..b0f232607d88 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -2790,13 +2790,13 @@ public final class Settings {
// dataPath - path to package's data path
// seinfo - seinfo label for the app (assigned at install time)
// gids - supplementary gids this app launches with
+ // profileableFromShellFlag - 0 or 1 if the package is profileable from shell.
//
// NOTE: We prefer not to expose all ApplicationInfo flags for now.
//
// DO NOT MODIFY THIS FORMAT UNLESS YOU CAN ALSO MODIFY ITS USERS
// FROM NATIVE CODE. AT THE MOMENT, LOOK AT THE FOLLOWING SOURCES:
- // frameworks/base/libs/packagelistparser
- // system/core/run-as/run-as.c
+ // system/core/libpackagelistparser
//
sb.setLength(0);
sb.append(ai.packageName);
@@ -2816,6 +2816,8 @@ public final class Settings {
} else {
sb.append("none");
}
+ sb.append(" ");
+ sb.append(ai.isProfileableByShell() ? "1" : "0");
sb.append("\n");
writer.append(sb);
}
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index 83f0fde066ec..563fd7f90c4b 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -20,8 +20,10 @@ import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.content.ComponentName;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.pm.PackageInfo;
import android.content.pm.ShortcutInfo;
+import android.content.pm.ShortcutManager;
import android.content.res.Resources;
import android.os.PersistableBundle;
import android.text.format.Formatter;
@@ -640,6 +642,55 @@ class ShortcutPackage extends ShortcutPackageItem {
}
/**
+ * Returns a list of ShortcutInfos that match the given intent filter and the category of
+ * available ShareTarget definitions in this package.
+ */
+ public List<ShortcutManager.ShareShortcutInfo> getMatchingShareTargets(
+ @NonNull IntentFilter filter) {
+ final List<ShareTargetInfo> matchedTargets = new ArrayList<>();
+ for (int i = 0; i < mShareTargets.size(); i++) {
+ final ShareTargetInfo target = mShareTargets.get(i);
+ for (ShareTargetInfo.TargetData data : target.mTargetData) {
+ if (filter.hasDataType(data.mMimeType)) {
+ // Matched at least with one data type
+ matchedTargets.add(target);
+ break;
+ }
+ }
+ }
+
+ if (matchedTargets.isEmpty()) {
+ return new ArrayList<>();
+ }
+
+ // Get the list of all dynamic shortcuts in this package
+ final ArrayList<ShortcutInfo> shortcuts = new ArrayList<>();
+ findAll(shortcuts, ShortcutInfo::isDynamicVisible, ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER);
+
+ final List<ShortcutManager.ShareShortcutInfo> result = new ArrayList<>();
+ for (int i = 0; i < shortcuts.size(); i++) {
+ final ShortcutInfo si = shortcuts.get(i);
+ for (int j = 0; j < matchedTargets.size(); j++) {
+ // Shortcut must have all of share target categories
+ boolean hasAllCategories = true;
+ final ShareTargetInfo target = matchedTargets.get(j);
+ for (int q = 0; q < target.mCategories.length; q++) {
+ if (!si.getCategories().contains(target.mCategories[q])) {
+ hasAllCategories = false;
+ break;
+ }
+ }
+ if (hasAllCategories) {
+ result.add(new ShortcutManager.ShareShortcutInfo(si, new ComponentName(
+ getPackageName(), target.mTargetClass)));
+ break;
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
* Return the filenames (excluding path names) of icon bitmap files from this package.
*/
public ArraySet<String> getUsedBitmapFiles() {
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 2b773f47e3e9..fdbaba24966b 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -46,6 +46,7 @@ import android.content.pm.PackageManagerInternal;
import android.content.pm.ParceledListSlice;
import android.content.pm.ResolveInfo;
import android.content.pm.ShortcutInfo;
+import android.content.pm.ShortcutManager;
import android.content.pm.ShortcutServiceInternal;
import android.content.pm.ShortcutServiceInternal.ShortcutChangeListener;
import android.content.res.Resources;
@@ -2149,6 +2150,23 @@ public class ShortcutService extends IShortcutService.Stub {
}
}
+ @Override
+ public ParceledListSlice<ShortcutManager.ShareShortcutInfo> getShareTargets(String packageName,
+ IntentFilter filter, @UserIdInt int userId) {
+ verifyCaller(packageName, userId);
+
+ synchronized (mLock) {
+ throwIfUserLockedL(userId);
+
+ final List<ShortcutManager.ShareShortcutInfo> shortcutInfoList = new ArrayList<>();
+
+ final ShortcutUser user = getUserShortcutsLocked(userId);
+ user.forAllPackages(p -> shortcutInfoList.addAll(p.getMatchingShareTargets(filter)));
+
+ return new ParceledListSlice<>(shortcutInfoList);
+ }
+ }
+
@GuardedBy("mLock")
private ParceledListSlice<ShortcutInfo> getShortcutsWithQueryLocked(@NonNull String packageName,
@UserIdInt int userId, int cloneFlags, @NonNull Predicate<ShortcutInfo> query) {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index ff93345a6e8d..41cab2d7ebd3 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -480,6 +480,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
int mShortPressOnSleepBehavior;
int mShortPressOnWindowBehavior;
boolean mHasSoftInput = false;
+ boolean mHapticTextHandleEnabled;
boolean mUseTvRouting;
int mVeryLongPressTimeout;
boolean mAllowStartActivityForLongPressOnPowerDuringSetup;
@@ -1836,6 +1837,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mAllowStartActivityForLongPressOnPowerDuringSetup = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_allowStartActivityForLongPressOnPowerInSetup);
+ mHapticTextHandleEnabled = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_enableHapticTextHandle);
+
mUseTvRouting = AudioSystem.getPlatformType(mContext) == AudioSystem.PLATFORM_TELEVISION;
mHandleVolumeKeysInWM = mContext.getResources().getBoolean(
@@ -2291,9 +2295,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
final LayoutParams attrs = win.getAttrs();
- final boolean showImeOverKeyguard = imeTarget != null && imeTarget.isVisibleLw() &&
- ((imeTarget.getAttrs().flags & FLAG_SHOW_WHEN_LOCKED) != 0
- || !canBeHiddenByKeyguardLw(imeTarget));
+ final boolean showImeOverKeyguard = imeTarget != null && imeTarget.isVisibleLw()
+ && (imeTarget.canShowWhenLocked() || !canBeHiddenByKeyguardLw(imeTarget));
// Show IME over the keyguard if the target allows it
boolean allowWhenLocked = (win.isInputMethodWindow() || imeTarget == this)
@@ -2301,7 +2304,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (isKeyguardLocked() && isKeyguardOccluded()) {
// Show SHOW_WHEN_LOCKED windows if Keyguard is occluded.
- allowWhenLocked |= (attrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0
+ allowWhenLocked |= win.canShowWhenLocked()
// Show error dialogs over apps that are shown on lockscreen
|| (attrs.privateFlags & PRIVATE_FLAG_SYSTEM_ERROR) != 0;
}
@@ -5201,8 +5204,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case HapticFeedbackConstants.CLOCK_TICK:
case HapticFeedbackConstants.CONTEXT_CLICK:
return VibrationEffect.get(VibrationEffect.EFFECT_TICK);
- case HapticFeedbackConstants.KEYBOARD_RELEASE:
case HapticFeedbackConstants.TEXT_HANDLE_MOVE:
+ if (!mHapticTextHandleEnabled) {
+ return null;
+ }
+ case HapticFeedbackConstants.KEYBOARD_RELEASE:
case HapticFeedbackConstants.VIRTUAL_KEY_RELEASE:
case HapticFeedbackConstants.ENTRY_BUMP:
case HapticFeedbackConstants.DRAG_CROSSING:
@@ -5367,11 +5373,13 @@ public class PhoneWindowManager implements WindowManagerPolicy {
pw.println(mAllowStartActivityForLongPressOnPowerDuringSetup);
pw.print(prefix);
pw.print("mHasSoftInput="); pw.print(mHasSoftInput);
- pw.print(" mDismissImeOnBackKeyPressed="); pw.println(mDismissImeOnBackKeyPressed);
+ pw.print(" mHapticTextHandleEnabled="); pw.println(mHapticTextHandleEnabled);
+ pw.print(prefix);
+ pw.print("mDismissImeOnBackKeyPressed="); pw.print(mDismissImeOnBackKeyPressed);
+ pw.print(" mIncallPowerBehavior=");
+ pw.println(incallPowerBehaviorToString(mIncallPowerBehavior));
pw.print(prefix);
- pw.print("mIncallPowerBehavior=");
- pw.print(incallPowerBehaviorToString(mIncallPowerBehavior));
- pw.print(" mIncallBackBehavior=");
+ pw.print("mIncallBackBehavior=");
pw.print(incallBackBehaviorToString(mIncallBackBehavior));
pw.print(" mEndcallBehavior=");
pw.println(endcallBehaviorToString(mEndcallBehavior));
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index c37254b22ea5..e1a911e8ada5 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -468,6 +468,9 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants {
/** @return true if this window desires key events. */
boolean canReceiveKeys();
+ /** @return true if the window can show over keyguard. */
+ boolean canShowWhenLocked();
+
/**
* Writes {@link com.android.server.wm.IdentifierProto} to stream.
*/
diff --git a/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java b/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java
index 45c975b26956..055c941f8b0a 100644
--- a/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java
+++ b/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java
@@ -62,6 +62,8 @@ public class LegacyRoleResolutionPolicy implements RoleManagerService.RoleHolder
mContext.getContentResolver(),
Settings.Secure.SMS_DEFAULT_APPLICATION, userId);
+ // TODO: STOPSHIP: Remove the following code once we remove default_sms_application
+ // and use the new config_defaultRoleHolders.
if (result == null) {
Collection<SmsApplication.SmsApplicationData> applications =
SmsApplication.getApplicationCollectionAsUser(mContext, userId);
diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java
index c0ec3672c665..5516b234925b 100644
--- a/services/core/java/com/android/server/role/RoleManagerService.java
+++ b/services/core/java/com/android/server/role/RoleManagerService.java
@@ -229,9 +229,12 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
// Any role for which we have a record are already migrated
RoleUserState userState = getOrCreateUserState(userId);
if (!userState.isRoleAvailable(role)) {
- userState.addRoleName(role);
List<String> roleHolders = mLegacyRoleResolver.getRoleHolders(role, userId);
+ if (roleHolders.isEmpty()) {
+ return;
+ }
Slog.i(LOG_TAG, "Migrating " + role + ", legacy holders: " + roleHolders);
+ userState.addRoleName(role);
int size = roleHolders.size();
for (int i = 0; i < size; i++) {
userState.addRoleHolder(role, roleHolders.get(i));
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 9f8af5048da2..b8634d88319a 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -2508,6 +2508,13 @@ final class ActivityRecord extends ConfigurationContainer {
final IBinder binder =
(freezeScreenIfNeeded && appToken != null) ? appToken.asBinder() : null;
mAppWindowToken.setOrientation(requestedOrientation, binder, this);
+
+ // Push the new configuration to the requested app in case where it's not pushed, e.g. when
+ // the request is handled at task level with letterbox.
+ if (!getMergedOverrideConfiguration().equals(
+ mLastReportedConfiguration.getMergedConfiguration())) {
+ ensureActivityConfiguration(0 /* globalChanges */, false /* preserveWindow */);
+ }
}
int getOrientation() {
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index a4cda5aac895..3a288ca5560d 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -2641,6 +2641,9 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
try {
mService.moveTaskToFrontLocked(task.taskId, 0, options,
true /* fromRecents */);
+ // Apply options to prevent pendingOptions be taken by client to make sure
+ // the override pending app transition will be applied immediately.
+ targetActivity.applyOptionsLocked();
} finally {
mActivityMetricsLogger.notifyActivityLaunched(START_TASK_TO_FRONT,
targetActivity);
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index b735115be61e..6527ca0e751d 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -328,14 +328,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
private int mLastOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
/**
- * Flag indicating that the application is receiving an orientation that has different metrics
- * than it expected. E.g. Portrait instead of Landscape.
- *
- * @see #updateRotationUnchecked()
- */
- private boolean mAltOrientation = false;
-
- /**
* Orientation forced by some window. If there is no visible window that specifies orientation
* it is set to {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED}.
*
@@ -1085,10 +1077,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
return mLastOrientation;
}
- boolean getAltOrientation() {
- return mAltOrientation;
- }
-
int getLastWindowForcedOrientation() {
return mLastWindowForcedOrientation;
}
@@ -1130,15 +1118,9 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
boolean rotationNeedsUpdate() {
final int lastOrientation = getLastOrientation();
final int oldRotation = getRotation();
- final boolean oldAltOrientation = getAltOrientation();
final int rotation = mDisplayRotation.rotationForOrientation(lastOrientation, oldRotation);
- final boolean altOrientation = !mDisplayRotation.rotationHasCompatibleMetrics(
- lastOrientation, rotation);
- if (oldRotation == rotation && oldAltOrientation == altOrientation) {
- return false;
- }
- return true;
+ return oldRotation != rotation;
}
/**
@@ -1336,7 +1318,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
final int oldRotation = mRotation;
final int lastOrientation = mLastOrientation;
- final boolean oldAltOrientation = mAltOrientation;
final int rotation = mDisplayRotation.rotationForOrientation(lastOrientation, oldRotation);
if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Computed rotation=" + rotation + " for display id="
+ mDisplayId + " based on lastOrientation=" + lastOrientation
@@ -1368,35 +1349,26 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
}
final boolean rotateSeamlessly = mayRotateSeamlessly;
- // TODO: Implement forced rotation changes.
- // Set mAltOrientation to indicate that the application is receiving
- // an orientation that has different metrics than it expected.
- // eg. Portrait instead of Landscape.
-
- final boolean altOrientation = !mDisplayRotation.rotationHasCompatibleMetrics(
- lastOrientation, rotation);
-
if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Display id=" + mDisplayId
+ " selected orientation " + lastOrientation
+ ", got rotation " + rotation + " which has "
- + (altOrientation ? "incompatible" : "compatible") + " metrics");
+ + " metrics");
- if (oldRotation == rotation && oldAltOrientation == altOrientation) {
+ if (oldRotation == rotation) {
// No change.
return false;
}
if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Display id=" + mDisplayId
+ " rotation changed to " + rotation
- + (altOrientation ? " (alt)" : "") + " from " + oldRotation
- + (oldAltOrientation ? " (alt)" : "") + ", lastOrientation=" + lastOrientation);
+ + " from " + oldRotation
+ + ", lastOrientation=" + lastOrientation);
if (DisplayContent.deltaRotation(rotation, oldRotation) != 2) {
mWaitingForConfig = true;
}
mRotation = rotation;
- mAltOrientation = altOrientation;
mWmService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_ACTIVE;
mWmService.mH.sendNewMessageDelayed(WindowManagerService.H.WINDOW_FREEZE_TIMEOUT,
@@ -1538,26 +1510,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
private DisplayInfo updateDisplayAndOrientation(int uiMode) {
// Use the effective "visual" dimensions based on current rotation
final boolean rotated = (mRotation == ROTATION_90 || mRotation == ROTATION_270);
- final int realdw = rotated ? mBaseDisplayHeight : mBaseDisplayWidth;
- final int realdh = rotated ? mBaseDisplayWidth : mBaseDisplayHeight;
- int dw = realdw;
- int dh = realdh;
-
- if (mAltOrientation) {
- if (realdw > realdh) {
- // Turn landscape into portrait.
- int maxw = (int)(realdh/1.3f);
- if (maxw < realdw) {
- dw = maxw;
- }
- } else {
- // Turn portrait into landscape.
- int maxh = (int)(realdw/1.3f);
- if (maxh < realdh) {
- dh = maxh;
- }
- }
- }
+ final int dw = rotated ? mBaseDisplayHeight : mBaseDisplayWidth;
+ final int dh = rotated ? mBaseDisplayWidth : mBaseDisplayHeight;
// Update application display metrics.
final WmDisplayCutout wmDisplayCutout = calculateDisplayCutoutForRotation(mRotation);
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index 7aabc15d9860..bc165dceb544 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -676,36 +676,6 @@ public class DisplayRotation {
return rotation == mPortraitRotation || rotation == mUpsideDownRotation;
}
- /**
- * Given an orientation constant and a rotation, returns true if the rotation
- * has compatible metrics to the requested orientation. For example, if
- * the application requested landscape and got seascape, then the rotation
- * has compatible metrics; if the application requested portrait and got landscape,
- * then the rotation has incompatible metrics; if the application did not specify
- * a preference, then anything goes.
- *
- * @param orientation An orientation constant, such as
- * {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_LANDSCAPE}.
- * @param rotation The rotation to check.
- * @return True if the rotation is compatible with the requested orientation.
- */
- boolean rotationHasCompatibleMetrics(int orientation, int rotation) {
- switch (orientation) {
- case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
- case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
- case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
- return isAnyPortrait(rotation);
-
- case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
- case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
- case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
- return isLandscapeOrSeascape(rotation);
-
- default:
- return true;
- }
- }
-
private boolean isValidRotationChoice(final int preferredRotation) {
// Determine if the given app orientation is compatible with the provided rotation choice.
switch (mCurrentAppOrientation) {
diff --git a/services/core/java/com/android/server/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java
index 55554a716478..9b7214120aed 100644
--- a/services/core/java/com/android/server/wm/RootActivityContainer.java
+++ b/services/core/java/com/android/server/wm/RootActivityContainer.java
@@ -234,7 +234,7 @@ class RootActivityContainer extends ConfigurationContainer
mWindowManager = wm;
setWindowContainer(mWindowManager.mRoot);
mDisplayManager = mService.mContext.getSystemService(DisplayManager.class);
- mDisplayManager.registerDisplayListener(this, mService.mH);
+ mDisplayManager.registerDisplayListener(this, mService.mUiHandler);
mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
final Display[] displays = mDisplayManager.getDisplays();
diff --git a/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java b/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java
index 905787051de8..2e5df45f9080 100644
--- a/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java
+++ b/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java
@@ -31,6 +31,10 @@ import android.view.WindowManagerPolicyConstants.PointerEventListener;
import com.android.server.wm.WindowManagerService.H;
+/**
+ * 1. Adjust the top most focus display if touch down on some display.
+ * 2. Adjust the pointer icon when cursor moves to the task bounds.
+ */
public class TaskTapPointerEventListener implements PointerEventListener {
private final Region mTouchExcludeRegion = new Region();
@@ -80,8 +84,7 @@ public class TaskTapPointerEventListener implements PointerEventListener {
if (motionEvent.getDisplayId() != getDisplayId()) {
return;
}
- final int action = motionEvent.getAction();
- switch (action & MotionEvent.ACTION_MASK) {
+ switch (motionEvent.getActionMasked()) {
case MotionEvent.ACTION_DOWN: {
final int x = (int) motionEvent.getX();
final int y = (int) motionEvent.getY();
@@ -97,7 +100,7 @@ public class TaskTapPointerEventListener implements PointerEventListener {
}
}
break;
-
+ case MotionEvent.ACTION_HOVER_ENTER:
case MotionEvent.ACTION_HOVER_MOVE: {
final int x = (int) motionEvent.getX();
final int y = (int) motionEvent.getY();
@@ -125,6 +128,7 @@ public class TaskTapPointerEventListener implements PointerEventListener {
mPointerIconType = iconType;
if (mPointerIconType == TYPE_NOT_SPECIFIED) {
// Find the underlying window and ask it restore the pointer icon.
+ mService.mH.removeMessages(H.RESTORE_POINTER_ICON);
mService.mH.obtainMessage(H.RESTORE_POINTER_ICON,
x, y, mDisplayContent).sendToTarget();
} else {
@@ -133,6 +137,18 @@ public class TaskTapPointerEventListener implements PointerEventListener {
}
}
break;
+ case MotionEvent.ACTION_HOVER_EXIT: {
+ final int x = (int) motionEvent.getX();
+ final int y = (int) motionEvent.getY();
+ if (mPointerIconType != TYPE_NOT_SPECIFIED) {
+ mPointerIconType = TYPE_NOT_SPECIFIED;
+ // Find the underlying window and ask it to restore the pointer icon.
+ mService.mH.removeMessages(H.RESTORE_POINTER_ICON);
+ mService.mH.obtainMessage(H.RESTORE_POINTER_ICON,
+ x, y, mDisplayContent).sendToTarget();
+ }
+ }
+ break;
}
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 0c4f4961d215..fda7a85c1270 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -5943,8 +5943,6 @@ public class WindowManagerService extends IWindowManager.Stub
pw.print(" apps="); pw.print(mAppsFreezingScreen);
final DisplayContent defaultDisplayContent = getDefaultDisplayContentLocked();
pw.print(" mRotation="); pw.print(defaultDisplayContent.getRotation());
- pw.print(" mAltOrientation=");
- pw.println(defaultDisplayContent.getAltOrientation());
pw.print(" mLastWindowForcedOrientation=");
pw.print(defaultDisplayContent.getLastWindowForcedOrientation());
pw.print(" mLastOrientation=");
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index cd29b3c29248..8f86c003e4b0 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2405,6 +2405,14 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
&& !cantReceiveTouchInput();
}
+ @Override
+ public boolean canShowWhenLocked() {
+ final boolean showBecauseOfActivity =
+ mAppToken != null && mAppToken.mActivityRecord.canShowWhenLocked();
+ final boolean showBecauseOfWindow = (getAttrs().flags & FLAG_SHOW_WHEN_LOCKED) != 0;
+ return showBecauseOfActivity || showBecauseOfWindow;
+ }
+
/** @return false if this window desires touch events. */
boolean cantReceiveTouchInput() {
return mAppToken != null && mAppToken.getTask() != null
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 641200769cf0..90c9cc2b0a35 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -111,6 +111,7 @@ static struct {
jmethodID getKeyboardLayoutOverlay;
jmethodID getDeviceAlias;
jmethodID getTouchCalibrationForInputDevice;
+ jmethodID getContextForDisplay;
} gServiceClassInfo;
static struct {
@@ -260,17 +261,16 @@ public:
/* --- PointerControllerPolicyInterface implementation --- */
- virtual void loadPointerIcon(SpriteIcon* icon);
- virtual void loadPointerResources(PointerResources* outResources);
+ virtual void loadPointerIcon(SpriteIcon* icon, int32_t displayId);
+ virtual void loadPointerResources(PointerResources* outResources, int32_t displayId);
virtual void loadAdditionalMouseResources(std::map<int32_t, SpriteIcon>* outResources,
- std::map<int32_t, PointerAnimation>* outAnimationResources);
+ std::map<int32_t, PointerAnimation>* outAnimationResources, int32_t displayId);
virtual int32_t getDefaultPointerIconId();
virtual int32_t getCustomPointerIconId();
private:
sp<InputManager> mInputManager;
- jobject mContextObj;
jobject mServiceObj;
sp<Looper> mLooper;
@@ -329,7 +329,6 @@ NativeInputManager::NativeInputManager(jobject contextObj,
mLooper(looper), mInteractive(true) {
JNIEnv* env = jniEnv();
- mContextObj = env->NewGlobalRef(contextObj);
mServiceObj = env->NewGlobalRef(serviceObj);
{
@@ -351,7 +350,6 @@ NativeInputManager::NativeInputManager(jobject contextObj,
NativeInputManager::~NativeInputManager() {
JNIEnv* env = jniEnv();
- env->DeleteGlobalRef(mContextObj);
env->DeleteGlobalRef(mServiceObj);
}
@@ -1202,19 +1200,22 @@ bool NativeInputManager::checkInjectEventsPermissionNonReentrant(
return result;
}
-void NativeInputManager::loadPointerIcon(SpriteIcon* icon) {
+void NativeInputManager::loadPointerIcon(SpriteIcon* icon, int32_t displayId) {
ATRACE_CALL();
JNIEnv* env = jniEnv();
ScopedLocalRef<jobject> pointerIconObj(env, env->CallObjectMethod(
- mServiceObj, gServiceClassInfo.getPointerIcon));
+ mServiceObj, gServiceClassInfo.getPointerIcon, displayId));
if (checkAndClearExceptionFromCallback(env, "getPointerIcon")) {
return;
}
+ ScopedLocalRef<jobject> displayContext(env, env->CallObjectMethod(
+ mServiceObj, gServiceClassInfo.getContextForDisplay, displayId));
+
PointerIcon pointerIcon;
status_t status = android_view_PointerIcon_load(env, pointerIconObj.get(),
- mContextObj, &pointerIcon);
+ displayContext.get(), &pointerIcon);
if (!status && !pointerIcon.isNullIcon()) {
*icon = SpriteIcon(pointerIcon.bitmap, pointerIcon.hotSpotX, pointerIcon.hotSpotY);
} else {
@@ -1222,28 +1223,34 @@ void NativeInputManager::loadPointerIcon(SpriteIcon* icon) {
}
}
-void NativeInputManager::loadPointerResources(PointerResources* outResources) {
+void NativeInputManager::loadPointerResources(PointerResources* outResources, int32_t displayId) {
ATRACE_CALL();
JNIEnv* env = jniEnv();
- loadSystemIconAsSprite(env, mContextObj, POINTER_ICON_STYLE_SPOT_HOVER,
+ ScopedLocalRef<jobject> displayContext(env, env->CallObjectMethod(
+ mServiceObj, gServiceClassInfo.getContextForDisplay, displayId));
+
+ loadSystemIconAsSprite(env, displayContext.get(), POINTER_ICON_STYLE_SPOT_HOVER,
&outResources->spotHover);
- loadSystemIconAsSprite(env, mContextObj, POINTER_ICON_STYLE_SPOT_TOUCH,
+ loadSystemIconAsSprite(env, displayContext.get(), POINTER_ICON_STYLE_SPOT_TOUCH,
&outResources->spotTouch);
- loadSystemIconAsSprite(env, mContextObj, POINTER_ICON_STYLE_SPOT_ANCHOR,
+ loadSystemIconAsSprite(env, displayContext.get(), POINTER_ICON_STYLE_SPOT_ANCHOR,
&outResources->spotAnchor);
}
void NativeInputManager::loadAdditionalMouseResources(std::map<int32_t, SpriteIcon>* outResources,
- std::map<int32_t, PointerAnimation>* outAnimationResources) {
+ std::map<int32_t, PointerAnimation>* outAnimationResources, int32_t displayId) {
ATRACE_CALL();
JNIEnv* env = jniEnv();
+ ScopedLocalRef<jobject> displayContext(env, env->CallObjectMethod(
+ mServiceObj, gServiceClassInfo.getContextForDisplay, displayId));
+
for (int iconId = POINTER_ICON_STYLE_CONTEXT_MENU; iconId <= POINTER_ICON_STYLE_GRABBING;
++iconId) {
PointerIcon pointerIcon;
loadSystemIconAsSpriteWithPointerIcon(
- env, mContextObj, iconId, &pointerIcon, &((*outResources)[iconId]));
+ env, displayContext.get(), iconId, &pointerIcon, &((*outResources)[iconId]));
if (!pointerIcon.bitmapFrames.empty()) {
PointerAnimation& animationData = (*outAnimationResources)[iconId];
size_t numFrames = pointerIcon.bitmapFrames.size() + 1;
@@ -1258,7 +1265,7 @@ void NativeInputManager::loadAdditionalMouseResources(std::map<int32_t, SpriteIc
}
}
}
- loadSystemIconAsSprite(env, mContextObj, POINTER_ICON_STYLE_NULL,
+ loadSystemIconAsSprite(env, displayContext.get(), POINTER_ICON_STYLE_NULL,
&((*outResources)[POINTER_ICON_STYLE_NULL]));
}
@@ -1819,7 +1826,7 @@ int register_android_server_InputManager(JNIEnv* env) {
"getPointerLayer", "()I");
GET_METHOD_ID(gServiceClassInfo.getPointerIcon, clazz,
- "getPointerIcon", "()Landroid/view/PointerIcon;");
+ "getPointerIcon", "(I)Landroid/view/PointerIcon;");
GET_METHOD_ID(gServiceClassInfo.getPointerDisplayId, clazz,
"getPointerDisplayId", "()I");
@@ -1835,6 +1842,10 @@ int register_android_server_InputManager(JNIEnv* env) {
"getTouchCalibrationForInputDevice",
"(Ljava/lang/String;I)Landroid/hardware/input/TouchCalibration;");
+ GET_METHOD_ID(gServiceClassInfo.getContextForDisplay, clazz,
+ "getContextForDisplay",
+ "(I)Landroid/content/Context;")
+
// InputDevice
FIND_CLASS(gInputDeviceClassInfo.clazz, "android/view/InputDevice");
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index 1f5c64e92ac0..bc1f7981258d 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -42,6 +42,7 @@ import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.IUidObserver;
+import android.app.Person;
import android.app.usage.UsageStatsManagerInternal;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
@@ -1588,6 +1589,14 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
}
/**
+ * Make a Person.
+ */
+ protected Person makePerson(CharSequence name, String key, String uri) {
+ final Person.Builder builder = new Person.Builder();
+ return builder.setName(name).setKey(key).setUri(uri).build();
+ }
+
+ /**
* Make an component name, with the client context.
*/
@NonNull
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
index 9b59f9151fd0..8d0365b534b5 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
@@ -248,6 +248,8 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
.setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
.setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"))
.setRank(123)
+ .setPerson(makePerson("person", "personKey", "personUri"))
+ .setLongLived()
.setExtras(pb)
.build();
si.addFlags(ShortcutInfo.FLAG_PINNED);
@@ -267,9 +269,12 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
assertEquals("action", si.getIntent().getAction());
assertEquals("val", si.getIntent().getStringExtra("key"));
assertEquals(123, si.getRank());
+ assertEquals("person", si.getPersons()[0].getName());
+ assertEquals("personKey", si.getPersons()[0].getKey());
+ assertEquals("personUri", si.getPersons()[0].getUri());
assertEquals(1, si.getExtras().getInt("k"));
- assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags());
+ assertEquals(ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_LONG_LIVED, si.getFlags());
assertEquals("abc", si.getBitmapPath());
assertEquals(456, si.getIconResourceId());
@@ -345,6 +350,8 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
.setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"))
.setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
.setRank(123)
+ .setPerson(makePerson("person", "personKey", "personUri"))
+ .setLongLived()
.setExtras(pb)
.build();
sorig.addFlags(ShortcutInfo.FLAG_PINNED);
@@ -368,9 +375,12 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
assertEquals("action", si.getIntent().getAction());
assertEquals("val", si.getIntent().getStringExtra("key"));
assertEquals(123, si.getRank());
+ assertEquals("person", si.getPersons()[0].getName());
+ assertEquals("personKey", si.getPersons()[0].getKey());
+ assertEquals("personUri", si.getPersons()[0].getUri());
assertEquals(1, si.getExtras().getInt("k"));
- assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags());
+ assertEquals(ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_LONG_LIVED, si.getFlags());
assertEquals("abc", si.getBitmapPath());
assertEquals(456, si.getIconResourceId());
assertEquals("string/r456", si.getIconResName());
@@ -388,9 +398,12 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
assertEquals("action", si.getIntent().getAction());
assertEquals("val", si.getIntent().getStringExtra("key"));
assertEquals(123, si.getRank());
+ assertEquals("person", si.getPersons()[0].getName());
+ assertEquals("personKey", si.getPersons()[0].getKey());
+ assertEquals("personUri", si.getPersons()[0].getUri());
assertEquals(1, si.getExtras().getInt("k"));
- assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags());
+ assertEquals(ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_LONG_LIVED, si.getFlags());
assertEquals(null, si.getBitmapPath());
assertEquals(456, si.getIconResourceId());
@@ -408,9 +421,12 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories());
assertEquals(null, si.getIntent());
assertEquals(123, si.getRank());
+ assertEquals("person", si.getPersons()[0].getName());
+ assertEquals("personKey", si.getPersons()[0].getKey());
+ assertEquals("personUri", si.getPersons()[0].getUri());
assertEquals(1, si.getExtras().getInt("k"));
- assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags());
+ assertEquals(ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_LONG_LIVED, si.getFlags());
assertEquals(null, si.getBitmapPath());
assertEquals(456, si.getIconResourceId());
@@ -428,9 +444,11 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
assertEquals(null, si.getCategories());
assertEquals(null, si.getIntent());
assertEquals(0, si.getRank());
+ assertEquals(null, si.getPersons());
assertEquals(null, si.getExtras());
- assertEquals(ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_KEY_FIELDS_ONLY, si.getFlags());
+ assertEquals(ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_KEY_FIELDS_ONLY
+ | ShortcutInfo.FLAG_LONG_LIVED, si.getFlags());
assertEquals(null, si.getBitmapPath());
assertEquals(456, si.getIconResourceId());
@@ -692,6 +710,12 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
si = sorig.clone(/* flags=*/ 0);
si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
+ .setPerson(makePerson("person", "", "")).build());
+ assertEquals("text", si.getText());
+ assertEquals("person", si.getPersons()[0].getName());
+
+ si = sorig.clone(/* flags=*/ 0);
+ si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
.setIntent(makeIntent("action2", ShortcutActivity.class)).build());
assertEquals("text", si.getText());
assertEquals("action2", si.getIntent().getAction());
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
index f947baceafd8..56f4a8544f00 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
@@ -57,11 +57,6 @@ import org.junit.Test;
@Presubmit
public class ActivityDisplayTests extends ActivityTestsBase {
- @Before
- public void setUp() throws Exception {
- setupActivityTaskManagerService();
- }
-
@Test
public void testLastFocusedStackIsUpdatedWhenMovingStack() {
// Create a stack at bottom.
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
index cac9cf69ce4d..ee228610ab21 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
@@ -70,8 +70,6 @@ public class ActivityMetricsLaunchObserverTests extends ActivityTestsBase {
@Before
public void setUpAMLO() throws Exception {
- setupActivityTaskManagerService();
-
mLaunchObserver = mock(ActivityMetricsLaunchObserver.class);
// ActivityStackSupervisor always creates its own instance of ActivityMetricsLogger.
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 06360c217b97..8be63fc43adb 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -19,8 +19,10 @@ package com.android.server.wm;
import static android.view.Display.DEFAULT_DISPLAY;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
@@ -39,6 +41,7 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import android.app.ActivityOptions;
+import android.app.servertransaction.ActivityConfigurationChangeItem;
import android.app.servertransaction.ClientTransaction;
import android.app.servertransaction.PauseActivityItem;
import android.content.pm.ActivityInfo;
@@ -69,7 +72,6 @@ public class ActivityRecordTests extends ActivityTestsBase {
@Before
public void setUp() throws Exception {
- setupActivityTaskManagerService();
mStack = (TestActivityStack) new StackBuilder(mRootActivityContainer).build();
mTask = mStack.getChildAt(0);
mActivity = mTask.getTopActivity();
@@ -321,4 +323,44 @@ public class ActivityRecordTests extends ActivityTestsBase {
assertEquals(ActivityTaskManagerService.RELAUNCH_REASON_NONE,
mActivity.mRelaunchReason);
}
+
+ @Test
+ public void testSetRequestedOrientationUpdatesConfiguration() throws Exception {
+ mActivity.setState(ActivityStack.ActivityState.RESUMED, "Testing");
+
+ mTask.onRequestedOverrideConfigurationChanged(mTask.getConfiguration());
+ mActivity.setLastReportedConfiguration(new MergedConfiguration(new Configuration(),
+ mActivity.getConfiguration()));
+
+ mActivity.info.configChanges |= ActivityInfo.CONFIG_ORIENTATION;
+ final Configuration newConfig = new Configuration(mActivity.getConfiguration());
+ newConfig.orientation = newConfig.orientation == Configuration.ORIENTATION_PORTRAIT
+ ? Configuration.ORIENTATION_LANDSCAPE
+ : Configuration.ORIENTATION_PORTRAIT;
+
+ // Mimic the behavior that display doesn't handle app's requested orientation.
+ doAnswer(invocation -> {
+ mTask.onConfigurationChanged(newConfig);
+ return null;
+ }).when(mActivity.mAppWindowToken).setOrientation(anyInt(), any(), any());
+
+ final int requestedOrientation;
+ switch (newConfig.orientation) {
+ case Configuration.ORIENTATION_LANDSCAPE:
+ requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
+ break;
+ case Configuration.ORIENTATION_PORTRAIT:
+ requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
+ break;
+ default:
+ throw new IllegalStateException("Orientation in new config should be either"
+ + "landscape or portrait.");
+ }
+ mActivity.setRequestedOrientation(requestedOrientation);
+
+ final ActivityConfigurationChangeItem expected =
+ ActivityConfigurationChangeItem.obtain(newConfig);
+ verify(mService.getLifecycleManager()).scheduleTransaction(eq(mActivity.app.getThread()),
+ eq(mActivity.appToken), eq(expected));
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java
index f7b5d26ac87e..59e71c417439 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java
@@ -64,7 +64,6 @@ public class ActivityStackSupervisorTests extends ActivityTestsBase {
@Before
public void setUp() throws Exception {
- setupActivityTaskManagerService();
mFullscreenStack = mRootActivityContainer.getDefaultDisplay().createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
index fda23e9cb73a..35c1edeace2d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
@@ -75,7 +75,6 @@ public class ActivityStackTests extends ActivityTestsBase {
@Before
public void setUp() throws Exception {
- setupActivityTaskManagerService();
mDefaultDisplay = mRootActivityContainer.getDefaultDisplay();
mStack = spy(mDefaultDisplay.createStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD,
true /* onTop */));
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStartControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStartControllerTests.java
index 2ba2fdbcb959..96db38b14ad5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStartControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStartControllerTests.java
@@ -56,7 +56,6 @@ public class ActivityStartControllerTests extends ActivityTestsBase {
@Before
public void setUp() throws Exception {
- mService = createActivityTaskManagerService();
mFactory = mock(Factory.class);
mController = new ActivityStartController(mService, mService.mStackSupervisor, mFactory);
mStarter = spy(new ActivityStarter(mController, mService,
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index 898d107d0c60..a381023590c3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -117,7 +117,6 @@ public class ActivityStarterTests extends ActivityTestsBase {
@Before
public void setUp() throws Exception {
- setupActivityTaskManagerService();
mController = mock(ActivityStartController.class);
mActivityMetricsLogger = mock(ActivityMetricsLogger.class);
clearInvocations(mActivityMetricsLogger);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
index d462e69e69c5..68df87e3e27d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
@@ -111,6 +111,10 @@ class ActivityTestsBase {
@Before
public void setUpBase() {
mTestInjector.setUp();
+
+ mService = new TestActivityTaskManagerService(mContext);
+ mSupervisor = mService.mStackSupervisor;
+ mRootActivityContainer = mService.mRootActivityContainer;
}
@After
@@ -122,17 +126,6 @@ class ActivityTestsBase {
}
}
- ActivityTaskManagerService createActivityTaskManagerService() {
- mService = new TestActivityTaskManagerService(mContext);
- mSupervisor = mService.mStackSupervisor;
- mRootActivityContainer = mService.mRootActivityContainer;
- return mService;
- }
-
- void setupActivityTaskManagerService() {
- createActivityTaskManagerService();
- }
-
/** Creates a {@link TestActivityDisplay}. */
TestActivityDisplay createNewActivityDisplay() {
return TestActivityDisplay.create(mSupervisor, sNextDisplayId++);
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
index 0c6e632ac9f3..123de2d227bc 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
@@ -60,7 +60,7 @@ public class AppTransitionTests extends WindowTestsBase {
@BeforeClass
public static void setUpRootWindowContainerMock() {
- final WindowManagerService wm = WmServiceUtils.getWindowManagerService();
+ final WindowManagerService wm = TestSystemServices.getWindowManagerService();
// For unit test, we don't need to test performSurfacePlacement to prevent some abnormal
// interaction with surfaceflinger native side.
sOriginalRootWindowContainer = wm.mRoot;
@@ -74,7 +74,7 @@ public class AppTransitionTests extends WindowTestsBase {
@AfterClass
public static void tearDownRootWindowContainerMock() {
- final WindowManagerService wm = WmServiceUtils.getWindowManagerService();
+ final WindowManagerService wm = TestSystemServices.getWindowManagerService();
wm.mRoot = sOriginalRootWindowContainer;
sOriginalRootWindowContainer = null;
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java
index 8c3dec7f1e75..b28ae40d5056 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java
@@ -71,7 +71,6 @@ public class LaunchParamsControllerTests extends ActivityTestsBase {
@Before
public void setUp() throws Exception {
- mService = createActivityTaskManagerService();
mPersister = new TestLaunchParamsPersister();
mController = new LaunchParamsController(mService, mPersister);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
index 86353643c128..aeda473a9e6e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
@@ -102,8 +102,6 @@ public class LaunchParamsPersisterTests extends ActivityTestsBase {
mFolder = new File(cacheFolder, "launch_params_tests");
deleteRecursively(mFolder);
- setupActivityTaskManagerService();
-
mDisplayUniqueId = "test:" + Integer.toString(sNextUniqueId++);
final DisplayInfo info = new DisplayInfo();
info.uniqueId = mDisplayUniqueId;
diff --git a/services/tests/wmtests/src/com/android/server/wm/PendingRemoteAnimationRegistryTest.java b/services/tests/wmtests/src/com/android/server/wm/PendingRemoteAnimationRegistryTest.java
index efd7d25c586d..beaac8e58686 100644
--- a/services/tests/wmtests/src/com/android/server/wm/PendingRemoteAnimationRegistryTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/PendingRemoteAnimationRegistryTest.java
@@ -52,7 +52,6 @@ public class PendingRemoteAnimationRegistryTest extends ActivityTestsBase {
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
- mService = createActivityTaskManagerService();
mService.mH.runWithScissors(() -> {
mHandler = new TestHandler(null, mClock);
}, 0);
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
index a3f535aa6357..e3bacf96a86c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
@@ -82,7 +82,6 @@ public class RootActivityContainerTests extends ActivityTestsBase {
@Before
public void setUp() throws Exception {
- setupActivityTaskManagerService();
mFullscreenStack = mRootActivityContainer.getDefaultDisplay().createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java
index a8b6dc373cbf..dc964806b7a9 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java
@@ -49,7 +49,6 @@ public class RunningTasksTest extends ActivityTestsBase {
@Before
public void setUp() throws Exception {
- setupActivityTaskManagerService();
mRunningTasks = new RunningTasks();
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
index 53e99fae95d4..ace179acdeb5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
@@ -75,10 +75,6 @@ public class TaskLaunchParamsModifierTests extends ActivityTestsBase {
@Before
public void setUp() throws Exception {
- setupActivityTaskManagerService();
- mService.mSupportsFreeformWindowManagement = true;
- when(mSupervisor.canUseActivityOptionsLaunchBounds(any())).thenCallRealMethod();
-
mActivity = new ActivityBuilder(mService).build();
mActivity.appInfo.targetSdkVersion = Build.VERSION_CODES.N_MR1;
mActivity.info.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES;
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
index 99be50be642e..e182c45f009e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
@@ -90,7 +90,6 @@ public class TaskRecordTests extends ActivityTestsBase {
@Before
public void setUp() throws Exception {
TaskRecord.setTaskRecordFactory(null);
- setupActivityTaskManagerService();
mParentBounds = new Rect(10 /*left*/, 30 /*top*/, 80 /*right*/, 60 /*bottom*/);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WmServiceUtils.java b/services/tests/wmtests/src/com/android/server/wm/TestSystemServices.java
index 05ac8c1072c0..b151fb7a613c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WmServiceUtils.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestSystemServices.java
@@ -66,7 +66,7 @@ import java.util.concurrent.CountDownLatch;
/**
* A Test utility class to create a mock {@link WindowManagerService} instance for tests.
*/
-class WmServiceUtils {
+class TestSystemServices {
private static StaticMockitoSession sMockitoSession;
private static WindowManagerService sService;
private static TestWindowManagerPolicy sPolicy;
@@ -78,7 +78,7 @@ class WmServiceUtils {
.strictness(Strictness.LENIENT)
.startMocking();
- runWithDexmakerShareClassLoader(WmServiceUtils::setUpTestWindowService);
+ runWithDexmakerShareClassLoader(TestSystemServices::setUpTestWindowService);
}
static void tearDownWindowManagerService() {
@@ -147,7 +147,7 @@ class WmServiceUtils {
final WindowManagerGlobalLock wmLock = new WindowManagerGlobalLock();
doReturn(wmLock).when(atms).getGlobalLock();
- sPolicy = new TestWindowManagerPolicy(WmServiceUtils::getWindowManagerService);
+ sPolicy = new TestWindowManagerPolicy(TestSystemServices::getWindowManagerService);
sService = WindowManagerService.main(context, ims, false, false, sPolicy, atms);
sService.onInitReady();
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index 89c1551dffaf..e38118e875e0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -101,14 +101,14 @@ class WindowTestsBase {
public static void setUpOnceBase() {
AttributeCache.init(getInstrumentation().getTargetContext());
- WmServiceUtils.setUpWindowManagerService();
+ TestSystemServices.setUpWindowManagerService();
sPowerManagerWrapper = mock(WindowState.PowerManagerWrapper.class);
}
@AfterClass
public static void tearDonwOnceBase() {
- WmServiceUtils.tearDownWindowManagerService();
+ TestSystemServices.tearDownWindowManagerService();
}
@Before
@@ -120,7 +120,7 @@ class WindowTestsBase {
final Context context = getInstrumentation().getTargetContext();
- mWm = WmServiceUtils.getWindowManagerService();
+ mWm = TestSystemServices.getWindowManagerService();
beforeCreateDisplay();
context.getDisplay().getDisplayInfo(mDisplayInfo);
@@ -198,7 +198,7 @@ class WindowTestsBase {
}
// Cleaned up everything in Handler.
- WmServiceUtils.cleanupWindowManagerHandlers();
+ TestSystemServices.cleanupWindowManagerHandlers();
} catch (Exception e) {
Log.e(TAG, "Failed to tear down test", e);
throw e;
@@ -219,7 +219,7 @@ class WindowTestsBase {
* Waits until the main handler for WM has processed all messages.
*/
void waitUntilHandlersIdle() {
- WmServiceUtils.waitUntilWindowManagerHandlersIdle();
+ TestSystemServices.waitUntilWindowManagerHandlersIdle();
}
private WindowToken createWindowToken(
diff --git a/telephony/java/android/telephony/CarrierRestrictionRules.aidl b/telephony/java/android/telephony/CarrierRestrictionRules.aidl
new file mode 100644
index 000000000000..8b1f0b918901
--- /dev/null
+++ b/telephony/java/android/telephony/CarrierRestrictionRules.aidl
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** @hide */
+package android.telephony;
+
+parcelable CarrierRestrictionRules;
diff --git a/telephony/java/android/telephony/CarrierRestrictionRules.java b/telephony/java/android/telephony/CarrierRestrictionRules.java
new file mode 100644
index 000000000000..37847aef9167
--- /dev/null
+++ b/telephony/java/android/telephony/CarrierRestrictionRules.java
@@ -0,0 +1,277 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.service.carrier.CarrierIdentifier;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Contains the list of carrier restrictions.
+ * Allowed list: it indicates the list of carriers that are allowed.
+ * Excluded list: it indicates the list of carriers that are excluded.
+ * Default carrier restriction: it indicates the default behavior and the priority between the two
+ * lists:
+ * - not allowed: the device only allows usage of carriers that are present in the allowed list
+ * and not present in the excluded list. This implies that if a carrier is not present in either
+ * list, it is not allowed.
+ * - allowed: the device allows all carriers, except those present in the excluded list and not
+ * present in the allowed list. This implies that if a carrier is not present in either list,
+ * it is allowed.
+ * MultiSim policy: it indicates the behavior in case of devices with two or more SIM cards.
+ * - MULTISIM_POLICY_NONE: the same configuration is applied to all SIM slots independently. This
+ * is the default value if none is set.
+ * - MULTISIM_POLICY_ONE_VALID_SIM_MUST_BE_PRESENT: it indicates that any SIM card can be used
+ * as far as one SIM card matching the configuration is present in the device.
+ *
+ * Both lists support the character '?' as wild character. For example, an entry indicating
+ * MCC=310 and MNC=??? will match all networks with MCC=310.
+ *
+ * Example 1: Allowed list contains MCC and MNC of operator A. Excluded list contains operator B,
+ * which has same MCC and MNC, but also GID1 value. The priority allowed list is set
+ * to true. Only SIM cards of operator A are allowed, but not those of B or any other
+ * operator.
+ * Example 2: Allowed list contains MCC and MNC of operator A. Excluded list contains an entry
+ * with same MCC, and '???' as MNC. The priority allowed list is set to false.
+ * SIM cards of operator A and all SIM cards with a different MCC value are allowed.
+ * SIM cards of operators with same MCC value and different MNC are not allowed.
+ * @hide
+ */
+@SystemApi
+public final class CarrierRestrictionRules implements Parcelable {
+ /**
+ * The device only allows usage of carriers that are present in the allowed list and not
+ * present in the excluded list. This implies that if a carrier is not present in either list,
+ * it is not allowed.
+ */
+ public static final int CARRIER_RESTRICTION_DEFAULT_NOT_ALLOWED = 0;
+
+ /**
+ * The device allows all carriers, except those present in the excluded list and not present
+ * in the allowed list. This implies that if a carrier is not present in either list, it is
+ * allowed.
+ */
+ public static final int CARRIER_RESTRICTION_DEFAULT_ALLOWED = 1;
+
+ /** The same configuration is applied to all SIM slots independently. */
+ public static final int MULTISIM_POLICY_NONE = 0;
+
+ /** Any SIM card can be used as far as one SIM card matching the configuration is present. */
+ public static final int MULTISIM_POLICY_ONE_VALID_SIM_MUST_BE_PRESENT = 1;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = "MULTISIM_POLICY_",
+ value = {MULTISIM_POLICY_NONE, MULTISIM_POLICY_ONE_VALID_SIM_MUST_BE_PRESENT})
+ public @interface MultiSimPolicy {}
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = "CARRIER_RESTRICTION_DEFAULT_",
+ value = {CARRIER_RESTRICTION_DEFAULT_NOT_ALLOWED, CARRIER_RESTRICTION_DEFAULT_ALLOWED})
+ public @interface CarrierRestrictionDefault {}
+
+ private List<CarrierIdentifier> mAllowedCarriers;
+ private List<CarrierIdentifier> mExcludedCarriers;
+ @CarrierRestrictionDefault
+ private int mCarrierRestrictionDefault;
+ @MultiSimPolicy
+ private int mMultiSimPolicy;
+
+ private CarrierRestrictionRules() {
+ mAllowedCarriers = new ArrayList<CarrierIdentifier>();
+ mExcludedCarriers = new ArrayList<CarrierIdentifier>();
+ mCarrierRestrictionDefault = CARRIER_RESTRICTION_DEFAULT_NOT_ALLOWED;
+ mMultiSimPolicy = MULTISIM_POLICY_NONE;
+ }
+
+ private CarrierRestrictionRules(Parcel in) {
+ mAllowedCarriers = new ArrayList<CarrierIdentifier>();
+ mExcludedCarriers = new ArrayList<CarrierIdentifier>();
+
+ in.readTypedList(mAllowedCarriers, CarrierIdentifier.CREATOR);
+ in.readTypedList(mExcludedCarriers, CarrierIdentifier.CREATOR);
+ mCarrierRestrictionDefault = in.readInt();
+ mMultiSimPolicy = in.readInt();
+ }
+
+ /**
+ * Creates a new builder for this class
+ * @hide
+ */
+ public static Builder newBuilder() {
+ return new Builder();
+ }
+
+ /**
+ * Indicates if all carriers are allowed
+ */
+ public boolean isAllCarriersAllowed() {
+ return (mAllowedCarriers.isEmpty() && mExcludedCarriers.isEmpty()
+ && mCarrierRestrictionDefault == CARRIER_RESTRICTION_DEFAULT_ALLOWED);
+ }
+
+ /**
+ * Retrieves list of allowed carriers
+ *
+ * @return the list of allowed carriers
+ */
+ public @NonNull List<CarrierIdentifier> getAllowedCarriers() {
+ return mAllowedCarriers;
+ }
+
+ /**
+ * Retrieves list of excluded carriers
+ *
+ * @return the list of excluded carriers
+ */
+ public @NonNull List<CarrierIdentifier> getExcludedCarriers() {
+ return mExcludedCarriers;
+ }
+
+ /**
+ * Retrieves the default behavior of carrier restrictions
+ */
+ public @CarrierRestrictionDefault int getDefaultCarrierRestriction() {
+ return mCarrierRestrictionDefault;
+ }
+
+ /**
+ * @return The policy used for multi-SIM devices
+ */
+ public @MultiSimPolicy int getMultiSimPolicy() {
+ return mMultiSimPolicy;
+ }
+
+ /**
+ * {@link Parcelable#writeToParcel}
+ */
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeTypedList(mAllowedCarriers);
+ out.writeTypedList(mExcludedCarriers);
+ out.writeInt(mCarrierRestrictionDefault);
+ out.writeInt(mMultiSimPolicy);
+ }
+
+ /**
+ * {@link Parcelable#describeContents}
+ */
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /**
+ * {@link Parcelable.Creator}
+ */
+ public static final Creator<CarrierRestrictionRules> CREATOR =
+ new Creator<CarrierRestrictionRules>() {
+ @Override
+ public CarrierRestrictionRules createFromParcel(Parcel in) {
+ return new CarrierRestrictionRules(in);
+ }
+
+ @Override
+ public CarrierRestrictionRules[] newArray(int size) {
+ return new CarrierRestrictionRules[size];
+ }
+ };
+
+ @Override
+ public String toString() {
+ return "CarrierRestrictionRules(allowed:" + mAllowedCarriers + ", excluded:"
+ + mExcludedCarriers + ", default:" + mCarrierRestrictionDefault
+ + ", multisim policy:" + mMultiSimPolicy + ")";
+ }
+
+ /**
+ * Builder for a {@link CarrierRestrictionRules}.
+ */
+ public static class Builder {
+ private final CarrierRestrictionRules mRules;
+
+ /** {@hide} */
+ public Builder() {
+ mRules = new CarrierRestrictionRules();
+ }
+
+ /** build command */
+ public CarrierRestrictionRules build() {
+ return mRules;
+ }
+
+ /**
+ * Indicate that all carriers are allowed.
+ */
+ public Builder setAllCarriersAllowed() {
+ mRules.mAllowedCarriers.clear();
+ mRules.mExcludedCarriers.clear();
+ mRules.mCarrierRestrictionDefault = CARRIER_RESTRICTION_DEFAULT_ALLOWED;
+ return this;
+ }
+
+ /**
+ * Set list of allowed carriers.
+ *
+ * @param allowedCarriers list of allowed carriers
+ */
+ public Builder setAllowedCarriers(List<CarrierIdentifier> allowedCarriers) {
+ mRules.mAllowedCarriers = new ArrayList<CarrierIdentifier>(allowedCarriers);
+ return this;
+ }
+
+ /**
+ * Set list of excluded carriers.
+ *
+ * @param excludedCarriers list of excluded carriers
+ */
+ public Builder setExcludedCarriers(List<CarrierIdentifier> excludedCarriers) {
+ mRules.mExcludedCarriers = new ArrayList<CarrierIdentifier>(excludedCarriers);
+ return this;
+ }
+
+ /**
+ * Set the default behavior of the carrier restrictions
+ *
+ * @param carrierRestrictionDefault prioritized carrier list
+ */
+ public Builder setDefaultCarrierRestriction(
+ @CarrierRestrictionDefault int carrierRestrictionDefault) {
+ mRules.mCarrierRestrictionDefault = carrierRestrictionDefault;
+ return this;
+ }
+
+ /**
+ * Set the policy to be used for multi-SIM devices
+ *
+ * @param multiSimPolicy multi SIM policy
+ */
+ public Builder setMultiSimPolicy(@MultiSimPolicy int multiSimPolicy) {
+ mRules.mMultiSimPolicy = multiSimPolicy;
+ return this;
+ }
+ }
+}
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java
index c81670139eae..9fee5932dadc 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/telephony/java/android/telephony/PhoneStateListener.java
@@ -805,9 +805,11 @@ public class PhoneStateListener {
PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
if (psl == null) return;
- Binder.withCleanCallingIdentity(
- () -> mExecutor.execute(
- () -> psl.onDataConnectionStateChanged(state, networkType)));
+ Binder.withCleanCallingIdentity(() -> mExecutor.execute(
+ () -> {
+ psl.onDataConnectionStateChanged(state, networkType);
+ psl.onDataConnectionStateChanged(state);
+ }));
}
public void onDataActivity(int direction) {
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 3311218bdb3c..75b117792844 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -9055,6 +9055,8 @@ public class TelephonyManager {
* <p>This method works only on devices with {@link
* android.content.pm.PackageManager#FEATURE_TELEPHONY_CARRIERLOCK} enabled.
*
+ * @deprecated use setCarrierRestrictionRules instead
+ *
* @return The number of carriers set successfully. Should be length of
* carrierList on success; -1 if carrierList null or on error.
* @hide
@@ -9062,44 +9064,144 @@ public class TelephonyManager {
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public int setAllowedCarriers(int slotIndex, List<CarrierIdentifier> carriers) {
+ // Execute the method setCarrierRestrictionRules with an empty excluded list and
+ // indicating priority for the allowed list.
+ CarrierRestrictionRules carrierRestrictionRules = CarrierRestrictionRules.newBuilder()
+ .setAllowedCarriers(carriers)
+ .setDefaultCarrierRestriction(
+ CarrierRestrictionRules.CARRIER_RESTRICTION_DEFAULT_NOT_ALLOWED)
+ .build();
+
+ int result = setCarrierRestrictionRules(carrierRestrictionRules);
+
+ // Convert boolean result into int, as required by this method.
+ if (result == SET_CARRIER_RESTRICTION_SUCCESS) {
+ return carriers.size();
+ } else {
+ return -1;
+ }
+ }
+
+ /**
+ * The carrier restrictions were successfully set.
+ * @hide
+ */
+ @SystemApi
+ public static final int SET_CARRIER_RESTRICTION_SUCCESS = 0;
+
+ /**
+ * The carrier restrictions were not set due to lack of support in the modem. This can happen
+ * if the modem does not support setting the carrier restrictions or if the configuration
+ * passed in the {@code setCarrierRestrictionRules} is not supported by the modem.
+ * @hide
+ */
+ @SystemApi
+ public static final int SET_CARRIER_RESTRICTION_NOT_SUPPORTED = 1;
+
+ /**
+ * The setting of carrier restrictions failed.
+ * @hide
+ */
+ @SystemApi
+ public static final int SET_CARRIER_RESTRICTION_ERROR = 2;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = {"SET_CARRIER_RESTRICTION_"},
+ value = {
+ SET_CARRIER_RESTRICTION_SUCCESS,
+ SET_CARRIER_RESTRICTION_NOT_SUPPORTED,
+ SET_CARRIER_RESTRICTION_ERROR
+ })
+ public @interface SetCarrierRestrictionResult {}
+
+ /**
+ * Set the allowed carrier list and the excluded carrier list indicating the priority between
+ * the two lists.
+ * Requires system privileges.
+ *
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE}
+ *
+ * <p>This method works only on devices with {@link
+ * android.content.pm.PackageManager#FEATURE_TELEPHONY_CARRIERLOCK} enabled.
+ *
+ * @return {@link #SET_CARRIER_RESTRICTION_SUCCESS} in case of success.
+ * {@link #SET_CARRIER_RESTRICTION_NOT_SUPPORTED} if the modem does not support the
+ * configuration. {@link #SET_CARRIER_RESTRICTION_ERROR} in all other error cases.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @SetCarrierRestrictionResult
+ public int setCarrierRestrictionRules(@NonNull CarrierRestrictionRules rules) {
try {
ITelephony service = getITelephony();
if (service != null) {
- return service.setAllowedCarriers(slotIndex, carriers);
+ return service.setAllowedCarriers(rules);
}
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelephony#setAllowedCarriers", e);
} catch (NullPointerException e) {
Log.e(TAG, "Error calling ITelephony#setAllowedCarriers", e);
}
- return -1;
+ return SET_CARRIER_RESTRICTION_ERROR;
}
/**
* Get the allowed carrier list for slotIndex.
- * Require system privileges. In the future we may add this to carrier APIs.
+ * Requires system privileges.
*
* <p>This method returns valid data on devices with {@link
* android.content.pm.PackageManager#FEATURE_TELEPHONY_CARRIERLOCK} enabled.
*
+ * @deprecated Apps should use {@link getCarriersRestrictionRules} to retrieve the list of
+ * allowed and excliuded carriers, as the result of this API is valid only when the excluded
+ * list is empty. This API could return an empty list, even if some restrictions are present.
+ *
* @return List of {@link android.telephony.CarrierIdentifier}; empty list
* means all carriers are allowed.
* @hide
*/
+ @Deprecated
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public List<CarrierIdentifier> getAllowedCarriers(int slotIndex) {
+ CarrierRestrictionRules carrierRestrictionRule = getCarrierRestrictionRules();
+ if (carrierRestrictionRule != null) {
+ return carrierRestrictionRule.getAllowedCarriers();
+ }
+ return new ArrayList<CarrierIdentifier>(0);
+ }
+
+ /**
+ * Get the allowed carrier list and the excluded carrier list indicating the priority between
+ * the two lists.
+ * Require system privileges. In the future we may add this to carrier APIs.
+ *
+ * <p>This method returns valid data on devices with {@link
+ * android.content.pm.PackageManager#FEATURE_TELEPHONY_CARRIERLOCK} enabled.
+ *
+ * @return {@link CarrierRestrictionRules} which contains the allowed carrier list and the
+ * excluded carrier list with the priority between the two lists. Returns {@code null}
+ * in case of error.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @Nullable
+ public CarrierRestrictionRules getCarrierRestrictionRules() {
try {
ITelephony service = getITelephony();
if (service != null) {
- return service.getAllowedCarriers(slotIndex);
+ return service.getAllowedCarriers();
}
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelephony#getAllowedCarriers", e);
} catch (NullPointerException e) {
Log.e(TAG, "Error calling ITelephony#getAllowedCarriers", e);
}
- return new ArrayList<CarrierIdentifier>(0);
+ return null;
}
/**
diff --git a/telephony/java/android/telephony/emergency/EmergencyNumber.java b/telephony/java/android/telephony/emergency/EmergencyNumber.java
index a5f56bbebd75..e68256d086bc 100644
--- a/telephony/java/android/telephony/emergency/EmergencyNumber.java
+++ b/telephony/java/android/telephony/emergency/EmergencyNumber.java
@@ -27,6 +27,7 @@ import android.telephony.Rlog;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
@@ -176,6 +177,12 @@ public final class EmergencyNumber implements Parcelable, Comparable<EmergencyNu
* Bit-field which indicates the number is from the platform-maintained database.
*/
public static final int EMERGENCY_NUMBER_SOURCE_DATABASE = 1 << 4;
+ /**
+ * Bit-field which indicates the number is from test mode.
+ *
+ * @hide
+ */
+ public static final int EMERGENCY_NUMBER_SOURCE_TEST = 1 << 5;
/** Bit-field which indicates the number is from the modem config. */
public static final int EMERGENCY_NUMBER_SOURCE_MODEM_CONFIG =
EmergencyNumberSource.MODEM_CONFIG;
@@ -327,6 +334,21 @@ public final class EmergencyNumber implements Parcelable, Comparable<EmergencyNu
}
/**
+ * Returns the bitmask of emergency service categories of the emergency number for
+ * internal dialing.
+ *
+ * @return bitmask of the emergency service categories
+ *
+ * @hide
+ */
+ public @EmergencyServiceCategories int getEmergencyServiceCategoryBitmaskInternalDial() {
+ if (mEmergencyNumberSourceBitmask == EMERGENCY_NUMBER_SOURCE_DATABASE) {
+ return EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED;
+ }
+ return mEmergencyServiceCategoryBitmask;
+ }
+
+ /**
* Returns the emergency service categories of the emergency number.
*
* Note: if the emergency number is in {@link #EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED}, only
@@ -577,6 +599,7 @@ public final class EmergencyNumber implements Parcelable, Comparable<EmergencyNu
emergencyNumberList.remove(i--);
}
}
+ Collections.sort(emergencyNumberList);
}
/**
@@ -613,6 +636,12 @@ public final class EmergencyNumber implements Parcelable, Comparable<EmergencyNu
if (first.getEmergencyCallRouting() != second.getEmergencyCallRouting()) {
return false;
}
+ // Never merge two numbers if one of them is from test mode but the other one is not;
+ // This supports to remove a number from the test mode.
+ if (first.isFromSources(EMERGENCY_NUMBER_SOURCE_TEST)
+ ^ second.isFromSources(EMERGENCY_NUMBER_SOURCE_TEST)) {
+ return false;
+ }
return true;
}
@@ -638,4 +667,13 @@ public final class EmergencyNumber implements Parcelable, Comparable<EmergencyNu
}
return null;
}
+
+ /**
+ * Validate Emergency Number address that only allows '0'-'9', '*', or '#'
+ *
+ * @hide
+ */
+ public static boolean validateEmergencyNumberAddress(String address) {
+ return address.matches("[0-9*#]+");
+ }
}
diff --git a/telephony/java/android/telephony/ims/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java
index 525a96a4dae9..59167b7d5bba 100644
--- a/telephony/java/android/telephony/ims/ImsCallProfile.java
+++ b/telephony/java/android/telephony/ims/ImsCallProfile.java
@@ -347,6 +347,9 @@ public final class ImsCallProfile implements Parcelable {
private @EmergencyCallRouting int mEmergencyCallRouting =
EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN;
+ /** Indicates if the call is for testing purpose */
+ private boolean mEmergencyCallTesting = false;
+
/**
* Extras associated with this {@link ImsCallProfile}.
* <p>
@@ -534,9 +537,10 @@ public final class ImsCallProfile implements Parcelable {
+ ", callType=" + mCallType
+ ", restrictCause=" + mRestrictCause
+ ", mediaProfile=" + mMediaProfile.toString()
- + ", emergencyServiceCategories=" + mEmergencyCallRouting
+ + ", emergencyServiceCategories=" + mEmergencyServiceCategories
+ ", emergencyUrns=" + mEmergencyUrns
- + ", emergencyCallRouting=" + mEmergencyCallRouting + " }";
+ + ", emergencyCallRouting=" + mEmergencyCallRouting
+ + ", emergencyCallTesting=" + mEmergencyCallTesting + " }";
}
@Override
@@ -554,6 +558,7 @@ public final class ImsCallProfile implements Parcelable {
out.writeInt(mEmergencyServiceCategories);
out.writeStringList(mEmergencyUrns);
out.writeInt(mEmergencyCallRouting);
+ out.writeBoolean(mEmergencyCallTesting);
}
private void readFromParcel(Parcel in) {
@@ -564,6 +569,7 @@ public final class ImsCallProfile implements Parcelable {
mEmergencyServiceCategories = in.readInt();
mEmergencyUrns = in.createStringArrayList();
mEmergencyCallRouting = in.readInt();
+ mEmergencyCallTesting = in.readBoolean();
}
public static final Creator<ImsCallProfile> CREATOR = new Creator<ImsCallProfile>() {
@@ -784,9 +790,11 @@ public final class ImsCallProfile implements Parcelable {
* @hide
*/
public void setEmergencyCallInfo(EmergencyNumber num) {
- setEmergencyServiceCategories(num.getEmergencyServiceCategoryBitmask());
+ setEmergencyServiceCategories(num.getEmergencyServiceCategoryBitmaskInternalDial());
setEmergencyUrns(num.getEmergencyUrns());
setEmergencyCallRouting(num.getEmergencyCallRouting());
+ setEmergencyCallTesting(num.getEmergencyNumberSourceBitmask()
+ == EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST);
}
/**
@@ -843,6 +851,15 @@ public final class ImsCallProfile implements Parcelable {
}
/**
+ * Set if this is for testing emergency call, only valid if {@link #getServiceType} returns
+ * {@link #SERVICE_TYPE_EMERGENCY}.
+ */
+ @VisibleForTesting
+ public void setEmergencyCallTesting(boolean isTesting) {
+ mEmergencyCallTesting = isTesting;
+ }
+
+ /**
* Get the emergency service categories, only valid if {@link #getServiceType} returns
* {@link #SERVICE_TYPE_EMERGENCY}
*
@@ -892,4 +909,11 @@ public final class ImsCallProfile implements Parcelable {
public @EmergencyCallRouting int getEmergencyCallRouting() {
return mEmergencyCallRouting;
}
+
+ /**
+ * Get if the emergency call is for testing purpose.
+ */
+ public boolean isEmergencyCallTesting() {
+ return mEmergencyCallTesting;
+ }
}
diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java
index e2350fe78500..9414abd98b1c 100644
--- a/telephony/java/android/telephony/ims/ImsMmTelManager.java
+++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java
@@ -92,7 +92,7 @@ public class ImsMmTelManager {
public static final int WIFI_MODE_WIFI_PREFERRED = 2;
/**
- * Callback class for receiving Registration callback events.
+ * Callback class for receiving IMS network Registration callback events.
* @see #registerImsRegistrationCallback(Executor, RegistrationCallback) (RegistrationCallback)
* @see #unregisterImsRegistrationCallback(RegistrationCallback)
*/
@@ -241,7 +241,8 @@ public class ImsMmTelManager {
}
/**
- * Receives IMS capability status updates from the ImsService.
+ * Receives IMS capability status updates from the ImsService. This information is also
+ * available via the {@link #isAvailable(int, int)} method below.
*
* @see #registerMmTelCapabilityCallback(Executor, CapabilityCallback) (CapabilityCallback)
* @see #unregisterMmTelCapabilityCallback(CapabilityCallback)
@@ -290,6 +291,8 @@ public class ImsMmTelManager {
* If unavailable, the feature is not able to support the unavailable capability at this
* time.
*
+ * This information can also be queried using the {@link #isAvailable(int, int)} API.
+ *
* @param capabilities The new availability of the capabilities.
*/
public void onCapabilitiesStatusChanged(
@@ -304,7 +307,7 @@ public class ImsMmTelManager {
/**@hide*/
// Only exposed as public method for compatibility with deprecated ImsManager APIs.
// TODO: clean up dependencies and change back to private visibility.
- public void setExecutor(Executor executor) {
+ public final void setExecutor(Executor executor) {
mBinder.setExecutor(executor);
}
}
@@ -342,8 +345,7 @@ public class ImsMmTelManager {
* Registers a {@link RegistrationCallback} with the system, which will provide registration
* updates for the subscription specified in {@link #createForSubscriptionId(Context, int)}. Use
* {@link SubscriptionManager.OnSubscriptionsChangedListener} to listen to Subscription changed
- * events and call {@link #unregisterImsRegistrationCallback(RegistrationCallback)} to clean up
- * after a subscription is removed.
+ * events and call {@link #unregisterImsRegistrationCallback(RegistrationCallback)} to clean up.
*
* When the callback is registered, it will initiate the callback c to be called with the
* current registration state.
@@ -351,6 +353,12 @@ public class ImsMmTelManager {
* @param executor The executor the callback events should be run on.
* @param c The {@link RegistrationCallback} to be added.
* @see #unregisterImsRegistrationCallback(RegistrationCallback)
+ * @throws IllegalArgumentException if the subscription associated with this callback is not
+ * active (SIM is not inserted, ESIM inactive) or invalid, or a null {@link Executor} or
+ * {@link CapabilityCallback} callback.
+ * @throws IllegalStateException if the subscription associated with this callback is valid, but
+ * the {@link ImsService} associated with the subscription is not available. This can happen if
+ * the service crashed, for example.
*/
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public void registerImsRegistrationCallback(@CallbackExecutor Executor executor,
@@ -370,11 +378,17 @@ public class ImsMmTelManager {
}
/**
- * Removes an existing {@link RegistrationCallback}. Ensure to call this method when cleaning
- * up to avoid memory leaks or when the subscription is removed.
+ * Removes an existing {@link RegistrationCallback}.
+ *
+ * When the subscription associated with this callback is removed (SIM removed, ESIM swap,
+ * etc...), this callback will automatically be removed. If this method is called for an
+ * inactive subscription, it will result in a no-op.
+ *
* @param c The {@link RegistrationCallback} to be removed.
* @see SubscriptionManager.OnSubscriptionsChangedListener
* @see #registerImsRegistrationCallback(Executor, RegistrationCallback)
+ * @throws IllegalArgumentException if the subscription ID associated with this callback is
+ * invalid.
*/
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public void unregisterImsRegistrationCallback(@NonNull RegistrationCallback c) {
@@ -389,12 +403,14 @@ public class ImsMmTelManager {
}
/**
- * Registers a {@link CapabilityCallback} with the system, which will provide MmTel capability
- * updates for the subscription specified in {@link #createForSubscriptionId(Context, int)}.
+ * Registers a {@link CapabilityCallback} with the system, which will provide MmTel service
+ * availability updates for the subscription specified in
+ * {@link #createForSubscriptionId(Context, int)}. The method {@link #isAvailable(int, int)}
+ * can also be used to query this information at any time.
+ *
* Use {@link SubscriptionManager.OnSubscriptionsChangedListener} to listen to
* subscription changed events and call
- * {@link #unregisterImsRegistrationCallback(RegistrationCallback)} to clean up after a
- * subscription is removed.
+ * {@link #unregisterImsRegistrationCallback(RegistrationCallback)} to clean up.
*
* When the callback is registered, it will initiate the callback c to be called with the
* current capabilities.
@@ -402,9 +418,15 @@ public class ImsMmTelManager {
* @param executor The executor the callback events should be run on.
* @param c The MmTel {@link CapabilityCallback} to be registered.
* @see #unregisterMmTelCapabilityCallback(CapabilityCallback)
+ * @throws IllegalArgumentException if the subscription associated with this callback is not
+ * active (SIM is not inserted, ESIM inactive) or invalid, or a null {@link Executor} or
+ * {@link CapabilityCallback} callback.
+ * @throws IllegalStateException if the subscription associated with this callback is valid, but
+ * the {@link ImsService} associated with the subscription is not available. This can happen if
+ * the service crashed, for example.
*/
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- public void registerMmTelCapabilityCallback(@CallbackExecutor Executor executor,
+ public void registerMmTelCapabilityCallback(@NonNull @CallbackExecutor Executor executor,
@NonNull CapabilityCallback c) {
if (c == null) {
throw new IllegalArgumentException("Must include a non-null RegistrationCallback.");
@@ -421,10 +443,15 @@ public class ImsMmTelManager {
}
/**
- * Removes an existing MmTel {@link CapabilityCallback}. Be sure to call this when cleaning
- * up to avoid memory leaks.
+ * Removes an existing MmTel {@link CapabilityCallback}.
+ *
+ * When the subscription associated with this callback is removed (SIM removed, ESIM swap,
+ * etc...), this callback will automatically be removed. If this method is called for an
+ * inactive subscription, it will result in a no-op.
* @param c The MmTel {@link CapabilityCallback} to be removed.
* @see #registerMmTelCapabilityCallback(Executor, CapabilityCallback)
+ * @throws IllegalArgumentException if the subscription ID associated with this callback is
+ * invalid.
*/
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public void unregisterMmTelCapabilityCallback(@NonNull CapabilityCallback c) {
diff --git a/telephony/java/android/telephony/ims/ProvisioningManager.java b/telephony/java/android/telephony/ims/ProvisioningManager.java
index 916e282f642e..d37198a3e25d 100644
--- a/telephony/java/android/telephony/ims/ProvisioningManager.java
+++ b/telephony/java/android/telephony/ims/ProvisioningManager.java
@@ -133,33 +133,40 @@ public class ProvisioningManager {
}
/**
- * Register a new {@link Callback} to listen to changes to changes in
- * IMS provisioning. Use {@link SubscriptionManager.OnSubscriptionsChangedListener} to listen to
- * Subscription changed events and call
- * {@link #unregisterProvisioningChangedCallback(Callback)} to clean up after a
- * subscription is removed.
+ * Register a new {@link Callback} to listen to changes to changes in IMS provisioning.
+ *
+ * When the subscription associated with this callback is removed (SIM removed, ESIM swap,
+ * etc...), this callback will automatically be removed.
* @param executor The {@link Executor} to call the callback methods on
* @param callback The provisioning callbackto be registered.
* @see #unregisterProvisioningChangedCallback(Callback)
* @see SubscriptionManager.OnSubscriptionsChangedListener
+ * @throws IllegalArgumentException if the subscription associated with this callback is not
+ * active (SIM is not inserted, ESIM inactive) or the subscription is invalid.
+ * @throws IllegalStateException if the subscription associated with this callback is valid, but
+ * the {@link ImsService} associated with the subscription is not available. This can happen if
+ * the service crashed, for example.
*/
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public void registerProvisioningChangedCallback(@CallbackExecutor Executor executor,
@NonNull Callback callback) {
callback.setExecutor(executor);
try {
- getITelephony().registerImsProvisioningChangedCallback(mSubId,
- callback.getBinder());
+ getITelephony().registerImsProvisioningChangedCallback(mSubId, callback.getBinder());
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
}
/**
- * Unregister an existing {@link Callback}. Ensure to call this method when cleaning
- * up to avoid memory leaks or when the subscription is removed.
+ * Unregister an existing {@link Callback}. When the subscription associated with this
+ * callback is removed (SIM removed, ESIM swap, etc...), this callback will automatically be
+ * removed. If this method is called for an inactive subscription, it will result in a no-op.
* @param callback The existing {@link Callback} to be removed.
* @see #registerProvisioningChangedCallback(Executor, Callback)
+ *
+ * @throws IllegalArgumentException if the subscription associated with this callback is
+ * invalid.
*/
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public void unregisterProvisioningChangedCallback(@NonNull Callback callback) {
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index c5d82c5949f0..62b9d363e35e 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -28,6 +28,7 @@ import android.net.Uri;
import android.service.carrier.CarrierIdentifier;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
+import android.telephony.CarrierRestrictionRules;
import android.telephony.CellInfo;
import android.telephony.ClientRequestStats;
import android.telephony.IccOpenLogicalChannelResponse;
@@ -41,6 +42,7 @@ import android.telephony.ServiceState;
import android.telephony.SignalStrength;
import android.telephony.TelephonyHistogram;
import android.telephony.VisualVoicemailSmsFilterSettings;
+import android.telephony.emergency.EmergencyNumber;
import android.telephony.ims.aidl.IImsCapabilityCallback;
import android.telephony.ims.aidl.IImsConfig;
import android.telephony.ims.aidl.IImsConfigCallback;
@@ -1292,22 +1294,27 @@ interface ITelephony {
List<TelephonyHistogram> getTelephonyHistograms();
/**
- * Set the allowed carrier list for slotIndex
- * Require system privileges. In the future we may add this to carrier APIs.
+ * Set the allowed carrier list and the excluded carrier list, indicating the priority between
+ * the two lists.
*
- * @return The number of carriers set successfully. Should match length of
- * carriers on success.
+ * <p>Requires system privileges. In the future we may add this to carrier APIs.
+ *
+ * @return {@link #SET_CARRIER_RESTRICTION_SUCCESS} in case of success.
+ * {@link #SET_CARRIER_RESTRICTION_NOT_SUPPORTED} if the modem does not support the
+ * configuration. {@link #SET_CARRIER_RESTRICTION_ERROR} in all other error cases.
*/
- int setAllowedCarriers(int slotIndex, in List<CarrierIdentifier> carriers);
+ int setAllowedCarriers(in CarrierRestrictionRules carrierRestrictionRules);
/**
- * Get the allowed carrier list for slotIndex.
- * Require system privileges. In the future we may add this to carrier APIs.
+ * Get the allowed carrier list and the excluded carrier list indicating the priority between
+ * the two lists.
+ *
+ * <p>Requires system privileges. In the future we may add this to carrier APIs.
*
- * @return List of {@link android.service.carrier.CarrierIdentifier}; empty list
- * means all carriers are allowed.
+ * @return {@link CarrierRestrictionRules}; empty lists mean all carriers are allowed. It
+ * returns null in case of error.
*/
- List<CarrierIdentifier> getAllowedCarriers(int slotIndex);
+ CarrierRestrictionRules getAllowedCarriers();
/**
* Returns carrier id of the given subscription.
@@ -1776,4 +1783,14 @@ interface ITelephony {
* Set the String provisioning value for the provisioning key specified.
*/
int setImsProvisioningString(int subId, int key, String value);
+
+ /**
+ * Update Emergency Number List for Test Mode.
+ */
+ void updateEmergencyNumberListTestMode(int action, in EmergencyNumber num);
+
+ /**
+ * Get the full emergency number list for Test Mode.
+ */
+ List<String> getEmergencyNumberListTestMode();
}
diff --git a/tests/ActivityViewTest/AndroidManifest.xml b/tests/ActivityViewTest/AndroidManifest.xml
index 0be1ea0fdfd2..17eb029166f0 100644
--- a/tests/ActivityViewTest/AndroidManifest.xml
+++ b/tests/ActivityViewTest/AndroidManifest.xml
@@ -57,5 +57,10 @@
android:exported="true"
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|colorMode|density">
</activity>
+
+ <activity android:name=".ActivityViewVisibilityActivity"
+ android:label="AV Visibility"
+ android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|colorMode|density">
+ </activity>
</application>
</manifest>
diff --git a/tests/ActivityViewTest/res/layout/activity_view_main_activity.xml b/tests/ActivityViewTest/res/layout/activity_view_main_activity.xml
index ba2e91166440..efcaef679a9c 100644
--- a/tests/ActivityViewTest/res/layout/activity_view_main_activity.xml
+++ b/tests/ActivityViewTest/res/layout/activity_view_main_activity.xml
@@ -41,4 +41,10 @@
android:text="Test Resize ActivityView"
android:textAllCaps="false"/>
+ <Button
+ android:id="@+id/visibility_activity_view_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Test ActivityView Visibility"
+ android:textAllCaps="false"/>
</LinearLayout>
diff --git a/tests/ActivityViewTest/res/layout/activity_view_visibility_activity.xml b/tests/ActivityViewTest/res/layout/activity_view_visibility_activity.xml
new file mode 100644
index 000000000000..d29d4dfc0428
--- /dev/null
+++ b/tests/ActivityViewTest/res/layout/activity_view_visibility_activity.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="#cfd8dc">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+
+ <Button
+ android:id="@+id/activity_launch_button"
+ android:layout_width="200dp"
+ android:layout_height="wrap_content"
+ android:text="Launch test activity" />
+
+ <Spinner
+ android:id="@+id/visibility_spinner"
+ android:layout_width="200dp"
+ android:layout_height="match_parent"/>
+
+ </LinearLayout>
+
+ <ActivityView
+ android:id="@+id/activity_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+</LinearLayout>
diff --git a/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewMainActivity.java b/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewMainActivity.java
index 66f0c6a56afd..4f09c28fe711 100644
--- a/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewMainActivity.java
+++ b/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewMainActivity.java
@@ -35,5 +35,8 @@ public class ActivityViewMainActivity extends Activity {
findViewById(R.id.resize_activity_view_button).setOnClickListener(
v -> startActivity(new Intent(this, ActivityViewResizeActivity.class)));
+
+ findViewById(R.id.visibility_activity_view_button).setOnClickListener(
+ v -> startActivity(new Intent(this, ActivityViewVisibilityActivity.class)));
}
}
diff --git a/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewTestActivity.java b/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewTestActivity.java
index ba2c764bd7d7..52aba2b13c42 100644
--- a/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewTestActivity.java
+++ b/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewTestActivity.java
@@ -24,12 +24,14 @@ import static android.view.MotionEvent.ACTION_UP;
import android.app.Activity;
import android.content.res.Configuration;
import android.os.Bundle;
+import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.TextView;
public class ActivityViewTestActivity extends Activity {
+ private static final String TAG = "ActivityViewTestActivity";
private View mRoot;
private TextView mTextView;
@@ -84,6 +86,7 @@ public class ActivityViewTestActivity extends Activity {
}
private void updateStateText(String state) {
+ Log.d(TAG, state);
mTextView.setText(state);
}
diff --git a/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewVisibilityActivity.java b/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewVisibilityActivity.java
new file mode 100644
index 000000000000..ecd2cf3c578e
--- /dev/null
+++ b/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewVisibilityActivity.java
@@ -0,0 +1,75 @@
+/**
+ * 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.google.android.test.activityview;
+
+import static android.view.View.GONE;
+import static android.view.View.INVISIBLE;
+import static android.view.View.VISIBLE;
+
+import android.app.Activity;
+import android.app.ActivityView;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.Spinner;
+
+public class ActivityViewVisibilityActivity extends Activity {
+ private static final String[] sVisibilityOptions = {"VISIBLE", "INVISIBLE", "GONE"};
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_view_visibility_activity);
+
+ final ActivityView activityView = findViewById(R.id.activity_view);
+ final Button launchButton = findViewById(R.id.activity_launch_button);
+ launchButton.setOnClickListener(v -> {
+ final Intent intent = new Intent(this, ActivityViewTestActivity.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
+ activityView.startActivity(intent);
+ });
+
+ final Spinner visibilitySpinner = findViewById(R.id.visibility_spinner);
+ final ArrayAdapter<String> adapter = new ArrayAdapter<>(this,
+ android.R.layout.simple_spinner_item, sVisibilityOptions);
+ adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ visibilitySpinner.setAdapter(adapter);
+ visibilitySpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+ switch (position) {
+ case 0:
+ activityView.setVisibility(VISIBLE);
+ break;
+ case 1:
+ activityView.setVisibility(INVISIBLE);
+ break;
+ case 2:
+ activityView.setVisibility(GONE);
+ break;
+ }
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView<?> parent) {
+ }
+ });
+ }
+}
diff --git a/tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java b/tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
index 77cd9d8f20a3..c2e735e184b0 100644
--- a/tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
+++ b/tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
@@ -178,10 +178,10 @@ public class RollbackTest {
}
/**
- * Test that rollback data is properly persisted.
+ * Test that multiple available rollbacks are properly persisted.
*/
@Test
- public void testRollbackDataPersistence() throws Exception {
+ public void testAvailableRollbackPersistence() throws Exception {
try {
RollbackTestUtils.adoptShellPermissionIdentity(
Manifest.permission.INSTALL_PACKAGES,
@@ -190,36 +190,157 @@ public class RollbackTest {
RollbackManager rm = RollbackTestUtils.getRollbackManager();
- // TODO: Test this with multi-package rollback, not just single
- // package rollback.
- // Prep installation of TEST_APP_A
RollbackTestUtils.uninstall(TEST_APP_A);
RollbackTestUtils.install("RollbackTestAppAv1.apk", false);
RollbackTestUtils.install("RollbackTestAppAv2.apk", true);
assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
+ RollbackTestUtils.uninstall(TEST_APP_B);
+ RollbackTestUtils.install("RollbackTestAppBv1.apk", false);
+ RollbackTestUtils.install("RollbackTestAppBv2.apk", true);
+ assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_B));
+
+ // Both test apps should now be available for rollback.
+ // TODO: See if there is a way to remove this race condition
+ // between when the app is installed and when the rollback
+ // is made available.
+ Thread.sleep(1000);
+
+ assertTrue(rm.getPackagesWithAvailableRollbacks().contains(TEST_APP_A));
+ RollbackInfo rollbackA = rm.getAvailableRollback(TEST_APP_A);
+ assertNotNull(rollbackA);
+ assertEquals(TEST_APP_A, rollbackA.targetPackage.packageName);
+ assertEquals(2, rollbackA.targetPackage.higherVersion.versionCode);
+ assertEquals(1, rollbackA.targetPackage.lowerVersion.versionCode);
+
+ assertTrue(rm.getPackagesWithAvailableRollbacks().contains(TEST_APP_B));
+ RollbackInfo rollbackB = rm.getAvailableRollback(TEST_APP_B);
+ assertNotNull(rollbackB);
+ assertEquals(TEST_APP_B, rollbackB.targetPackage.packageName);
+ assertEquals(2, rollbackB.targetPackage.higherVersion.versionCode);
+ assertEquals(1, rollbackB.targetPackage.lowerVersion.versionCode);
+
+ // Reload the persisted data.
+ rm.reloadPersistedData();
+
+ // The apps should still be available for rollback.
+ rollbackA = rm.getAvailableRollback(TEST_APP_A);
+ assertNotNull(rollbackA);
+ assertEquals(TEST_APP_A, rollbackA.targetPackage.packageName);
+ assertEquals(2, rollbackA.targetPackage.higherVersion.versionCode);
+ assertEquals(1, rollbackA.targetPackage.lowerVersion.versionCode);
+
+ assertTrue(rm.getPackagesWithAvailableRollbacks().contains(TEST_APP_B));
+ rollbackB = rm.getAvailableRollback(TEST_APP_B);
+ assertNotNull(rollbackB);
+ assertEquals(TEST_APP_B, rollbackB.targetPackage.packageName);
+ assertEquals(2, rollbackB.targetPackage.higherVersion.versionCode);
+ assertEquals(1, rollbackB.targetPackage.lowerVersion.versionCode);
+
+ // Rollback of B should not rollback A
+ RollbackTestUtils.rollback(rollbackB);
+ assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
+ assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_B));
+ } finally {
+ RollbackTestUtils.dropShellPermissionIdentity();
+ }
+ }
+
+ /**
+ * Test that available multi-package rollbacks are properly persisted.
+ */
+ @Test
+ public void testAvailableMultiPackageRollbackPersistence() throws Exception {
+ try {
+ RollbackTestUtils.adoptShellPermissionIdentity(
+ Manifest.permission.INSTALL_PACKAGES,
+ Manifest.permission.DELETE_PACKAGES,
+ Manifest.permission.MANAGE_ROLLBACKS);
+
+ RollbackManager rm = RollbackTestUtils.getRollbackManager();
+
+ RollbackTestUtils.uninstall(TEST_APP_A);
+ RollbackTestUtils.uninstall(TEST_APP_B);
+ RollbackTestUtils.installMultiPackage(false,
+ "RollbackTestAppAv1.apk",
+ "RollbackTestAppBv1.apk");
+ RollbackTestUtils.installMultiPackage(true,
+ "RollbackTestAppAv2.apk",
+ "RollbackTestAppBv2.apk");
+ assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
+ assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_B));
+
// The app should now be available for rollback.
// TODO: See if there is a way to remove this race condition
// between when the app is installed and when the rollback
// is made available.
Thread.sleep(1000);
+
assertTrue(rm.getPackagesWithAvailableRollbacks().contains(TEST_APP_A));
- RollbackInfo rollback = rm.getAvailableRollback(TEST_APP_A);
- assertNotNull(rollback);
- assertEquals(TEST_APP_A, rollback.targetPackage.packageName);
- assertEquals(2, rollback.targetPackage.higherVersion.versionCode);
- assertEquals(1, rollback.targetPackage.lowerVersion.versionCode);
+ RollbackInfo rollbackA = rm.getAvailableRollback(TEST_APP_A);
+ assertNotNull(rollbackA);
+ assertEquals(TEST_APP_A, rollbackA.targetPackage.packageName);
+ assertEquals(2, rollbackA.targetPackage.higherVersion.versionCode);
+ assertEquals(1, rollbackA.targetPackage.lowerVersion.versionCode);
+
+ assertTrue(rm.getPackagesWithAvailableRollbacks().contains(TEST_APP_B));
+ RollbackInfo rollbackB = rm.getAvailableRollback(TEST_APP_B);
+ assertNotNull(rollbackB);
+ assertEquals(TEST_APP_B, rollbackB.targetPackage.packageName);
+ assertEquals(2, rollbackB.targetPackage.higherVersion.versionCode);
+ assertEquals(1, rollbackB.targetPackage.lowerVersion.versionCode);
// Reload the persisted data.
rm.reloadPersistedData();
- // The app should still be available for rollback.
+ // The apps should still be available for rollback.
+ rollbackA = rm.getAvailableRollback(TEST_APP_A);
+ assertNotNull(rollbackA);
+ assertEquals(TEST_APP_A, rollbackA.targetPackage.packageName);
+ assertEquals(2, rollbackA.targetPackage.higherVersion.versionCode);
+ assertEquals(1, rollbackA.targetPackage.lowerVersion.versionCode);
+
+ assertTrue(rm.getPackagesWithAvailableRollbacks().contains(TEST_APP_B));
+ rollbackB = rm.getAvailableRollback(TEST_APP_B);
+ assertNotNull(rollbackB);
+ assertEquals(TEST_APP_B, rollbackB.targetPackage.packageName);
+ assertEquals(2, rollbackB.targetPackage.higherVersion.versionCode);
+ assertEquals(1, rollbackB.targetPackage.lowerVersion.versionCode);
+
+ // Rollback of B should rollback A as well
+ RollbackTestUtils.rollback(rollbackB);
+ assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
+ assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_B));
+ } finally {
+ RollbackTestUtils.dropShellPermissionIdentity();
+ }
+ }
+
+ /**
+ * Test that recently executed rollback data is properly persisted.
+ */
+ @Test
+ public void testRecentlyExecutedRollbackPersistence() throws Exception {
+ try {
+ RollbackTestUtils.adoptShellPermissionIdentity(
+ Manifest.permission.INSTALL_PACKAGES,
+ Manifest.permission.DELETE_PACKAGES,
+ Manifest.permission.MANAGE_ROLLBACKS);
+
+ RollbackManager rm = RollbackTestUtils.getRollbackManager();
+
+ RollbackTestUtils.uninstall(TEST_APP_A);
+ RollbackTestUtils.install("RollbackTestAppAv1.apk", false);
+ RollbackTestUtils.install("RollbackTestAppAv2.apk", true);
+ assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
+
+ // The app should now be available for rollback.
+ // TODO: See if there is a way to remove this race condition
+ // between when the app is installed and when the rollback
+ // is made available.
+ Thread.sleep(1000);
assertTrue(rm.getPackagesWithAvailableRollbacks().contains(TEST_APP_A));
- rollback = rm.getAvailableRollback(TEST_APP_A);
- assertNotNull(rollback);
- assertEquals(TEST_APP_A, rollback.targetPackage.packageName);
- assertEquals(2, rollback.targetPackage.higherVersion.versionCode);
- assertEquals(1, rollback.targetPackage.lowerVersion.versionCode);
+ RollbackInfo rollback = rm.getAvailableRollback(TEST_APP_A);
// Roll back the app.
RollbackTestUtils.rollback(rollback);
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 2a92a7dabd98..882babff4aee 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -122,7 +122,6 @@ import android.net.NetworkSpecifier;
import android.net.NetworkStack;
import android.net.NetworkUtils;
import android.net.RouteInfo;
-import android.net.StringNetworkSpecifier;
import android.net.UidRange;
import android.net.metrics.IpConnectivityLog;
import android.net.shared.NetworkMonitorUtils;
@@ -145,6 +144,7 @@ import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import android.test.mock.MockContentResolver;
+import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
@@ -2567,16 +2567,76 @@ public class ConnectivityServiceTest {
return new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI);
}
+ /**
+ * Verify request matching behavior with network specifiers.
+ *
+ * Note: this test is somewhat problematic since it involves removing capabilities from
+ * agents - i.e. agents rejecting requests which they previously accepted. This is flagged
+ * as a WTF bug in
+ * {@link ConnectivityService#mixInCapabilities(NetworkAgentInfo, NetworkCapabilities)} but
+ * does work.
+ */
@Test
public void testNetworkSpecifier() {
+ // A NetworkSpecifier subclass that matches all networks but must not be visible to apps.
+ class ConfidentialMatchAllNetworkSpecifier extends NetworkSpecifier implements
+ Parcelable {
+ @Override
+ public boolean satisfiedBy(NetworkSpecifier other) {
+ return true;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {}
+
+ @Override
+ public NetworkSpecifier redact() {
+ return null;
+ }
+ }
+
+ // A network specifier that matches either another LocalNetworkSpecifier with the same
+ // string or a ConfidentialMatchAllNetworkSpecifier, and can be passed to apps as is.
+ class LocalStringNetworkSpecifier extends NetworkSpecifier implements Parcelable {
+ private String mString;
+
+ LocalStringNetworkSpecifier(String string) {
+ mString = string;
+ }
+
+ @Override
+ public boolean satisfiedBy(NetworkSpecifier other) {
+ if (other instanceof LocalStringNetworkSpecifier) {
+ return TextUtils.equals(mString,
+ ((LocalStringNetworkSpecifier) other).mString);
+ }
+ if (other instanceof ConfidentialMatchAllNetworkSpecifier) return true;
+ return false;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {}
+ }
+
+
NetworkRequest rEmpty1 = newWifiRequestBuilder().build();
NetworkRequest rEmpty2 = newWifiRequestBuilder().setNetworkSpecifier((String) null).build();
NetworkRequest rEmpty3 = newWifiRequestBuilder().setNetworkSpecifier("").build();
NetworkRequest rEmpty4 = newWifiRequestBuilder().setNetworkSpecifier(
(NetworkSpecifier) null).build();
- NetworkRequest rFoo = newWifiRequestBuilder().setNetworkSpecifier("foo").build();
+ NetworkRequest rFoo = newWifiRequestBuilder().setNetworkSpecifier(
+ new LocalStringNetworkSpecifier("foo")).build();
NetworkRequest rBar = newWifiRequestBuilder().setNetworkSpecifier(
- new StringNetworkSpecifier("bar")).build();
+ new LocalStringNetworkSpecifier("bar")).build();
TestNetworkCallback cEmpty1 = new TestNetworkCallback();
TestNetworkCallback cEmpty2 = new TestNetworkCallback();
@@ -2585,7 +2645,7 @@ public class ConnectivityServiceTest {
TestNetworkCallback cFoo = new TestNetworkCallback();
TestNetworkCallback cBar = new TestNetworkCallback();
TestNetworkCallback[] emptyCallbacks = new TestNetworkCallback[] {
- cEmpty1, cEmpty2, cEmpty3 };
+ cEmpty1, cEmpty2, cEmpty3, cEmpty4 };
mCm.registerNetworkCallback(rEmpty1, cEmpty1);
mCm.registerNetworkCallback(rEmpty2, cEmpty2);
@@ -2594,6 +2654,9 @@ public class ConnectivityServiceTest {
mCm.registerNetworkCallback(rFoo, cFoo);
mCm.registerNetworkCallback(rBar, cBar);
+ LocalStringNetworkSpecifier nsFoo = new LocalStringNetworkSpecifier("foo");
+ LocalStringNetworkSpecifier nsBar = new LocalStringNetworkSpecifier("bar");
+
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(false);
cEmpty1.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
@@ -2602,30 +2665,54 @@ public class ConnectivityServiceTest {
cEmpty4.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
assertNoCallbacks(cFoo, cBar);
- mWiFiNetworkAgent.setNetworkSpecifier(new StringNetworkSpecifier("foo"));
+ mWiFiNetworkAgent.setNetworkSpecifier(nsFoo);
cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
for (TestNetworkCallback c: emptyCallbacks) {
- c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
+ c.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsFoo),
+ mWiFiNetworkAgent);
}
- cFoo.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
+ cFoo.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsFoo),
+ mWiFiNetworkAgent);
+ assertEquals(nsFoo,
+ mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
cFoo.assertNoCallback();
- mWiFiNetworkAgent.setNetworkSpecifier(new StringNetworkSpecifier("bar"));
+ mWiFiNetworkAgent.setNetworkSpecifier(nsBar);
cFoo.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
cBar.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
for (TestNetworkCallback c: emptyCallbacks) {
- c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
+ c.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsBar),
+ mWiFiNetworkAgent);
}
- cBar.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
+ cBar.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsBar),
+ mWiFiNetworkAgent);
+ assertEquals(nsBar,
+ mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
+ cBar.assertNoCallback();
+
+ mWiFiNetworkAgent.setNetworkSpecifier(new ConfidentialMatchAllNetworkSpecifier());
+ cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+ for (TestNetworkCallback c : emptyCallbacks) {
+ c.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier() == null,
+ mWiFiNetworkAgent);
+ }
+ cFoo.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier() == null,
+ mWiFiNetworkAgent);
+ cBar.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier() == null,
+ mWiFiNetworkAgent);
+ assertNull(
+ mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
+ cFoo.assertNoCallback();
cBar.assertNoCallback();
mWiFiNetworkAgent.setNetworkSpecifier(null);
+ cFoo.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
cBar.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
for (TestNetworkCallback c: emptyCallbacks) {
c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
}
- assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cFoo, cBar);
+ assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar);
}
@Test
diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp
index 58702dc465cc..e0d2f48e8dcf 100644
--- a/tools/aapt2/ResourceParser.cpp
+++ b/tools/aapt2/ResourceParser.cpp
@@ -1164,8 +1164,6 @@ bool ResourceParser::ParseOverlayable(xml::XmlPullParser* parser, ParsedResource
current_policies |= OverlayableItem::Policy::kPublic;
} else if (trimmed_part == "product") {
current_policies |= OverlayableItem::Policy::kProduct;
- } else if (trimmed_part == "product_services") {
- current_policies |= OverlayableItem::Policy::kProductServices;
} else if (trimmed_part == "system") {
current_policies |= OverlayableItem::Policy::kSystem;
} else if (trimmed_part == "vendor") {
diff --git a/tools/aapt2/ResourceParser_test.cpp b/tools/aapt2/ResourceParser_test.cpp
index debca9c1e1ba..827c7deaf452 100644
--- a/tools/aapt2/ResourceParser_test.cpp
+++ b/tools/aapt2/ResourceParser_test.cpp
@@ -935,9 +935,6 @@ TEST_F(ResourceParserTest, ParseOverlayablePolicy) {
<policy type="product">
<item type="string" name="bar" />
</policy>
- <policy type="product_services">
- <item type="string" name="baz" />
- </policy>
<policy type="system">
<item type="string" name="fiz" />
</policy>
@@ -966,14 +963,6 @@ TEST_F(ResourceParserTest, ParseOverlayablePolicy) {
EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("Name"));
EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kProduct));
- search_result = table_.FindResource(test::ParseNameOrDie("string/baz"));
- ASSERT_TRUE(search_result);
- ASSERT_THAT(search_result.value().entry, NotNull());
- ASSERT_TRUE(search_result.value().entry->overlayable_item);
- result_overlayable_item = search_result.value().entry->overlayable_item.value();
- EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("Name"));
- EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kProductServices));
-
search_result = table_.FindResource(test::ParseNameOrDie("string/fiz"));
ASSERT_TRUE(search_result);
ASSERT_THAT(search_result.value().entry, NotNull());
@@ -1028,7 +1017,7 @@ TEST_F(ResourceParserTest, ParseOverlayableBadPolicyError) {
TEST_F(ResourceParserTest, ParseOverlayableMultiplePolicy) {
std::string input = R"(
<overlayable name="Name">
- <policy type="vendor|product_services">
+ <policy type="vendor|public">
<item type="string" name="foo" />
</policy>
<policy type="product|system">
@@ -1044,7 +1033,7 @@ TEST_F(ResourceParserTest, ParseOverlayableMultiplePolicy) {
OverlayableItem result_overlayable_item = search_result.value().entry->overlayable_item.value();
EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("Name"));
EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kVendor
- | OverlayableItem::Policy::kProductServices));
+ | OverlayableItem::Policy::kPublic));
search_result = table_.FindResource(test::ParseNameOrDie("string/bar"));
ASSERT_TRUE(search_result);
@@ -1139,7 +1128,7 @@ TEST_F(ResourceParserTest, NestPolicyInOverlayableError) {
std::string input = R"(
<overlayable name="Name">
<policy type="vendor|product">
- <policy type="product_services">
+ <policy type="public">
<item type="string" name="foo" />
</policy>
</policy>
diff --git a/tools/aapt2/ResourceTable.h b/tools/aapt2/ResourceTable.h
index eaf6a47a15fd..7ca99ea42b50 100644
--- a/tools/aapt2/ResourceTable.h
+++ b/tools/aapt2/ResourceTable.h
@@ -92,9 +92,6 @@ struct OverlayableItem {
// The resource can be overlaid by any overlay on the product partition.
kProduct = 0x08,
-
- // The resource can be overlaid by any overlay on the product services partition.
- kProductServices = 0x10
};
std::shared_ptr<Overlayable> overlayable;
diff --git a/tools/aapt2/ResourceTable_test.cpp b/tools/aapt2/ResourceTable_test.cpp
index a733134f123c..b97dc6b205ca 100644
--- a/tools/aapt2/ResourceTable_test.cpp
+++ b/tools/aapt2/ResourceTable_test.cpp
@@ -248,7 +248,7 @@ TEST(ResourceTableTest, SetOverlayable) {
Source("res/values/overlayable.xml", 40));
OverlayableItem overlayable_item(overlayable);
overlayable_item.policies |= OverlayableItem::Policy::kProduct;
- overlayable_item.policies |= OverlayableItem::Policy::kProductServices;
+ overlayable_item.policies |= OverlayableItem::Policy::kVendor;
overlayable_item.comment = "comment";
overlayable_item.source = Source("res/values/overlayable.xml", 42);
@@ -265,7 +265,7 @@ TEST(ResourceTableTest, SetOverlayable) {
EXPECT_THAT(result_overlayable_item.overlayable->source.path, Eq("res/values/overlayable.xml"));
EXPECT_THAT(result_overlayable_item.overlayable->source.line, 40);
EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kProduct
- | OverlayableItem::Policy::kProductServices));
+ | OverlayableItem::Policy::kVendor));
ASSERT_THAT(result_overlayable_item.comment, StrEq("comment"));
EXPECT_THAT(result_overlayable_item.source.path, Eq("res/values/overlayable.xml"));
EXPECT_THAT(result_overlayable_item.source.line, 42);
diff --git a/tools/aapt2/Resources.proto b/tools/aapt2/Resources.proto
index da541be9502b..73b568e77689 100644
--- a/tools/aapt2/Resources.proto
+++ b/tools/aapt2/Resources.proto
@@ -155,7 +155,6 @@ message OverlayableItem {
SYSTEM = 1;
VENDOR = 2;
PRODUCT = 3;
- PRODUCT_SERVICES = 4;
}
// The location of the <item> declaration in source.
diff --git a/tools/aapt2/format/binary/BinaryResourceParser.cpp b/tools/aapt2/format/binary/BinaryResourceParser.cpp
index 7d4c6f348403..40aaa05c2b30 100644
--- a/tools/aapt2/format/binary/BinaryResourceParser.cpp
+++ b/tools/aapt2/format/binary/BinaryResourceParser.cpp
@@ -473,10 +473,6 @@ bool BinaryResourceParser::ParseOverlayable(const ResChunk_header* chunk) {
& ResTable_overlayable_policy_header::POLICY_PRODUCT_PARTITION) {
policies |= OverlayableItem::Policy::kProduct;
}
- if (policy_header->policy_flags
- & ResTable_overlayable_policy_header::POLICY_PRODUCT_SERVICES_PARTITION) {
- policies |= OverlayableItem::Policy::kProductServices;
- }
const ResTable_ref* const ref_begin = reinterpret_cast<const ResTable_ref*>(
((uint8_t *)policy_header) + util::DeviceToHost32(policy_header->header.headerSize));
diff --git a/tools/aapt2/format/binary/TableFlattener.cpp b/tools/aapt2/format/binary/TableFlattener.cpp
index c4ecbafc008b..9d341cc1ca4a 100644
--- a/tools/aapt2/format/binary/TableFlattener.cpp
+++ b/tools/aapt2/format/binary/TableFlattener.cpp
@@ -485,9 +485,6 @@ class PackageFlattener {
if (item.policies & OverlayableItem::Policy::kProduct) {
policy_flags |= ResTable_overlayable_policy_header::POLICY_PRODUCT_PARTITION;
}
- if (item.policies & OverlayableItem::Policy::kProductServices) {
- policy_flags |= ResTable_overlayable_policy_header::POLICY_PRODUCT_SERVICES_PARTITION;
- }
}
auto policy = overlayable_chunk->policy_ids.find(policy_flags);
diff --git a/tools/aapt2/format/binary/TableFlattener_test.cpp b/tools/aapt2/format/binary/TableFlattener_test.cpp
index 18fecf60c977..ddc117399390 100644
--- a/tools/aapt2/format/binary/TableFlattener_test.cpp
+++ b/tools/aapt2/format/binary/TableFlattener_test.cpp
@@ -660,12 +660,10 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayablePolicies) {
OverlayableItem overlayable_item_zero(overlayable);
overlayable_item_zero.policies |= OverlayableItem::Policy::kProduct;
overlayable_item_zero.policies |= OverlayableItem::Policy::kSystem;
- overlayable_item_zero.policies |= OverlayableItem::Policy::kProductServices;
std::string name_one = "com.app.test:integer/overlayable_one_item";
OverlayableItem overlayable_item_one(overlayable);
overlayable_item_one.policies |= OverlayableItem::Policy::kPublic;
- overlayable_item_one.policies |= OverlayableItem::Policy::kProductServices;
std::string name_two = "com.app.test:integer/overlayable_two_item";
OverlayableItem overlayable_item_two(overlayable);
@@ -698,16 +696,14 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayablePolicies) {
ASSERT_TRUE(search_result.value().entry->overlayable_item);
OverlayableItem& overlayable_item = search_result.value().entry->overlayable_item.value();
EXPECT_EQ(overlayable_item.policies, OverlayableItem::Policy::kSystem
- | OverlayableItem::Policy::kProduct
- | OverlayableItem::Policy::kProductServices);
+ | OverlayableItem::Policy::kProduct);
search_result = output_table.FindResource(test::ParseNameOrDie(name_one));
ASSERT_TRUE(search_result);
ASSERT_THAT(search_result.value().entry, NotNull());
ASSERT_TRUE(search_result.value().entry->overlayable_item);
overlayable_item = search_result.value().entry->overlayable_item.value();
- EXPECT_EQ(overlayable_item.policies, OverlayableItem::Policy::kPublic
- | OverlayableItem::Policy::kProductServices);
+ EXPECT_EQ(overlayable_item.policies, OverlayableItem::Policy::kPublic);
search_result = output_table.FindResource(test::ParseNameOrDie(name_two));
ASSERT_TRUE(search_result);
@@ -735,13 +731,11 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayable) {
OverlayableItem overlayable_item_zero(group);
overlayable_item_zero.policies |= OverlayableItem::Policy::kProduct;
overlayable_item_zero.policies |= OverlayableItem::Policy::kSystem;
- overlayable_item_zero.policies |= OverlayableItem::Policy::kProductServices;
auto group_one = std::make_shared<Overlayable>("OtherName", "overlay://customization");
std::string name_one = "com.app.test:integer/overlayable_one";
OverlayableItem overlayable_item_one(group_one);
overlayable_item_one.policies |= OverlayableItem::Policy::kPublic;
- overlayable_item_one.policies |= OverlayableItem::Policy::kProductServices;
std::string name_two = "com.app.test:integer/overlayable_two";
OverlayableItem overlayable_item_two(group);
@@ -773,8 +767,7 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayable) {
EXPECT_EQ(result_overlayable.overlayable->name, "TestName");
EXPECT_EQ(result_overlayable.overlayable->actor, "overlay://theme");
EXPECT_EQ(result_overlayable.policies, OverlayableItem::Policy::kSystem
- | OverlayableItem::Policy::kProduct
- | OverlayableItem::Policy::kProductServices);
+ | OverlayableItem::Policy::kProduct);
search_result = output_table.FindResource(test::ParseNameOrDie(name_one));
ASSERT_TRUE(search_result);
ASSERT_THAT(search_result.value().entry, NotNull());
@@ -782,8 +775,7 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayable) {
result_overlayable = search_result.value().entry->overlayable_item.value();
EXPECT_EQ(result_overlayable.overlayable->name, "OtherName");
EXPECT_EQ(result_overlayable.overlayable->actor, "overlay://customization");
- EXPECT_EQ(result_overlayable.policies, OverlayableItem::Policy::kPublic
- | OverlayableItem::Policy::kProductServices);
+ EXPECT_EQ(result_overlayable.policies, OverlayableItem::Policy::kPublic);
search_result = output_table.FindResource(test::ParseNameOrDie(name_two));
ASSERT_TRUE(search_result);
ASSERT_THAT(search_result.value().entry, NotNull());
diff --git a/tools/aapt2/format/proto/ProtoDeserialize.cpp b/tools/aapt2/format/proto/ProtoDeserialize.cpp
index 6b5746d63bf8..aff1b391f861 100644
--- a/tools/aapt2/format/proto/ProtoDeserialize.cpp
+++ b/tools/aapt2/format/proto/ProtoDeserialize.cpp
@@ -390,9 +390,6 @@ bool DeserializeOverlayableItemFromPb(const pb::OverlayableItem& pb_overlayable,
case pb::OverlayableItem::PRODUCT:
out_overlayable->policies |= OverlayableItem::Policy::kProduct;
break;
- case pb::OverlayableItem::PRODUCT_SERVICES:
- out_overlayable->policies |= OverlayableItem::Policy::kProductServices;
- break;
default:
*out_error = "unknown overlayable policy";
return false;
diff --git a/tools/aapt2/format/proto/ProtoSerialize.cpp b/tools/aapt2/format/proto/ProtoSerialize.cpp
index 76fbb464b62a..b549e2369f98 100644
--- a/tools/aapt2/format/proto/ProtoSerialize.cpp
+++ b/tools/aapt2/format/proto/ProtoSerialize.cpp
@@ -303,9 +303,6 @@ static void SerializeOverlayableItemToPb(const OverlayableItem& overlayable_item
if (overlayable_item.policies & OverlayableItem::Policy::kProduct) {
pb_overlayable_item->add_policy(pb::OverlayableItem::PRODUCT);
}
- if (overlayable_item.policies & OverlayableItem::Policy::kProductServices) {
- pb_overlayable_item->add_policy(pb::OverlayableItem::PRODUCT_SERVICES);
- }
if (overlayable_item.policies & OverlayableItem::Policy::kSystem) {
pb_overlayable_item->add_policy(pb::OverlayableItem::SYSTEM);
}
diff --git a/tools/aapt2/format/proto/ProtoSerialize_test.cpp b/tools/aapt2/format/proto/ProtoSerialize_test.cpp
index 4a3c1b86236e..cce3939704cf 100644
--- a/tools/aapt2/format/proto/ProtoSerialize_test.cpp
+++ b/tools/aapt2/format/proto/ProtoSerialize_test.cpp
@@ -519,7 +519,7 @@ TEST(ProtoSerializeTest, SerializeAndDeserializeOverlayable) {
OverlayableItem overlayable_item_bar(std::make_shared<Overlayable>(
"TaskBar", "overlay://theme"));
- overlayable_item_bar.policies |= OverlayableItem::Policy::kProductServices;
+ overlayable_item_bar.policies |= OverlayableItem::Policy::kPublic;
overlayable_item_bar.policies |= OverlayableItem::Policy::kVendor;
OverlayableItem overlayable_item_baz(std::make_shared<Overlayable>(
@@ -565,7 +565,7 @@ TEST(ProtoSerializeTest, SerializeAndDeserializeOverlayable) {
overlayable_item = search_result.value().entry->overlayable_item.value();
EXPECT_THAT(overlayable_item.overlayable->name, Eq("TaskBar"));
EXPECT_THAT(overlayable_item.overlayable->actor, Eq("overlay://theme"));
- EXPECT_THAT(overlayable_item.policies, Eq(OverlayableItem::Policy::kProductServices
+ EXPECT_THAT(overlayable_item.policies, Eq(OverlayableItem::Policy::kPublic
| OverlayableItem::Policy::kVendor));
search_result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/baz"));
diff --git a/tools/aapt2/link/TableMerger_test.cpp b/tools/aapt2/link/TableMerger_test.cpp
index 921d634e583e..ad3674e16774 100644
--- a/tools/aapt2/link/TableMerger_test.cpp
+++ b/tools/aapt2/link/TableMerger_test.cpp
@@ -484,7 +484,7 @@ TEST_F(TableMergerTest, SetOverlayableLater) {
OverlayableItem overlayable_item(overlayable);
overlayable_item.policies |= OverlayableItem::Policy::kPublic;
- overlayable_item.policies |= OverlayableItem::Policy::kProductServices;
+ overlayable_item.policies |= OverlayableItem::Policy::kSystem;
std::unique_ptr<ResourceTable> table_b =
test::ResourceTableBuilder()
.SetPackageId("com.app.a", 0x7f)
@@ -506,7 +506,7 @@ TEST_F(TableMergerTest, SetOverlayableLater) {
EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("CustomizableResources"));
EXPECT_THAT(result_overlayable_item.overlayable->actor, Eq("overlay://customization"));
EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kPublic
- | OverlayableItem::Policy::kProductServices));
+ | OverlayableItem::Policy::kSystem));
}
TEST_F(TableMergerTest, SameResourceDifferentNameFail) {
diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index 840af5d5cd06..35fba3dcf7cf 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -16,6 +16,7 @@
package android.net.wifi;
+import android.annotation.SystemApi;
import android.annotation.UnsupportedAppUsage;
import android.net.NetworkInfo.DetailedState;
import android.net.NetworkUtils;
@@ -470,6 +471,7 @@ public class WifiInfo implements Parcelable {
}
/** {@hide} */
+ @SystemApi
public boolean isOsuAp() {
return mOsuAp;
}
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 559f4ad8264e..801342dc0c6e 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -236,9 +236,11 @@ public class WifiManager {
public static final int WIFI_CREDENTIAL_FORGOT = 1;
/** @hide */
+ @SystemApi
public static final int PASSPOINT_HOME_NETWORK = 0;
/** @hide */
+ @SystemApi
public static final int PASSPOINT_ROAMING_NETWORK = 1;
/**
@@ -1219,7 +1221,11 @@ public class WifiManager {
* @throws UnsupportedOperationException if Passpoint is not enabled on the device.
* @hide
*/
- @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
+ @SystemApi
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD
+ })
public List<Pair<WifiConfiguration, Map<Integer, List<ScanResult>>>> getAllMatchingWifiConfigs(
@NonNull List<ScanResult> scanResults) {
List<Pair<WifiConfiguration, Map<Integer, List<ScanResult>>>> configs = new ArrayList<>();
@@ -1258,7 +1264,11 @@ public class WifiManager {
* @throws UnsupportedOperationException if Passpoint is not enabled on the device.
* @hide
*/
- @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
+ @SystemApi
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD
+ })
public Map<OsuProvider, List<ScanResult>> getMatchingOsuProviders(
List<ScanResult> scanResults) {
try {
@@ -1281,7 +1291,11 @@ public class WifiManager {
* @throws UnsupportedOperationException if Passpoint is not enabled on the device.
* @hide
*/
- @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
+ @SystemApi
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD
+ })
public Map<OsuProvider, PasspointConfiguration> getMatchingPasspointConfigsForOsuProviders(
@NonNull Set<OsuProvider> osuProviders) {
try {
@@ -1727,7 +1741,13 @@ public class WifiManager {
* @param fqdn The FQDN of the Passpoint configuration to be removed
* @throws IllegalArgumentException if no configuration is associated with the given FQDN.
* @throws UnsupportedOperationException if Passpoint is not enabled on the device.
+ * @deprecated This is no longer supported.
*/
+ @Deprecated
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD
+ })
public void removePasspointConfiguration(String fqdn) {
try {
if (!mService.removePasspointConfiguration(fqdn, mContext.getOpPackageName())) {
@@ -1745,7 +1765,13 @@ public class WifiManager {
*
* @return A list of {@link PasspointConfiguration}
* @throws UnsupportedOperationException if Passpoint is not enabled on the device.
+ * @deprecated This is no longer supported.
*/
+ @Deprecated
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD
+ })
public List<PasspointConfiguration> getPasspointConfigurations() {
try {
return mService.getPasspointConfigurations();
@@ -4323,6 +4349,11 @@ public class WifiManager {
* @param callback {@link ProvisioningCallback} for updates regarding provisioning flow
* @hide
*/
+ @SystemApi
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD
+ })
public void startSubscriptionProvisioning(OsuProvider provider, ProvisioningCallback callback,
@Nullable Handler handler) {
Looper looper = (handler == null) ? Looper.getMainLooper() : handler.getLooper();
diff --git a/wifi/java/android/net/wifi/WifiNetworkAgentSpecifier.java b/wifi/java/android/net/wifi/WifiNetworkAgentSpecifier.java
index 955e040a46f1..b8175d2338ec 100644
--- a/wifi/java/android/net/wifi/WifiNetworkAgentSpecifier.java
+++ b/wifi/java/android/net/wifi/WifiNetworkAgentSpecifier.java
@@ -168,8 +168,9 @@ public final class WifiNetworkAgentSpecifier extends NetworkSpecifier implements
@Override
public String toString() {
StringBuilder sb = new StringBuilder("WifiNetworkAgentSpecifier [");
- sb.append("WifiConfiguration=").append(
- mWifiConfiguration == null ? null : mWifiConfiguration.configKey())
+ sb.append("WifiConfiguration=")
+ .append(", SSID=").append(mWifiConfiguration.SSID)
+ .append(", BSSID=").append(mWifiConfiguration.BSSID)
.append(", mOriginalRequestorUid=").append(mOriginalRequestorUid)
.append("]");
return sb.toString();
diff --git a/wifi/java/android/net/wifi/WifiNetworkSpecifier.java b/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
index 4348399b404b..6e4eeef4dd55 100644
--- a/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
+++ b/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
@@ -162,11 +162,11 @@ public final class WifiNetworkSpecifier extends NetworkSpecifier implements Parc
@Override
public String toString() {
return new StringBuilder()
- .append("WifiNetworkSpecifierWifiNetworkSpecifier [")
+ .append("WifiNetworkSpecifier [")
.append(", SSID Match pattern=").append(ssidPatternMatcher)
.append(", BSSID Match pattern=").append(bssidPatternMatcher)
- .append(", WifiConfiguration=").append(
- wifiConfiguration == null ? null : wifiConfiguration.configKey())
+ .append(", SSID=").append(wifiConfiguration.SSID)
+ .append(", BSSID=").append(wifiConfiguration.BSSID)
.append(", requestorUid=").append(requestorUid)
.append("]")
.toString();
diff --git a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
index 760f1e6bc5e2..3c90eb763e81 100644
--- a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
+++ b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
@@ -130,7 +130,8 @@ public final class WifiNetworkSuggestion implements Parcelable {
@Override
public String toString() {
StringBuilder sb = new StringBuilder("WifiNetworkSuggestion [")
- .append(", WifiConfiguration=").append(wifiConfiguration)
+ .append(", SSID=").append(wifiConfiguration.SSID)
+ .append(", BSSID=").append(wifiConfiguration.BSSID)
.append(", isAppInteractionRequired=").append(isAppInteractionRequired)
.append(", isUserInteractionRequired=").append(isUserInteractionRequired)
.append(", suggestorUid=").append(suggestorUid)
diff --git a/wifi/java/android/net/wifi/hotspot2/OsuProvider.java b/wifi/java/android/net/wifi/hotspot2/OsuProvider.java
index 6d82ca152202..f91790f5b3b1 100644
--- a/wifi/java/android/net/wifi/hotspot2/OsuProvider.java
+++ b/wifi/java/android/net/wifi/hotspot2/OsuProvider.java
@@ -16,6 +16,7 @@
package android.net.wifi.hotspot2;
+import android.annotation.SystemApi;
import android.graphics.drawable.Icon;
import android.net.Uri;
import android.net.wifi.WifiSsid;
@@ -36,16 +37,19 @@ import java.util.Objects;
*
* @hide
*/
+@SystemApi
public final class OsuProvider implements Parcelable {
/**
* OSU (Online Sign-Up) method: OMA DM (Open Mobile Alliance Device Management).
* For more info, refer to Section 8.3 of the Hotspot 2.0 Release 2 Technical Specification.
+ * @hide
*/
public static final int METHOD_OMA_DM = 0;
/**
* OSU (Online Sign-Up) method: SOAP XML SPP (Subscription Provisioning Protocol).
* For more info, refer to Section 8.4 of the Hotspot 2.0 Release 2 Technical Specification.
+ * @hide
*/
public static final int METHOD_SOAP_XML_SPP = 1;
@@ -84,6 +88,7 @@ public final class OsuProvider implements Parcelable {
*/
private final Icon mIcon;
+ /** @hide */
public OsuProvider(WifiSsid osuSsid, Map<String, String> friendlyNames,
String serviceDescription, Uri serverUri, String nai, List<Integer> methodList,
Icon icon) {
@@ -104,6 +109,7 @@ public final class OsuProvider implements Parcelable {
* Copy constructor.
*
* @param source The source to copy from
+ * @hide
*/
public OsuProvider(OsuProvider source) {
if (source == null) {
@@ -130,10 +136,12 @@ public final class OsuProvider implements Parcelable {
mIcon = source.mIcon;
}
+ /** @hide */
public WifiSsid getOsuSsid() {
return mOsuSsid;
}
+ /** @hide */
public void setOsuSsid(WifiSsid osuSsid) {
mOsuSsid = osuSsid;
}
@@ -162,10 +170,12 @@ public final class OsuProvider implements Parcelable {
return mFriendlyNames.get(mFriendlyNames.keySet().stream().findFirst().get());
}
+ /** @hide */
public Map<String, String> getFriendlyNameList() {
return mFriendlyNames;
}
+ /** @hide */
public String getServiceDescription() {
return mServiceDescription;
}
@@ -174,14 +184,17 @@ public final class OsuProvider implements Parcelable {
return mServerUri;
}
+ /** @hide */
public String getNetworkAccessIdentifier() {
return mNetworkAccessIdentifier;
}
+ /** @hide */
public List<Integer> getMethodList() {
return mMethodList;
}
+ /** @hide */
public Icon getIcon() {
return mIcon;
}
diff --git a/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java b/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java
index a62d63cd8910..1ee874a9698b 100644
--- a/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java
+++ b/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java
@@ -16,6 +16,7 @@
package android.net.wifi.hotspot2;
+import android.annotation.SystemApi;
import android.net.wifi.WifiManager;
import android.os.Handler;
@@ -25,6 +26,7 @@ import android.os.Handler;
*
* @hide
*/
+@SystemApi
public abstract class ProvisioningCallback {
/**