summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt84
-rw-r--r--api/system-current.txt25
-rw-r--r--api/system-removed.txt25
-rw-r--r--api/test-current.txt120
-rw-r--r--api/test-removed.txt13
-rw-r--r--cmds/idmap2/idmap2/Create.cpp1
-rw-r--r--cmds/idmap2/idmap2/Lookup.cpp5
-rw-r--r--cmds/idmap2/idmap2/Main.cpp3
-rw-r--r--cmds/idmap2/idmap2/Scan.cpp9
-rw-r--r--cmds/idmap2/idmap2d/Idmap2Service.cpp7
-rw-r--r--cmds/idmap2/idmap2d/Main.cpp4
-rw-r--r--cmds/idmap2/include/idmap2/Idmap.h2
-rw-r--r--cmds/idmap2/include/idmap2/Policies.h3
-rw-r--r--cmds/idmap2/include/idmap2/PrettyPrintVisitor.h1
-rw-r--r--cmds/idmap2/include/idmap2/RawPrintVisitor.h1
-rw-r--r--cmds/idmap2/include/idmap2/ResourceUtils.h1
-rw-r--r--cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp4
-rw-r--r--cmds/idmap2/libidmap2/CommandLineOptions.cpp4
-rw-r--r--cmds/idmap2/libidmap2/FileUtils.cpp4
-rw-r--r--cmds/idmap2/libidmap2/Idmap.cpp8
-rw-r--r--cmds/idmap2/libidmap2/Policies.cpp4
-rw-r--r--cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp4
-rw-r--r--cmds/idmap2/libidmap2/RawPrintVisitor.cpp4
-rw-r--r--cmds/idmap2/libidmap2/ResourceUtils.cpp4
-rw-r--r--cmds/idmap2/libidmap2/Result.cpp4
-rw-r--r--cmds/idmap2/libidmap2/Xml.cpp4
-rw-r--r--cmds/idmap2/libidmap2/ZipFile.cpp3
-rw-r--r--cmds/idmap2/tests/BinaryStreamVisitorTests.cpp9
-rw-r--r--cmds/idmap2/tests/CommandLineOptionsTests.cpp9
-rw-r--r--cmds/idmap2/tests/FileUtilsTests.cpp12
-rw-r--r--cmds/idmap2/tests/Idmap2BinaryTests.cpp27
-rw-r--r--cmds/idmap2/tests/IdmapTests.cpp10
-rw-r--r--cmds/idmap2/tests/Main.cpp4
-rw-r--r--cmds/idmap2/tests/PoliciesTests.cpp3
-rw-r--r--cmds/idmap2/tests/PrettyPrintVisitorTests.cpp9
-rw-r--r--cmds/idmap2/tests/RawPrintVisitorTests.cpp4
-rw-r--r--cmds/idmap2/tests/ResourceUtilsTests.cpp6
-rw-r--r--cmds/idmap2/tests/ResultTests.cpp1
-rw-r--r--cmds/idmap2/tests/TestHelpers.h3
-rw-r--r--cmds/idmap2/tests/XmlTests.cpp8
-rw-r--r--cmds/idmap2/tests/ZipFileTests.cpp8
-rw-r--r--cmds/idmap2/tests/data/signature-overlay/AndroidManifest.xml4
-rw-r--r--cmds/idmap2/tests/data/signature-overlay/signature-overlay.apkbin1183 -> 1315 bytes
-rw-r--r--core/java/android/app/ActivityThread.java152
-rw-r--r--core/java/android/app/ClientTransactionHandler.java2
-rw-r--r--core/java/android/app/IActivityManager.aidl2
-rw-r--r--core/java/android/app/TaskInfo.java9
-rw-r--r--core/java/android/app/prediction/AppTarget.java53
-rw-r--r--core/java/android/app/servertransaction/LaunchActivityItem.java7
-rw-r--r--core/java/android/attention/AttentionManagerInternal.java7
-rw-r--r--core/java/android/bluetooth/le/ScanRecord.java6
-rw-r--r--core/java/android/content/ContentProviderOperation.java33
-rw-r--r--core/java/android/content/ContentProviderResult.java75
-rw-r--r--core/java/android/hardware/hdmi/HdmiControlManager.java111
-rw-r--r--core/java/android/inputmethodservice/MultiClientInputMethodServiceDelegate.java11
-rw-r--r--core/java/android/inputmethodservice/MultiClientInputMethodServiceDelegateImpl.java4
-rw-r--r--core/java/android/provider/DeviceConfig.java3
-rw-r--r--core/java/android/provider/Settings.java20
-rw-r--r--core/java/android/service/attention/AttentionService.java15
-rw-r--r--core/java/android/service/contentcapture/ContentCaptureService.java16
-rw-r--r--core/java/android/service/contentcapture/IContentCaptureService.aidl4
-rw-r--r--core/java/android/service/euicc/EuiccService.java17
-rw-r--r--core/java/android/service/voice/VoiceInteractionSession.java2
-rwxr-xr-xcore/java/android/util/DisplayMetrics.java28
-rw-r--r--core/java/android/view/ScaleGestureDetector.java2
-rw-r--r--core/java/android/view/View.java537
-rw-r--r--core/java/android/view/ViewGroup.java60
-rw-r--r--core/java/android/view/ViewRootImpl.java157
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureManager.java13
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureSession.java48
-rw-r--r--core/java/android/view/contentcapture/DataRemovalRequest.aidl (renamed from core/java/android/view/contentcapture/UserDataRemovalRequest.aidl)2
-rw-r--r--core/java/android/view/contentcapture/DataRemovalRequest.java (renamed from core/java/android/view/contentcapture/UserDataRemovalRequest.java)40
-rw-r--r--core/java/android/view/contentcapture/IContentCaptureManager.aidl6
-rw-r--r--core/java/android/view/textclassifier/ConversationActions.java34
-rw-r--r--core/java/android/webkit/WebView.java8
-rw-r--r--core/java/android/widget/AdapterView.java3
-rw-r--r--core/java/android/widget/TextView.java39
-rw-r--r--core/java/com/android/internal/app/ChooserActivity.java93
-rw-r--r--core/java/com/android/internal/inputmethod/IMultiClientInputMethodPrivilegedOperations.aidl1
-rw-r--r--core/java/com/android/internal/inputmethod/MultiClientInputMethodPrivilegedOperations.java17
-rw-r--r--core/jni/android_nio_utils.cpp37
-rw-r--r--core/jni/android_nio_utils.h9
-rw-r--r--core/proto/android/stats/devicepolicy/device_policy_enums.proto4
-rw-r--r--core/res/res/values/attrs.xml19
-rw-r--r--core/res/res/values/config.xml4
-rw-r--r--core/res/res/values/public.xml2
-rw-r--r--core/res/res/values/strings.xml8
-rw-r--r--core/res/res/values/symbols.xml1
-rw-r--r--core/tests/coretests/src/android/app/activity/ActivityThreadTest.java29
-rw-r--r--core/tests/coretests/src/android/graphics/BitmapTest.java72
-rw-r--r--core/tests/coretests/src/android/provider/SettingsBackupTest.java4
-rw-r--r--core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java17
-rw-r--r--core/tests/coretests/src/android/view/InsetsControllerTest.java2
-rw-r--r--core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java2
-rw-r--r--core/tests/coretests/src/android/view/InsetsSourceTest.java2
-rw-r--r--core/tests/coretests/src/android/view/InsetsStateTest.java2
-rw-r--r--core/tests/coretests/src/android/view/contentcapture/ContentCaptureManagerTest.java2
-rw-r--r--core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java35
-rw-r--r--libs/hwui/Properties.cpp13
-rw-r--r--libs/hwui/Properties.h2
-rw-r--r--libs/hwui/TreeInfo.cpp3
-rw-r--r--libs/hwui/TreeInfo.h3
-rw-r--r--libs/hwui/VectorDrawable.cpp5
-rw-r--r--libs/hwui/pipeline/skia/ShaderCache.cpp2
-rw-r--r--libs/hwui/pipeline/skia/SkiaDisplayList.cpp46
-rw-r--r--libs/hwui/pipeline/skia/SkiaDisplayList.h19
-rw-r--r--libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp20
-rw-r--r--libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h2
-rw-r--r--libs/hwui/pipeline/skia/SkiaPipeline.cpp24
-rw-r--r--libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp7
-rw-r--r--libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp13
-rw-r--r--libs/hwui/pipeline/skia/SkiaVulkanPipeline.h2
-rw-r--r--libs/hwui/pipeline/skia/VkFunctorDrawable.cpp28
-rw-r--r--libs/hwui/renderthread/CacheManager.cpp13
-rw-r--r--libs/hwui/renderthread/CanvasContext.cpp56
-rw-r--r--libs/hwui/renderthread/CanvasContext.h20
-rw-r--r--libs/hwui/renderthread/DrawFrameTask.cpp5
-rw-r--r--libs/hwui/renderthread/EglManager.cpp35
-rw-r--r--libs/hwui/renderthread/IRenderPipeline.h4
-rw-r--r--libs/hwui/renderthread/ReliableSurface.cpp22
-rw-r--r--libs/hwui/renderthread/RenderProxy.cpp19
-rw-r--r--libs/hwui/renderthread/RenderThread.cpp6
-rw-r--r--libs/hwui/renderthread/RenderThread.h2
-rw-r--r--libs/hwui/renderthread/VulkanManager.cpp126
-rw-r--r--libs/hwui/renderthread/VulkanManager.h8
-rw-r--r--libs/hwui/renderthread/VulkanSurface.cpp107
-rw-r--r--libs/hwui/renderthread/VulkanSurface.h24
-rw-r--r--libs/hwui/tests/unit/SkiaDisplayListTests.cpp184
-rw-r--r--libs/hwui/tests/unit/SkiaPipelineTests.cpp15
-rw-r--r--media/Android.bp1
-rw-r--r--media/apex/java/android/media/MediaItem2.java310
-rw-r--r--media/apex/java/android/media/Session2Command.java34
-rw-r--r--media/java/android/media/AudioAttributes.java17
-rw-r--r--media/java/android/media/AudioFocusInfo.java2
-rw-r--r--media/java/android/media/AudioManager.java35
-rw-r--r--media/java/android/media/AudioPlaybackCaptureConfiguration.java36
-rw-r--r--media/java/android/media/AudioTrack.java6
-rw-r--r--media/java/android/media/IAudioService.aidl2
-rw-r--r--media/java/android/media/audiopolicy/AudioMix.java2
-rw-r--r--media/java/android/media/audiopolicy/AudioMixingRule.java12
-rw-r--r--media/java/android/media/audiopolicy/AudioPolicy.java4
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/graph/ThemedBatteryDrawable.kt2
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/BatteryMeterView.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java14
-rw-r--r--services/accessibility/java/com/android/server/accessibility/MotionEventInjector.java9
-rw-r--r--services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java6
-rw-r--r--services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java6
-rw-r--r--services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java8
-rw-r--r--services/core/java/com/android/server/BluetoothService.java7
-rw-r--r--services/core/java/com/android/server/attention/AttentionManagerService.java20
-rw-r--r--services/core/java/com/android/server/audio/AudioDeviceBroker.java4
-rw-r--r--services/core/java/com/android/server/audio/AudioDeviceInventory.java5
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java24
-rw-r--r--services/core/java/com/android/server/audio/AudioServiceEvents.java8
-rw-r--r--services/core/java/com/android/server/audio/MediaFocusControl.java6
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodManagerService.java10
-rw-r--r--services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java18
-rw-r--r--services/core/java/com/android/server/locksettings/PasswordSlotManager.java30
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java6
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java51
-rw-r--r--services/core/java/com/android/server/pm/StagingManager.java4
-rw-r--r--services/core/java/com/android/server/power/AttentionDetector.java30
-rw-r--r--services/core/java/com/android/server/stats/StatsCompanionService.java3
-rw-r--r--services/core/java/com/android/server/wm/ActivityStartController.java2
-rw-r--r--services/core/java/com/android/server/wm/ActivityStarter.java90
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java2
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java38
-rw-r--r--services/core/java/com/android/server/wm/CompatModePackages.java6
-rw-r--r--services/core/java/com/android/server/wm/Dimmer.java10
-rw-r--r--services/core/java/com/android/server/wm/ImmersiveModeConfirmation.java21
-rw-r--r--services/core/java/com/android/server/wm/RecentTasks.java28
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java7
-rw-r--r--services/core/java/com/android/server/wm/SurfaceAnimator.java8
-rw-r--r--services/core/java/com/android/server/wm/WindowProcessController.java43
-rw-r--r--services/core/java/com/android/server/wm/WindowProcessControllerMap.java86
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/AbUpdateInstaller.java13
-rw-r--r--services/tests/mockingservicestests/AndroidManifest.xml2
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/display/color/DisplayTransformManagerTest.java (renamed from services/tests/servicestests/src/com/android/server/display/color/DisplayTransformManagerTest.java)66
-rw-r--r--services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java23
-rw-r--r--services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java29
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java51
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityStartControllerTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java32
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AssistDataRequesterTest.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java7
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java10
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java3
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerMapTests.java130
-rw-r--r--telecomm/java/android/telecom/InCallService.java65
-rw-r--r--telecomm/java/android/telecom/PhoneAccountHandle.java18
-rw-r--r--telecomm/java/android/telecom/TelecomManager.java21
-rw-r--r--telephony/java/android/provider/Telephony.java2
-rwxr-xr-xtelephony/java/android/telephony/CarrierConfigManager.java4
-rw-r--r--telephony/java/android/telephony/SubscriptionInfo.java59
-rw-r--r--telephony/java/android/telephony/SubscriptionManager.java12
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java12
202 files changed, 2590 insertions, 2269 deletions
diff --git a/api/current.txt b/api/current.txt
index af842b5c76bc..eb244e4cd1eb 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -224,6 +224,7 @@ package android {
field public static final int __removed3 = 16844187; // 0x101059b
field public static final int __removed4 = 16844188; // 0x101059c
field public static final int __removed5 = 16844189; // 0x101059d
+ field public static final int __removed6 = 16844182; // 0x1010596
field public static final int absListViewStyle = 16842858; // 0x101006a
field public static final int accessibilityEventTypes = 16843648; // 0x1010380
field public static final int accessibilityFeedbackType = 16843650; // 0x1010382
@@ -750,7 +751,6 @@ package android {
field public static final int immersive = 16843456; // 0x10102c0
field public static final int importantForAccessibility = 16843690; // 0x10103aa
field public static final int importantForAutofill = 16844120; // 0x1010558
- field public static final int importantForContentCapture = 16844182; // 0x1010596
field public static final int inAnimation = 16843127; // 0x1010177
field public static final int includeFontPadding = 16843103; // 0x101015f
field public static final int includeInGlobalSearch = 16843374; // 0x101026e
@@ -6235,14 +6235,14 @@ package android.app {
}
public class TaskInfo {
- field public android.content.ComponentName baseActivity;
- field public android.content.Intent baseIntent;
+ field @Nullable public android.content.ComponentName baseActivity;
+ field @NonNull public android.content.Intent baseIntent;
field public boolean isRunning;
field public int numActivities;
- field public android.content.ComponentName origActivity;
- field public android.app.ActivityManager.TaskDescription taskDescription;
+ field @Nullable public android.content.ComponentName origActivity;
+ field @Nullable public android.app.ActivityManager.TaskDescription taskDescription;
field public int taskId;
- field public android.content.ComponentName topActivity;
+ field @Nullable public android.content.ComponentName topActivity;
}
public class TaskStackBuilder {
@@ -9001,7 +9001,7 @@ package android.bluetooth.le {
method @Nullable public byte[] getManufacturerSpecificData(int);
method public java.util.Map<android.os.ParcelUuid,byte[]> getServiceData();
method @Nullable public byte[] getServiceData(android.os.ParcelUuid);
- method @Nullable public java.util.List<android.os.ParcelUuid> getServiceSolicitationUuids();
+ method @NonNull public java.util.List<android.os.ParcelUuid> getServiceSolicitationUuids();
method public java.util.List<android.os.ParcelUuid> getServiceUuids();
method public int getTxPowerLevel();
}
@@ -23045,6 +23045,7 @@ package android.media {
public final class AudioAttributes implements android.os.Parcelable {
method public boolean areHapticChannelsMuted();
method public int describeContents();
+ method public int getAllowedCapturePolicy();
method public int getContentType();
method public int getFlags();
method public int getUsage();
@@ -23250,6 +23251,7 @@ package android.media {
method public int generateAudioSessionId();
method @NonNull public java.util.List<android.media.AudioPlaybackConfiguration> getActivePlaybackConfigurations();
method @NonNull public java.util.List<android.media.AudioRecordingConfiguration> getActiveRecordingConfigurations();
+ method public int getAllowedCapturePolicy();
method public android.media.AudioDeviceInfo[] getDevices(int);
method public java.util.List<android.media.MicrophoneInfo> getMicrophones() throws java.io.IOException;
method public int getMode();
@@ -23422,6 +23424,10 @@ package android.media {
}
public final class AudioPlaybackCaptureConfiguration {
+ method @NonNull public int[] getExcludeUids();
+ method @NonNull public int[] getExcludeUsages();
+ method @NonNull public int[] getMatchingUids();
+ method @NonNull public int[] getMatchingUsages();
method @NonNull public android.media.projection.MediaProjection getMediaProjection();
}
@@ -25132,25 +25138,6 @@ package android.media {
field public static final int TYPE_STRING = 4; // 0x4
}
- public final class MediaItem2 implements android.os.Parcelable {
- method public int describeContents();
- method public long getEndPosition();
- method @Nullable public android.media.MediaMetadata getMetadata();
- method public long getStartPosition();
- method public void setMetadata(@Nullable android.media.MediaMetadata);
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.media.MediaItem2> CREATOR;
- field public static final long POSITION_UNKNOWN = 576460752303423487L; // 0x7ffffffffffffffL
- }
-
- public static final class MediaItem2.Builder {
- ctor public MediaItem2.Builder();
- method @NonNull public android.media.MediaItem2 build();
- method @NonNull public android.media.MediaItem2.Builder setEndPosition(long);
- method @NonNull public android.media.MediaItem2.Builder setMetadata(@Nullable android.media.MediaMetadata);
- method @NonNull public android.media.MediaItem2.Builder setStartPosition(long);
- }
-
public final class MediaMetadata implements android.os.Parcelable {
method public boolean containsKey(String);
method public int describeContents();
@@ -26171,8 +26158,8 @@ package android.media {
ctor public Session2Command(@NonNull String, @Nullable android.os.Bundle);
method public int describeContents();
method public int getCommandCode();
- method @Nullable public String getCustomCommand();
- method @Nullable public android.os.Bundle getExtras();
+ method @Nullable public String getCustomAction();
+ method @Nullable public android.os.Bundle getCustomExtras();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field public static final int COMMAND_CODE_CUSTOM = 0; // 0x0
field @NonNull public static final android.os.Parcelable.Creator<android.media.Session2Command> CREATOR;
@@ -38619,6 +38606,7 @@ package android.provider {
field public static final String ACTION_APPLICATION_DETAILS_SETTINGS = "android.settings.APPLICATION_DETAILS_SETTINGS";
field public static final String ACTION_APPLICATION_DEVELOPMENT_SETTINGS = "android.settings.APPLICATION_DEVELOPMENT_SETTINGS";
field public static final String ACTION_APPLICATION_SETTINGS = "android.settings.APPLICATION_SETTINGS";
+ field public static final String ACTION_APP_BATTERY_SETTINGS = "android.settings.APP_BATTERY_SETTINGS";
field public static final String ACTION_APP_NOTIFICATION_BUBBLE_SETTINGS = "android.settings.APP_NOTIFICATION_BUBBLE_SETTINGS";
field public static final String ACTION_APP_NOTIFICATION_SETTINGS = "android.settings.APP_NOTIFICATION_SETTINGS";
field public static final String ACTION_APP_SEARCH_SETTINGS = "android.settings.APP_SEARCH_SETTINGS";
@@ -39090,7 +39078,7 @@ package android.provider {
field @Deprecated public static final String BEARER = "bearer";
field public static final String CARRIER_ENABLED = "carrier_enabled";
field public static final String CARRIER_ID = "carrier_id";
- field public static final android.net.Uri CONTENT_URI;
+ field @NonNull public static final android.net.Uri CONTENT_URI;
field public static final String CURRENT = "current";
field public static final String DEFAULT_SORT_ORDER = "name ASC";
field @Deprecated public static final String MCC = "mcc";
@@ -39109,7 +39097,7 @@ package android.provider {
field public static final String PROXY = "proxy";
field public static final String ROAMING_PROTOCOL = "roaming_protocol";
field public static final String SERVER = "server";
- field public static final android.net.Uri SIM_APN_URI;
+ field @NonNull public static final android.net.Uri SIM_APN_URI;
field public static final String SUBSCRIPTION_ID = "sub_id";
field public static final String TYPE = "type";
field public static final String USER = "user";
@@ -47812,6 +47800,10 @@ package android.util {
method public boolean equals(android.util.DisplayMetrics);
method public void setTo(android.util.DisplayMetrics);
method public void setToDefaults();
+ field public static final int DENSITY_140 = 140; // 0x8c
+ field public static final int DENSITY_180 = 180; // 0xb4
+ field public static final int DENSITY_200 = 200; // 0xc8
+ field public static final int DENSITY_220 = 220; // 0xdc
field public static final int DENSITY_260 = 260; // 0x104
field public static final int DENSITY_280 = 280; // 0x118
field public static final int DENSITY_300 = 300; // 0x12c
@@ -50195,7 +50187,6 @@ package android.view {
method @android.view.ViewDebug.CapturedViewProperty @IdRes public int getId();
method @android.view.ViewDebug.ExportedProperty(category="accessibility", mapping={@android.view.ViewDebug.IntToString(from=android.view.View.IMPORTANT_FOR_ACCESSIBILITY_AUTO, to="auto"), @android.view.ViewDebug.IntToString(from=android.view.View.IMPORTANT_FOR_ACCESSIBILITY_YES, to="yes"), @android.view.ViewDebug.IntToString(from=android.view.View.IMPORTANT_FOR_ACCESSIBILITY_NO, to="no"), @android.view.ViewDebug.IntToString(from=android.view.View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS, to="noHideDescendants")}) public int getImportantForAccessibility();
method @android.view.ViewDebug.ExportedProperty(mapping={@android.view.ViewDebug.IntToString(from=android.view.View.IMPORTANT_FOR_AUTOFILL_AUTO, to="auto"), @android.view.ViewDebug.IntToString(from=android.view.View.IMPORTANT_FOR_AUTOFILL_YES, to="yes"), @android.view.ViewDebug.IntToString(from=android.view.View.IMPORTANT_FOR_AUTOFILL_NO, to="no"), @android.view.ViewDebug.IntToString(from=android.view.View.IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS, to="yesExcludeDescendants"), @android.view.ViewDebug.IntToString(from=android.view.View.IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS, to="noExcludeDescendants")}) public int getImportantForAutofill();
- method @android.view.ViewDebug.ExportedProperty(mapping={@android.view.ViewDebug.IntToString(from=android.view.View.IMPORTANT_FOR_CONTENT_CAPTURE_AUTO, to="auto"), @android.view.ViewDebug.IntToString(from=android.view.View.IMPORTANT_FOR_CONTENT_CAPTURE_YES, to="yes"), @android.view.ViewDebug.IntToString(from=android.view.View.IMPORTANT_FOR_CONTENT_CAPTURE_NO, to="no"), @android.view.ViewDebug.IntToString(from=android.view.View.IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS, to="yesExcludeDescendants"), @android.view.ViewDebug.IntToString(from=android.view.View.IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS, to="noExcludeDescendants")}) public int getImportantForContentCapture();
method public boolean getKeepScreenOn();
method public android.view.KeyEvent.DispatcherState getKeyDispatcherState();
method @android.view.ViewDebug.ExportedProperty(category="accessibility") @IdRes public int getLabelFor();
@@ -50336,7 +50327,6 @@ package android.view {
method @android.view.ViewDebug.ExportedProperty public boolean isHovered();
method public boolean isImportantForAccessibility();
method public final boolean isImportantForAutofill();
- method public final boolean isImportantForContentCapture();
method public boolean isInEditMode();
method public boolean isInLayout();
method @android.view.ViewDebug.ExportedProperty public boolean isInTouchMode();
@@ -50411,7 +50401,6 @@ package android.view {
method @CallSuper public void onPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
method public void onProvideAutofillStructure(android.view.ViewStructure, int);
method public void onProvideAutofillVirtualStructure(android.view.ViewStructure, int);
- method public void onProvideContentCaptureStructure(@NonNull android.view.ViewStructure, int);
method public void onProvideStructure(android.view.ViewStructure);
method public void onProvideVirtualStructure(android.view.ViewStructure);
method public android.view.PointerIcon onResolvePointerIcon(android.view.MotionEvent, int);
@@ -50537,7 +50526,6 @@ package android.view {
method public void setId(@IdRes int);
method public void setImportantForAccessibility(int);
method public void setImportantForAutofill(int);
- method public void setImportantForContentCapture(int);
method public void setKeepScreenOn(boolean);
method public void setKeyboardNavigationCluster(boolean);
method public void setLabelFor(@IdRes int);
@@ -50716,11 +50704,6 @@ package android.view {
field public static final int IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS = 8; // 0x8
field public static final int IMPORTANT_FOR_AUTOFILL_YES = 1; // 0x1
field public static final int IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS = 4; // 0x4
- field public static final int IMPORTANT_FOR_CONTENT_CAPTURE_AUTO = 0; // 0x0
- field public static final int IMPORTANT_FOR_CONTENT_CAPTURE_NO = 2; // 0x2
- field public static final int IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS = 8; // 0x8
- field public static final int IMPORTANT_FOR_CONTENT_CAPTURE_YES = 1; // 0x1
- field public static final int IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS = 4; // 0x4
field public static final int INVISIBLE = 4; // 0x4
field public static final int KEEP_SCREEN_ON = 67108864; // 0x4000000
field public static final int LAYER_TYPE_HARDWARE = 2; // 0x2
@@ -52828,7 +52811,7 @@ package android.view.contentcapture {
method @Nullable public java.util.Set<android.view.contentcapture.ContentCaptureCondition> getContentCaptureConditions();
method @Nullable public android.content.ComponentName getServiceComponentName();
method public boolean isContentCaptureEnabled();
- method public void removeUserData(@NonNull android.view.contentcapture.UserDataRemovalRequest);
+ method public void removeData(@NonNull android.view.contentcapture.DataRemovalRequest);
method public void setContentCaptureEnabled(boolean);
}
@@ -52839,6 +52822,7 @@ package android.view.contentcapture {
method @Nullable public final android.view.contentcapture.ContentCaptureContext getContentCaptureContext();
method @NonNull public final android.view.contentcapture.ContentCaptureSessionId getContentCaptureSessionId();
method @NonNull public android.view.autofill.AutofillId newAutofillId(@NonNull android.view.autofill.AutofillId, long);
+ method @NonNull public final android.view.ViewStructure newViewStructure(@NonNull android.view.View);
method @NonNull public final android.view.ViewStructure newVirtualViewStructure(@NonNull android.view.autofill.AutofillId, long);
method public final void notifyViewAppeared(@NonNull android.view.ViewStructure);
method public final void notifyViewDisappeared(@NonNull android.view.autofill.AutofillId);
@@ -52853,24 +52837,24 @@ package android.view.contentcapture {
field @NonNull public static final android.os.Parcelable.Creator<android.view.contentcapture.ContentCaptureSessionId> CREATOR;
}
- public final class UserDataRemovalRequest implements android.os.Parcelable {
+ public final class DataRemovalRequest implements android.os.Parcelable {
method public int describeContents();
- method @NonNull public java.util.List<android.view.contentcapture.UserDataRemovalRequest.LocusIdRequest> getLocusIdRequests();
+ method @NonNull public java.util.List<android.view.contentcapture.DataRemovalRequest.LocusIdRequest> getLocusIdRequests();
method @NonNull public String getPackageName();
method public boolean isForEverything();
method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.view.contentcapture.UserDataRemovalRequest> CREATOR;
+ field @NonNull public static final android.os.Parcelable.Creator<android.view.contentcapture.DataRemovalRequest> CREATOR;
field public static final int FLAG_IS_PREFIX = 1; // 0x1
}
- public static final class UserDataRemovalRequest.Builder {
- ctor public UserDataRemovalRequest.Builder();
- method @NonNull public android.view.contentcapture.UserDataRemovalRequest.Builder addLocusId(@NonNull android.content.LocusId, int);
- method @NonNull public android.view.contentcapture.UserDataRemovalRequest build();
- method @NonNull public android.view.contentcapture.UserDataRemovalRequest.Builder forEverything();
+ public static final class DataRemovalRequest.Builder {
+ ctor public DataRemovalRequest.Builder();
+ method @NonNull public android.view.contentcapture.DataRemovalRequest.Builder addLocusId(@NonNull android.content.LocusId, int);
+ method @NonNull public android.view.contentcapture.DataRemovalRequest build();
+ method @NonNull public android.view.contentcapture.DataRemovalRequest.Builder forEverything();
}
- public final class UserDataRemovalRequest.LocusIdRequest {
+ public final class DataRemovalRequest.LocusIdRequest {
method @NonNull public int getFlags();
method @NonNull public android.content.LocusId getLocusId();
}
@@ -53420,6 +53404,7 @@ package android.view.textclassifier {
method public int describeContents();
method @Nullable public String getCallingPackageName();
method @NonNull public java.util.List<android.view.textclassifier.ConversationActions.Message> getConversation();
+ method @NonNull public android.os.Bundle getExtras();
method @Nullable public java.util.List<java.lang.String> getHints();
method @IntRange(from=0xffffffff) public int getMaxSuggestions();
method @NonNull public android.view.textclassifier.TextClassifier.EntityConfig getTypeConfig();
@@ -53432,6 +53417,7 @@ package android.view.textclassifier {
public static final class ConversationActions.Request.Builder {
ctor public ConversationActions.Request.Builder(@NonNull java.util.List<android.view.textclassifier.ConversationActions.Message>);
method @NonNull public android.view.textclassifier.ConversationActions.Request build();
+ method @NonNull public android.view.textclassifier.ConversationActions.Request.Builder setExtras(@Nullable android.os.Bundle);
method @NonNull public android.view.textclassifier.ConversationActions.Request.Builder setHints(@Nullable java.util.List<java.lang.String>);
method @NonNull public android.view.textclassifier.ConversationActions.Request.Builder setMaxSuggestions(@IntRange(from=0xffffffff) int);
method @NonNull public android.view.textclassifier.ConversationActions.Request.Builder setTypeConfig(@Nullable android.view.textclassifier.TextClassifier.EntityConfig);
diff --git a/api/system-current.txt b/api/system-current.txt
index 2d8b09293abb..d15d00682817 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -1092,12 +1092,11 @@ package android.app.prediction {
}
public static final class AppTarget.Builder {
- ctor public AppTarget.Builder(@NonNull android.app.prediction.AppTargetId);
+ ctor public AppTarget.Builder(@NonNull android.app.prediction.AppTargetId, @NonNull String, @NonNull android.os.UserHandle);
+ ctor public AppTarget.Builder(@NonNull android.app.prediction.AppTargetId, @NonNull android.content.pm.ShortcutInfo);
method @NonNull public android.app.prediction.AppTarget build();
method @NonNull public android.app.prediction.AppTarget.Builder setClassName(@NonNull String);
method @NonNull public android.app.prediction.AppTarget.Builder setRank(@IntRange(from=0) int);
- method @NonNull public android.app.prediction.AppTarget.Builder setTarget(@NonNull String, @NonNull android.os.UserHandle);
- method @NonNull public android.app.prediction.AppTarget.Builder setTarget(@NonNull android.content.pm.ShortcutInfo);
}
public final class AppTargetEvent implements android.os.Parcelable {
@@ -2002,15 +2001,15 @@ package android.hardware.hdmi {
public final class HdmiControlManager {
method @RequiresPermission(android.Manifest.permission.HDMI_CEC) public void addHotplugEventListener(android.hardware.hdmi.HdmiControlManager.HotplugEventListener);
method @Nullable public android.hardware.hdmi.HdmiClient getClient(int);
- method @Nullable public java.util.List<android.hardware.hdmi.HdmiDeviceInfo> getConnectedDevicesList();
+ method @NonNull public java.util.List<android.hardware.hdmi.HdmiDeviceInfo> getConnectedDevices();
method public int getPhysicalAddress();
method @Nullable public android.hardware.hdmi.HdmiPlaybackClient getPlaybackClient();
method @Nullable public android.hardware.hdmi.HdmiSwitchClient getSwitchClient();
method @Nullable public android.hardware.hdmi.HdmiTvClient getTvClient();
- method public boolean isRemoteDeviceConnected(@NonNull android.hardware.hdmi.HdmiDeviceInfo);
- method public void powerOffRemoteDevice(@NonNull android.hardware.hdmi.HdmiDeviceInfo);
+ method public boolean isDeviceConnected(@NonNull android.hardware.hdmi.HdmiDeviceInfo);
+ method public void powerOffDevice(@NonNull android.hardware.hdmi.HdmiDeviceInfo);
method @RequiresPermission(android.Manifest.permission.HDMI_CEC) public void removeHotplugEventListener(android.hardware.hdmi.HdmiControlManager.HotplugEventListener);
- method public void requestRemoteDeviceToBecomeActiveSource(@NonNull android.hardware.hdmi.HdmiDeviceInfo);
+ method public void setActiveSource(@NonNull android.hardware.hdmi.HdmiDeviceInfo);
method @RequiresPermission(android.Manifest.permission.HDMI_CEC) public void setStandbyMode(boolean);
field public static final String ACTION_OSD_MESSAGE = "android.hardware.hdmi.action.OSD_MESSAGE";
field public static final int AVR_VOLUME_MUTED = 101; // 0x65
@@ -3672,7 +3671,6 @@ package android.media.audiopolicy {
method public void setAudioPolicyStatusListener(android.media.audiopolicy.AudioPolicy.AudioPolicyStatusListener);
method @NonNull public android.media.audiopolicy.AudioPolicy.Builder setAudioPolicyVolumeCallback(@NonNull android.media.audiopolicy.AudioPolicy.AudioPolicyVolumeCallback);
method @NonNull public android.media.audiopolicy.AudioPolicy.Builder setIsAudioFocusPolicy(boolean);
- method @NonNull public android.media.audiopolicy.AudioPolicy.Builder setIsTestFocusPolicy(boolean);
method @NonNull public android.media.audiopolicy.AudioPolicy.Builder setLooper(@NonNull android.os.Looper) throws java.lang.IllegalArgumentException;
}
@@ -5823,7 +5821,6 @@ package android.provider {
public final class DeviceConfig {
method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static void addOnPropertiesChangedListener(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.provider.DeviceConfig.OnPropertiesChangedListener);
- method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static void addOnPropertyChangedListener(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.provider.DeviceConfig.OnPropertyChangedListener);
method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static boolean getBoolean(@NonNull String, @NonNull String, boolean);
method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static float getFloat(@NonNull String, @NonNull String, float);
method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static int getInt(@NonNull String, @NonNull String, int);
@@ -5831,7 +5828,6 @@ package android.provider {
method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static String getProperty(@NonNull String, @NonNull String);
method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static String getString(@NonNull String, @NonNull String, @Nullable String);
method public static void removeOnPropertiesChangedListener(@NonNull android.provider.DeviceConfig.OnPropertiesChangedListener);
- method public static void removeOnPropertyChangedListener(@NonNull android.provider.DeviceConfig.OnPropertyChangedListener);
method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static void resetToDefaults(int, @Nullable String);
method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static boolean setProperty(@NonNull String, @NonNull String, @Nullable String, boolean);
field public static final String NAMESPACE_ACTIVITY_MANAGER = "activity_manager";
@@ -5864,10 +5860,6 @@ package android.provider {
method public void onPropertiesChanged(@NonNull android.provider.DeviceConfig.Properties);
}
- public static interface DeviceConfig.OnPropertyChangedListener {
- method public void onPropertyChanged(@NonNull String, @NonNull String, @Nullable String);
- }
-
public static class DeviceConfig.Properties {
method public boolean getBoolean(@NonNull String, boolean);
method public float getFloat(@NonNull String, float);
@@ -6275,7 +6267,6 @@ package android.service.attention {
public abstract class AttentionService extends android.app.Service {
ctor public AttentionService();
- method public final void disableSelf();
method @Nullable public final android.os.IBinder onBind(@NonNull android.content.Intent);
method public abstract void onCancelAttentionCheck(@NonNull android.service.attention.AttentionService.AttentionCallback);
method public abstract void onCheckAttention(@NonNull android.service.attention.AttentionService.AttentionCallback);
@@ -6396,9 +6387,9 @@ package android.service.contentcapture {
method public void onConnected();
method public void onContentCaptureEvent(@NonNull android.view.contentcapture.ContentCaptureSessionId, @NonNull android.view.contentcapture.ContentCaptureEvent);
method public void onCreateContentCaptureSession(@NonNull android.view.contentcapture.ContentCaptureContext, @NonNull android.view.contentcapture.ContentCaptureSessionId);
+ method public void onDataRemovalRequest(@NonNull android.view.contentcapture.DataRemovalRequest);
method public void onDestroyContentCaptureSession(@NonNull android.view.contentcapture.ContentCaptureSessionId);
method public void onDisconnected();
- method public void onUserDataRemovalRequest(@NonNull android.view.contentcapture.UserDataRemovalRequest);
method public final void setContentCaptureConditions(@NonNull String, @Nullable java.util.Set<android.view.contentcapture.ContentCaptureCondition>);
method public final void setContentCaptureWhitelist(@Nullable java.util.Set<java.lang.String>, @Nullable java.util.Set<android.content.ComponentName>);
field public static final String SERVICE_INTERFACE = "android.service.contentcapture.ContentCaptureService";
@@ -6498,7 +6489,7 @@ package android.service.euicc {
ctor public EuiccService();
method @CallSuper public android.os.IBinder onBind(android.content.Intent);
method public abstract int onDeleteSubscription(int, String);
- method public abstract android.service.euicc.DownloadSubscriptionResult onDownloadSubscription(int, @NonNull android.telephony.euicc.DownloadableSubscription, boolean, boolean, @Nullable android.os.Bundle);
+ method public android.service.euicc.DownloadSubscriptionResult onDownloadSubscription(int, @NonNull android.telephony.euicc.DownloadableSubscription, boolean, boolean, @Nullable android.os.Bundle);
method @Deprecated public int onDownloadSubscription(int, @NonNull android.telephony.euicc.DownloadableSubscription, boolean, boolean);
method public abstract int onEraseSubscriptions(int);
method public abstract android.service.euicc.GetDefaultDownloadableSubscriptionListResult onGetDefaultDownloadableSubscriptionList(int, boolean);
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 162f212a787e..8f7112266457 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -60,6 +60,18 @@ package android.content {
}
+package android.hardware.hdmi {
+
+ public final class HdmiControlManager {
+ method @Deprecated public java.util.List<android.hardware.hdmi.HdmiDeviceInfo> getConnectedDevicesList();
+ method @Deprecated public boolean isRemoteDeviceConnected(@NonNull android.hardware.hdmi.HdmiDeviceInfo);
+ method @Deprecated public void powerOffRemoteDevice(@NonNull android.hardware.hdmi.HdmiDeviceInfo);
+ method @Deprecated public void powerOnRemoteDevice(android.hardware.hdmi.HdmiDeviceInfo);
+ method @Deprecated public void requestRemoteDeviceToBecomeActiveSource(@NonNull android.hardware.hdmi.HdmiDeviceInfo);
+ }
+
+}
+
package android.location {
public class LocationManager {
@@ -113,6 +125,19 @@ package android.os {
}
+package android.provider {
+
+ public final class DeviceConfig {
+ method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static void addOnPropertyChangedListener(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.provider.DeviceConfig.OnPropertyChangedListener);
+ method public static void removeOnPropertyChangedListener(@NonNull android.provider.DeviceConfig.OnPropertyChangedListener);
+ }
+
+ public static interface DeviceConfig.OnPropertyChangedListener {
+ method public void onPropertyChanged(@NonNull String, @NonNull String, @Nullable String);
+ }
+
+}
+
package android.service.notification {
public abstract class NotificationListenerService extends android.app.Service {
diff --git a/api/test-current.txt b/api/test-current.txt
index 6fb4a92d7816..811ad43b5a9e 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -498,12 +498,11 @@ package android.app.prediction {
}
public static final class AppTarget.Builder {
- ctor public AppTarget.Builder(@NonNull android.app.prediction.AppTargetId);
+ ctor public AppTarget.Builder(@NonNull android.app.prediction.AppTargetId, @NonNull String, @NonNull android.os.UserHandle);
+ ctor public AppTarget.Builder(@NonNull android.app.prediction.AppTargetId, @NonNull android.content.pm.ShortcutInfo);
method @NonNull public android.app.prediction.AppTarget build();
method @NonNull public android.app.prediction.AppTarget.Builder setClassName(@NonNull String);
method @NonNull public android.app.prediction.AppTarget.Builder setRank(@IntRange(from=0) int);
- method @NonNull public android.app.prediction.AppTarget.Builder setTarget(@NonNull String, @NonNull android.os.UserHandle);
- method @NonNull public android.app.prediction.AppTarget.Builder setTarget(@NonNull android.content.pm.ShortcutInfo);
}
public final class AppTargetEvent implements android.os.Parcelable {
@@ -1074,6 +1073,19 @@ package android.location {
package android.media {
+ public final class AudioFocusInfo implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public android.media.AudioAttributes getAttributes();
+ method @NonNull public String getClientId();
+ method public int getClientUid();
+ method public int getFlags();
+ method public int getGainRequest();
+ method public int getLossReceived();
+ method @NonNull public String getPackageName();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.media.AudioFocusInfo> CREATOR;
+ }
+
public final class AudioFocusRequest {
method @Nullable public android.media.AudioManager.OnAudioFocusChangeListener getOnAudioFocusChangeListener();
}
@@ -1085,6 +1097,15 @@ package android.media {
method public static boolean isEncodingLinearPcm(int);
}
+ public class AudioManager {
+ method @RequiresPermission("android.permission.MODIFY_AUDIO_ROUTING") public int dispatchAudioFocusChange(@NonNull android.media.AudioFocusInfo, int, @NonNull android.media.audiopolicy.AudioPolicy);
+ method public boolean hasRegisteredDynamicPolicy();
+ method @RequiresPermission("android.permission.MODIFY_AUDIO_ROUTING") public int registerAudioPolicy(@NonNull android.media.audiopolicy.AudioPolicy);
+ method @RequiresPermission("android.permission.MODIFY_AUDIO_ROUTING") public void setFocusRequestResult(@NonNull android.media.AudioFocusInfo, int, @NonNull android.media.audiopolicy.AudioPolicy);
+ method @RequiresPermission("android.permission.MODIFY_AUDIO_ROUTING") public void unregisterAudioPolicy(@NonNull android.media.audiopolicy.AudioPolicy);
+ method @RequiresPermission("android.permission.MODIFY_AUDIO_ROUTING") public void unregisterAudioPolicyAsync(@NonNull android.media.audiopolicy.AudioPolicy);
+ }
+
public static final class AudioRecord.MetricsConstants {
field public static final String ATTRIBUTES = "android.media.audiorecord.attributes";
field public static final String CHANNEL_MASK = "android.media.audiorecord.channelMask";
@@ -1178,6 +1199,91 @@ package android.media.audiofx {
}
+package android.media.audiopolicy {
+
+ public class AudioMix {
+ method public int getMixState();
+ field public static final int MIX_STATE_DISABLED = -1; // 0xffffffff
+ field public static final int MIX_STATE_IDLE = 0; // 0x0
+ field public static final int MIX_STATE_MIXING = 1; // 0x1
+ field public static final int ROUTE_FLAG_LOOP_BACK = 2; // 0x2
+ field public static final int ROUTE_FLAG_RENDER = 1; // 0x1
+ }
+
+ public static class AudioMix.Builder {
+ ctor public AudioMix.Builder(android.media.audiopolicy.AudioMixingRule) throws java.lang.IllegalArgumentException;
+ method public android.media.audiopolicy.AudioMix build() throws java.lang.IllegalArgumentException;
+ method public android.media.audiopolicy.AudioMix.Builder setDevice(@NonNull android.media.AudioDeviceInfo) throws java.lang.IllegalArgumentException;
+ method public android.media.audiopolicy.AudioMix.Builder setFormat(android.media.AudioFormat) throws java.lang.IllegalArgumentException;
+ method public android.media.audiopolicy.AudioMix.Builder setRouteFlags(int) throws java.lang.IllegalArgumentException;
+ }
+
+ public class AudioMixingRule {
+ field public static final int RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET = 2; // 0x2
+ field public static final int RULE_MATCH_ATTRIBUTE_USAGE = 1; // 0x1
+ field public static final int RULE_MATCH_UID = 4; // 0x4
+ }
+
+ public static class AudioMixingRule.Builder {
+ ctor public AudioMixingRule.Builder();
+ method public android.media.audiopolicy.AudioMixingRule.Builder addMixRule(int, Object) throws java.lang.IllegalArgumentException;
+ method public android.media.audiopolicy.AudioMixingRule.Builder addRule(android.media.AudioAttributes, int) throws java.lang.IllegalArgumentException;
+ method @NonNull public android.media.audiopolicy.AudioMixingRule.Builder allowPrivilegedPlaybackCapture(boolean);
+ method public android.media.audiopolicy.AudioMixingRule build();
+ method public android.media.audiopolicy.AudioMixingRule.Builder excludeMixRule(int, Object) throws java.lang.IllegalArgumentException;
+ method public android.media.audiopolicy.AudioMixingRule.Builder excludeRule(android.media.AudioAttributes, int) throws java.lang.IllegalArgumentException;
+ }
+
+ public class AudioPolicy {
+ method public int attachMixes(@NonNull java.util.List<android.media.audiopolicy.AudioMix>);
+ method public android.media.AudioRecord createAudioRecordSink(android.media.audiopolicy.AudioMix) throws java.lang.IllegalArgumentException;
+ method public android.media.AudioTrack createAudioTrackSource(android.media.audiopolicy.AudioMix) throws java.lang.IllegalArgumentException;
+ method public int detachMixes(@NonNull java.util.List<android.media.audiopolicy.AudioMix>);
+ method public int getFocusDuckingBehavior();
+ method public int getStatus();
+ method public int setFocusDuckingBehavior(int) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException;
+ method public void setRegistration(String);
+ method public String toLogFriendlyString();
+ field public static final int FOCUS_POLICY_DUCKING_DEFAULT = 0; // 0x0
+ field public static final int FOCUS_POLICY_DUCKING_IN_APP = 0; // 0x0
+ field public static final int FOCUS_POLICY_DUCKING_IN_POLICY = 1; // 0x1
+ field public static final int POLICY_STATUS_REGISTERED = 2; // 0x2
+ field public static final int POLICY_STATUS_UNREGISTERED = 1; // 0x1
+ }
+
+ public abstract static class AudioPolicy.AudioPolicyFocusListener {
+ ctor public AudioPolicy.AudioPolicyFocusListener();
+ method public void onAudioFocusAbandon(android.media.AudioFocusInfo);
+ method public void onAudioFocusGrant(android.media.AudioFocusInfo, int);
+ method public void onAudioFocusLoss(android.media.AudioFocusInfo, boolean);
+ method public void onAudioFocusRequest(android.media.AudioFocusInfo, int);
+ }
+
+ public abstract static class AudioPolicy.AudioPolicyStatusListener {
+ ctor public AudioPolicy.AudioPolicyStatusListener();
+ method public void onMixStateUpdate(android.media.audiopolicy.AudioMix);
+ method public void onStatusChange();
+ }
+
+ public abstract static class AudioPolicy.AudioPolicyVolumeCallback {
+ ctor public AudioPolicy.AudioPolicyVolumeCallback();
+ method public void onVolumeAdjustment(int);
+ }
+
+ public static class AudioPolicy.Builder {
+ ctor public AudioPolicy.Builder(android.content.Context);
+ method @NonNull public android.media.audiopolicy.AudioPolicy.Builder addMix(@NonNull android.media.audiopolicy.AudioMix) throws java.lang.IllegalArgumentException;
+ method @NonNull public android.media.audiopolicy.AudioPolicy build();
+ method public void setAudioPolicyFocusListener(android.media.audiopolicy.AudioPolicy.AudioPolicyFocusListener);
+ method public void setAudioPolicyStatusListener(android.media.audiopolicy.AudioPolicy.AudioPolicyStatusListener);
+ method @NonNull public android.media.audiopolicy.AudioPolicy.Builder setAudioPolicyVolumeCallback(@NonNull android.media.audiopolicy.AudioPolicy.AudioPolicyVolumeCallback);
+ method @NonNull public android.media.audiopolicy.AudioPolicy.Builder setIsAudioFocusPolicy(boolean);
+ method @NonNull public android.media.audiopolicy.AudioPolicy.Builder setIsTestFocusPolicy(boolean);
+ method @NonNull public android.media.audiopolicy.AudioPolicy.Builder setLooper(@NonNull android.os.Looper) throws java.lang.IllegalArgumentException;
+ }
+
+}
+
package android.metrics {
public class LogMaker {
@@ -2106,7 +2212,6 @@ package android.provider {
public final class DeviceConfig {
method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static void addOnPropertiesChangedListener(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.provider.DeviceConfig.OnPropertiesChangedListener);
- method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static void addOnPropertyChangedListener(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.provider.DeviceConfig.OnPropertyChangedListener);
method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static boolean getBoolean(@NonNull String, @NonNull String, boolean);
method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static float getFloat(@NonNull String, @NonNull String, float);
method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static int getInt(@NonNull String, @NonNull String, int);
@@ -2114,7 +2219,6 @@ package android.provider {
method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static String getProperty(@NonNull String, @NonNull String);
method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static String getString(@NonNull String, @NonNull String, @Nullable String);
method public static void removeOnPropertiesChangedListener(@NonNull android.provider.DeviceConfig.OnPropertiesChangedListener);
- method public static void removeOnPropertyChangedListener(@NonNull android.provider.DeviceConfig.OnPropertyChangedListener);
method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static void resetToDefaults(int, @Nullable String);
method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static boolean setProperty(@NonNull String, @NonNull String, @Nullable String, boolean);
field public static final String NAMESPACE_AUTOFILL = "autofill";
@@ -2128,10 +2232,6 @@ package android.provider {
method public void onPropertiesChanged(@NonNull android.provider.DeviceConfig.Properties);
}
- public static interface DeviceConfig.OnPropertyChangedListener {
- method public void onPropertyChanged(@NonNull String, @NonNull String, @Nullable String);
- }
-
public static class DeviceConfig.Properties {
method public boolean getBoolean(@NonNull String, boolean);
method public float getFloat(@NonNull String, float);
@@ -2445,9 +2545,9 @@ package android.service.contentcapture {
method public void onConnected();
method public void onContentCaptureEvent(@NonNull android.view.contentcapture.ContentCaptureSessionId, @NonNull android.view.contentcapture.ContentCaptureEvent);
method public void onCreateContentCaptureSession(@NonNull android.view.contentcapture.ContentCaptureContext, @NonNull android.view.contentcapture.ContentCaptureSessionId);
+ method public void onDataRemovalRequest(@NonNull android.view.contentcapture.DataRemovalRequest);
method public void onDestroyContentCaptureSession(@NonNull android.view.contentcapture.ContentCaptureSessionId);
method public void onDisconnected();
- method public void onUserDataRemovalRequest(@NonNull android.view.contentcapture.UserDataRemovalRequest);
method public final void setContentCaptureConditions(@NonNull String, @Nullable java.util.Set<android.view.contentcapture.ContentCaptureCondition>);
method public final void setContentCaptureWhitelist(@Nullable java.util.Set<java.lang.String>, @Nullable java.util.Set<android.content.ComponentName>);
field public static final String SERVICE_INTERFACE = "android.service.contentcapture.ContentCaptureService";
diff --git a/api/test-removed.txt b/api/test-removed.txt
index d802177e249b..83a5708a2eb3 100644
--- a/api/test-removed.txt
+++ b/api/test-removed.txt
@@ -1 +1,14 @@
// Signature format: 2.0
+package android.provider {
+
+ public final class DeviceConfig {
+ method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static void addOnPropertyChangedListener(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.provider.DeviceConfig.OnPropertyChangedListener);
+ method public static void removeOnPropertyChangedListener(@NonNull android.provider.DeviceConfig.OnPropertyChangedListener);
+ }
+
+ public static interface DeviceConfig.OnPropertyChangedListener {
+ method public void onPropertyChanged(@NonNull String, @NonNull String, @Nullable String);
+ }
+
+}
+
diff --git a/cmds/idmap2/idmap2/Create.cpp b/cmds/idmap2/idmap2/Create.cpp
index 47617e045c12..bb8d92737563 100644
--- a/cmds/idmap2/idmap2/Create.cpp
+++ b/cmds/idmap2/idmap2/Create.cpp
@@ -16,6 +16,7 @@
#include <sys/stat.h> // umask
#include <sys/types.h> // umask
+
#include <fstream>
#include <memory>
#include <ostream>
diff --git a/cmds/idmap2/idmap2/Lookup.cpp b/cmds/idmap2/idmap2/Lookup.cpp
index 677c6fa155dd..b7ae9d090cee 100644
--- a/cmds/idmap2/idmap2/Lookup.cpp
+++ b/cmds/idmap2/idmap2/Lookup.cpp
@@ -31,15 +31,14 @@
#include "androidfw/ResourceUtils.h"
#include "androidfw/StringPiece.h"
#include "androidfw/Util.h"
-#include "utils/String16.h"
-#include "utils/String8.h"
-
#include "idmap2/CommandLineOptions.h"
#include "idmap2/Idmap.h"
#include "idmap2/Result.h"
#include "idmap2/SysTrace.h"
#include "idmap2/Xml.h"
#include "idmap2/ZipFile.h"
+#include "utils/String16.h"
+#include "utils/String8.h"
using android::ApkAssets;
using android::ApkAssetsCookie;
diff --git a/cmds/idmap2/idmap2/Main.cpp b/cmds/idmap2/idmap2/Main.cpp
index d8867fe8f497..87949085cf1d 100644
--- a/cmds/idmap2/idmap2/Main.cpp
+++ b/cmds/idmap2/idmap2/Main.cpp
@@ -23,12 +23,11 @@
#include <string>
#include <vector>
+#include "Commands.h"
#include "idmap2/CommandLineOptions.h"
#include "idmap2/Result.h"
#include "idmap2/SysTrace.h"
-#include "Commands.h"
-
using android::idmap2::CommandLineOptions;
using android::idmap2::Result;
using android::idmap2::Unit;
diff --git a/cmds/idmap2/idmap2/Scan.cpp b/cmds/idmap2/idmap2/Scan.cpp
index 55b1003c38af..fa9a77aa69c6 100644
--- a/cmds/idmap2/idmap2/Scan.cpp
+++ b/cmds/idmap2/idmap2/Scan.cpp
@@ -15,6 +15,7 @@
*/
#include <dirent.h>
+
#include <fstream>
#include <memory>
#include <ostream>
@@ -24,8 +25,8 @@
#include <utility>
#include <vector>
+#include "Commands.h"
#include "android-base/properties.h"
-
#include "idmap2/CommandLineOptions.h"
#include "idmap2/FileUtils.h"
#include "idmap2/Idmap.h"
@@ -35,8 +36,6 @@
#include "idmap2/Xml.h"
#include "idmap2/ZipFile.h"
-#include "Commands.h"
-
using android::idmap2::CommandLineOptions;
using android::idmap2::Error;
using android::idmap2::Idmap;
@@ -211,7 +210,9 @@ Result<Unit> Scan(const std::vector<std::string>& args) {
const auto create_ok = Create(create_args);
if (!create_ok) {
- return Error(create_ok.GetError(), "failed to create idmap");
+ LOG(WARNING) << "failed to create idmap for overlay apk path \"" << overlay.apk_path
+ << "\": " << create_ok.GetError().GetMessage();
+ continue;
}
}
diff --git a/cmds/idmap2/idmap2d/Idmap2Service.cpp b/cmds/idmap2/idmap2d/Idmap2Service.cpp
index 4f653796ce3f..8ee79f61520a 100644
--- a/cmds/idmap2/idmap2d/Idmap2Service.cpp
+++ b/cmds/idmap2/idmap2d/Idmap2Service.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#include "idmap2d/Idmap2Service.h"
+
#include <sys/stat.h> // umask
#include <sys/types.h> // umask
#include <unistd.h>
@@ -28,15 +30,12 @@
#include "android-base/macros.h"
#include "android-base/stringprintf.h"
#include "binder/IPCThreadState.h"
-#include "utils/String8.h"
-
#include "idmap2/BinaryStreamVisitor.h"
#include "idmap2/FileUtils.h"
#include "idmap2/Idmap.h"
#include "idmap2/Policies.h"
#include "idmap2/SysTrace.h"
-
-#include "idmap2d/Idmap2Service.h"
+#include "utils/String8.h"
using android::IPCThreadState;
using android::binder::Status;
diff --git a/cmds/idmap2/idmap2d/Main.cpp b/cmds/idmap2/idmap2d/Main.cpp
index 4393dcc130ec..2707049fa677 100644
--- a/cmds/idmap2/idmap2d/Main.cpp
+++ b/cmds/idmap2/idmap2d/Main.cpp
@@ -21,13 +21,11 @@
#include <binder/ProcessState.h>
#include <cstdlib> // EXIT_{FAILURE,SUCCESS}
-
#include <iostream>
#include <sstream>
-#include "android-base/macros.h"
-
#include "Idmap2Service.h"
+#include "android-base/macros.h"
using android::BinderService;
using android::IPCThreadState;
diff --git a/cmds/idmap2/include/idmap2/Idmap.h b/cmds/idmap2/include/idmap2/Idmap.h
index 5cc0664b2bed..ebbb5ffc989d 100644
--- a/cmds/idmap2/include/idmap2/Idmap.h
+++ b/cmds/idmap2/include/idmap2/Idmap.h
@@ -52,11 +52,9 @@
#include <vector>
#include "android-base/macros.h"
-
#include "androidfw/ApkAssets.h"
#include "androidfw/ResourceTypes.h"
#include "androidfw/StringPiece.h"
-
#include "idmap2/Policies.h"
namespace android::idmap2 {
diff --git a/cmds/idmap2/include/idmap2/Policies.h b/cmds/idmap2/include/idmap2/Policies.h
index cd76b84ccc0a..90c698cc6e49 100644
--- a/cmds/idmap2/include/idmap2/Policies.h
+++ b/cmds/idmap2/include/idmap2/Policies.h
@@ -17,11 +17,10 @@
#include <string>
#include <vector>
+#include "Result.h"
#include "androidfw/ResourceTypes.h"
#include "androidfw/StringPiece.h"
-#include "Result.h"
-
#ifndef IDMAP2_INCLUDE_IDMAP2_POLICIES_H_
#define IDMAP2_INCLUDE_IDMAP2_POLICIES_H_
diff --git a/cmds/idmap2/include/idmap2/PrettyPrintVisitor.h b/cmds/idmap2/include/idmap2/PrettyPrintVisitor.h
index c388f4b94251..5111bb2eaab2 100644
--- a/cmds/idmap2/include/idmap2/PrettyPrintVisitor.h
+++ b/cmds/idmap2/include/idmap2/PrettyPrintVisitor.h
@@ -21,7 +21,6 @@
#include <memory>
#include "androidfw/AssetManager2.h"
-
#include "idmap2/Idmap.h"
namespace android {
diff --git a/cmds/idmap2/include/idmap2/RawPrintVisitor.h b/cmds/idmap2/include/idmap2/RawPrintVisitor.h
index 7e33b3b06fc3..2e543d4fabdd 100644
--- a/cmds/idmap2/include/idmap2/RawPrintVisitor.h
+++ b/cmds/idmap2/include/idmap2/RawPrintVisitor.h
@@ -22,7 +22,6 @@
#include <string>
#include "androidfw/AssetManager2.h"
-
#include "idmap2/Idmap.h"
namespace android {
diff --git a/cmds/idmap2/include/idmap2/ResourceUtils.h b/cmds/idmap2/include/idmap2/ResourceUtils.h
index 1d81c486d504..8797a788dd1d 100644
--- a/cmds/idmap2/include/idmap2/ResourceUtils.h
+++ b/cmds/idmap2/include/idmap2/ResourceUtils.h
@@ -21,7 +21,6 @@
#include <string>
#include "androidfw/AssetManager2.h"
-
#include "idmap2/Idmap.h"
#include "idmap2/Result.h"
#include "idmap2/ZipFile.h"
diff --git a/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp b/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp
index 96513283ac51..dee2d219cbe1 100644
--- a/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp
+++ b/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp
@@ -14,14 +14,14 @@
* limitations under the License.
*/
+#include "idmap2/BinaryStreamVisitor.h"
+
#include <algorithm>
#include <cstring>
#include <string>
#include "android-base/macros.h"
-#include "idmap2/BinaryStreamVisitor.h"
-
namespace android::idmap2 {
void BinaryStreamVisitor::Write16(uint16_t value) {
diff --git a/cmds/idmap2/libidmap2/CommandLineOptions.cpp b/cmds/idmap2/libidmap2/CommandLineOptions.cpp
index d5fd2ce38b11..5b0ae92df887 100644
--- a/cmds/idmap2/libidmap2/CommandLineOptions.cpp
+++ b/cmds/idmap2/libidmap2/CommandLineOptions.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#include "idmap2/CommandLineOptions.h"
+
#include <algorithm>
#include <iomanip>
#include <iostream>
@@ -24,8 +26,6 @@
#include <vector>
#include "android-base/macros.h"
-
-#include "idmap2/CommandLineOptions.h"
#include "idmap2/Result.h"
namespace android::idmap2 {
diff --git a/cmds/idmap2/libidmap2/FileUtils.cpp b/cmds/idmap2/libidmap2/FileUtils.cpp
index a9b68cd6d5d5..3e8e32989a09 100644
--- a/cmds/idmap2/libidmap2/FileUtils.cpp
+++ b/cmds/idmap2/libidmap2/FileUtils.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#include "idmap2/FileUtils.h"
+
#include <dirent.h>
#include <sys/types.h>
#include <unistd.h>
@@ -33,8 +35,6 @@
#include "android-base/stringprintf.h"
#include "private/android_filesystem_config.h"
-#include "idmap2/FileUtils.h"
-
namespace android::idmap2::utils {
std::unique_ptr<std::vector<std::string>> FindFiles(const std::string& root, bool recurse,
diff --git a/cmds/idmap2/libidmap2/Idmap.cpp b/cmds/idmap2/libidmap2/Idmap.cpp
index 49470b4f4e95..aec1a6fc2bae 100644
--- a/cmds/idmap2/libidmap2/Idmap.cpp
+++ b/cmds/idmap2/libidmap2/Idmap.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#include "idmap2/Idmap.h"
+
#include <algorithm>
#include <iostream>
#include <iterator>
@@ -28,14 +30,12 @@
#include "android-base/macros.h"
#include "android-base/stringprintf.h"
#include "androidfw/AssetManager2.h"
-#include "utils/String16.h"
-#include "utils/String8.h"
-
-#include "idmap2/Idmap.h"
#include "idmap2/ResourceUtils.h"
#include "idmap2/Result.h"
#include "idmap2/SysTrace.h"
#include "idmap2/ZipFile.h"
+#include "utils/String16.h"
+#include "utils/String8.h"
namespace android::idmap2 {
diff --git a/cmds/idmap2/libidmap2/Policies.cpp b/cmds/idmap2/libidmap2/Policies.cpp
index 7c4555633fd2..0a0cecf13932 100644
--- a/cmds/idmap2/libidmap2/Policies.cpp
+++ b/cmds/idmap2/libidmap2/Policies.cpp
@@ -14,15 +14,15 @@
* limitations under the License.
*/
+#include "idmap2/Policies.h"
+
#include <iterator>
#include <map>
#include <string>
#include <vector>
#include "androidfw/ResourceTypes.h"
-
#include "idmap2/Idmap.h"
-#include "idmap2/Policies.h"
#include "idmap2/Result.h"
namespace android::idmap2 {
diff --git a/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp b/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp
index fc9677994fc0..fbf2c777be9a 100644
--- a/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp
+++ b/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp
@@ -14,13 +14,13 @@
* limitations under the License.
*/
+#include "idmap2/PrettyPrintVisitor.h"
+
#include <string>
#include "android-base/macros.h"
#include "android-base/stringprintf.h"
#include "androidfw/ApkAssets.h"
-
-#include "idmap2/PrettyPrintVisitor.h"
#include "idmap2/ResourceUtils.h"
#include "idmap2/Result.h"
diff --git a/cmds/idmap2/libidmap2/RawPrintVisitor.cpp b/cmds/idmap2/libidmap2/RawPrintVisitor.cpp
index 1149c905a178..dd14fd47aea8 100644
--- a/cmds/idmap2/libidmap2/RawPrintVisitor.cpp
+++ b/cmds/idmap2/libidmap2/RawPrintVisitor.cpp
@@ -14,14 +14,14 @@
* limitations under the License.
*/
+#include "idmap2/RawPrintVisitor.h"
+
#include <cstdarg>
#include <string>
#include "android-base/macros.h"
#include "android-base/stringprintf.h"
#include "androidfw/ApkAssets.h"
-
-#include "idmap2/RawPrintVisitor.h"
#include "idmap2/ResourceUtils.h"
#include "idmap2/Result.h"
diff --git a/cmds/idmap2/libidmap2/ResourceUtils.cpp b/cmds/idmap2/libidmap2/ResourceUtils.cpp
index a24836da7f3a..71ba3f0f1ac2 100644
--- a/cmds/idmap2/libidmap2/ResourceUtils.cpp
+++ b/cmds/idmap2/libidmap2/ResourceUtils.cpp
@@ -14,13 +14,13 @@
* limitations under the License.
*/
+#include "idmap2/ResourceUtils.h"
+
#include <memory>
#include <string>
#include "androidfw/StringPiece.h"
#include "androidfw/Util.h"
-
-#include "idmap2/ResourceUtils.h"
#include "idmap2/Result.h"
#include "idmap2/Xml.h"
#include "idmap2/ZipFile.h"
diff --git a/cmds/idmap2/libidmap2/Result.cpp b/cmds/idmap2/libidmap2/Result.cpp
index 471dab2e0411..1eac25f1b955 100644
--- a/cmds/idmap2/libidmap2/Result.cpp
+++ b/cmds/idmap2/libidmap2/Result.cpp
@@ -14,12 +14,12 @@
* limitations under the License.
*/
+#include "idmap2/Result.h"
+
#include <cstdarg>
#include "android-base/stringprintf.h"
-#include "idmap2/Result.h"
-
namespace android::idmap2 {
// NOLINTNEXTLINE(cert-dcl50-cpp)
diff --git a/cmds/idmap2/libidmap2/Xml.cpp b/cmds/idmap2/libidmap2/Xml.cpp
index 0075a922d676..264586829c47 100644
--- a/cmds/idmap2/libidmap2/Xml.cpp
+++ b/cmds/idmap2/libidmap2/Xml.cpp
@@ -14,13 +14,13 @@
* limitations under the License.
*/
+#include "idmap2/Xml.h"
+
#include <map>
#include <memory>
#include <string>
#include <utility>
-#include "idmap2/Xml.h"
-
namespace android::idmap2 {
std::unique_ptr<const Xml> Xml::Create(const uint8_t* data, size_t size, bool copyData) {
diff --git a/cmds/idmap2/libidmap2/ZipFile.cpp b/cmds/idmap2/libidmap2/ZipFile.cpp
index 0f0732466256..812fd6eacbf9 100644
--- a/cmds/idmap2/libidmap2/ZipFile.cpp
+++ b/cmds/idmap2/libidmap2/ZipFile.cpp
@@ -14,11 +14,12 @@
* limitations under the License.
*/
+#include "idmap2/ZipFile.h"
+
#include <memory>
#include <string>
#include "idmap2/Result.h"
-#include "idmap2/ZipFile.h"
namespace android::idmap2 {
diff --git a/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp b/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp
index 9a5b6331cb20..9cdc86ca181a 100644
--- a/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp
+++ b/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp
@@ -19,17 +19,14 @@
#include <string>
#include <utility>
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-
+#include "TestHelpers.h"
#include "androidfw/ApkAssets.h"
#include "androidfw/Idmap.h"
-
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
#include "idmap2/BinaryStreamVisitor.h"
#include "idmap2/Idmap.h"
-#include "TestHelpers.h"
-
using ::testing::NotNull;
namespace android::idmap2 {
diff --git a/cmds/idmap2/tests/CommandLineOptionsTests.cpp b/cmds/idmap2/tests/CommandLineOptionsTests.cpp
index d567af64b16a..6e83fc9abdb1 100644
--- a/cmds/idmap2/tests/CommandLineOptionsTests.cpp
+++ b/cmds/idmap2/tests/CommandLineOptionsTests.cpp
@@ -25,19 +25,16 @@
#include <string>
#include <vector>
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-
+#include "TestHelpers.h"
#include "android-base/file.h"
#include "androidfw/ApkAssets.h"
#include "androidfw/Idmap.h"
#include "androidfw/LoadedArsc.h"
-
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
#include "idmap2/CommandLineOptions.h"
#include "idmap2/Idmap.h"
-#include "TestHelpers.h"
-
namespace android::idmap2 {
TEST(CommandLineOptionsTests, Flag) {
diff --git a/cmds/idmap2/tests/FileUtilsTests.cpp b/cmds/idmap2/tests/FileUtilsTests.cpp
index 34a0097b0316..f4a306e41e32 100644
--- a/cmds/idmap2/tests/FileUtilsTests.cpp
+++ b/cmds/idmap2/tests/FileUtilsTests.cpp
@@ -15,19 +15,17 @@
*/
#include <dirent.h>
+
#include <set>
#include <string>
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-
+#include "TestHelpers.h"
#include "android-base/macros.h"
#include "android-base/stringprintf.h"
-#include "private/android_filesystem_config.h"
-
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
#include "idmap2/FileUtils.h"
-
-#include "TestHelpers.h"
+#include "private/android_filesystem_config.h"
using ::testing::NotNull;
diff --git a/cmds/idmap2/tests/Idmap2BinaryTests.cpp b/cmds/idmap2/tests/Idmap2BinaryTests.cpp
index 91bc4ddb397f..c18744ccb2d5 100644
--- a/cmds/idmap2/tests/Idmap2BinaryTests.cpp
+++ b/cmds/idmap2/tests/Idmap2BinaryTests.cpp
@@ -34,16 +34,13 @@
#include <string>
#include <vector>
+#include "TestHelpers.h"
+#include "androidfw/PosixUtils.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-
-#include "androidfw/PosixUtils.h"
-#include "private/android_filesystem_config.h"
-
#include "idmap2/FileUtils.h"
#include "idmap2/Idmap.h"
-
-#include "TestHelpers.h"
+#include "private/android_filesystem_config.h"
using ::android::util::ExecuteBinary;
using ::testing::NotNull;
@@ -264,6 +261,24 @@ TEST_F(Idmap2BinaryTests, Scan) {
ASSERT_THAT(result, NotNull());
ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
ASSERT_EQ(result->stdout, "");
+
+ // the signature idmap failing to generate should not cause scanning to fail
+ // clang-format off
+ result = ExecuteBinary({"idmap2",
+ "scan",
+ "--input-directory", GetTestDataPath(),
+ "--recursive",
+ "--target-package-name", "test.target",
+ "--target-apk-path", GetTargetApkPath(),
+ "--output-directory", GetTempDirPath(),
+ "--override-policy", "public"});
+ // clang-format on
+ ASSERT_THAT(result, NotNull());
+ ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
+ ASSERT_EQ(result->stdout, expected.str());
+ unlink(idmap_static_no_name_path.c_str());
+ unlink(idmap_static_2_path.c_str());
+ unlink(idmap_static_1_path.c_str());
}
TEST_F(Idmap2BinaryTests, Lookup) {
diff --git a/cmds/idmap2/tests/IdmapTests.cpp b/cmds/idmap2/tests/IdmapTests.cpp
index 621f50337aa3..90fe9a79bd1f 100644
--- a/cmds/idmap2/tests/IdmapTests.cpp
+++ b/cmds/idmap2/tests/IdmapTests.cpp
@@ -15,7 +15,6 @@
*/
#include <cstdio> // fclose
-
#include <fstream>
#include <memory>
#include <sstream>
@@ -23,18 +22,15 @@
#include <utility>
#include <vector>
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-
+#include "TestHelpers.h"
#include "android-base/macros.h"
#include "androidfw/ApkAssets.h"
-
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
#include "idmap2/BinaryStreamVisitor.h"
#include "idmap2/CommandLineOptions.h"
#include "idmap2/Idmap.h"
-#include "TestHelpers.h"
-
using ::testing::IsNull;
using ::testing::NotNull;
diff --git a/cmds/idmap2/tests/Main.cpp b/cmds/idmap2/tests/Main.cpp
index 2b13fed8d60d..3e753e974465 100644
--- a/cmds/idmap2/tests/Main.cpp
+++ b/cmds/idmap2/tests/Main.cpp
@@ -16,12 +16,10 @@
#include <string>
+#include "TestHelpers.h"
#include "android-base/file.h"
-
#include "gtest/gtest.h"
-#include "TestHelpers.h"
-
namespace android::idmap2 {
std::string GetTestDataPath() {
diff --git a/cmds/idmap2/tests/PoliciesTests.cpp b/cmds/idmap2/tests/PoliciesTests.cpp
index a76da533cdcb..e30da76ddd98 100644
--- a/cmds/idmap2/tests/PoliciesTests.cpp
+++ b/cmds/idmap2/tests/PoliciesTests.cpp
@@ -16,9 +16,8 @@
#include <string>
-#include "gtest/gtest.h"
-
#include "TestHelpers.h"
+#include "gtest/gtest.h"
#include "idmap2/Policies.h"
using android::idmap2::PolicyBitmask;
diff --git a/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp b/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp
index 27a3880f67b6..c41250457678 100644
--- a/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp
+++ b/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp
@@ -18,18 +18,15 @@
#include <sstream>
#include <string>
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-
+#include "TestHelpers.h"
#include "androidfw/ApkAssets.h"
#include "androidfw/Idmap.h"
-
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
#include "idmap2/Idmap.h"
#include "idmap2/Policies.h"
#include "idmap2/PrettyPrintVisitor.h"
-#include "TestHelpers.h"
-
using ::testing::NotNull;
using android::ApkAssets;
diff --git a/cmds/idmap2/tests/RawPrintVisitorTests.cpp b/cmds/idmap2/tests/RawPrintVisitorTests.cpp
index 7372148f0f0e..64518fdf8dee 100644
--- a/cmds/idmap2/tests/RawPrintVisitorTests.cpp
+++ b/cmds/idmap2/tests/RawPrintVisitorTests.cpp
@@ -19,14 +19,12 @@
#include <sstream>
#include <string>
+#include "TestHelpers.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-
#include "idmap2/Idmap.h"
#include "idmap2/RawPrintVisitor.h"
-#include "TestHelpers.h"
-
using ::testing::NotNull;
namespace android::idmap2 {
diff --git a/cmds/idmap2/tests/ResourceUtilsTests.cpp b/cmds/idmap2/tests/ResourceUtilsTests.cpp
index ad78685646b4..9ed807ccd8f9 100644
--- a/cmds/idmap2/tests/ResourceUtilsTests.cpp
+++ b/cmds/idmap2/tests/ResourceUtilsTests.cpp
@@ -17,15 +17,13 @@
#include <memory>
#include <string>
+#include "TestHelpers.h"
+#include "androidfw/ApkAssets.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-
-#include "androidfw/ApkAssets.h"
#include "idmap2/ResourceUtils.h"
#include "idmap2/Result.h"
-#include "TestHelpers.h"
-
using ::testing::NotNull;
namespace android::idmap2 {
diff --git a/cmds/idmap2/tests/ResultTests.cpp b/cmds/idmap2/tests/ResultTests.cpp
index 5f4daed521c0..cbced0ae32fb 100644
--- a/cmds/idmap2/tests/ResultTests.cpp
+++ b/cmds/idmap2/tests/ResultTests.cpp
@@ -20,7 +20,6 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-
#include "idmap2/Result.h"
namespace android::idmap2 {
diff --git a/cmds/idmap2/tests/TestHelpers.h b/cmds/idmap2/tests/TestHelpers.h
index 45525a5b7657..adea3293534d 100644
--- a/cmds/idmap2/tests/TestHelpers.h
+++ b/cmds/idmap2/tests/TestHelpers.h
@@ -19,6 +19,9 @@
#include <string>
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
namespace android::idmap2 {
const unsigned char idmap_raw_data[] = {
diff --git a/cmds/idmap2/tests/XmlTests.cpp b/cmds/idmap2/tests/XmlTests.cpp
index fe79d8f2c5a9..df63211a9209 100644
--- a/cmds/idmap2/tests/XmlTests.cpp
+++ b/cmds/idmap2/tests/XmlTests.cpp
@@ -16,13 +16,11 @@
#include <cstdio> // fclose
-#include "idmap2/Xml.h"
-#include "idmap2/ZipFile.h"
-
+#include "TestHelpers.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-
-#include "TestHelpers.h"
+#include "idmap2/Xml.h"
+#include "idmap2/ZipFile.h"
using ::testing::IsNull;
using ::testing::NotNull;
diff --git a/cmds/idmap2/tests/ZipFileTests.cpp b/cmds/idmap2/tests/ZipFileTests.cpp
index 79be43ce0e42..3fca43621945 100644
--- a/cmds/idmap2/tests/ZipFileTests.cpp
+++ b/cmds/idmap2/tests/ZipFileTests.cpp
@@ -17,13 +17,11 @@
#include <cstdio> // fclose
#include <string>
-#include "idmap2/Result.h"
-#include "idmap2/ZipFile.h"
-
+#include "TestHelpers.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-
-#include "TestHelpers.h"
+#include "idmap2/Result.h"
+#include "idmap2/ZipFile.h"
using ::testing::IsNull;
using ::testing::NotNull;
diff --git a/cmds/idmap2/tests/data/signature-overlay/AndroidManifest.xml b/cmds/idmap2/tests/data/signature-overlay/AndroidManifest.xml
index 9e6a4536cb51..5df0bea555b1 100644
--- a/cmds/idmap2/tests/data/signature-overlay/AndroidManifest.xml
+++ b/cmds/idmap2/tests/data/signature-overlay/AndroidManifest.xml
@@ -19,5 +19,7 @@
<application android:hasCode="false"/>
<overlay
android:targetPackage="test.target"
- android:targetName="TestResources"/>
+ android:targetName="TestResources"
+ android:isStatic="true"
+ android:priority="10"/>
</manifest>
diff --git a/cmds/idmap2/tests/data/signature-overlay/signature-overlay.apk b/cmds/idmap2/tests/data/signature-overlay/signature-overlay.apk
index b2c490dcbb90..51e19de082ed 100644
--- a/cmds/idmap2/tests/data/signature-overlay/signature-overlay.apk
+++ b/cmds/idmap2/tests/data/signature-overlay/signature-overlay.apk
Binary files differ
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index b6e5754aa65f..0260faae4567 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -16,6 +16,7 @@
package android.app;
+import static android.app.ActivityManager.PROCESS_STATE_UNKNOWN;
import static android.app.servertransaction.ActivityLifecycleItem.ON_CREATE;
import static android.app.servertransaction.ActivityLifecycleItem.ON_DESTROY;
import static android.app.servertransaction.ActivityLifecycleItem.ON_PAUSE;
@@ -27,6 +28,8 @@ import static android.content.ContentResolver.DEPRECATE_DATA_COLUMNS;
import static android.content.ContentResolver.DEPRECATE_DATA_PREFIX;
import static android.view.Display.INVALID_DISPLAY;
+import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
@@ -193,6 +196,7 @@ import java.util.Map;
import java.util.Objects;
import java.util.TimeZone;
import java.util.concurrent.Executor;
+import java.util.concurrent.atomic.AtomicInteger;
final class RemoteServiceException extends AndroidRuntimeException {
public RemoteServiceException(String msg) {
@@ -224,6 +228,17 @@ public final class ActivityThread extends ClientTransactionHandler {
private static final boolean DEBUG_PROVIDER = false;
public static final boolean DEBUG_ORDER = false;
private static final long MIN_TIME_BETWEEN_GCS = 5*1000;
+ /**
+ * If the activity doesn't become idle in time, the timeout will ensure to apply the pending top
+ * process state.
+ */
+ private static final long PENDING_TOP_PROCESS_STATE_TIMEOUT = 1000;
+ /**
+ * The delay to release the provider when it has no more references. It reduces the number of
+ * transactions for acquiring and releasing provider if the client accesses the provider
+ * frequently in a short time.
+ */
+ private static final long CONTENT_PROVIDER_RETAIN_TIME = 1000;
private static final int SQLITE_MEM_RELEASED_EVENT_LOG_TAG = 75003;
/** Type for IActivityManager.serviceDoneExecuting: anonymous operation */
@@ -236,6 +251,11 @@ public final class ActivityThread extends ClientTransactionHandler {
// Whether to invoke an activity callback after delivering new configuration.
private static final boolean REPORT_TO_ACTIVITY = true;
+ /** Use foreground GC policy (less pause time) and higher JIT weight. */
+ private static final int VM_PROCESS_STATE_JANK_PERCEPTIBLE = 0;
+ /** Use background GC policy and default JIT threshold. */
+ private static final int VM_PROCESS_STATE_JANK_IMPERCEPTIBLE = 1;
+
/**
* Denotes an invalid sequence number corresponding to a process state change.
*/
@@ -290,6 +310,11 @@ public final class ActivityThread extends ClientTransactionHandler {
// Number of activities that are currently visible on-screen.
@UnsupportedAppUsage
int mNumVisibleActivities = 0;
+ private final AtomicInteger mNumLaunchingActivities = new AtomicInteger();
+ @GuardedBy("mAppThread")
+ private int mLastProcessState = PROCESS_STATE_UNKNOWN;
+ @GuardedBy("mAppThread")
+ private int mPendingProcessState = PROCESS_STATE_UNKNOWN;
ArrayList<WeakReference<AssistStructure>> mLastAssistStructures = new ArrayList<>();
private int mLastSessionId;
@UnsupportedAppUsage
@@ -867,17 +892,6 @@ public final class ActivityThread extends ClientTransactionHandler {
private class ApplicationThread extends IApplicationThread.Stub {
private static final String DB_INFO_FORMAT = " %8s %8s %14s %14s %s";
- private int mLastProcessState = -1;
-
- private void updatePendingConfiguration(Configuration config) {
- synchronized (mResourcesManager) {
- if (mPendingConfiguration == null ||
- mPendingConfiguration.isOtherSeqNewer(config)) {
- mPendingConfiguration = config;
- }
- }
- }
-
public final void scheduleSleeping(IBinder token, boolean sleeping) {
sendMessage(H.SLEEPING, token, sleeping ? 1 : 0);
}
@@ -1554,27 +1568,6 @@ public final class ActivityThread extends ClientTransactionHandler {
updateProcessState(state, true);
}
- public void updateProcessState(int processState, boolean fromIpc) {
- synchronized (this) {
- if (mLastProcessState != processState) {
- mLastProcessState = processState;
- // Update Dalvik state based on ActivityManager.PROCESS_STATE_* constants.
- final int DALVIK_PROCESS_STATE_JANK_PERCEPTIBLE = 0;
- final int DALVIK_PROCESS_STATE_JANK_IMPERCEPTIBLE = 1;
- int dalvikProcessState = DALVIK_PROCESS_STATE_JANK_IMPERCEPTIBLE;
- // TODO: Tune this since things like gmail sync are important background but not jank perceptible.
- if (processState <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
- dalvikProcessState = DALVIK_PROCESS_STATE_JANK_PERCEPTIBLE;
- }
- VMRuntime.getRuntime().updateProcessState(dalvikProcessState);
- if (false) {
- Slog.i(TAG, "******************* PROCESS STATE CHANGED TO: " + processState
- + (fromIpc ? " (from ipc": ""));
- }
- }
- }
- }
-
/**
* Updates {@link #mNetworkBlockSeq}. This is used by ActivityManagerService to inform
* the main thread that it needs to wait for the network rules to get updated before
@@ -1655,16 +1648,6 @@ public final class ActivityThread extends ClientTransactionHandler {
}
}
- @Override
- public void updatePendingConfiguration(Configuration config) {
- mAppThread.updatePendingConfiguration(config);
- }
-
- @Override
- public void updateProcessState(int processState, boolean fromIpc) {
- mAppThread.updateProcessState(processState, fromIpc);
- }
-
class H extends Handler {
public static final int BIND_APPLICATION = 110;
@UnsupportedAppUsage
@@ -1989,6 +1972,7 @@ public final class ActivityThread extends ClientTransactionHandler {
if (stopProfiling) {
mProfiler.stopProfiling();
}
+ applyPendingProcessState();
return false;
}
}
@@ -2933,6 +2917,68 @@ public final class ActivityThread extends ClientTransactionHandler {
return mActivities.get(token);
}
+ @Override
+ public void updatePendingConfiguration(Configuration config) {
+ synchronized (mResourcesManager) {
+ if (mPendingConfiguration == null || mPendingConfiguration.isOtherSeqNewer(config)) {
+ mPendingConfiguration = config;
+ }
+ }
+ }
+
+ @Override
+ public void updateProcessState(int processState, boolean fromIpc) {
+ synchronized (mAppThread) {
+ if (mLastProcessState == processState) {
+ return;
+ }
+ mLastProcessState = processState;
+ // Defer the top state for VM to avoid aggressive JIT compilation affecting activity
+ // launch time.
+ if (processState == ActivityManager.PROCESS_STATE_TOP
+ && mNumLaunchingActivities.get() > 0) {
+ mPendingProcessState = processState;
+ mH.postDelayed(this::applyPendingProcessState, PENDING_TOP_PROCESS_STATE_TIMEOUT);
+ } else {
+ mPendingProcessState = PROCESS_STATE_UNKNOWN;
+ updateVmProcessState(processState);
+ }
+ if (localLOGV) {
+ Slog.i(TAG, "******************* PROCESS STATE CHANGED TO: " + processState
+ + (fromIpc ? " (from ipc" : ""));
+ }
+ }
+ }
+
+ /** Update VM state based on ActivityManager.PROCESS_STATE_* constants. */
+ private void updateVmProcessState(int processState) {
+ // TODO: Tune this since things like gmail sync are important background but not jank
+ // perceptible.
+ final int state = processState <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
+ ? VM_PROCESS_STATE_JANK_PERCEPTIBLE
+ : VM_PROCESS_STATE_JANK_IMPERCEPTIBLE;
+ VMRuntime.getRuntime().updateProcessState(state);
+ }
+
+ private void applyPendingProcessState() {
+ synchronized (mAppThread) {
+ if (mPendingProcessState == PROCESS_STATE_UNKNOWN) {
+ return;
+ }
+ final int pendingState = mPendingProcessState;
+ mPendingProcessState = PROCESS_STATE_UNKNOWN;
+ // Only apply the pending state if the last state doesn't change.
+ if (pendingState == mLastProcessState) {
+ updateVmProcessState(pendingState);
+ }
+ }
+ }
+
+ @Override
+ public void countLaunchingActivities(int num) {
+ mNumLaunchingActivities.getAndAdd(num);
+ }
+
@UnsupportedAppUsage
public final void sendActivityResult(
IBinder token, String id, int requestCode,
@@ -4564,7 +4610,7 @@ public final class ActivityThread extends ClientTransactionHandler {
private void onCoreSettingsChange() {
if (updateDebugViewAttributeState()) {
// request all activities to relaunch for the changes to take place
- relaunchAllActivities();
+ relaunchAllActivities(false /* preserveWindows */);
}
}
@@ -4581,10 +4627,13 @@ public final class ActivityThread extends ClientTransactionHandler {
return previousState != View.sDebugViewAttributes;
}
- private void relaunchAllActivities() {
+ private void relaunchAllActivities(boolean preserveWindows) {
for (Map.Entry<IBinder, ActivityClientRecord> entry : mActivities.entrySet()) {
- final Activity activity = entry.getValue().activity;
- if (!activity.mFinished) {
+ final ActivityClientRecord r = entry.getValue();
+ if (!r.activity.mFinished) {
+ if (preserveWindows && r.window != null) {
+ r.mPreserveWindow = true;
+ }
scheduleRelaunchActivity(entry.getKey());
}
}
@@ -5417,7 +5466,8 @@ public final class ActivityThread extends ClientTransactionHandler {
}
}
- void handleApplicationInfoChanged(@NonNull final ApplicationInfo ai) {
+ @VisibleForTesting(visibility = PACKAGE)
+ public void handleApplicationInfoChanged(@NonNull final ApplicationInfo ai) {
// Updates triggered by package installation go through a package update
// receiver. Here we try to capture ApplicationInfo changes that are
// caused by other sources, such as overlays. That means we want to be as conservative
@@ -5463,7 +5513,8 @@ public final class ActivityThread extends ClientTransactionHandler {
newConfig.assetsSeq = (mConfiguration != null ? mConfiguration.assetsSeq : 0) + 1;
handleConfigurationChanged(newConfig, null);
- relaunchAllActivities();
+ // Preserve windows to avoid black flickers when overlays change.
+ relaunchAllActivities(true /* preserveWindows */);
}
static void freeTextLayoutCachesIfNeeded(int configDiff) {
@@ -6498,16 +6549,13 @@ public final class ActivityThread extends ClientTransactionHandler {
if (!prc.removePending) {
// Schedule the actual remove asynchronously, since we don't know the context
// this will be called in.
- // TODO: it would be nice to post a delayed message, so
- // if we come back and need the same provider quickly
- // we will still have it available.
if (DEBUG_PROVIDER) {
Slog.v(TAG, "releaseProvider: Enqueueing pending removal - "
+ prc.holder.info.name);
}
prc.removePending = true;
Message msg = mH.obtainMessage(H.REMOVE_PROVIDER, prc);
- mH.sendMessage(msg);
+ mH.sendMessageDelayed(msg, CONTENT_PROVIDER_RETAIN_TIME);
} else {
Slog.w(TAG, "Duplicate remove pending of provider " + prc.holder.info.name);
}
diff --git a/core/java/android/app/ClientTransactionHandler.java b/core/java/android/app/ClientTransactionHandler.java
index 9dc8b45a71dc..d308adc52e15 100644
--- a/core/java/android/app/ClientTransactionHandler.java
+++ b/core/java/android/app/ClientTransactionHandler.java
@@ -78,6 +78,8 @@ public abstract class ClientTransactionHandler {
/** Set current process state. */
public abstract void updateProcessState(int processState, boolean fromIpc);
+ /** Count how many activities are launching. */
+ public abstract void countLaunchingActivities(int num);
// Execute phase related logic and handlers. Methods here execute actual lifecycle transactions
// and deliver callbacks.
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 1785d2a0843b..48ca71690a1b 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -223,7 +223,7 @@ interface IActivityManager {
void enterSafeMode();
void noteWakeupAlarm(in IIntentSender sender, in WorkSource workSource, int sourceUid,
in String sourcePkg, in String tag);
- void removeContentProvider(in IBinder connection, boolean stable);
+ oneway void removeContentProvider(in IBinder connection, boolean stable);
@UnsupportedAppUsage
void setRequestedOrientation(in IBinder token, int requestedOrientation);
void unbindFinished(in IBinder token, in Intent service, boolean doRebind);
diff --git a/core/java/android/app/TaskInfo.java b/core/java/android/app/TaskInfo.java
index dd00e5a74382..de64db9def64 100644
--- a/core/java/android/app/TaskInfo.java
+++ b/core/java/android/app/TaskInfo.java
@@ -16,6 +16,8 @@
package android.app;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Intent;
@@ -58,23 +60,27 @@ public class TaskInfo {
* The base intent of the task (generally the intent that launched the task). This intent can
* be used to relaunch the task (if it is no longer running) or brought to the front if it is.
*/
+ @NonNull
public Intent baseIntent;
/**
* The component of the first activity in the task, can be considered the "application" of this
* task.
*/
+ @Nullable
public ComponentName baseActivity;
/**
* The component of the top activity in the task, currently showing to the user.
*/
+ @Nullable
public ComponentName topActivity;
/**
* The component of the target activity if this task was started from an activity alias.
* Otherwise, this is null.
*/
+ @Nullable
public ComponentName origActivity;
/**
@@ -82,6 +88,7 @@ public class TaskInfo {
* alias).
* @hide
*/
+ @Nullable
public ComponentName realActivity;
/**
@@ -106,6 +113,7 @@ public class TaskInfo {
* The recent activity values for the highest activity in the stack to have set the values.
* {@link Activity#setTaskDescription(android.app.ActivityManager.TaskDescription)}.
*/
+ @Nullable
public ActivityManager.TaskDescription taskDescription;
/**
@@ -126,6 +134,7 @@ public class TaskInfo {
* The current configuration of the task.
* @hide
*/
+ @NonNull
@UnsupportedAppUsage
public final Configuration configuration = new Configuration();
diff --git a/core/java/android/app/prediction/AppTarget.java b/core/java/android/app/prediction/AppTarget.java
index ed45b2f45383..4704661c2b24 100644
--- a/core/java/android/app/prediction/AppTarget.java
+++ b/core/java/android/app/prediction/AppTarget.java
@@ -204,24 +204,49 @@ public final class AppTarget implements Parcelable {
private int mRank;
/**
- * @param id A unique id for this launchable target.
+ * @deprecated Use the other Builder constructors.
* @hide
*/
- @SystemApi
- @TestApi
+ @Deprecated
public Builder(@NonNull AppTargetId id) {
mId = id;
}
/**
- * Sets the target to be an app.
- *
- * @param packageName PackageName of the app
+ * @param id A unique id for this launchable target.
+ * @param packageName PackageName of the target.
* @param user The UserHandle of the user which this target belongs to.
- *
- * @throws IllegalArgumentException is the target is already set
+ * @hide
+ */
+ @SystemApi
+ @TestApi
+ public Builder(@NonNull AppTargetId id, @NonNull String packageName,
+ @NonNull UserHandle user) {
+ mId = Preconditions.checkNotNull(id);
+ mPackageName = Preconditions.checkNotNull(packageName);
+ mUser = Preconditions.checkNotNull(user);
+ }
+
+ /**
+ * @param id A unique id for this launchable target.
+ * @param info The ShortcutInfo that represents this launchable target.
+ * @hide
+ */
+ @SystemApi
+ @TestApi
+ public Builder(@NonNull AppTargetId id, @NonNull ShortcutInfo info) {
+ mId = Preconditions.checkNotNull(id);
+ mShortcutInfo = Preconditions.checkNotNull(info);
+ mPackageName = info.getPackage();
+ mUser = info.getUserHandle();
+ }
+
+ /**
+ * @deprecated Use the appropriate constructor.
+ * @hide
*/
@NonNull
+ @Deprecated
public Builder setTarget(@NonNull String packageName, @NonNull UserHandle user) {
if (mPackageName != null) {
throw new IllegalArgumentException("Target is already set");
@@ -232,11 +257,11 @@ public final class AppTarget implements Parcelable {
}
/**
- * Sets the target to be a ShortcutInfo.
- *
- * @throws IllegalArgumentException is the target is already set
+ * @deprecated Use the appropriate constructor.
+ * @hide
*/
@NonNull
+ @Deprecated
public Builder setTarget(@NonNull ShortcutInfo info) {
setTarget(info.getPackage(), info.getUserHandle());
mShortcutInfo = Preconditions.checkNotNull(info);
@@ -244,7 +269,7 @@ public final class AppTarget implements Parcelable {
}
/**
- * Sets the className for the target
+ * Sets the className for the target.
*/
@NonNull
public Builder setClassName(@NonNull String className) {
@@ -253,7 +278,7 @@ public final class AppTarget implements Parcelable {
}
/**
- * Sets the rank of the for the target.
+ * Sets the rank of the target.
*/
@NonNull
public Builder setRank(@IntRange(from = 0) int rank) {
@@ -274,7 +299,7 @@ public final class AppTarget implements Parcelable {
@NonNull
public AppTarget build() {
if (mPackageName == null) {
- throw new IllegalStateException("No target set");
+ throw new IllegalStateException("No target is set");
}
return new AppTarget(mId, mPackageName, mUser, mShortcutInfo, mClassName, mRank);
}
diff --git a/core/java/android/app/servertransaction/LaunchActivityItem.java b/core/java/android/app/servertransaction/LaunchActivityItem.java
index db22f8d1de87..cdf5d4912ad5 100644
--- a/core/java/android/app/servertransaction/LaunchActivityItem.java
+++ b/core/java/android/app/servertransaction/LaunchActivityItem.java
@@ -66,6 +66,7 @@ public class LaunchActivityItem extends ClientTransactionItem {
@Override
public void preExecute(ClientTransactionHandler client, IBinder token) {
+ client.countLaunchingActivities(1);
client.updateProcessState(mProcState, false);
client.updatePendingConfiguration(mCurConfig);
}
@@ -82,6 +83,12 @@ public class LaunchActivityItem extends ClientTransactionItem {
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
+ @Override
+ public void postExecute(ClientTransactionHandler client, IBinder token,
+ PendingTransactionActions pendingActions) {
+ client.countLaunchingActivities(-1);
+ }
+
// ObjectPoolItem implementation
diff --git a/core/java/android/attention/AttentionManagerInternal.java b/core/java/android/attention/AttentionManagerInternal.java
index fa3d3b8dea0c..941e9e2ecce5 100644
--- a/core/java/android/attention/AttentionManagerInternal.java
+++ b/core/java/android/attention/AttentionManagerInternal.java
@@ -46,13 +46,6 @@ public abstract class AttentionManagerInternal {
*/
public abstract void cancelAttentionCheck(AttentionCallbackInternal callback);
- /**
- * Disables the dependants.
- *
- * Example: called if the service does not have sufficient permissions to perform the task.
- */
- public abstract void disableSelf();
-
/** Internal interface for attention callback. */
public abstract static class AttentionCallbackInternal {
/**
diff --git a/core/java/android/bluetooth/le/ScanRecord.java b/core/java/android/bluetooth/le/ScanRecord.java
index 2174255a3619..30868bfeac66 100644
--- a/core/java/android/bluetooth/le/ScanRecord.java
+++ b/core/java/android/bluetooth/le/ScanRecord.java
@@ -16,6 +16,7 @@
package android.bluetooth.le;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
import android.bluetooth.BluetoothUuid;
@@ -97,7 +98,7 @@ public final class ScanRecord {
* Returns a list of service solicitation UUIDs within the advertisement that are used to
* identify the Bluetooth GATT services.
*/
- @Nullable
+ @NonNull
public List<ParcelUuid> getServiceSolicitationUuids() {
return mServiceSolicitationUuids;
}
@@ -297,9 +298,6 @@ public final class ScanRecord {
if (serviceUuids.isEmpty()) {
serviceUuids = null;
}
- if (serviceSolicitationUuids.isEmpty()) {
- serviceSolicitationUuids = null;
- }
return new ScanRecord(serviceUuids, serviceSolicitationUuids, manufacturerData,
serviceData, advertiseFlag, txPowerLevel, localName, scanRecord);
} catch (Exception e) {
diff --git a/core/java/android/content/ContentProviderOperation.java b/core/java/android/content/ContentProviderOperation.java
index a41b5d3fb781..a646e49f4f61 100644
--- a/core/java/android/content/ContentProviderOperation.java
+++ b/core/java/android/content/ContentProviderOperation.java
@@ -17,7 +17,6 @@
package android.content;
import android.annotation.UnsupportedAppUsage;
-import android.content.ContentProvider;
import android.database.Cursor;
import android.net.Uri;
import android.os.Parcel;
@@ -59,6 +58,7 @@ public class ContentProviderOperation implements Parcelable {
private final ContentValues mValuesBackReferences;
private final Map<Integer, Integer> mSelectionArgsBackReferences;
private final boolean mYieldAllowed;
+ private final boolean mFailureAllowed;
private final static String TAG = "ContentProviderOperation";
@@ -76,6 +76,7 @@ public class ContentProviderOperation implements Parcelable {
mSelectionArgsBackReferences = builder.mSelectionArgsBackReferences;
mValuesBackReferences = builder.mValuesBackReferences;
mYieldAllowed = builder.mYieldAllowed;
+ mFailureAllowed = builder.mFailureAllowed;
}
private ContentProviderOperation(Parcel source) {
@@ -98,6 +99,7 @@ public class ContentProviderOperation implements Parcelable {
}
}
mYieldAllowed = source.readInt() != 0;
+ mFailureAllowed = source.readInt() != 0;
}
/** @hide */
@@ -111,6 +113,7 @@ public class ContentProviderOperation implements Parcelable {
mSelectionArgsBackReferences = cpo.mSelectionArgsBackReferences;
mValuesBackReferences = cpo.mValuesBackReferences;
mYieldAllowed = cpo.mYieldAllowed;
+ mFailureAllowed = cpo.mFailureAllowed;
}
public void writeToParcel(Parcel dest, int flags) {
@@ -157,6 +160,7 @@ public class ContentProviderOperation implements Parcelable {
dest.writeInt(0);
}
dest.writeInt(mYieldAllowed ? 1 : 0);
+ dest.writeInt(mFailureAllowed ? 1 : 0);
}
/**
@@ -212,6 +216,11 @@ public class ContentProviderOperation implements Parcelable {
return mYieldAllowed;
}
+ /** {@hide} */
+ public boolean isFailureAllowed() {
+ return mFailureAllowed;
+ }
+
/** @hide exposed for unit tests */
@UnsupportedAppUsage
public int getType() {
@@ -274,6 +283,14 @@ public class ContentProviderOperation implements Parcelable {
return mType == TYPE_ASSERT;
}
+ private ContentProviderResult fail(String msg) throws OperationApplicationException {
+ if (mFailureAllowed) {
+ return new ContentProviderResult(msg);
+ } else {
+ throw new OperationApplicationException(msg);
+ }
+ }
+
/**
* Applies this operation using the given provider. The backRefs array is used to resolve any
* back references that were requested using
@@ -297,7 +314,8 @@ public class ContentProviderOperation implements Parcelable {
if (mType == TYPE_INSERT) {
Uri newUri = provider.insert(mUri, values);
if (newUri == null) {
- throw new OperationApplicationException("insert failed");
+ Log.e(TAG, this.toString());
+ return fail("Insert into " + mUri + " returned no result");
}
return new ContentProviderResult(newUri);
}
@@ -329,7 +347,7 @@ public class ContentProviderOperation implements Parcelable {
if (!TextUtils.equals(cursorValue, expectedValue)) {
// Throw exception when expected values don't match
Log.e(TAG, this.toString());
- throw new OperationApplicationException("Found value " + cursorValue
+ return fail("Found value " + cursorValue
+ " when expected " + expectedValue + " for column "
+ projection[i]);
}
@@ -346,7 +364,7 @@ public class ContentProviderOperation implements Parcelable {
if (mExpectedCount != null && mExpectedCount != numRows) {
Log.e(TAG, this.toString());
- throw new OperationApplicationException("wrong number of rows: " + numRows);
+ return fail("Expected " + mExpectedCount + " rows but actual " + numRows);
}
return new ContentProviderResult(numRows);
@@ -491,6 +509,7 @@ public class ContentProviderOperation implements Parcelable {
private ContentValues mValuesBackReferences;
private Map<Integer, Integer> mSelectionArgsBackReferences;
private boolean mYieldAllowed;
+ private boolean mFailureAllowed;
/** Create a {@link Builder} of a given type. The uri must not be null. */
private Builder(int type, Uri uri) {
@@ -683,5 +702,11 @@ public class ContentProviderOperation implements Parcelable {
mYieldAllowed = yieldAllowed;
return this;
}
+
+ /** {@hide} */
+ public Builder withFailureAllowed(boolean failureAllowed) {
+ mFailureAllowed = failureAllowed;
+ return this;
+ }
}
}
diff --git a/core/java/android/content/ContentProviderResult.java b/core/java/android/content/ContentProviderResult.java
index d90173ceb3cd..b3010116a115 100644
--- a/core/java/android/content/ContentProviderResult.java
+++ b/core/java/android/content/ContentProviderResult.java
@@ -16,10 +16,11 @@
package android.content;
-import android.content.ContentProvider;
import android.net.Uri;
-import android.os.Parcelable;
import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.Preconditions;
/**
* Contains the result of the application of a {@link ContentProviderOperation}. It is guaranteed
@@ -28,26 +29,44 @@ import android.os.Parcel;
public class ContentProviderResult implements Parcelable {
public final Uri uri;
public final Integer count;
+ /** {@hide} */
+ public final String failure;
public ContentProviderResult(Uri uri) {
- if (uri == null) throw new IllegalArgumentException("uri must not be null");
- this.uri = uri;
- this.count = null;
+ this(Preconditions.checkNotNull(uri), null, null);
}
public ContentProviderResult(int count) {
+ this(null, count, null);
+ }
+
+ /** {@hide} */
+ public ContentProviderResult(String failure) {
+ this(null, null, failure);
+ }
+
+ /** {@hide} */
+ public ContentProviderResult(Uri uri, Integer count, String failure) {
+ this.uri = uri;
this.count = count;
- this.uri = null;
+ this.failure = failure;
}
public ContentProviderResult(Parcel source) {
- int type = source.readInt();
- if (type == 1) {
- count = source.readInt();
+ if (source.readInt() != 0) {
+ uri = Uri.CREATOR.createFromParcel(source);
+ } else {
uri = null;
+ }
+ if (source.readInt() != 0) {
+ count = source.readInt();
} else {
count = null;
- uri = Uri.CREATOR.createFromParcel(source);
+ }
+ if (source.readInt() != 0) {
+ failure = source.readString();
+ } else {
+ failure = null;
}
}
@@ -55,37 +74,63 @@ public class ContentProviderResult implements Parcelable {
public ContentProviderResult(ContentProviderResult cpr, int userId) {
uri = ContentProvider.maybeAddUserId(cpr.uri, userId);
count = cpr.count;
+ failure = cpr.failure;
}
+ @Override
public void writeToParcel(Parcel dest, int flags) {
- if (uri == null) {
+ if (uri != null) {
+ dest.writeInt(1);
+ uri.writeToParcel(dest, flags);
+ } else {
+ dest.writeInt(0);
+ }
+ if (count != null) {
dest.writeInt(1);
dest.writeInt(count);
} else {
- dest.writeInt(2);
- uri.writeToParcel(dest, 0);
+ dest.writeInt(0);
+ }
+ if (failure != null) {
+ dest.writeInt(1);
+ dest.writeString(failure);
+ } else {
+ dest.writeInt(0);
}
}
+ @Override
public int describeContents() {
return 0;
}
public static final @android.annotation.NonNull Creator<ContentProviderResult> CREATOR =
new Creator<ContentProviderResult>() {
+ @Override
public ContentProviderResult createFromParcel(Parcel source) {
return new ContentProviderResult(source);
}
+ @Override
public ContentProviderResult[] newArray(int size) {
return new ContentProviderResult[size];
}
};
+ @Override
public String toString() {
+ final StringBuilder sb = new StringBuilder("ContentProviderResult(");
+ if (uri != null) {
+ sb.append("uri=" + uri + " ");
+ }
+ if (count != null) {
+ sb.append("count=" + count + " ");
+ }
if (uri != null) {
- return "ContentProviderResult(uri=" + uri.toString() + ")";
+ sb.append("failure=" + failure + " ");
}
- return "ContentProviderResult(count=" + count + ")";
+ sb.deleteCharAt(sb.length() - 1);
+ sb.append(")");
+ return sb.toString();
}
}
diff --git a/core/java/android/hardware/hdmi/HdmiControlManager.java b/core/java/android/hardware/hdmi/HdmiControlManager.java
index aff385dc23e1..d05ba799205c 100644
--- a/core/java/android/hardware/hdmi/HdmiControlManager.java
+++ b/core/java/android/hardware/hdmi/HdmiControlManager.java
@@ -428,17 +428,33 @@ public final class HdmiControlManager {
}
/**
- * Get a snapshot of the real-time status of the remote devices.
+ * Get a snapshot of the real-time status of the devices on the CEC bus.
*
- * <p>This only applies to devices with multiple HDMI inputs.
+ * <p>This only applies to devices with switch functionality, which are devices with one
+ * or more than one HDMI inputs.
*
- * @return a list of {@link HdmiDeviceInfo} of the connected CEC devices. An empty
- * list will be returned if there is none.
+ * @return a list of {@link HdmiDeviceInfo} of the connected CEC devices on the CEC bus. An
+ * empty list will be returned if there is none.
*
* @hide
*/
+ @NonNull
+ @SystemApi
+ public List<HdmiDeviceInfo> getConnectedDevices() {
+ try {
+ return mService.getDeviceList();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * @removed
+ * @hide
+ * @deprecated Please use {@link #getConnectedDevices()} instead.
+ */
+ @Deprecated
@SystemApi
- @Nullable
public List<HdmiDeviceInfo> getConnectedDevicesList() {
try {
return mService.getDeviceList();
@@ -448,7 +464,8 @@ public final class HdmiControlManager {
}
/**
- * Power off the target device by sending CEC commands.
+ * Power off the target device by sending CEC commands. Note that this device can't be the
+ * current device itself.
*
* <p>The target device info can be obtained by calling {@link #getConnectedDevicesList()}.
*
@@ -457,6 +474,23 @@ public final class HdmiControlManager {
* @hide
*/
@SystemApi
+ public void powerOffDevice(@NonNull HdmiDeviceInfo deviceInfo) {
+ Preconditions.checkNotNull(deviceInfo);
+ try {
+ mService.powerOffRemoteDevice(
+ deviceInfo.getLogicalAddress(), deviceInfo.getDevicePowerStatus());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * @removed
+ * @hide
+ * @deprecated Please use {@link #powerOffDevice(deviceInfo)} instead.
+ */
+ @Deprecated
+ @SystemApi
public void powerOffRemoteDevice(@NonNull HdmiDeviceInfo deviceInfo) {
Preconditions.checkNotNull(deviceInfo);
try {
@@ -468,7 +502,8 @@ public final class HdmiControlManager {
}
/**
- * Power on the target device by sending CEC commands.
+ * Power on the target device by sending CEC commands. Note that this device can't be the
+ * current device itself.
*
* <p>The target device info can be obtained by calling {@link #getConnectedDevicesList()}.
*
@@ -476,6 +511,23 @@ public final class HdmiControlManager {
*
* @hide
*/
+ public void powerOnDevice(HdmiDeviceInfo deviceInfo) {
+ Preconditions.checkNotNull(deviceInfo);
+ try {
+ mService.powerOnRemoteDevice(
+ deviceInfo.getLogicalAddress(), deviceInfo.getDevicePowerStatus());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * @removed
+ * @hide
+ * @deprecated Please use {@link #powerOnDevice(deviceInfo)} instead.
+ */
+ @Deprecated
+ @SystemApi
public void powerOnRemoteDevice(HdmiDeviceInfo deviceInfo) {
Preconditions.checkNotNull(deviceInfo);
try {
@@ -487,15 +539,35 @@ public final class HdmiControlManager {
}
/**
- * Request the target device to be the new Active Source by sending CEC commands.
+ * Request the target device to be the new Active Source by sending CEC commands. Note that
+ * this device can't be the current device itself.
*
* <p>The target device info can be obtained by calling {@link #getConnectedDevicesList()}.
*
+ * <p>If the target device responds to the command, the users should see the target device
+ * streaming on their TVs.
+ *
* @param deviceInfo HdmiDeviceInfo of the target device
*
* @hide
*/
@SystemApi
+ public void setActiveSource(@NonNull HdmiDeviceInfo deviceInfo) {
+ Preconditions.checkNotNull(deviceInfo);
+ try {
+ mService.askRemoteDeviceToBecomeActiveSource(deviceInfo.getPhysicalAddress());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * @removed
+ * @hide
+ * @deprecated Please use {@link #setActiveSource(deviceInfo)} instead.
+ */
+ @Deprecated
+ @SystemApi
public void requestRemoteDeviceToBecomeActiveSource(@NonNull HdmiDeviceInfo deviceInfo) {
Preconditions.checkNotNull(deviceInfo);
try {
@@ -556,7 +628,7 @@ public final class HdmiControlManager {
}
/**
- * Check if the target remote device is connected to the current device.
+ * Check if the target device is connected to the current device.
*
* <p>The API also returns true if the current device is the target.
*
@@ -567,6 +639,27 @@ public final class HdmiControlManager {
* @hide
*/
@SystemApi
+ public boolean isDeviceConnected(@NonNull HdmiDeviceInfo targetDevice) {
+ Preconditions.checkNotNull(targetDevice);
+ mPhysicalAddress = getPhysicalAddress();
+ if (mPhysicalAddress == INVALID_PHYSICAL_ADDRESS) {
+ return false;
+ }
+ int targetPhysicalAddress = targetDevice.getPhysicalAddress();
+ if (targetPhysicalAddress == INVALID_PHYSICAL_ADDRESS) {
+ return false;
+ }
+ return HdmiUtils.getLocalPortFromPhysicalAddress(targetPhysicalAddress, mPhysicalAddress)
+ != HdmiUtils.TARGET_NOT_UNDER_LOCAL_DEVICE;
+ }
+
+ /**
+ * @removed
+ * @hide
+ * @deprecated Please use {@link #isDeviceConnected(targetDevice)} instead.
+ */
+ @Deprecated
+ @SystemApi
public boolean isRemoteDeviceConnected(@NonNull HdmiDeviceInfo targetDevice) {
Preconditions.checkNotNull(targetDevice);
mPhysicalAddress = getPhysicalAddress();
diff --git a/core/java/android/inputmethodservice/MultiClientInputMethodServiceDelegate.java b/core/java/android/inputmethodservice/MultiClientInputMethodServiceDelegate.java
index 0604f6a69d00..4b02085726f1 100644
--- a/core/java/android/inputmethodservice/MultiClientInputMethodServiceDelegate.java
+++ b/core/java/android/inputmethodservice/MultiClientInputMethodServiceDelegate.java
@@ -374,4 +374,15 @@ public final class MultiClientInputMethodServiceDelegate {
public boolean isUidAllowedOnDisplay(int displayId, int uid) {
return mImpl.isUidAllowedOnDisplay(displayId, uid);
}
+
+ /**
+ * Can be called by MSIME to activate/deactivate a client when it is gaining/losing focus
+ * respectively.
+ *
+ * @param clientId client ID to activate/deactivate.
+ * @param active {@code true} to activate a client.
+ */
+ public void setActive(int clientId, boolean active) {
+ mImpl.setActive(clientId, active);
+ }
}
diff --git a/core/java/android/inputmethodservice/MultiClientInputMethodServiceDelegateImpl.java b/core/java/android/inputmethodservice/MultiClientInputMethodServiceDelegateImpl.java
index bbe3a7fe1b31..04db8d625806 100644
--- a/core/java/android/inputmethodservice/MultiClientInputMethodServiceDelegateImpl.java
+++ b/core/java/android/inputmethodservice/MultiClientInputMethodServiceDelegateImpl.java
@@ -190,4 +190,8 @@ final class MultiClientInputMethodServiceDelegateImpl {
boolean isUidAllowedOnDisplay(int displayId, int uid) {
return mPrivOps.isUidAllowedOnDisplay(displayId, uid);
}
+
+ void setActive(int clientId, boolean active) {
+ mPrivOps.setActive(clientId, active);
+ }
}
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 166de3fde741..6c498c736854 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -493,6 +493,7 @@ public final class DeviceConfig {
* @param onPropertyChangedListener The listener to add.
* @hide
* @see #removeOnPropertyChangedListener(OnPropertyChangedListener)
+ * @removed
*/
@SystemApi
@TestApi
@@ -569,6 +570,7 @@ public final class DeviceConfig {
* @param onPropertyChangedListener The listener to remove.
* @hide
* @see #addOnPropertyChangedListener(String, Executor, OnPropertyChangedListener)
+ * @removed
*/
@SystemApi
@TestApi
@@ -737,6 +739,7 @@ public final class DeviceConfig {
* Override {@link #onPropertyChanged(String, String, String)} to handle callbacks for changes.
*
* @hide
+ * @removed
*/
@SystemApi
@TestApi
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 0491c732db81..cc39e56a556b 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -955,18 +955,16 @@ public final class Settings {
"android.settings.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS";
/**
- * Activity Action: Open the advanced power usage details page of an associated app.
+ * Activity Action: Open the battery details page of an associated app.
* <p>
* Input: Intent's data URI set with an application name, using the
* "package" schema (like "package:com.my.app")
* <p>
* Output: Nothing.
- *
- * @hide
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_VIEW_ADVANCED_POWER_USAGE_DETAIL =
- "android.settings.VIEW_ADVANCED_POWER_USAGE_DETAIL";
+ public static final String ACTION_APP_BATTERY_SETTINGS =
+ "android.settings.APP_BATTERY_SETTINGS";
/**
* Activity Action: Show screen for controlling background data
@@ -8139,7 +8137,14 @@ public final class Settings {
public static final String FACE_UNLOCK_ATTENTION_REQUIRED =
"face_unlock_attention_required";
- private static final Validator FACE_UNLOCK_ATTENTION_REQUIRED_VALIDATOR = BOOLEAN_VALIDATOR;
+ /**
+ * Whether or not face unlock requires a diverse set of poses during enrollment. This is a
+ * cached value, the source of truth is obtained through the HAL.
+ * @hide
+ */
+ public static final String FACE_UNLOCK_DIVERSITY_REQUIRED =
+ "face_unlock_diversity_required";
+
/**
* Whether or not face unlock is allowed for apps (through BiometricPrompt).
@@ -8797,7 +8802,6 @@ public final class Settings {
AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN,
FACE_UNLOCK_KEYGUARD_ENABLED,
FACE_UNLOCK_DISMISSES_KEYGUARD,
- FACE_UNLOCK_ATTENTION_REQUIRED,
FACE_UNLOCK_APP_ENABLED,
FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION,
ASSIST_GESTURE_ENABLED,
@@ -8964,8 +8968,6 @@ public final class Settings {
VALIDATORS.put(FACE_UNLOCK_KEYGUARD_ENABLED, FACE_UNLOCK_KEYGUARD_ENABLED_VALIDATOR);
VALIDATORS.put(FACE_UNLOCK_DISMISSES_KEYGUARD,
FACE_UNLOCK_DISMISSES_KEYGUARD_VALIDATOR);
- VALIDATORS.put(FACE_UNLOCK_ATTENTION_REQUIRED,
- FACE_UNLOCK_ATTENTION_REQUIRED_VALIDATOR);
VALIDATORS.put(FACE_UNLOCK_APP_ENABLED, FACE_UNLOCK_APP_ENABLED_VALIDATOR);
VALIDATORS.put(FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION,
FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION_VALIDATOR);
diff --git a/core/java/android/service/attention/AttentionService.java b/core/java/android/service/attention/AttentionService.java
index 6172ce501590..49ab5db74b87 100644
--- a/core/java/android/service/attention/AttentionService.java
+++ b/core/java/android/service/attention/AttentionService.java
@@ -21,13 +21,11 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.app.Service;
-import android.attention.AttentionManagerInternal;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import com.android.internal.util.Preconditions;
-import com.android.server.LocalServices;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -132,19 +130,6 @@ public abstract class AttentionService extends Service {
}
/**
- * Disables the dependants.
- *
- * Example: called if the service does not have sufficient permissions to perform the task.
- */
- public final void disableSelf() {
- AttentionManagerInternal attentionManager = LocalServices.getService(
- AttentionManagerInternal.class);
- if (attentionManager != null) {
- attentionManager.disableSelf();
- }
- }
-
- /**
* Checks the user attention and calls into the provided callback.
*
* @param callback the callback to return the result to
diff --git a/core/java/android/service/contentcapture/ContentCaptureService.java b/core/java/android/service/contentcapture/ContentCaptureService.java
index 5be73b92fbc0..d8614a9d66af 100644
--- a/core/java/android/service/contentcapture/ContentCaptureService.java
+++ b/core/java/android/service/contentcapture/ContentCaptureService.java
@@ -46,9 +46,9 @@ import android.view.contentcapture.ContentCaptureEvent;
import android.view.contentcapture.ContentCaptureManager;
import android.view.contentcapture.ContentCaptureSession;
import android.view.contentcapture.ContentCaptureSessionId;
+import android.view.contentcapture.DataRemovalRequest;
import android.view.contentcapture.IContentCaptureDirectManager;
import android.view.contentcapture.MainContentCaptureSession;
-import android.view.contentcapture.UserDataRemovalRequest;
import com.android.internal.os.IResultReceiver;
@@ -138,7 +138,7 @@ public abstract class ContentCaptureService extends Service {
}
@Override
- public void onUserDataRemovalRequest(UserDataRemovalRequest request) {
+ public void onDataRemovalRequest(DataRemovalRequest request) {
mHandler.sendMessage(
obtainMessage(ContentCaptureService::handleOnUserDataRemovalRequest,
ContentCaptureService.this, request));
@@ -288,12 +288,12 @@ public abstract class ContentCaptureService extends Service {
}
/**
- * Notifies the service that the app requested to remove data associated with the user.
+ * Notifies the service that the app requested to remove content capture data.
*
- * @param request the user data requested to be removed
+ * @param request the content capture data requested to be removed
*/
- public void onUserDataRemovalRequest(@NonNull UserDataRemovalRequest request) {
- if (sVerbose) Log.v(TAG, "onUserDataRemovalRequest()");
+ public void onDataRemovalRequest(@NonNull DataRemovalRequest request) {
+ if (sVerbose) Log.v(TAG, "onDataRemovalRequest()");
}
/**
@@ -449,8 +449,8 @@ public abstract class ContentCaptureService extends Service {
onDestroyContentCaptureSession(new ContentCaptureSessionId(sessionId));
}
- private void handleOnUserDataRemovalRequest(@NonNull UserDataRemovalRequest request) {
- onUserDataRemovalRequest(request);
+ private void handleOnUserDataRemovalRequest(@NonNull DataRemovalRequest request) {
+ onDataRemovalRequest(request);
}
private void handleOnActivityEvent(@NonNull ActivityEvent event) {
diff --git a/core/java/android/service/contentcapture/IContentCaptureService.aidl b/core/java/android/service/contentcapture/IContentCaptureService.aidl
index 03e1b7857837..a7578af94004 100644
--- a/core/java/android/service/contentcapture/IContentCaptureService.aidl
+++ b/core/java/android/service/contentcapture/IContentCaptureService.aidl
@@ -21,7 +21,7 @@ import android.os.IBinder;
import android.service.contentcapture.ActivityEvent;
import android.service.contentcapture.SnapshotData;
import android.view.contentcapture.ContentCaptureContext;
-import android.view.contentcapture.UserDataRemovalRequest;
+import android.view.contentcapture.DataRemovalRequest;
import com.android.internal.os.IResultReceiver;
@@ -39,6 +39,6 @@ oneway interface IContentCaptureService {
in IResultReceiver clientReceiver, int initialState);
void onSessionFinished(int sessionId);
void onActivitySnapshot(int sessionId, in SnapshotData snapshotData);
- void onUserDataRemovalRequest(in UserDataRemovalRequest request);
+ void onDataRemovalRequest(in DataRemovalRequest request);
void onActivityEvent(in ActivityEvent event);
}
diff --git a/core/java/android/service/euicc/EuiccService.java b/core/java/android/service/euicc/EuiccService.java
index 2288106d8351..d2f22bfac84a 100644
--- a/core/java/android/service/euicc/EuiccService.java
+++ b/core/java/android/service/euicc/EuiccService.java
@@ -418,12 +418,15 @@ public abstract class EuiccService extends Service {
* bit map, and original the card Id. The result code may be one of the predefined
* {@code RESULT_} constants or any implementation-specific code starting with
* {@link #RESULT_FIRST_USER}. The resolvable error bit map can be either 0 or values
- * defined in {@code RESOLVABLE_ERROR_}.
+ * defined in {@code RESOLVABLE_ERROR_}. A subclass should override this method. Otherwise,
+ * this method does nothing and returns null by default.
* @see android.telephony.euicc.EuiccManager#downloadSubscription
*/
- public abstract DownloadSubscriptionResult onDownloadSubscription(int slotId,
+ public DownloadSubscriptionResult onDownloadSubscription(int slotId,
@NonNull DownloadableSubscription subscription, boolean switchAfterDownload,
- boolean forceDeactivateSim, @Nullable Bundle resolvedBundle);
+ boolean forceDeactivateSim, @Nullable Bundle resolvedBundle) {
+ return null;
+ }
/**
* Download the given subscription.
@@ -439,14 +442,14 @@ public abstract class EuiccService extends Service {
* constants or any implementation-specific code starting with {@link #RESULT_FIRST_USER}.
* @see android.telephony.euicc.EuiccManager#downloadSubscription
*
- * @deprecated From Q, please use the above
- * {@link #onDownloadSubscription(int, DownloadableSubscription, boolean, boolean, Bundle)}.
+ * @deprecated From Q, a subclass should use and override the above
+ * {@link #onDownloadSubscription(int, DownloadableSubscription, boolean, boolean, Bundle)}. The
+ * default return value for this one is Integer.MIN_VALUE.
*/
@Deprecated public @Result int onDownloadSubscription(int slotId,
@NonNull DownloadableSubscription subscription, boolean switchAfterDownload,
boolean forceDeactivateSim) {
- throw new UnsupportedOperationException("onDownloadSubscription(int, "
- + "DownloadableSubscription, boolean, boolean) is deprecated.");
+ return Integer.MIN_VALUE;
}
/**
diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java
index 6f274477431f..5b5f3b843c50 100644
--- a/core/java/android/service/voice/VoiceInteractionSession.java
+++ b/core/java/android/service/voice/VoiceInteractionSession.java
@@ -123,7 +123,7 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall
/**
* Flag for use with {@link #onShow}: indicates that the voice interaction service was invoked
- * from an Android automotive system Ui.
+ * from an Android automotive system UI.
*/
public static final int SHOW_SOURCE_AUTOMOTIVE_SYSTEM_UI = 1 << 7;
diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java
index f2747cf426fa..1bcfc05224ca 100755
--- a/core/java/android/util/DisplayMetrics.java
+++ b/core/java/android/util/DisplayMetrics.java
@@ -34,11 +34,32 @@ public class DisplayMetrics {
public static final int DENSITY_LOW = 120;
/**
+ * Intermediate density for screens that sit between {@link #DENSITY_LOW} (120dpi) and
+ * {@link #DENSITY_MEDIUM} (160dpi). This is not a density that applications should target,
+ * instead relying on the system to scale their {@link #DENSITY_MEDIUM} assets for them.
+ */
+ public static final int DENSITY_140 = 140;
+
+ /**
* Standard quantized DPI for medium-density screens.
*/
public static final int DENSITY_MEDIUM = 160;
/**
+ * Intermediate density for screens that sit between {@link #DENSITY_MEDIUM} (160dpi) and
+ * {@link #DENSITY_HIGH} (240dpi). This is not a density that applications should target,
+ * instead relying on the system to scale their {@link #DENSITY_HIGH} assets for them.
+ */
+ public static final int DENSITY_180 = 180;
+
+ /**
+ * Intermediate density for screens that sit between {@link #DENSITY_MEDIUM} (160dpi) and
+ * {@link #DENSITY_HIGH} (240dpi). This is not a density that applications should target,
+ * instead relying on the system to scale their {@link #DENSITY_HIGH} assets for them.
+ */
+ public static final int DENSITY_200 = 200;
+
+ /**
* This is a secondary density, added for some common screen configurations.
* It is recommended that applications not generally target this as a first
* class density -- that is, don't supply specific graphics for this
@@ -58,6 +79,13 @@ public class DisplayMetrics {
public static final int DENSITY_TV = 213;
/**
+ * Intermediate density for screens that sit between {@link #DENSITY_MEDIUM} (160dpi) and
+ * {@link #DENSITY_HIGH} (240dpi). This is not a density that applications should target,
+ * instead relying on the system to scale their {@link #DENSITY_HIGH} assets for them.
+ */
+ public static final int DENSITY_220 = 220;
+
+ /**
* Standard quantized DPI for high-density screens.
*/
public static final int DENSITY_HIGH = 240;
diff --git a/core/java/android/view/ScaleGestureDetector.java b/core/java/android/view/ScaleGestureDetector.java
index 7c69cfde2b9e..1d721516a979 100644
--- a/core/java/android/view/ScaleGestureDetector.java
+++ b/core/java/android/view/ScaleGestureDetector.java
@@ -551,7 +551,7 @@ public class ScaleGestureDetector {
(mEventBeforeOrAboveStartingGestureEvent && (mCurrSpan < mPrevSpan)) ||
(!mEventBeforeOrAboveStartingGestureEvent && (mCurrSpan > mPrevSpan));
final float spanDiff = (Math.abs(1 - (mCurrSpan / mPrevSpan)) * SCALE_FACTOR);
- return mPrevSpan <= 0 ? 1 : scaleUp ? (1 + spanDiff) : (1 - spanDiff);
+ return mPrevSpan <= mSpanSlop ? 1 : scaleUp ? (1 + spanDiff) : (1 - spanDiff);
}
return mPrevSpan > 0 ? mCurrSpan / mPrevSpan : 1;
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 51bcbbdb7e7d..c3a94655d7d5 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -1377,59 +1377,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
public static final int AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x1;
- /** @hide */
- @IntDef(prefix = { "IMPORTANT_FOR_CONTENT_CAPTURE_" }, value = {
- IMPORTANT_FOR_CONTENT_CAPTURE_AUTO,
- IMPORTANT_FOR_CONTENT_CAPTURE_YES,
- IMPORTANT_FOR_CONTENT_CAPTURE_NO,
- IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS,
- IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface ContentCaptureImportance {}
-
- /**
- * Automatically determine whether a view is important for content capture.
- *
- * @see #isImportantForContentCapture()
- * @see #setImportantForContentCapture(int)
- */
- public static final int IMPORTANT_FOR_CONTENT_CAPTURE_AUTO = 0x0;
-
- /**
- * The view is important for content capture, and its children (if any) will be traversed.
- *
- * @see #isImportantForContentCapture()
- * @see #setImportantForContentCapture(int)
- */
- public static final int IMPORTANT_FOR_CONTENT_CAPTURE_YES = 0x1;
-
- /**
- * The view is not important for content capture, but its children (if any) will be traversed.
- *
- * @see #isImportantForContentCapture()
- * @see #setImportantForContentCapture(int)
- */
- public static final int IMPORTANT_FOR_CONTENT_CAPTURE_NO = 0x2;
-
- /**
- * The view is important for content capture, but its children (if any) will not be traversed.
- *
- * @see #isImportantForContentCapture()
- * @see #setImportantForContentCapture(int)
- */
- public static final int IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS = 0x4;
-
- /**
- * The view is not important for content capture, and its children (if any) will not be
- * traversed.
- *
- * @see #isImportantForContentCapture()
- * @see #setImportantForContentCapture(int)
- */
- public static final int IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS = 0x8;
-
-
/**
* This view is enabled. Interpretation varies by subclass.
* Use with ENABLED_MASK when calling setFlags.
@@ -3402,55 +3349,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
/* End of masks for mPrivateFlags3 */
- /*
- * Masks for mPrivateFlags4, as generated by dumpFlags():
- *
- * |-------|-------|-------|-------|
- * 1111 PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK
- * 1 PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED
- * 1 PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED
- * 1 PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED
- * 1 PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE
- * 11 PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK
- * |-------|-------|-------|-------|
- */
-
- /**
- * Mask for obtaining the bits which specify how to determine
- * whether a view is important for autofill.
- *
- * <p>NOTE: the important for content capture values were the first flags added and are set in
- * the rightmost position, so we don't need to shift them
- */
- private static final int PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK =
- IMPORTANT_FOR_CONTENT_CAPTURE_AUTO | IMPORTANT_FOR_CONTENT_CAPTURE_YES
- | IMPORTANT_FOR_CONTENT_CAPTURE_NO
- | IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS
- | IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS;
-
- /*
- * Variables used to control when the IntelligenceManager.notifyNodeAdded()/removed() methods
- * should be called.
- *
- * The idea is to call notifyAppeared() after the view is layout and visible, then call
- * notifyDisappeared() when it's gone (without known when it was removed from the parent).
- */
- private static final int PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED = 0x10;
- private static final int PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED = 0x20;
-
- /*
- * Flags used to cache the value returned by isImportantForContentCapture while the view
- * hierarchy is being traversed.
- */
- private static final int PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED = 0x40;
- private static final int PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE = 0x80;
-
- private static final int PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK =
- PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED
- | PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE;
-
- /* End of masks for mPrivateFlags4 */
-
/** @hide */
protected static final int VIEW_STRUCTURE_FOR_ASSIST = 0;
/** @hide */
@@ -4074,8 +3972,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 129147060)
int mPrivateFlags3;
- private int mPrivateFlags4;
-
/**
* This view's request for the visibility of the status bar.
* @hide
@@ -5808,11 +5704,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
setImportantForAutofill(a.getInt(attr, IMPORTANT_FOR_AUTOFILL_AUTO));
}
break;
- case R.styleable.View_importantForContentCapture:
- if (a.peekValue(attr) != null) {
- setImportantForContentCapture(a.getInt(attr,
- IMPORTANT_FOR_CONTENT_CAPTURE_AUTO));
- }
case R.styleable.View_defaultFocusHighlightEnabled:
if (a.peekValue(attr) != null) {
setDefaultFocusHighlightEnabled(a.getBoolean(attr, true));
@@ -8532,62 +8423,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
onProvideStructure(structure, VIEW_STRUCTURE_FOR_AUTOFILL, flags);
}
- /**
- * Populates a {@link ViewStructure} for content capture.
- *
- * <p>This method is called after a view is that is eligible for content capture
- * (for example, if it {@link #isImportantForAutofill()}, an intelligence service is enabled for
- * the user, and the activity rendering the view is enabled for content capture) is laid out and
- * is visible.
- *
- * <p>The populated structure is then passed to the service through
- * {@link ContentCaptureSession#notifyViewAppeared(ViewStructure)}.
- *
- * <p><b>Note: </b>views that manage a virtual structure under this view must populate just
- * the node representing this view and return right away, then asynchronously report (not
- * necessarily in the UI thread) when the children nodes appear, disappear or have their text
- * changed by calling
- * {@link ContentCaptureSession#notifyViewAppeared(ViewStructure)},
- * {@link ContentCaptureSession#notifyViewDisappeared(AutofillId)}, and
- * {@link ContentCaptureSession#notifyViewTextChanged(AutofillId, CharSequence)}
- * respectively. The structure for the a child must be created using
- * {@link ContentCaptureSession#newVirtualViewStructure(AutofillId, long)}, and the
- * {@code autofillId} for a child can be obtained either through
- * {@code childStructure.getAutofillId()} or
- * {@link ContentCaptureSession#newAutofillId(AutofillId, long)}.
- *
- * <p>When the virtual view hierarchy represents a web page, you should also:
- *
- * <ul>
- * <li>Call {@link ContentCaptureManager#getContentCaptureConditions()} to infer content
- * capture events should be generate for that URL.
- * <li>Create a new {@link ContentCaptureSession} child for every HTML element that
- * renders a new URL (like an {@code IFRAME}) and use that session to notify events from
- * that subtree.
- * </ul>
- *
- * <p><b>Note: </b>the following methods of the {@code structure} will be ignored:
- * <ul>
- * <li>{@link ViewStructure#setChildCount(int)}
- * <li>{@link ViewStructure#addChildCount(int)}
- * <li>{@link ViewStructure#getChildCount()}
- * <li>{@link ViewStructure#newChild(int)}
- * <li>{@link ViewStructure#asyncNewChild(int)}
- * <li>{@link ViewStructure#asyncCommit()}
- * <li>{@link ViewStructure#setWebDomain(String)}
- * <li>{@link ViewStructure#newHtmlInfoBuilder(String)}
- * <li>{@link ViewStructure#setHtmlInfo(android.view.ViewStructure.HtmlInfo)}
- * <li>{@link ViewStructure#setDataIsSensitive(boolean)}
- * <li>{@link ViewStructure#setAlpha(float)}
- * <li>{@link ViewStructure#setElevation(float)}
- * <li>{@link ViewStructure#setTransformation(Matrix)}
- *
- * </ul>
- */
- public void onProvideContentCaptureStructure(@NonNull ViewStructure structure, int flags) {
- onProvideStructure(structure, VIEW_STRUCTURE_FOR_CONTENT_CAPTURE, flags);
- }
-
/** @hide */
protected void onProvideStructure(@NonNull ViewStructure structure,
@ViewStructureType int viewFor, int flags) {
@@ -9225,265 +9060,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
- * Gets the mode for determining whether this view is important for content capture.
- *
- * <p>See {@link #setImportantForContentCapture(int)} and
- * {@link #isImportantForContentCapture()} for more info about this mode.
- *
- * @return {@link #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO} by default, or value passed to
- * {@link #setImportantForContentCapture(int)}.
- *
- * @attr ref android.R.styleable#View_importantForContentCapture
- */
- @ViewDebug.ExportedProperty(mapping = {
- @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_AUTO, to = "auto"),
- @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_YES, to = "yes"),
- @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_NO, to = "no"),
- @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS,
- to = "yesExcludeDescendants"),
- @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS,
- to = "noExcludeDescendants")})
- @InspectableProperty(enumMapping = {
- @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_AUTO, name = "auto"),
- @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_YES, name = "yes"),
- @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_NO, name = "no"),
- @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS,
- name = "yesExcludeDescendants"),
- @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS,
- name = "noExcludeDescendants"),
- })
- public @ContentCaptureImportance int getImportantForContentCapture() {
- // NOTE: the important for content capture values were the first flags added and are set in
- // the rightmost position, so we don't need to shift them
- return mPrivateFlags4 & PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK;
- }
-
- /**
- * Sets the mode for determining whether this view is considered important for content capture.
- *
- * <p>The platform determines the importance for autofill automatically but you
- * can use this method to customize the behavior. Typically, a view that provides text should
- * be marked as {@link #IMPORTANT_FOR_CONTENT_CAPTURE_YES}.
- *
- * @param mode {@link #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO},
- * {@link #IMPORTANT_FOR_CONTENT_CAPTURE_YES}, {@link #IMPORTANT_FOR_CONTENT_CAPTURE_NO},
- * {@link #IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS},
- * or {@link #IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS}.
- *
- * @attr ref android.R.styleable#View_importantForContentCapture
- */
- public void setImportantForContentCapture(@ContentCaptureImportance int mode) {
- // Reset first
- mPrivateFlags4 &= ~PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK;
- // Then set again
- // NOTE: the important for content capture values were the first flags added and are set in
- // the rightmost position, so we don't need to shift them
- mPrivateFlags4 |= (mode & PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK);
- }
-
- /**
- * Hints the Android System whether this view is considered important for content capture, based
- * on the value explicitly set by {@link #setImportantForContentCapture(int)} and heuristics
- * when it's {@link #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO}.
- *
- * <p>See {@link ContentCaptureManager} for more info about content capture.
- *
- * @return whether the view is considered important for content capture.
- *
- * @see #setImportantForContentCapture(int)
- * @see #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO
- * @see #IMPORTANT_FOR_CONTENT_CAPTURE_YES
- * @see #IMPORTANT_FOR_CONTENT_CAPTURE_NO
- * @see #IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS
- * @see #IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
- */
- public final boolean isImportantForContentCapture() {
- boolean isImportant;
- if ((mPrivateFlags4 & PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED) != 0) {
- isImportant = (mPrivateFlags4 & PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE) != 0;
- return isImportant;
- }
-
- isImportant = calculateIsImportantForContentCapture();
-
- mPrivateFlags4 &= ~PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE;
- if (isImportant) {
- mPrivateFlags4 |= PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE;
- }
- mPrivateFlags4 |= PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED;
- return isImportant;
- }
-
- /**
- * Calculates whether the flag is important for content capture so it can be used by
- * {@link #isImportantForContentCapture()} while the tree is traversed.
- */
- private boolean calculateIsImportantForContentCapture() {
- // Check parent mode to ensure we're important
- ViewParent parent = mParent;
- while (parent instanceof View) {
- final int parentImportance = ((View) parent).getImportantForContentCapture();
- if (parentImportance == IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
- || parentImportance == IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS) {
- if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) {
- Log.v(CONTENT_CAPTURE_LOG_TAG, "View (" + this + ") is not important for "
- + "content capture because parent " + parent + "'s importance is "
- + parentImportance);
- }
- return false;
- }
- parent = parent.getParent();
- }
-
- final int importance = getImportantForContentCapture();
-
- // First, check the explicit states.
- if (importance == IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS
- || importance == IMPORTANT_FOR_CONTENT_CAPTURE_YES) {
- return true;
- }
- if (importance == IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
- || importance == IMPORTANT_FOR_CONTENT_CAPTURE_NO) {
- if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) {
- Log.v(CONTENT_CAPTURE_LOG_TAG, "View (" + this + ") is not important for content "
- + "capture because its importance is " + importance);
- }
- return false;
- }
-
- // Then use some heuristics to handle AUTO.
- if (importance != IMPORTANT_FOR_CONTENT_CAPTURE_AUTO) {
- Log.w(CONTENT_CAPTURE_LOG_TAG, "invalid content capture importance (" + importance
- + " on view " + this);
- return false;
- }
-
- // View group is important if at least one children also is
- if (this instanceof ViewGroup) {
- final ViewGroup group = (ViewGroup) this;
- for (int i = 0; i < group.getChildCount(); i++) {
- final View child = group.getChildAt(i);
- if (child.isImportantForContentCapture()) {
- return true;
- }
- }
- }
-
- // If the app developer explicitly set hints or autofill hintsfor it, it's important.
- if (getAutofillHints() != null) {
- return true;
- }
-
- // Otherwise, assume it's not important...
- return false;
- }
-
- /**
- * Helper used to notify the {@link ContentCaptureManager} when the view is removed or
- * added, based on whether it's laid out and visible, and without knowing if the parent removed
- * it from the view hierarchy.
- *
- * <p>This method is called from many places (visibility changed, view laid out, view attached
- * or detached to/from window, etc...) and hence must contain the logic to call the manager, as
- * described below:
- *
- * <ol>
- * <li>It should only be called when content capture is enabled for the view.
- * <li>It must call viewAppeared() before viewDisappeared()
- * <li>viewAppearead() can only be called when the view is visible and laidout
- * <li>It should not call the same event twice.
- * </ol>
- */
- private void notifyAppearedOrDisappearedForContentCaptureIfNeeded(boolean appeared) {
- AttachInfo ai = mAttachInfo;
- // Skip it while the view is being laided out for the first time
- if (ai != null && !ai.mReadyForContentCaptureUpdates) return;
-
- if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
- Trace.traceBegin(Trace.TRACE_TAG_VIEW,
- "notifyContentCapture(" + appeared + ") for " + getClass().getSimpleName());
- }
- try {
- notifyAppearedOrDisappearedForContentCaptureIfNeededNoTrace(appeared);
- } finally {
- Trace.traceEnd(Trace.TRACE_TAG_VIEW);
- }
- }
-
- private void notifyAppearedOrDisappearedForContentCaptureIfNeededNoTrace(boolean appeared) {
- AttachInfo ai = mAttachInfo;
-
- // First check if context has client, so it saves a service lookup when it doesn't
- if (mContext.getContentCaptureOptions() == null) return;
-
- // Then check if it's enabled in the context...
- final ContentCaptureManager ccm = ai != null ? ai.getContentCaptureManager(mContext)
- : mContext.getSystemService(ContentCaptureManager.class);
- if (ccm == null || !ccm.isContentCaptureEnabled()) return;
-
- // ... and finally at the view level
- // NOTE: isImportantForContentCapture() is more expensive than cm.isContentCaptureEnabled()
- if (!isImportantForContentCapture()) return;
-
- ContentCaptureSession session = getContentCaptureSession();
- if (session == null) return;
-
- if (appeared) {
- if (!isLaidOut() || getVisibility() != VISIBLE
- || (mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED) != 0) {
- if (DEBUG_CONTENT_CAPTURE) {
- Log.v(CONTENT_CAPTURE_LOG_TAG, "Ignoring 'appeared' on " + this + ": laid="
- + isLaidOut() + ", visibleToUser=" + isVisibleToUser()
- + ", visible=" + (getVisibility() == VISIBLE)
- + ": alreadyNotifiedAppeared=" + ((mPrivateFlags4
- & PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED) != 0)
- + ", alreadyNotifiedDisappeared=" + ((mPrivateFlags4
- & PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED) != 0));
- }
- return;
- }
- setNotifiedContentCaptureAppeared();
-
- if (ai != null) {
- ai.delayNotifyContentCaptureEvent(session, this, appeared);
- } else {
- if (DEBUG_CONTENT_CAPTURE) {
- Log.w(CONTENT_CAPTURE_LOG_TAG, "no AttachInfo on appeared for " + this);
- }
- }
- } else {
- if ((mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED) == 0
- || (mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED) != 0) {
- if (DEBUG_CONTENT_CAPTURE) {
- Log.v(CONTENT_CAPTURE_LOG_TAG, "Ignoring 'disappeared' on " + this + ": laid="
- + isLaidOut() + ", visibleToUser=" + isVisibleToUser()
- + ", visible=" + (getVisibility() == VISIBLE)
- + ": alreadyNotifiedAppeared=" + ((mPrivateFlags4
- & PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED) != 0)
- + ", alreadyNotifiedDisappeared=" + ((mPrivateFlags4
- & PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED) != 0));
- }
- return;
- }
- mPrivateFlags4 |= PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED;
- mPrivateFlags4 &= ~PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED;
-
- if (ai != null) {
- ai.delayNotifyContentCaptureEvent(session, this, appeared);
- } else {
- if (DEBUG_CONTENT_CAPTURE) {
- Log.v(CONTENT_CAPTURE_LOG_TAG, "no AttachInfo on disappeared for " + this);
- }
- }
- }
- }
-
- private void setNotifiedContentCaptureAppeared() {
- mPrivateFlags4 |= PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED;
- mPrivateFlags4 &= ~PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED;
- }
-
- /**
* Sets the (optional) {@link ContentCaptureSession} associated with this view.
*
* <p>This method should be called when you need to associate a {@link ContentCaptureContext} to
@@ -9739,68 +9315,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
- * Dispatches the initial content capture events for a view structure.
- *
- * @hide
- */
- public void dispatchInitialProvideContentCaptureStructure() {
- AttachInfo ai = mAttachInfo;
- if (ai == null) {
- Log.w(CONTENT_CAPTURE_LOG_TAG,
- "dispatchProvideContentCaptureStructure(): no AttachInfo for " + this);
- return;
- }
- ContentCaptureManager ccm = ai.mContentCaptureManager;
- if (ccm == null) {
- Log.w(CONTENT_CAPTURE_LOG_TAG, "dispatchProvideContentCaptureStructure(): "
- + "no ContentCaptureManager for " + this);
- return;
- }
-
- // We must set it before checkign if the view itself is important, because it might
- // initially not be (for example, if it's empty), although that might change later (for
- // example, if important views are added)
- ai.mReadyForContentCaptureUpdates = true;
-
- if (!isImportantForContentCapture()) {
- if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.DEBUG)) {
- Log.d(CONTENT_CAPTURE_LOG_TAG,
- "dispatchProvideContentCaptureStructure(): decorView is not important");
- }
- return;
- }
-
- ai.mContentCaptureManager = ccm;
-
- ContentCaptureSession session = getContentCaptureSession();
- if (session == null) {
- if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.DEBUG)) {
- Log.d(CONTENT_CAPTURE_LOG_TAG,
- "dispatchProvideContentCaptureStructure(): no session for " + this);
- }
- return;
- }
-
- session.internalNotifyViewTreeEvent(/* started= */ true);
- try {
- dispatchProvideContentCaptureStructure();
- } finally {
- session.internalNotifyViewTreeEvent(/* started= */ false);
- }
- }
-
- /** @hide */
- void dispatchProvideContentCaptureStructure() {
- ContentCaptureSession session = getContentCaptureSession();
- if (session != null) {
- ViewStructure structure = session.newViewStructure(this);
- onProvideContentCaptureStructure(structure, /* flags= */ 0);
- setNotifiedContentCaptureAppeared();
- session.notifyViewAppeared(structure);
- }
- }
-
- /**
* @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
*
* Note: Called from the default {@link AccessibilityDelegate}.
@@ -13753,7 +13267,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
public void dispatchStartTemporaryDetach() {
mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH;
notifyEnterOrExitForAutoFillIfNeeded(false);
- notifyAppearedOrDisappearedForContentCaptureIfNeeded(false);
onStartTemporaryDetach();
}
@@ -13780,7 +13293,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
notifyFocusChangeToInputMethodManager(true /* hasFocus */);
}
notifyEnterOrExitForAutoFillIfNeeded(true);
- notifyAppearedOrDisappearedForContentCaptureIfNeeded(true);
}
/**
@@ -14372,8 +13884,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
: AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED);
}
}
-
- notifyAppearedOrDisappearedForContentCaptureIfNeeded(isVisible);
}
/**
@@ -18069,7 +17579,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
// Reset content capture caches
- mPrivateFlags4 &= ~PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK;
mCachedContentCaptureSession = null;
if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
@@ -20079,7 +19588,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
needGlobalAttributesUpdate(false);
notifyEnterOrExitForAutoFillIfNeeded(true);
- notifyAppearedOrDisappearedForContentCaptureIfNeeded(true);
}
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
@@ -20129,7 +19637,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
notifyEnterOrExitForAutoFillIfNeeded(false);
- notifyAppearedOrDisappearedForContentCaptureIfNeeded(false);
}
/**
@@ -22442,8 +21949,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
mPrivateFlags3 &= ~PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
notifyEnterOrExitForAutoFillIfNeeded(true);
}
-
- notifyAppearedOrDisappearedForContentCaptureIfNeeded(true);
}
private boolean hasParentWantsFocus() {
@@ -28650,23 +28155,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
View mTooltipHost;
/**
- * The initial structure has been reported so the view is ready to report updates.
- */
- boolean mReadyForContentCaptureUpdates;
-
- /**
- * Map(keyed by session) of content capture events that need to be notified after the view
- * hierarchy is traversed: value is either the view itself for appearead events, or its
- * autofill id for disappeared.
- */
- SparseArray<ArrayList<Object>> mContentCaptureEvents;
-
- /**
- * Cached reference to the {@link ContentCaptureManager}.
- */
- ContentCaptureManager mContentCaptureManager;
-
- /**
* Creates a new set of attachment information with the specified
* events handler and thread.
*
@@ -28684,31 +28172,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
mRootCallbacks = effectPlayer;
mTreeObserver = new ViewTreeObserver(context);
}
-
- private void delayNotifyContentCaptureEvent(@NonNull ContentCaptureSession session,
- @NonNull View view, boolean appeared) {
- if (mContentCaptureEvents == null) {
- // Most of the time there will be just one session, so intial capacity is 1
- mContentCaptureEvents = new SparseArray<>(1);
- }
- int sessionId = session.getId();
- // TODO: life would be much easier if we provided a MultiMap implementation somwhere...
- ArrayList<Object> events = mContentCaptureEvents.get(sessionId);
- if (events == null) {
- events = new ArrayList<>();
- mContentCaptureEvents.put(sessionId, events);
- }
- events.add(appeared ? view : view.getAutofillId());
- }
-
- @Nullable
- ContentCaptureManager getContentCaptureManager(@NonNull Context context) {
- if (mContentCaptureManager != null) {
- return mContentCaptureManager;
- }
- mContentCaptureManager = context.getSystemService(ContentCaptureManager.class);
- return mContentCaptureManager;
- }
}
/**
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 937bd1b34e61..d362024ed525 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -3606,7 +3606,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
return;
}
- final ChildListForAutoFillOrContentCapture children = getChildrenForAutofill(flags);
+ final ChildListForAutofill children = getChildrenForAutofill(flags);
final int childrenCount = children.size();
structure.setChildCount(childrenCount);
for (int i = 0; i < childrenCount; i++) {
@@ -3617,30 +3617,14 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
children.recycle();
}
- /** @hide */
- @Override
- public void dispatchProvideContentCaptureStructure() {
- super.dispatchProvideContentCaptureStructure();
-
- if (!isLaidOut()) return;
-
- final ChildListForAutoFillOrContentCapture children = getChildrenForContentCapture();
- final int childrenCount = children.size();
- for (int i = 0; i < childrenCount; i++) {
- final View child = children.get(i);
- child.dispatchProvideContentCaptureStructure();
- }
- children.recycle();
- }
-
/**
* Gets the children for autofill. Children for autofill are the first
* level descendants that are important for autofill. The returned
* child list object is pooled and the caller must recycle it once done.
* @hide */
- private @NonNull ChildListForAutoFillOrContentCapture getChildrenForAutofill(
+ private @NonNull ChildListForAutofill getChildrenForAutofill(
@AutofillFlags int flags) {
- final ChildListForAutoFillOrContentCapture children = ChildListForAutoFillOrContentCapture
+ final ChildListForAutofill children = ChildListForAutofill
.obtain();
populateChildrenForAutofill(children, flags);
return children;
@@ -3668,34 +3652,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
}
}
- private @NonNull ChildListForAutoFillOrContentCapture getChildrenForContentCapture() {
- final ChildListForAutoFillOrContentCapture children = ChildListForAutoFillOrContentCapture
- .obtain();
- populateChildrenForContentCapture(children);
- return children;
- }
-
- /** @hide */
- private void populateChildrenForContentCapture(ArrayList<View> list) {
- final int childrenCount = mChildrenCount;
- if (childrenCount <= 0) {
- return;
- }
- final ArrayList<View> preorderedList = buildOrderedChildList();
- final boolean customOrder = preorderedList == null
- && isChildrenDrawingOrderEnabled();
- for (int i = 0; i < childrenCount; i++) {
- final int childIndex = getAndVerifyPreorderedIndex(childrenCount, i, customOrder);
- final View child = (preorderedList == null)
- ? mChildren[childIndex] : preorderedList.get(childIndex);
- if (child.isImportantForContentCapture()) {
- list.add(child);
- } else if (child instanceof ViewGroup) {
- ((ViewGroup) child).populateChildrenForContentCapture(list);
- }
- }
- }
-
private static View getAndVerifyPreorderedView(ArrayList<View> preorderedList, View[] children,
int childIndex) {
final View child;
@@ -8678,16 +8634,16 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
/**
* Pooled class that to hold the children for autifill.
*/
- private static class ChildListForAutoFillOrContentCapture extends ArrayList<View> {
+ private static class ChildListForAutofill extends ArrayList<View> {
private static final int MAX_POOL_SIZE = 32;
- private static final Pools.SimplePool<ChildListForAutoFillOrContentCapture> sPool =
+ private static final Pools.SimplePool<ChildListForAutofill> sPool =
new Pools.SimplePool<>(MAX_POOL_SIZE);
- public static ChildListForAutoFillOrContentCapture obtain() {
- ChildListForAutoFillOrContentCapture list = sPool.acquire();
+ public static ChildListForAutofill obtain() {
+ ChildListForAutofill list = sPool.acquire();
if (list == null) {
- list = new ChildListForAutoFillOrContentCapture();
+ list = new ChildListForAutofill();
}
return list;
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index f3b7ad5e557c..5ca70ba9a575 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -105,11 +105,7 @@ import android.view.accessibility.IAccessibilityInteractionConnection;
import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Interpolator;
-import android.view.autofill.AutofillId;
import android.view.autofill.AutofillManager;
-import android.view.contentcapture.ContentCaptureManager;
-import android.view.contentcapture.ContentCaptureSession;
-import android.view.contentcapture.MainContentCaptureSession;
import android.view.inputmethod.InputMethodManager;
import android.widget.Scroller;
@@ -224,21 +220,6 @@ public final class ViewRootImpl implements ViewParent,
*/
static final int MAX_TRACKBALL_DELAY = 250;
- /**
- * Initial value for {@link #mContentCaptureEnabled}.
- */
- private static final int CONTENT_CAPTURE_ENABLED_NOT_CHECKED = 0;
-
- /**
- * Value for {@link #mContentCaptureEnabled} when it was checked and set to {@code true}.
- */
- private static final int CONTENT_CAPTURE_ENABLED_TRUE = 1;
-
- /**
- * Value for {@link #mContentCaptureEnabled} when it was checked and set to {@code false}.
- */
- private static final int CONTENT_CAPTURE_ENABLED_FALSE = 2;
-
@UnsupportedAppUsage
static final ThreadLocal<HandlerActionQueue> sRunQueues = new ThreadLocal<HandlerActionQueue>();
@@ -435,10 +416,6 @@ public final class ViewRootImpl implements ViewParent,
boolean mLayoutRequested;
boolean mFirst;
- @Nullable
- int mContentCaptureEnabled = CONTENT_CAPTURE_ENABLED_NOT_CHECKED;
- boolean mPerformContentCapture;
-
boolean mReportNextDraw;
boolean mFullRedrawNeeded;
boolean mNewSurfaceNeeded;
@@ -637,7 +614,6 @@ public final class ViewRootImpl implements ViewParent,
mTransparentRegion = new Region();
mPreviousTransparentRegion = new Region();
mFirst = true; // true for the first time the view is added
- mPerformContentCapture = true; // also true for the first time the view is added
mAdded = false;
mAttachInfo = new View.AttachInfo(mWindowSession, mWindow, display, this, mHandler, this,
context);
@@ -2787,55 +2763,9 @@ public final class ViewRootImpl implements ViewParent,
}
}
- if (mAttachInfo.mContentCaptureEvents != null) {
- notifyContentCatpureEvents();
- }
-
mIsInTraversal = false;
}
- private void notifyContentCatpureEvents() {
- Trace.traceBegin(Trace.TRACE_TAG_VIEW, "notifyContentCaptureEvents");
- try {
- MainContentCaptureSession mainSession = mAttachInfo.mContentCaptureManager
- .getMainContentCaptureSession();
- for (int i = 0; i < mAttachInfo.mContentCaptureEvents.size(); i++) {
- int sessionId = mAttachInfo.mContentCaptureEvents.keyAt(i);
- mainSession.notifyViewTreeEvent(sessionId, /* started= */ true);
- ArrayList<Object> events = mAttachInfo.mContentCaptureEvents
- .valueAt(i);
- for_each_event: for (int j = 0; j < events.size(); j++) {
- Object event = events.get(j);
- if (event instanceof AutofillId) {
- mainSession.notifyViewDisappeared(sessionId, (AutofillId) event);
- } else if (event instanceof View) {
- View view = (View) event;
- ContentCaptureSession session = view.getContentCaptureSession();
- if (session == null) {
- Log.w(mTag, "no content capture session on view: " + view);
- continue for_each_event;
- }
- int actualId = session.getId();
- if (actualId != sessionId) {
- Log.w(mTag, "content capture session mismatch for view (" + view
- + "): was " + sessionId + " before, it's " + actualId + " now");
- continue for_each_event;
- }
- ViewStructure structure = session.newViewStructure(view);
- view.onProvideContentCaptureStructure(structure, /* flags= */ 0);
- session.notifyViewAppeared(structure);
- } else {
- Log.w(mTag, "invalid content capture event: " + event);
- }
- }
- mainSession.notifyViewTreeEvent(sessionId, /* started= */ false);
- }
- mAttachInfo.mContentCaptureEvents = null;
- } finally {
- Trace.traceEnd(Trace.TRACE_TAG_VIEW);
- }
- }
-
private void notifySurfaceDestroyed() {
mSurfaceHolder.ungetCallbacks();
SurfaceHolder.Callback[] callbacks = mSurfaceHolder.getCallbacks();
@@ -2966,13 +2896,6 @@ public final class ViewRootImpl implements ViewParent,
}
}
mFirstInputStage.onWindowFocusChanged(hasWindowFocus);
-
- // NOTE: there's no view visibility (appeared / disapparead) events when the windows focus
- // is lost, so we don't need to to force a flush - there might be other events such as
- // text changes, but these should be flushed independently.
- if (hasWindowFocus) {
- handleContentCaptureFlush();
- }
}
private void fireAccessibilityFocusEventIfHasFocusedNode() {
@@ -3539,86 +3462,6 @@ public final class ViewRootImpl implements ViewParent,
pendingDrawFinished();
}
}
- if (mPerformContentCapture) {
- performContentCaptureInitialReport();
- }
- }
-
- /**
- * Checks (and caches) if content capture is enabled for this context.
- */
- private boolean isContentCaptureEnabled() {
- switch (mContentCaptureEnabled) {
- case CONTENT_CAPTURE_ENABLED_TRUE:
- return true;
- case CONTENT_CAPTURE_ENABLED_FALSE:
- return false;
- case CONTENT_CAPTURE_ENABLED_NOT_CHECKED:
- final boolean reallyEnabled = isContentCaptureReallyEnabled();
- mContentCaptureEnabled = reallyEnabled ? CONTENT_CAPTURE_ENABLED_TRUE
- : CONTENT_CAPTURE_ENABLED_FALSE;
- return reallyEnabled;
- default:
- Log.w(TAG, "isContentCaptureEnabled(): invalid state " + mContentCaptureEnabled);
- return false;
- }
-
- }
-
- /**
- * Checks (without caching) if content capture is enabled for this context.
- */
- private boolean isContentCaptureReallyEnabled() {
- // First check if context supports it, so it saves a service lookup when it doesn't
- if (mContext.getContentCaptureOptions() == null) return false;
-
- final ContentCaptureManager ccm = mAttachInfo.getContentCaptureManager(mContext);
- // Then check if it's enabled in the contex itself.
- if (ccm == null || !ccm.isContentCaptureEnabled()) return false;
-
- return true;
- }
-
- private void performContentCaptureInitialReport() {
- mPerformContentCapture = false; // One-time offer!
- final View rootView = mView;
- if (DEBUG_CONTENT_CAPTURE) {
- Log.v(mTag, "performContentCaptureInitialReport() on " + rootView);
- }
- if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
- Trace.traceBegin(Trace.TRACE_TAG_VIEW, "dispatchContentCapture() for "
- + getClass().getSimpleName());
- }
- try {
- if (!isContentCaptureEnabled()) return;
-
- // Content capture is a go!
- rootView.dispatchInitialProvideContentCaptureStructure();
- } finally {
- Trace.traceEnd(Trace.TRACE_TAG_VIEW);
- }
- }
-
- private void handleContentCaptureFlush() {
- if (DEBUG_CONTENT_CAPTURE) {
- Log.v(mTag, "handleContentCaptureFlush()");
- }
- if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
- Trace.traceBegin(Trace.TRACE_TAG_VIEW, "flushContentCapture for "
- + getClass().getSimpleName());
- }
- try {
- if (!isContentCaptureEnabled()) return;
-
- final ContentCaptureManager ccm = mAttachInfo.mContentCaptureManager;
- if (ccm == null) {
- Log.w(TAG, "No ContentCapture on AttachInfo");
- return;
- }
- ccm.flush(ContentCaptureSession.FLUSH_REASON_VIEW_ROOT_ENTERED);
- } finally {
- Trace.traceEnd(Trace.TRACE_TAG_VIEW);
- }
}
private boolean draw(boolean fullRedrawNeeded) {
diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java
index 253935680cb8..7a6e2adfcaa4 100644
--- a/core/java/android/view/contentcapture/ContentCaptureManager.java
+++ b/core/java/android/view/contentcapture/ContentCaptureManager.java
@@ -191,8 +191,8 @@ import java.util.Set;
*
* <p>If your view provides its own virtual hierarchy (for example, if it's a browser that draws
* the HTML using {@link Canvas} or native libraries in a different render process), then the view
- * is also responsible to notify the session when the virtual elements appear and disappear - see
- * {@link View#onProvideContentCaptureStructure(ViewStructure, int)} for more info.
+ * is also responsible to notify the session when the virtual elements appear and disappear -
+ * see {@link ContentCaptureSession#newViewStructure(View)} for more info.
*/
@SystemService(Context.CONTENT_CAPTURE_MANAGER_SERVICE)
public final class ContentCaptureManager {
@@ -578,16 +578,15 @@ public final class ContentCaptureManager {
}
/**
- * Called by the app to request the content capture service to remove user-data associated with
- * some context.
+ * Called by the app to remove content capture data associated with some context.
*
- * @param request object specifying what user data should be removed.
+ * @param request object specifying what data should be removed.
*/
- public void removeUserData(@NonNull UserDataRemovalRequest request) {
+ public void removeData(@NonNull DataRemovalRequest request) {
Preconditions.checkNotNull(request);
try {
- mService.removeUserData(request);
+ mService.removeData(request);
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
diff --git a/core/java/android/view/contentcapture/ContentCaptureSession.java b/core/java/android/view/contentcapture/ContentCaptureSession.java
index 7761038f8af1..17a1fb405321 100644
--- a/core/java/android/view/contentcapture/ContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/ContentCaptureSession.java
@@ -356,10 +356,6 @@ public abstract class ContentCaptureSession implements AutoCloseable {
/**
* Notifies the Content Capture Service that a node has been added to the view structure.
*
- * <p>Typically called "manually" by views that handle their own virtual view hierarchy, or
- * automatically by the Android System for views that return {@code true} on
- * {@link View#onProvideContentCaptureStructure(ViewStructure, int)}.
- *
* @param node node that has been added.
*/
public final void notifyViewAppeared(@NonNull ViewStructure node) {
@@ -378,9 +374,6 @@ public abstract class ContentCaptureSession implements AutoCloseable {
/**
* Notifies the Content Capture Service that a node has been removed from the view structure.
*
- * <p>Typically called "manually" by views that handle their own virtual view hierarchy, or
- * automatically by the Android System for standard views.
- *
* @param id id of the node that has been removed.
*/
public final void notifyViewDisappeared(@NonNull AutofillId id) {
@@ -441,7 +434,46 @@ public abstract class ContentCaptureSession implements AutoCloseable {
/**
* Creates a {@link ViewStructure} for a "standard" view.
*
- * @hide
+ * <p>This method should be called after a visible view is laid out; the view then must populate
+ * the structure and pass it to {@link #notifyViewAppeared(ViewStructure)}.
+ *
+ * <b>Note: </b>views that manage a virtual structure under this view must populate just the
+ * node representing this view and return right away, then asynchronously report (not
+ * necessarily in the UI thread) when the children nodes appear, disappear or have their text
+ * changed by calling {@link ContentCaptureSession#notifyViewAppeared(ViewStructure)},
+ * {@link ContentCaptureSession#notifyViewDisappeared(AutofillId)}, and
+ * {@link ContentCaptureSession#notifyViewTextChanged(AutofillId, CharSequence)} respectively.
+ * The structure for the a child must be created using
+ * {@link ContentCaptureSession#newVirtualViewStructure(AutofillId, long)}, and the
+ * {@code autofillId} for a child can be obtained either through
+ * {@code childStructure.getAutofillId()} or
+ * {@link ContentCaptureSession#newAutofillId(AutofillId, long)}.
+ *
+ * <p>When the virtual view hierarchy represents a web page, you should also:
+ *
+ * <ul>
+ * <li>Call {@link ContentCaptureManager#getContentCaptureConditions()} to infer content capture
+ * events should be generate for that URL.
+ * <li>Create a new {@link ContentCaptureSession} child for every HTML element that renders a
+ * new URL (like an {@code IFRAME}) and use that session to notify events from that subtree.
+ * </ul>
+ *
+ * <p><b>Note: </b>the following methods of the {@code structure} will be ignored:
+ * <ul>
+ * <li>{@link ViewStructure#setChildCount(int)}
+ * <li>{@link ViewStructure#addChildCount(int)}
+ * <li>{@link ViewStructure#getChildCount()}
+ * <li>{@link ViewStructure#newChild(int)}
+ * <li>{@link ViewStructure#asyncNewChild(int)}
+ * <li>{@link ViewStructure#asyncCommit()}
+ * <li>{@link ViewStructure#setWebDomain(String)}
+ * <li>{@link ViewStructure#newHtmlInfoBuilder(String)}
+ * <li>{@link ViewStructure#setHtmlInfo(android.view.ViewStructure.HtmlInfo)}
+ * <li>{@link ViewStructure#setDataIsSensitive(boolean)}
+ * <li>{@link ViewStructure#setAlpha(float)}
+ * <li>{@link ViewStructure#setElevation(float)}
+ * <li>{@link ViewStructure#setTransformation(android.graphics.Matrix)}
+ * </ul>
*/
@NonNull
public final ViewStructure newViewStructure(@NonNull View view) {
diff --git a/core/java/android/view/contentcapture/UserDataRemovalRequest.aidl b/core/java/android/view/contentcapture/DataRemovalRequest.aidl
index fbe47e08ea7c..c89d222d159f 100644
--- a/core/java/android/view/contentcapture/UserDataRemovalRequest.aidl
+++ b/core/java/android/view/contentcapture/DataRemovalRequest.aidl
@@ -16,4 +16,4 @@
package android.view.contentcapture;
-parcelable UserDataRemovalRequest;
+parcelable DataRemovalRequest;
diff --git a/core/java/android/view/contentcapture/UserDataRemovalRequest.java b/core/java/android/view/contentcapture/DataRemovalRequest.java
index 3e1e4abaa84c..3792846bea71 100644
--- a/core/java/android/view/contentcapture/UserDataRemovalRequest.java
+++ b/core/java/android/view/contentcapture/DataRemovalRequest.java
@@ -31,14 +31,12 @@ import java.util.ArrayList;
import java.util.List;
/**
- * Class used by apps to request the Content Capture service to remove user-data associated with
- * some context.
+ * Class used by apps to remove content capture data associated with {@link LocusId LocusIds}.
*/
-public final class UserDataRemovalRequest implements Parcelable {
+public final class DataRemovalRequest implements Parcelable {
/**
- * When set, service should use the {@link LocusId#getId()} as prefix for the data to be
- * removed.
+ * When set, the {@link LocusId#getId()} is the prefix for the data to be removed.
*/
public static final int FLAG_IS_PREFIX = 0x1;
@@ -54,7 +52,7 @@ public final class UserDataRemovalRequest implements Parcelable {
private final boolean mForEverything;
private ArrayList<LocusIdRequest> mLocusIdRequests;
- private UserDataRemovalRequest(@NonNull Builder builder) {
+ private DataRemovalRequest(@NonNull Builder builder) {
mPackageName = ActivityThread.currentActivityThread().getApplication().getPackageName();
mForEverything = builder.mForEverything;
if (builder.mLocusIds != null) {
@@ -67,7 +65,7 @@ public final class UserDataRemovalRequest implements Parcelable {
}
}
- private UserDataRemovalRequest(@NonNull Parcel parcel) {
+ private DataRemovalRequest(@NonNull Parcel parcel) {
mPackageName = parcel.readString();
mForEverything = parcel.readBoolean();
if (!mForEverything) {
@@ -89,7 +87,7 @@ public final class UserDataRemovalRequest implements Parcelable {
}
/**
- * Checks if app is requesting to remove all user data associated with its package.
+ * Checks if app is requesting to remove content capture data associated with its package.
*/
public boolean isForEverything() {
return mForEverything;
@@ -104,7 +102,7 @@ public final class UserDataRemovalRequest implements Parcelable {
}
/**
- * Builder for {@link UserDataRemovalRequest} objects.
+ * Builder for {@link DataRemovalRequest} objects.
*/
public static final class Builder {
@@ -115,7 +113,7 @@ public final class UserDataRemovalRequest implements Parcelable {
private boolean mDestroyed;
/**
- * Requests servive to remove all user data associated with the app's package.
+ * Requests to remove all content capture data associated with the app's package.
*
* @return this builder
*/
@@ -132,7 +130,7 @@ public final class UserDataRemovalRequest implements Parcelable {
* Request service to remove data associated with a given {@link LocusId}.
*
* @param locusId the {@link LocusId} being requested to be removed.
- * @param flags either {@link UserDataRemovalRequest#FLAG_IS_PREFIX} or {@code 0}
+ * @param flags either {@link DataRemovalRequest#FLAG_IS_PREFIX} or {@code 0}
*
* @return this builder
*/
@@ -154,17 +152,17 @@ public final class UserDataRemovalRequest implements Parcelable {
}
/**
- * Builds the {@link UserDataRemovalRequest}.
+ * Builds the {@link DataRemovalRequest}.
*/
@NonNull
- public UserDataRemovalRequest build() {
+ public DataRemovalRequest build() {
throwIfDestroyed();
Preconditions.checkState(mForEverything || mLocusIds != null,
"must call either #forEverything() or add one #addLocusId()");
mDestroyed = true;
- return new UserDataRemovalRequest(this);
+ return new DataRemovalRequest(this);
}
private void throwIfDestroyed() {
@@ -192,19 +190,19 @@ public final class UserDataRemovalRequest implements Parcelable {
}
}
- public static final @android.annotation.NonNull Parcelable.Creator<UserDataRemovalRequest> CREATOR =
- new Parcelable.Creator<UserDataRemovalRequest>() {
+ public static final @android.annotation.NonNull Parcelable.Creator<DataRemovalRequest> CREATOR =
+ new Parcelable.Creator<DataRemovalRequest>() {
@Override
@NonNull
- public UserDataRemovalRequest createFromParcel(Parcel parcel) {
- return new UserDataRemovalRequest(parcel);
+ public DataRemovalRequest createFromParcel(Parcel parcel) {
+ return new DataRemovalRequest(parcel);
}
@Override
@NonNull
- public UserDataRemovalRequest[] newArray(int size) {
- return new UserDataRemovalRequest[size];
+ public DataRemovalRequest[] newArray(int size) {
+ return new DataRemovalRequest[size];
}
};
@@ -231,7 +229,7 @@ public final class UserDataRemovalRequest implements Parcelable {
/**
* Gets the flags associates with request.
*
- * @return either {@link UserDataRemovalRequest#FLAG_IS_PREFIX} or {@code 0}.
+ * @return either {@link DataRemovalRequest#FLAG_IS_PREFIX} or {@code 0}.
*/
@NonNull
public @Flags int getFlags() {
diff --git a/core/java/android/view/contentcapture/IContentCaptureManager.aidl b/core/java/android/view/contentcapture/IContentCaptureManager.aidl
index 7335073c59e0..ced941744387 100644
--- a/core/java/android/view/contentcapture/IContentCaptureManager.aidl
+++ b/core/java/android/view/contentcapture/IContentCaptureManager.aidl
@@ -19,7 +19,7 @@ package android.view.contentcapture;
import android.content.ComponentName;
import android.view.contentcapture.ContentCaptureContext;
import android.view.contentcapture.ContentCaptureEvent;
-import android.view.contentcapture.UserDataRemovalRequest;
+import android.view.contentcapture.DataRemovalRequest;
import android.os.IBinder;
import com.android.internal.os.IResultReceiver;
@@ -59,9 +59,9 @@ oneway interface IContentCaptureManager {
void getServiceComponentName(in IResultReceiver result);
/**
- * Requests the removal of user data for the calling user.
+ * Requests the removal of content capture data for the calling user.
*/
- void removeUserData(in UserDataRemovalRequest request);
+ void removeData(in DataRemovalRequest request);
/**
* Returns whether the content capture feature is enabled for the calling user.
diff --git a/core/java/android/view/textclassifier/ConversationActions.java b/core/java/android/view/textclassifier/ConversationActions.java
index b408129231e7..f2fa67d58839 100644
--- a/core/java/android/view/textclassifier/ConversationActions.java
+++ b/core/java/android/view/textclassifier/ConversationActions.java
@@ -316,16 +316,20 @@ public final class ConversationActions implements Parcelable {
private final List<String> mHints;
@Nullable
private String mCallingPackageName;
+ @NonNull
+ private Bundle mExtras;
private Request(
@NonNull List<Message> conversation,
@NonNull TextClassifier.EntityConfig typeConfig,
int maxSuggestions,
- @Nullable @Hint List<String> hints) {
+ @Nullable @Hint List<String> hints,
+ @NonNull Bundle extras) {
mConversation = Preconditions.checkNotNull(conversation);
mTypeConfig = Preconditions.checkNotNull(typeConfig);
mMaxSuggestions = maxSuggestions;
mHints = hints;
+ mExtras = extras;
}
private static Request readFromParcel(Parcel in) {
@@ -336,12 +340,13 @@ public final class ConversationActions implements Parcelable {
List<String> hints = new ArrayList<>();
in.readStringList(hints);
String callingPackageName = in.readString();
-
+ Bundle extras = in.readBundle();
Request request = new Request(
conversation,
typeConfig,
maxSuggestions,
- hints);
+ hints,
+ extras);
request.setCallingPackageName(callingPackageName);
return request;
}
@@ -353,6 +358,7 @@ public final class ConversationActions implements Parcelable {
parcel.writeInt(mMaxSuggestions);
parcel.writeStringList(mHints);
parcel.writeString(mCallingPackageName);
+ parcel.writeBundle(mExtras);
}
@Override
@@ -421,6 +427,16 @@ public final class ConversationActions implements Parcelable {
return mCallingPackageName;
}
+ /**
+ * Returns the extended data related to this request.
+ *
+ * <p><b>NOTE: </b>Do not modify this bundle.
+ */
+ @NonNull
+ public Bundle getExtras() {
+ return mExtras;
+ }
+
/** Builder object to construct the {@link Request} object. */
public static final class Builder {
@NonNull
@@ -431,6 +447,8 @@ public final class ConversationActions implements Parcelable {
@Nullable
@Hint
private List<String> mHints;
+ @Nullable
+ private Bundle mExtras;
/**
* Constructs a builder.
@@ -469,6 +487,13 @@ public final class ConversationActions implements Parcelable {
return this;
}
+ /** Sets a set of extended data to the request. */
+ @NonNull
+ public Builder setExtras(@Nullable Bundle bundle) {
+ mExtras = bundle;
+ return this;
+ }
+
/** Builds the {@link Request} object. */
@NonNull
public Request build() {
@@ -480,7 +505,8 @@ public final class ConversationActions implements Parcelable {
mMaxSuggestions,
mHints == null
? Collections.emptyList()
- : Collections.unmodifiableList(mHints));
+ : Collections.unmodifiableList(mHints),
+ mExtras == null ? Bundle.EMPTY : mExtras);
}
}
}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 26dba45666fc..137b67c6e63e 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -413,9 +413,6 @@ public class WebView extends AbsoluteLayout
if (getImportantForAutofill() == IMPORTANT_FOR_AUTOFILL_AUTO) {
setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_YES);
}
- if (getImportantForContentCapture() == IMPORTANT_FOR_CONTENT_CAPTURE_AUTO) {
- setImportantForContentCapture(IMPORTANT_FOR_CONTENT_CAPTURE_YES);
- }
if (context == null) {
throw new IllegalArgumentException("Invalid context argument");
@@ -2799,11 +2796,6 @@ public class WebView extends AbsoluteLayout
}
@Override
- public void onProvideContentCaptureStructure(ViewStructure structure, int flags) {
- mProvider.getViewDelegate().onProvideContentCaptureStructure(structure, flags);
- }
-
- @Override
public void autofill(SparseArray<AutofillValue>values) {
mProvider.getViewDelegate().autofill(values);
}
diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java
index c55f7d654548..c3bb9a0201d0 100644
--- a/core/java/android/widget/AdapterView.java
+++ b/core/java/android/widget/AdapterView.java
@@ -1318,8 +1318,7 @@ public abstract class AdapterView<T extends Adapter> extends ViewGroup {
@ViewStructureType int viewFor, int flags) {
super.onProvideStructure(structure, viewFor, flags);
- if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
- || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
+ if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) {
final Adapter adapter = getAdapter();
if (adapter == null) return;
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index a961783dab7c..618b05f8cb00 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -161,8 +161,6 @@ import android.view.accessibility.AccessibilityNodeInfo;
import android.view.animation.AnimationUtils;
import android.view.autofill.AutofillManager;
import android.view.autofill.AutofillValue;
-import android.view.contentcapture.ContentCaptureManager;
-import android.view.contentcapture.ContentCaptureSession;
import android.view.inputmethod.BaseInputConnection;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.CorrectionInfo;
@@ -978,9 +976,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if (getImportantForAutofill() == IMPORTANT_FOR_AUTOFILL_AUTO) {
setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_YES);
}
- if (getImportantForContentCapture() == IMPORTANT_FOR_CONTENT_CAPTURE_AUTO) {
- setImportantForContentCapture(IMPORTANT_FOR_CONTENT_CAPTURE_YES);
- }
setTextInternal("");
@@ -10520,8 +10515,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
/**
- * Notify managers (such as {@link AutofillManager} and {@link ContentCaptureManager}) that are
- * interested on text changes.
+ * Notify managers (such as {@link AutofillManager}) that are interested in text changes.
*/
private void notifyListeningManagersAfterTextChanged() {
@@ -10537,22 +10531,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
afm.notifyValueChanged(TextView.this);
}
}
-
- // TODO(b/121045053): should use a flag / boolean to keep status of SHOWN / HIDDEN instead
- // of using isLaidout(), so it's not called in cases where it's laid out but a
- // notifyAppeared was not sent.
-
- // ContentCapture
- if (isLaidOut() && isImportantForContentCapture() && isTextEditable()) {
- final ContentCaptureManager cm = mContext.getSystemService(ContentCaptureManager.class);
- if (cm != null && cm.isContentCaptureEnabled()) {
- final ContentCaptureSession session = getContentCaptureSession();
- if (session != null) {
- // TODO(b/111276913): pass flags when edited by user / add CTS test
- session.notifyViewTextChanged(getAutofillId(), getText());
- }
- }
- }
}
private boolean isAutofillable() {
@@ -11386,8 +11364,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
final boolean isPassword = hasPasswordTransformationMethod()
|| isPasswordInputType(getInputType());
- if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
- || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
+ if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) {
if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) {
structure.setDataIsSensitive(!mTextSetFromXmlOrResourceId);
}
@@ -11403,12 +11380,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
}
- if (!isPassword || viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
- || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
+ if (!isPassword || viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) {
if (mLayout == null) {
- if (viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
- Log.w(LOG_TAG, "onProvideContentCaptureStructure(): calling assumeLayout()");
- }
assumeLayout();
}
Layout layout = mLayout;
@@ -11496,8 +11469,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
}
- if (viewFor == VIEW_STRUCTURE_FOR_ASSIST
- || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
+ if (viewFor == VIEW_STRUCTURE_FOR_ASSIST) {
// Extract style information that applies to the TextView as a whole.
int style = 0;
int typefaceStyle = getTypefaceStyle();
@@ -11525,8 +11497,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
structure.setTextStyle(getTextSize(), getCurrentTextColor(),
AssistStructure.ViewNode.TEXT_COLOR_UNDEFINED /* bgColor */, style);
}
- if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
- || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
+ if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) {
structure.setMinTextEms(getMinEms());
structure.setMaxTextEms(getMaxEms());
int maxLength = -1;
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 4d4fe0397791..1597ab735680 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -24,6 +24,7 @@ import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.annotation.IntDef;
+import android.annotation.Nullable;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.prediction.AppPredictionContext;
@@ -131,6 +132,7 @@ import java.util.List;
public class ChooserActivity extends ResolverActivity {
private static final String TAG = "ChooserActivity";
+
/**
* Boolean extra to change the following behavior: Normally, ChooserActivity finishes itself
* in onStop when launched in a new task. If this extra is set to true, we do not finish
@@ -141,7 +143,6 @@ public class ChooserActivity extends ResolverActivity {
private static final boolean DEBUG = false;
-
/**
* If {@link #USE_SHORTCUT_MANAGER_FOR_DIRECT_TARGETS} and this is set to true,
* {@link AppPredictionManager} will be queried for direct share targets.
@@ -433,18 +434,8 @@ public class ChooserActivity extends ResolverActivity {
.addTaggedData(MetricsEvent.FIELD_SHARESHEET_MIMETYPE, target.getType())
.addTaggedData(MetricsEvent.FIELD_TIME_TO_APP_TARGETS, systemCost));
- if (USE_PREDICTION_MANAGER_FOR_DIRECT_TARGETS) {
- final IntentFilter filter = getTargetIntentFilter();
- Bundle extras = new Bundle();
- extras.putParcelable(APP_PREDICTION_INTENT_FILTER_KEY, filter);
- AppPredictionManager appPredictionManager =
- getSystemService(AppPredictionManager.class);
- mAppPredictor = appPredictionManager.createAppPredictionSession(
- new AppPredictionContext.Builder(this)
- .setPredictedTargetCount(APP_PREDICTION_SHARE_TARGET_QUERY_PACKAGE_LIMIT)
- .setUiSurface(APP_PREDICTION_SHARE_UI_SURFACE)
- .setExtras(extras)
- .build());
+ AppPredictor appPredictor = getAppPredictorForDirectShareIfEnabled();
+ if (appPredictor != null) {
mAppPredictorCallback = resultList -> {
if (isFinishing() || isDestroyed()) {
return;
@@ -467,8 +458,10 @@ public class ChooserActivity extends ResolverActivity {
appTarget.getPackageName(), appTarget.getClassName())));
}
sendShareShortcutInfoList(shareShortcutInfos, driList);
+ sendShortcutManagerShareTargetResultCompleted();
};
- mAppPredictor.registerPredictionUpdates(this.getMainExecutor(), mAppPredictorCallback);
+ appPredictor
+ .registerPredictionUpdates(this.getMainExecutor(), mAppPredictorCallback);
}
mChooserRowLayer = getResources().getDrawable(R.drawable.chooser_row_layer_list, null);
@@ -872,7 +865,7 @@ public class ChooserActivity extends ResolverActivity {
mChooserHandler.removeMessages(LIST_VIEW_UPDATE_MESSAGE);
mChooserHandler.removeMessages(CHOOSER_TARGET_SERVICE_WATCHDOG_TIMEOUT);
mChooserHandler.removeMessages(CHOOSER_TARGET_SERVICE_RESULT);
- if (USE_PREDICTION_MANAGER_FOR_DIRECT_TARGETS) {
+ if (mAppPredictor != null) {
mAppPredictor.unregisterPredictionUpdates(mAppPredictorCallback);
mAppPredictor.destroy();
}
@@ -1205,10 +1198,12 @@ public class ChooserActivity extends ResolverActivity {
}
private void queryDirectShareTargets(ChooserListAdapter adapter) {
- if (USE_PREDICTION_MANAGER_FOR_DIRECT_TARGETS) {
- mAppPredictor.requestPredictionUpdate();
+ AppPredictor appPredictor = getAppPredictorForDirectShareIfEnabled();
+ if (appPredictor != null) {
+ appPredictor.requestPredictionUpdate();
return;
}
+ // Default to just querying ShortcutManager if AppPredictor not present.
final IntentFilter filter = getTargetIntentFilter();
if (filter == null) {
return;
@@ -1248,12 +1243,16 @@ public class ChooserActivity extends ResolverActivity {
}
if (resultMessageSent) {
- final Message msg = Message.obtain();
- msg.what = SHORTCUT_MANAGER_SHARE_TARGET_RESULT_COMPLETED;
- mChooserHandler.sendMessage(msg);
+ sendShortcutManagerShareTargetResultCompleted();
}
}
+ private void sendShortcutManagerShareTargetResultCompleted() {
+ final Message msg = Message.obtain();
+ msg.what = SHORTCUT_MANAGER_SHARE_TARGET_RESULT_COMPLETED;
+ mChooserHandler.sendMessage(msg);
+ }
+
private ChooserTarget convertToChooserTarget(ShortcutManager.ShareShortcutInfo shareShortcut) {
ShortcutInfo shortcutInfo = shareShortcut.getShortcutInfo();
Bundle extras = new Bundle();
@@ -1309,9 +1308,7 @@ public class ChooserActivity extends ResolverActivity {
void updateModelAndChooserCounts(TargetInfo info) {
if (info != null) {
- if (USE_PREDICTION_MANAGER_FOR_DIRECT_TARGETS) {
- sendClickToAppPredictor(info);
- }
+ sendClickToAppPredictor(info);
final ResolveInfo ri = info.getResolveInfo();
Intent targetIntent = getTargetIntent();
if (ri != null && ri.activityInfo != null && targetIntent != null) {
@@ -1332,6 +1329,10 @@ public class ChooserActivity extends ResolverActivity {
}
private void sendClickToAppPredictor(TargetInfo targetInfo) {
+ AppPredictor appPredictor = getAppPredictorForDirectShareIfEnabled();
+ if (appPredictor == null) {
+ return;
+ }
if (!(targetInfo instanceof ChooserTargetInfo)) {
return;
}
@@ -1345,15 +1346,44 @@ public class ChooserActivity extends ResolverActivity {
if (shortcutId == null) {
return;
}
- mAppPredictor.notifyAppTargetEvent(
+ appPredictor.notifyAppTargetEvent(
new AppTargetEvent.Builder(
- new AppTarget.Builder(new AppTargetId(shortcutId))
- .setTarget(componentName.getPackageName(), getUser())
+ // TODO(b/124404997) Send full shortcut info, not just Id with AppTargetId.
+ new AppTarget.Builder(new AppTargetId(shortcutId),
+ componentName.getPackageName(), getUser())
.setClassName(componentName.getClassName())
.build(),
- AppTargetEvent.ACTION_LAUNCH
- ).setLaunchLocation(LAUNCH_LOCATON_DIRECT_SHARE)
- .build());
+ AppTargetEvent.ACTION_LAUNCH)
+ .setLaunchLocation(LAUNCH_LOCATON_DIRECT_SHARE)
+ .build());
+ }
+
+ @Nullable
+ private AppPredictor getAppPredictor() {
+ if (mAppPredictor == null
+ && getPackageManager().getAppPredictionServicePackageName() != null) {
+ final IntentFilter filter = getTargetIntentFilter();
+ Bundle extras = new Bundle();
+ extras.putParcelable(APP_PREDICTION_INTENT_FILTER_KEY, filter);
+ AppPredictionContext appPredictionContext = new AppPredictionContext.Builder(this)
+ .setUiSurface(APP_PREDICTION_SHARE_UI_SURFACE)
+ .setPredictedTargetCount(APP_PREDICTION_SHARE_TARGET_QUERY_PACKAGE_LIMIT)
+ .setExtras(extras)
+ .build();
+ AppPredictionManager appPredictionManager
+ = getSystemService(AppPredictionManager.class);
+ mAppPredictor = appPredictionManager.createAppPredictionSession(appPredictionContext);
+ }
+ return mAppPredictor;
+ }
+
+ /**
+ * This will return an app predictor if it is enabled for direct share sorting
+ * and if one exists. Otherwise, it returns null.
+ */
+ @Nullable
+ private AppPredictor getAppPredictorForDirectShareIfEnabled() {
+ return USE_PREDICTION_MANAGER_FOR_DIRECT_TARGETS ? getAppPredictor() : null;
}
void onRefinementResult(TargetInfo selectedTarget, Intent matchingIntent) {
@@ -2014,7 +2044,8 @@ public class ChooserActivity extends ResolverActivity {
}
}
- if (USE_SHORTCUT_MANAGER_FOR_DIRECT_TARGETS) {
+ if (USE_SHORTCUT_MANAGER_FOR_DIRECT_TARGETS
+ || USE_PREDICTION_MANAGER_FOR_DIRECT_TARGETS) {
if (DEBUG) {
Log.d(TAG, "querying direct share targets from ShortcutManager");
}
@@ -2242,7 +2273,7 @@ public class ChooserActivity extends ResolverActivity {
return CALLER_TARGET_SCORE_BOOST;
}
- if (USE_PREDICTION_MANAGER_FOR_DIRECT_TARGETS) {
+ if (getAppPredictorForDirectShareIfEnabled() != null) {
return SHORTCUT_TARGET_SCORE_BOOST;
}
diff --git a/core/java/com/android/internal/inputmethod/IMultiClientInputMethodPrivilegedOperations.aidl b/core/java/com/android/internal/inputmethod/IMultiClientInputMethodPrivilegedOperations.aidl
index 69d9ccc9825b..b5f2147784c0 100644
--- a/core/java/com/android/internal/inputmethod/IMultiClientInputMethodPrivilegedOperations.aidl
+++ b/core/java/com/android/internal/inputmethod/IMultiClientInputMethodPrivilegedOperations.aidl
@@ -31,4 +31,5 @@ interface IMultiClientInputMethodPrivilegedOperations {
in IMultiClientInputMethodSession multiClientSession, in InputChannel writeChannel);
void reportImeWindowTarget(int clientId, int targetWindowHandle, in IBinder imeWindowToken);
boolean isUidAllowedOnDisplay(int displayId, int uid);
+ void setActive(int clientId, boolean active);
}
diff --git a/core/java/com/android/internal/inputmethod/MultiClientInputMethodPrivilegedOperations.java b/core/java/com/android/internal/inputmethod/MultiClientInputMethodPrivilegedOperations.java
index 922011707c4a..1cf68872e2cf 100644
--- a/core/java/com/android/internal/inputmethod/MultiClientInputMethodPrivilegedOperations.java
+++ b/core/java/com/android/internal/inputmethod/MultiClientInputMethodPrivilegedOperations.java
@@ -212,4 +212,21 @@ public class MultiClientInputMethodPrivilegedOperations {
}
}
+ /**
+ * Calls {@link IMultiClientInputMethodPrivilegedOperations#setActive(int, boolean)}.
+ * @param clientId client ID to be set active/inactive
+ * @param active {@code true} set set active.
+ */
+ @AnyThread
+ public void setActive(int clientId, boolean active) {
+ final IMultiClientInputMethodPrivilegedOperations ops = mOps.getAndWarnIfNull();
+ if (ops == null) {
+ return;
+ }
+ try {
+ ops.setActive(clientId, active);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/core/jni/android_nio_utils.cpp b/core/jni/android_nio_utils.cpp
index 19a1c7212fae..a62dd7c4048f 100644
--- a/core/jni/android_nio_utils.cpp
+++ b/core/jni/android_nio_utils.cpp
@@ -18,42 +18,51 @@
#include "core_jni_helpers.h"
-void* android::nio_getPointer(JNIEnv *_env, jobject buffer, jarray *array) {
- assert(array);
+namespace {
+void* getPointer(JNIEnv *_env, jobject buffer, jarray *array, void** elements) {
+ assert(array);
jint position;
jint limit;
jint elementSizeShift;
jlong pointer = jniGetNioBufferFields(_env, buffer, &position, &limit, &elementSizeShift);
if (pointer != 0L) {
+ *array = nullptr;
+ *elements = nullptr;
pointer += position << elementSizeShift;
return reinterpret_cast<void*>(pointer);
}
-
jint offset = jniGetNioBufferBaseArrayOffset(_env, buffer);
*array = jniGetNioBufferBaseArray(_env, buffer);
- void * data = _env->GetPrimitiveArrayCritical(*array, (jboolean *) 0);
- return reinterpret_cast<void*>(reinterpret_cast<char*>(data) + offset);
+ *elements = _env->GetPrimitiveArrayCritical(*array, (jboolean *) 0);
+ return reinterpret_cast<void*>(reinterpret_cast<char*>(*elements) + offset);
}
+void releasePointer(JNIEnv *_env, jarray array, void *elements, jboolean commit) {
+ _env->ReleasePrimitiveArrayCritical(array, elements, commit ? 0 : JNI_ABORT);
+}
+
+} // namespace
+
+void* android::nio_getPointer(JNIEnv *_env, jobject buffer, jarray *array) {
+ void* elements;
+ return getPointer(_env, buffer, array, &elements);
+}
-void android::nio_releasePointer(JNIEnv *_env, jarray array, void *data,
- jboolean commit) {
- _env->ReleasePrimitiveArrayCritical(array, data,
- commit ? 0 : JNI_ABORT);
+void android::nio_releasePointer(JNIEnv *_env, jarray array, void *data, jboolean commit) {
+ releasePointer(_env, array, data, commit);
}
///////////////////////////////////////////////////////////////////////////////
-android::AutoBufferPointer::AutoBufferPointer(JNIEnv* env, jobject nioBuffer,
- jboolean commit) {
+android::AutoBufferPointer::AutoBufferPointer(JNIEnv* env, jobject nioBuffer, jboolean commit) {
fEnv = env;
fCommit = commit;
- fPointer = android::nio_getPointer(env, nioBuffer, &fArray);
+ fPointer = getPointer(env, nioBuffer, &fArray, &fElements);
}
android::AutoBufferPointer::~AutoBufferPointer() {
- if (NULL != fArray) {
- android::nio_releasePointer(fEnv, fArray, fPointer, fCommit);
+ if (nullptr != fArray) {
+ releasePointer(fEnv, fArray, fElements, fCommit);
}
}
diff --git a/core/jni/android_nio_utils.h b/core/jni/android_nio_utils.h
index c634cb917719..7c9acd2638da 100644
--- a/core/jni/android_nio_utils.h
+++ b/core/jni/android_nio_utils.h
@@ -20,7 +20,7 @@
#include <android_runtime/AndroidRuntime.h>
namespace android {
-
+
/**
* Given an nio.Buffer, return a pointer to it, beginning at its current
* position. The returned pointer is only valid for the current JNI stack-frame.
@@ -63,9 +63,10 @@ public:
private:
JNIEnv* fEnv;
- void* fPointer;
- jarray fArray;
- jboolean fCommit;
+ void* fPointer; // pointer to current buffer position.
+ void* fElements; // pointer to array element 0 (may be directly in fArray or a copy).
+ jarray fArray; // pointer to array on managed heap.
+ jboolean fCommit; // commit data to source if required (when fElements is a copy of fArray).
};
} /* namespace android */
diff --git a/core/proto/android/stats/devicepolicy/device_policy_enums.proto b/core/proto/android/stats/devicepolicy/device_policy_enums.proto
index 589a6a71d5fd..0db74243222c 100644
--- a/core/proto/android/stats/devicepolicy/device_policy_enums.proto
+++ b/core/proto/android/stats/devicepolicy/device_policy_enums.proto
@@ -145,4 +145,8 @@ enum EventId {
ESTABLISH_VPN = 118;
SET_NETWORK_LOGGING_ENABLED = 119;
RETRIEVE_NETWORK_LOGS = 120;
+ PROVISIONING_PREPARE_TOTAL_TIME_MS = 121;
+ PROVISIONING_PREPARE_STARTED = 122;
+ PROVISIONING_PREPARE_COMPLETED = 123;
+ PROVISIONING_FLOW_TYPE = 124;
}
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index ed8f2c196b72..ab9a298f3060 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2485,24 +2485,7 @@
<flag name="noExcludeDescendants" value="0x8" />
</attr>
- <!-- Hints the Android System whether the view node associated with this View should be
- use for content capture purposes. -->
- <attr name="importantForContentCapture">
- <!-- Let the Android System use its heuristics to determine if the view is important for content capture. -->
- <flag name="auto" value="0" />
- <!-- Hint the Android System that this view is important for content capture,
- and its children (if any) will be traversed.. -->
- <flag name="yes" value="0x1" />
- <!-- Hint the Android System that this view is *not* important for content capture,
- but its children (if any) will be traversed.. -->
- <flag name="no" value="0x2" />
- <!-- Hint the Android System that this view is important for content capture,
- but its children (if any) will not be traversed. -->
- <flag name="yesExcludeDescendants" value="0x4" />
- <!-- Hint the Android System that this view is *not* important for content capture,
- and its children (if any) will not be traversed. -->
- <flag name="noExcludeDescendants" value="0x8" />
- </attr>
+ <attr name="__removed6" />
<!-- Boolean that controls whether a view can take focus while in touch mode.
If this is true for a view, that view can gain focus when clicked on, and can keep
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index edcc0572cb2e..526818949b3d 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -745,10 +745,6 @@
<!-- XXXXXX END OF RESOURCES USING WRONG NAMING CONVENTION -->
- <!-- If this is true, notification effects will be played by the notification server.
- When false, car notification effects will be handled elsewhere. -->
- <bool name="config_enableServerNotificationEffectsForAutomotive">false</bool>
-
<!-- If this is true, the screen will come on when you unplug usb/power/whatever. -->
<bool name="config_unplugTurnsOnScreen">false</bool>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 9a8c754cf197..b7d61c8f8d39 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2922,7 +2922,7 @@
<public name="settingsSliceUri" />
<public name="shell" />
<public name="interactiveUiTimeout" />
- <public name="importantForContentCapture" />
+ <public name="__removed6" />
<public name="supportsMultipleDisplays" />
<public name="useAppZygote" />
<public name="__removed1" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index f8a2ac9f3e18..4bd2cc758cbb 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1521,10 +1521,10 @@
<string name="face_acquired_too_high">Move phone higher.</string>
<!-- Message shown during face acquisition when the user is too low relatively to sensor [CHAR LIMIT=50] -->
<string name="face_acquired_too_low">Move phone lower.</string>
- <!-- Message shown during face acquisition when the user is too right relatively to sensor [CHAR LIMIT=50] -->
- <string name="face_acquired_too_right">Move phone to the right.</string>
- <!-- Message shown during face acquisition when the user is too left relatively to sensor [CHAR LIMIT=50] -->
- <string name="face_acquired_too_left">Move phone to the left.</string>
+ <!-- Message shown during face acquisition when only the right part of the user's face was detected [CHAR LIMIT=50] -->
+ <string name="face_acquired_too_right">Move phone to the left.</string>
+ <!-- Message shown during face acquisition when only the left part of the user's face was detected [CHAR LIMIT=50] -->
+ <string name="face_acquired_too_left">Move phone to the right.</string>
<!-- Message shown during face acquisition when the user is not front facing the sensor [CHAR LIMIT=50] -->
<string name="face_acquired_poor_gaze">Look at the screen with your eyes open.</string>
<!-- Message shown during face acquisition when the user is not detected [CHAR LIMIT=50] -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index da2f89083fef..94b5da6baa07 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1910,7 +1910,6 @@
<java-symbol type="array" name="config_testLocationProviders" />
<java-symbol type="array" name="config_defaultNotificationVibePattern" />
<java-symbol type="array" name="config_notificationFallbackVibePattern" />
- <java-symbol type="bool" name="config_enableServerNotificationEffectsForAutomotive" />
<java-symbol type="bool" name="config_useAttentionLight" />
<java-symbol type="bool" name="config_adaptive_sleep_available" />
<java-symbol type="bool" name="config_animateScreenLights" />
diff --git a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
index 9cb34895dea4..711eaa7edc2a 100644
--- a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
+++ b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
@@ -38,6 +38,7 @@ import android.content.res.Configuration;
import android.os.IBinder;
import android.util.MergedConfiguration;
import android.view.Display;
+import android.view.View;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.MediumTest;
@@ -153,6 +154,34 @@ public class ActivityThreadTest {
}
@Test
+ public void testHandleActivity_assetsChanged() {
+ final TestActivity activity = mActivityTestRule.launchActivity(new Intent());
+
+ final IBinder[] token = new IBinder[1];
+ final View[] decorView = new View[1];
+
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+ final ActivityThread activityThread = activity.getActivityThread();
+
+ token[0] = activity.getActivityToken();
+ decorView[0] = activity.getWindow().getDecorView();
+
+ // Relaunches all activities
+ activityThread.handleApplicationInfoChanged(activity.getApplicationInfo());
+ });
+
+ final View[] newDecorView = new View[1];
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+ final ActivityThread activityThread = activity.getActivityThread();
+
+ final Activity newActivity = activityThread.getActivity(token[0]);
+ newDecorView[0] = activity.getWindow().getDecorView();
+ });
+
+ assertEquals("Window must be preserved", decorView[0], newDecorView[0]);
+ }
+
+ @Test
public void testHandleActivityConfigurationChanged_DropStaleConfigurations() {
final TestActivity activity = mActivityTestRule.launchActivity(new Intent());
diff --git a/core/tests/coretests/src/android/graphics/BitmapTest.java b/core/tests/coretests/src/android/graphics/BitmapTest.java
index d2a1dd9a7b5c..4bee24385cc5 100644
--- a/core/tests/coretests/src/android/graphics/BitmapTest.java
+++ b/core/tests/coretests/src/android/graphics/BitmapTest.java
@@ -22,6 +22,8 @@ import androidx.test.filters.SmallTest;
import junit.framework.TestCase;
+import java.nio.ByteBuffer;
+
public class BitmapTest extends TestCase {
@SmallTest
@@ -262,4 +264,74 @@ public class BitmapTest extends TestCase {
assertFalse(hardwareBitmap.isMutable());
assertEquals(ColorSpace.get(ColorSpace.Named.DISPLAY_P3), hardwareBitmap.getColorSpace());
}
+
+ @SmallTest
+ public void testCopyWithDirectBuffer() {
+ // Initialize Bitmap
+ final int width = 2;
+ final int height = 2;
+ Bitmap bm1 = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
+ bm1.setPixels(new int[] { 0xff, 0xeeee, 0xdddddd, 0xcccccccc }, 0, 2, 0, 0, 2, 2);
+
+ // Copy bytes to direct buffer, buffer is padded by fixed amount (pad bytes) either side
+ // of bitmap.
+ final int pad = 1;
+ final byte padValue = 0x5a;
+ final int bufferSize = pad + width * height * 2 + pad;
+ ByteBuffer directBuffer = ByteBuffer.allocateDirect(bufferSize);
+
+ // Write padding
+ directBuffer.put(0, padValue);
+ directBuffer.put(directBuffer.limit() - 1, padValue);
+
+ // Copy bitmap
+ directBuffer.position(pad);
+ bm1.copyPixelsToBuffer(directBuffer);
+ assertEquals(directBuffer.position(), pad + width * height * 2);
+
+ // Check padding
+ assertEquals(directBuffer.get(0), padValue);
+ assertEquals(directBuffer.get(directBuffer.limit() - 1), padValue);
+
+ // Create bitmap from direct buffer and check match.
+ directBuffer.position(pad);
+ Bitmap bm2 = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
+ bm2.copyPixelsFromBuffer(directBuffer);
+ assertTrue(bm2.sameAs(bm1));
+ }
+
+ @SmallTest
+ public void testCopyWithHeapBuffer() {
+ // Initialize Bitmap
+ final int width = 2;
+ final int height = 2;
+ Bitmap bm1 = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
+ bm1.setPixels(new int[] { 0xff, 0xeeee, 0xdddddd, 0xcccccccc }, 0, 2, 0, 0, 2, 2);
+
+ // Copy bytes to heap buffer, buffer is padded by fixed amount (pad bytes) either side
+ // of bitmap.
+ final int pad = 1;
+ final byte padValue = 0x5a;
+ final int bufferSize = pad + width * height * 2 + pad;
+ ByteBuffer heapBuffer = ByteBuffer.allocate(bufferSize);
+
+ // Write padding
+ heapBuffer.put(0, padValue);
+ heapBuffer.put(heapBuffer.limit() - 1, padValue);
+
+ // Copy bitmap
+ heapBuffer.position(pad);
+ bm1.copyPixelsToBuffer(heapBuffer);
+ assertEquals(heapBuffer.position(), pad + width * height * 2);
+
+ // Check padding
+ assertEquals(heapBuffer.get(0), padValue);
+ assertEquals(heapBuffer.get(heapBuffer.limit() - 1), padValue);
+
+ // Create bitmap from heap buffer and check match.
+ heapBuffer.position(pad);
+ Bitmap bm2 = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
+ bm2.copyPixelsFromBuffer(heapBuffer);
+ assertTrue(bm2.sameAs(bm1));
+ }
}
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index fafd8333f236..0e94abc0dcac 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -709,7 +709,9 @@ public class SettingsBackupTest {
Settings.Secure.CROSS_PROFILE_CALENDAR_ENABLED,
Settings.Secure.LOCATION_ACCESS_CHECK_INTERVAL_MILLIS,
Settings.Secure.LOCATION_ACCESS_CHECK_DELAY_MILLIS,
- Settings.Secure.BIOMETRIC_DEBUG_ENABLED);
+ Settings.Secure.BIOMETRIC_DEBUG_ENABLED,
+ Settings.Secure.FACE_UNLOCK_ATTENTION_REQUIRED,
+ Settings.Secure.FACE_UNLOCK_DIVERSITY_REQUIRED);
@Test
public void systemSettingsBackedUpOrBlacklisted() {
diff --git a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
index ebbbdec7d376..bdd3038cfee5 100644
--- a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
+++ b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
@@ -39,11 +39,13 @@ import android.platform.test.annotations.Presubmit;
import android.util.SparseArray;
import android.view.SurfaceControl.Transaction;
import android.view.SyncRtSurfaceTransactionApplier.SurfaceParams;
+import android.view.test.InsetsModeSession;
-import androidx.test.filters.FlakyTest;
import androidx.test.runner.AndroidJUnit4;
+import org.junit.AfterClass;
import org.junit.Before;
+import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
@@ -62,7 +64,6 @@ import java.util.List;
* {@link com.android.server.wm.test.filters.FrameworksTestsFilter}.
*/
@Presubmit
-@FlakyTest(detail = "Promote once confirmed non-flaky")
@RunWith(AndroidJUnit4.class)
public class InsetsAnimationControlImplTest {
@@ -72,15 +73,25 @@ public class InsetsAnimationControlImplTest {
private SurfaceControl mTopLeash;
private SurfaceControl mNavLeash;
private InsetsState mInsetsState;
+ private static InsetsModeSession sInsetsModeSession;
@Mock Transaction mMockTransaction;
@Mock InsetsController mMockController;
@Mock WindowInsetsAnimationControlListener mMockListener;
@Mock SyncRtSurfaceTransactionApplier mMockTransactionApplier;
+ @BeforeClass
+ public static void setupOnce() {
+ sInsetsModeSession = new InsetsModeSession(NEW_INSETS_MODE_FULL);
+ }
+
+ @AfterClass
+ public static void tearDownOnce() throws Exception {
+ sInsetsModeSession.close();
+ }
+
@Before
public void setup() {
- ViewRootImpl.sNewInsetsMode = NEW_INSETS_MODE_FULL;
MockitoAnnotations.initMocks(this);
mTopLeash = new SurfaceControl.Builder(mSession)
.setName("testSurface")
diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java
index 4d8d3f68f875..1e558287e21b 100644
--- a/core/tests/coretests/src/android/view/InsetsControllerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java
@@ -43,7 +43,6 @@ import android.view.WindowManager.LayoutParams;
import android.widget.TextView;
import androidx.test.InstrumentationRegistry;
-import androidx.test.filters.FlakyTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Before;
@@ -63,7 +62,6 @@ import java.util.concurrent.CountDownLatch;
* {@link com.android.server.wm.test.filters.FrameworksTestsFilter}.
*/
@Presubmit
-@FlakyTest(detail = "Promote once confirmed non-flaky")
@RunWith(AndroidJUnit4.class)
public class InsetsControllerTest {
diff --git a/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java b/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java
index a32fa778e736..971e143927b3 100644
--- a/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java
@@ -34,7 +34,6 @@ import android.view.WindowManager.LayoutParams;
import android.widget.TextView;
import androidx.test.InstrumentationRegistry;
-import androidx.test.filters.FlakyTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Before;
@@ -53,7 +52,6 @@ import org.mockito.MockitoAnnotations;
* {@link com.android.server.wm.test.filters.FrameworksTestsFilter}.
*/
@Presubmit
-@FlakyTest(detail = "Promote once confirmed non-flaky")
@RunWith(AndroidJUnit4.class)
public class InsetsSourceConsumerTest {
diff --git a/core/tests/coretests/src/android/view/InsetsSourceTest.java b/core/tests/coretests/src/android/view/InsetsSourceTest.java
index b55a9c600a61..533a58ef1dfb 100644
--- a/core/tests/coretests/src/android/view/InsetsSourceTest.java
+++ b/core/tests/coretests/src/android/view/InsetsSourceTest.java
@@ -24,7 +24,6 @@ import android.graphics.Insets;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
-import androidx.test.filters.FlakyTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Before;
@@ -41,7 +40,6 @@ import org.junit.runner.RunWith;
* {@link com.android.server.wm.test.filters.FrameworksTestsFilter}.
*/
@Presubmit
-@FlakyTest(detail = "Promote once confirmed non-flaky")
@RunWith(AndroidJUnit4.class)
public class InsetsSourceTest {
diff --git a/core/tests/coretests/src/android/view/InsetsStateTest.java b/core/tests/coretests/src/android/view/InsetsStateTest.java
index 8e167da84e08..a73269a81b11 100644
--- a/core/tests/coretests/src/android/view/InsetsStateTest.java
+++ b/core/tests/coretests/src/android/view/InsetsStateTest.java
@@ -40,7 +40,6 @@ import android.util.SparseIntArray;
import android.view.WindowInsets.Type;
import android.view.test.InsetsModeSession;
-import androidx.test.filters.FlakyTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
@@ -56,7 +55,6 @@ import org.junit.runner.RunWith;
* {@link com.android.server.wm.test.filters.FrameworksTestsFilter}.
*/
@Presubmit
-@FlakyTest(detail = "Promote once confirmed non-flaky")
@RunWith(AndroidJUnit4.class)
public class InsetsStateTest {
diff --git a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureManagerTest.java b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureManagerTest.java
index cd885e0b9bcf..7c255c9168cc 100644
--- a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureManagerTest.java
+++ b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureManagerTest.java
@@ -47,6 +47,6 @@ public class ContentCaptureManagerTest {
@Test
public void testRemoveUserData_invalid() {
- assertThrows(NullPointerException.class, () -> mManager.removeUserData(null));
+ assertThrows(NullPointerException.class, () -> mManager.removeData(null));
}
}
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
index 00b4a225c55f..ac039dddb66c 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
@@ -42,6 +42,7 @@ import android.content.ClipboardManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.database.Cursor;
import android.graphics.Bitmap;
@@ -53,7 +54,6 @@ import android.metrics.LogMaker;
import android.net.Uri;
import android.service.chooser.ChooserTarget;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.rule.ActivityTestRule;
@@ -62,10 +62,14 @@ import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.function.Function;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
@@ -75,21 +79,48 @@ import java.util.List;
/**
* Chooser activity instrumentation tests
*/
-@RunWith(AndroidJUnit4.class)
+@RunWith(Parameterized.class)
public class ChooserActivityTest {
+ private static final Function<PackageManager, PackageManager> DEFAULT_PM = pm -> pm;
+ private static final Function<PackageManager, PackageManager> NO_APP_PREDICTION_SERVICE_PM =
+ pm -> {
+ PackageManager mock = Mockito.spy(pm);
+ when(mock.getAppPredictionServicePackageName()).thenReturn(null);
+ return mock;
+ };
+
+ @Parameterized.Parameters
+ public static Collection packageManagers() {
+ return Arrays.asList(new Object[][] {
+ {0, "Default PackageManager", DEFAULT_PM},
+ {1, "No App Prediction Service", NO_APP_PREDICTION_SERVICE_PM}
+ });
+ }
+
private static final int CONTENT_PREVIEW_IMAGE = 1;
private static final int CONTENT_PREVIEW_FILE = 2;
private static final int CONTENT_PREVIEW_TEXT = 3;
+ private Function<PackageManager, PackageManager> mPackageManagerOverride;
+ private int mTestNum;
@Rule
public ActivityTestRule<ChooserWrapperActivity> mActivityRule =
new ActivityTestRule<>(ChooserWrapperActivity.class, false,
false);
+ public ChooserActivityTest(
+ int testNum,
+ String testName,
+ Function<PackageManager, PackageManager> packageManagerOverride) {
+ mPackageManagerOverride = packageManagerOverride;
+ mTestNum = testNum;
+ }
+
@Before
public void cleanOverrideData() {
sOverrides.reset();
+ sOverrides.createPackageManager = mPackageManagerOverride;
}
@Test
diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp
index 9b1f25986d56..99988542d619 100644
--- a/libs/hwui/Properties.cpp
+++ b/libs/hwui/Properties.cpp
@@ -17,8 +17,8 @@
#include "Properties.h"
#include "Debug.h"
#include "DeviceInfo.h"
-#include "SkTraceEventCommon.h"
#include "HWUIProperties.sysprop.h"
+#include "SkTraceEventCommon.h"
#include <algorithm>
#include <cstdlib>
@@ -67,7 +67,7 @@ bool Properties::debuggingEnabled = false;
bool Properties::isolatedProcess = false;
int Properties::contextPriority = 0;
-int Properties::defaultRenderAhead = 0;
+uint32_t Properties::defaultRenderAhead = 0;
static int property_get_int(const char* key, int defaultValue) {
char buf[PROPERTY_VALUE_MAX] = {
@@ -130,12 +130,9 @@ bool Properties::load() {
enableForceDarkSupport = property_get_bool(PROPERTY_ENABLE_FORCE_DARK, true);
- defaultRenderAhead = std::max(0, std::min(2, property_get_int(PROPERTY_RENDERAHEAD,
- render_ahead().value_or(0))));
-
- if (defaultRenderAhead && sRenderPipelineType == RenderPipelineType::SkiaVulkan) {
- ALOGW("hwui.render_ahead of %d ignored because pipeline is skiavk", defaultRenderAhead);
- }
+ defaultRenderAhead =
+ std::max(0u, std::min(2u, static_cast<uint32_t>(property_get_int(
+ PROPERTY_RENDERAHEAD, render_ahead().value_or(0)))));
return (prevDebugLayersUpdates != debugLayersUpdates) || (prevDebugOverdraw != debugOverdraw);
}
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index 3e91c63fcbde..3105e58362ec 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -253,7 +253,7 @@ public:
ANDROID_API static int contextPriority;
- static int defaultRenderAhead;
+ static uint32_t defaultRenderAhead;
private:
static ProfileType sProfileType;
diff --git a/libs/hwui/TreeInfo.cpp b/libs/hwui/TreeInfo.cpp
index cdad20ec6caa..dc53dd6c27c3 100644
--- a/libs/hwui/TreeInfo.cpp
+++ b/libs/hwui/TreeInfo.cpp
@@ -25,6 +25,7 @@ TreeInfo::TreeInfo(TraversalMode mode, renderthread::CanvasContext& canvasContex
, prepareTextures(mode == MODE_FULL)
, canvasContext(canvasContext)
, damageGenerationId(canvasContext.getFrameNumber())
- , disableForceDark(canvasContext.useForceDark() ? 0 : 1) {}
+ , disableForceDark(canvasContext.useForceDark() ? 0 : 1)
+ , screenSize(canvasContext.getNextFrameSize()) {}
} // namespace android::uirenderer
diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h
index 04eabac395f0..7e8d12fd4597 100644
--- a/libs/hwui/TreeInfo.h
+++ b/libs/hwui/TreeInfo.h
@@ -20,6 +20,7 @@
#include "utils/Macros.h"
#include <utils/Timers.h>
+#include "SkSize.h"
#include <string>
@@ -96,6 +97,8 @@ public:
int disableForceDark;
+ const SkISize screenSize;
+
struct Out {
bool hasFunctors = false;
// This is only updated if evaluateAnimations is true
diff --git a/libs/hwui/VectorDrawable.cpp b/libs/hwui/VectorDrawable.cpp
index da905cf9e63a..5418b337c371 100644
--- a/libs/hwui/VectorDrawable.cpp
+++ b/libs/hwui/VectorDrawable.cpp
@@ -547,6 +547,11 @@ void Tree::Cache::clear() {
}
void Tree::draw(SkCanvas* canvas, const SkRect& bounds, const SkPaint& inPaint) {
+ if (canvas->quickReject(bounds)) {
+ // The RenderNode is on screen, but the AVD is not.
+ return;
+ }
+
// Update the paint for any animatable properties
SkPaint paint = inPaint;
paint.setAlpha(mProperties.getRootAlpha() * 255);
diff --git a/libs/hwui/pipeline/skia/ShaderCache.cpp b/libs/hwui/pipeline/skia/ShaderCache.cpp
index 8508274676fd..66aa8c203799 100644
--- a/libs/hwui/pipeline/skia/ShaderCache.cpp
+++ b/libs/hwui/pipeline/skia/ShaderCache.cpp
@@ -15,6 +15,7 @@
*/
#include "ShaderCache.h"
+#include <GrContext.h>
#include <log/log.h>
#include <openssl/sha.h>
#include <algorithm>
@@ -23,7 +24,6 @@
#include "FileBlobCache.h"
#include "Properties.h"
#include "utils/TraceUtils.h"
-#include <GrContext.h>
namespace android {
namespace uirenderer {
diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
index 29d5ef233338..41bcfc25f5c1 100644
--- a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
+++ b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
@@ -22,6 +22,7 @@
#include "renderthread/CanvasContext.h"
#include <SkImagePriv.h>
+#include <SkPathOps.h>
namespace android {
namespace uirenderer {
@@ -35,7 +36,7 @@ void SkiaDisplayList::syncContents(const WebViewSyncData& data) {
animatedImage->syncProperties();
}
for (auto& vectorDrawable : mVectorDrawables) {
- vectorDrawable->syncProperties();
+ vectorDrawable.first->syncProperties();
}
}
@@ -51,6 +52,29 @@ void SkiaDisplayList::updateChildren(std::function<void(RenderNode*)> updateFn)
}
}
+static bool intersects(const SkISize screenSize, const Matrix4& mat, const SkRect& bounds) {
+ Vector3 points[] = { Vector3 {bounds.fLeft, bounds.fTop, 0},
+ Vector3 {bounds.fRight, bounds.fTop, 0},
+ Vector3 {bounds.fRight, bounds.fBottom, 0},
+ Vector3 {bounds.fLeft, bounds.fBottom, 0}};
+ float minX, minY, maxX, maxY;
+ bool first = true;
+ for (auto& point : points) {
+ mat.mapPoint3d(point);
+ if (first) {
+ minX = maxX = point.x;
+ minY = maxY = point.y;
+ first = false;
+ } else {
+ minX = std::min(minX, point.x);
+ minY = std::min(minY, point.y);
+ maxX = std::max(maxX, point.x);
+ maxY = std::max(maxY, point.y);
+ }
+ }
+ return SkRect::Make(screenSize).intersects(SkRect::MakeLTRB(minX, minY, maxX, maxY));
+}
+
bool SkiaDisplayList::prepareListAndChildren(
TreeObserver& observer, TreeInfo& info, bool functorsNeedLayer,
std::function<void(RenderNode*, TreeObserver&, TreeInfo&, bool)> childFn) {
@@ -107,15 +131,23 @@ bool SkiaDisplayList::prepareListAndChildren(
}
}
- for (auto& vectorDrawable : mVectorDrawables) {
+ for (auto& vectorDrawablePair : mVectorDrawables) {
// If any vector drawable in the display list needs update, damage the node.
+ auto& vectorDrawable = vectorDrawablePair.first;
if (vectorDrawable->isDirty()) {
- isDirty = true;
- static_cast<SkiaPipeline*>(info.canvasContext.getRenderPipeline())
- ->getVectorDrawables()
- ->push_back(vectorDrawable);
+ Matrix4 totalMatrix;
+ info.damageAccumulator->computeCurrentTransform(&totalMatrix);
+ Matrix4 canvasMatrix(vectorDrawablePair.second);
+ totalMatrix.multiply(canvasMatrix);
+ const SkRect& bounds = vectorDrawable->properties().getBounds();
+ if (intersects(info.screenSize, totalMatrix, bounds)) {
+ isDirty = true;
+ static_cast<SkiaPipeline*>(info.canvasContext.getRenderPipeline())
+ ->getVectorDrawables()
+ ->push_back(vectorDrawable);
+ vectorDrawable->setPropertyChangeWillBeConsumed(true);
+ }
}
- vectorDrawable->setPropertyChangeWillBeConsumed(true);
}
return isDirty;
}
diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.h b/libs/hwui/pipeline/skia/SkiaDisplayList.h
index 3219ad1deeff..b79103787023 100644
--- a/libs/hwui/pipeline/skia/SkiaDisplayList.h
+++ b/libs/hwui/pipeline/skia/SkiaDisplayList.h
@@ -22,6 +22,7 @@
#include "TreeInfo.h"
#include "hwui/AnimatedImageDrawable.h"
#include "utils/LinearAllocator.h"
+#include "utils/Pair.h"
#include <deque>
@@ -41,12 +42,6 @@ typedef uirenderer::VectorDrawable::Tree VectorDrawableRoot;
namespace skiapipeline {
-/**
- * This class is intended to be self contained, but still subclasses from
- * DisplayList to make it easier to support switching between the two at
- * runtime. The downside of this inheritance is that we pay for the overhead
- * of the parent class construction/destruction without any real benefit.
- */
class SkiaDisplayList {
public:
size_t getUsedSize() { return allocator.usedSize() + mDisplayList.usedSize(); }
@@ -156,7 +151,17 @@ public:
std::deque<RenderNodeDrawable> mChildNodes;
std::deque<FunctorDrawable*> mChildFunctors;
std::vector<SkImage*> mMutableImages;
- std::vector<VectorDrawableRoot*> mVectorDrawables;
+private:
+ std::vector<Pair<VectorDrawableRoot*, SkMatrix>> mVectorDrawables;
+public:
+ void appendVD(VectorDrawableRoot* r) {
+ appendVD(r, SkMatrix::I());
+ }
+
+ void appendVD(VectorDrawableRoot* r, const SkMatrix& mat) {
+ mVectorDrawables.push_back(Pair<VectorDrawableRoot*, SkMatrix>(r, mat));
+ }
+
std::vector<AnimatedImageDrawable*> mAnimatedImages;
DisplayListData mDisplayList;
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
index 570e895a012d..9248eadbd0ef 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
@@ -101,7 +101,7 @@ bool SkiaOpenGLPipeline::draw(const Frame& frame, const SkRect& screenDirty, con
SkiaPipeline::updateLighting(lightGeometry, lightInfo);
renderFrame(*layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface,
- SkMatrix::I());
+ SkMatrix::I());
layerUpdateQueue->clear();
// Draw visual debugging features
@@ -156,8 +156,23 @@ void SkiaOpenGLPipeline::onStop() {
}
}
+static void setBufferCount(ANativeWindow* window, uint32_t extraBuffers) {
+ int query_value;
+ int err = window->query(window, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &query_value);
+ if (err != 0 || query_value < 0) {
+ ALOGE("window->query failed: %s (%d) value=%d", strerror(-err), err, query_value);
+ return;
+ }
+ auto min_undequeued_buffers = static_cast<uint32_t>(query_value);
+
+ int bufferCount = min_undequeued_buffers + 2 + extraBuffers;
+ ALOGD("Setting buffer count to %d, min_undequeued %u, extraBuffers %u",
+ bufferCount, min_undequeued_buffers, extraBuffers);
+ native_window_set_buffer_count(window, bufferCount);
+}
+
bool SkiaOpenGLPipeline::setSurface(ANativeWindow* surface, SwapBehavior swapBehavior,
- ColorMode colorMode) {
+ ColorMode colorMode, uint32_t extraBuffers) {
if (mEglSurface != EGL_NO_SURFACE) {
mEglManager.destroySurface(mEglSurface);
mEglSurface = EGL_NO_SURFACE;
@@ -177,6 +192,7 @@ bool SkiaOpenGLPipeline::setSurface(ANativeWindow* surface, SwapBehavior swapBeh
if (mEglSurface != EGL_NO_SURFACE) {
const bool preserveBuffer = (swapBehavior != SwapBehavior::kSwap_discardBuffer);
mBufferPreserved = mEglManager.setPreserveBuffer(mEglSurface, preserveBuffer);
+ setBufferCount(surface, extraBuffers);
return true;
}
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h
index 66929226a5e2..3fe0f92b1924 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h
@@ -44,7 +44,7 @@ public:
FrameInfo* currentFrameInfo, bool* requireSwap) override;
DeferredLayerUpdater* createTextureLayer() override;
bool setSurface(ANativeWindow* surface, renderthread::SwapBehavior swapBehavior,
- renderthread::ColorMode colorMode) override;
+ renderthread::ColorMode colorMode, uint32_t extraBuffers) override;
void onStop() override;
bool isSurfaceReady() override;
bool isContextReady() override;
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
index 721a115c1381..ccc1701dcc0b 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
@@ -250,8 +250,9 @@ SkCanvas* SkiaPipeline::tryCapture(SkSurface* surface) {
}
if (mCaptureSequence > 0 || mPictureCapturedCallback) {
mRecorder.reset(new SkPictureRecorder());
- SkCanvas* pictureCanvas = mRecorder->beginRecording(surface->width(), surface->height(), nullptr,
- SkPictureRecorder::kPlaybackDrawPicture_RecordFlag);
+ SkCanvas* pictureCanvas =
+ mRecorder->beginRecording(surface->width(), surface->height(), nullptr,
+ SkPictureRecorder::kPlaybackDrawPicture_RecordFlag);
mNwayCanvas = std::make_unique<SkNWayCanvas>(surface->width(), surface->height());
mNwayCanvas->addCanvas(surface->getCanvas());
mNwayCanvas->addCanvas(pictureCanvas);
@@ -276,8 +277,7 @@ void SkiaPipeline::endCapture(SkSurface* surface) {
if (1 == mCaptureSequence) {
savePictureAsync(data, mCapturedFile);
} else {
- savePictureAsync(data,
- mCapturedFile + "_" + std::to_string(mCaptureSequence));
+ savePictureAsync(data, mCapturedFile + "_" + std::to_string(mCaptureSequence));
}
mCaptureSequence--;
}
@@ -327,7 +327,7 @@ static Rect nodeBounds(RenderNode& node) {
auto& props = node.properties();
return Rect(props.getLeft(), props.getTop(), props.getRight(), props.getBottom());
}
-}
+} // namespace
void SkiaPipeline::renderFrameImpl(const LayerUpdateQueue& layers, const SkRect& clip,
const std::vector<sp<RenderNode>>& nodes, bool opaque,
@@ -464,10 +464,20 @@ void SkiaPipeline::setSurfaceColorProperties(ColorMode colorMode) {
// (3) Requires RGBA colors (instead of BGRA).
static const uint32_t kOverdrawColors[2][6] = {
{
- 0x00000000, 0x00000000, 0x2f2f0000, 0x2f002f00, 0x3f00003f, 0x7f00007f,
+ 0x00000000,
+ 0x00000000,
+ 0x2f2f0000,
+ 0x2f002f00,
+ 0x3f00003f,
+ 0x7f00007f,
},
{
- 0x00000000, 0x00000000, 0x2f2f0000, 0x4f004f4f, 0x5f50335f, 0x7f00007f,
+ 0x00000000,
+ 0x00000000,
+ 0x2f2f0000,
+ 0x4f004f4f,
+ 0x5f50335f,
+ 0x7f00007f,
},
};
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
index d9456355cb88..0a2894945dc8 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
@@ -142,8 +142,7 @@ void SkiaRecordingCanvas::callDrawGLFunction(Functor* functor,
void SkiaRecordingCanvas::drawWebViewFunctor(int functor) {
FunctorDrawable* functorDrawable;
if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) {
- functorDrawable =
- mDisplayList->allocateDrawable<VkFunctorDrawable>(functor, asSkCanvas());
+ functorDrawable = mDisplayList->allocateDrawable<VkFunctorDrawable>(functor, asSkCanvas());
} else {
functorDrawable = mDisplayList->allocateDrawable<GLFunctorDrawable>(functor, asSkCanvas());
}
@@ -153,7 +152,9 @@ void SkiaRecordingCanvas::drawWebViewFunctor(int functor) {
void SkiaRecordingCanvas::drawVectorDrawable(VectorDrawableRoot* tree) {
mRecorder.drawVectorDrawable(tree);
- mDisplayList->mVectorDrawables.push_back(tree);
+ SkMatrix mat;
+ this->getMatrix(&mat);
+ mDisplayList->appendVD(tree, mat);
}
// ----------------------------------------------------------------------------
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
index edde6d3e05c0..e8cb219db320 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
@@ -18,12 +18,12 @@
#include "DeferredLayerUpdater.h"
#include "Readback.h"
+#include "ShaderCache.h"
#include "SkiaPipeline.h"
#include "SkiaProfileRenderer.h"
#include "VkInteropFunctorDrawable.h"
#include "renderstate/RenderState.h"
#include "renderthread/Frame.h"
-#include "ShaderCache.h"
#include <SkSurface.h>
#include <SkTypes.h>
@@ -70,8 +70,8 @@ bool SkiaVulkanPipeline::draw(const Frame& frame, const SkRect& screenDirty, con
return false;
}
SkiaPipeline::updateLighting(lightGeometry, lightInfo);
- renderFrame(*layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds,
- backBuffer, mVkSurface->getCurrentPreTransform());
+ renderFrame(*layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, backBuffer,
+ mVkSurface->getCurrentPreTransform());
ShaderCache::get().onVkFrameFlushed(mRenderThread.getGrContext());
layerUpdateQueue->clear();
@@ -116,7 +116,7 @@ DeferredLayerUpdater* SkiaVulkanPipeline::createTextureLayer() {
void SkiaVulkanPipeline::onStop() {}
bool SkiaVulkanPipeline::setSurface(ANativeWindow* surface, SwapBehavior swapBehavior,
- ColorMode colorMode) {
+ ColorMode colorMode, uint32_t extraBuffers) {
if (mVkSurface) {
mVkManager.destroySurface(mVkSurface);
mVkSurface = nullptr;
@@ -125,8 +125,9 @@ bool SkiaVulkanPipeline::setSurface(ANativeWindow* surface, SwapBehavior swapBeh
setSurfaceColorProperties(colorMode);
if (surface) {
mRenderThread.requireVkContext();
- mVkSurface = mVkManager.createSurface(surface, colorMode, mSurfaceColorSpace,
- mSurfaceColorType, mRenderThread.getGrContext());
+ mVkSurface =
+ mVkManager.createSurface(surface, colorMode, mSurfaceColorSpace, mSurfaceColorType,
+ mRenderThread.getGrContext(), extraBuffers);
}
return mVkSurface != nullptr;
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
index 77a7ab171ee1..31734783de7f 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
@@ -43,7 +43,7 @@ public:
FrameInfo* currentFrameInfo, bool* requireSwap) override;
DeferredLayerUpdater* createTextureLayer() override;
bool setSurface(ANativeWindow* surface, renderthread::SwapBehavior swapBehavior,
- renderthread::ColorMode colorMode) override;
+ renderthread::ColorMode colorMode, uint32_t extraBuffers) override;
void onStop() override;
bool isSurfaceReady() override;
bool isContextReady() override;
diff --git a/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp b/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp
index 1b9e53b21adb..112792611fc3 100644
--- a/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp
+++ b/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp
@@ -17,16 +17,16 @@
#include "VkFunctorDrawable.h"
#include <private/hwui/DrawVkInfo.h>
-#include "renderthread/VulkanManager.h"
-#include "renderthread/RenderThread.h"
-#include <SkAndroidFrameworkUtils.h>
#include <GrBackendDrawableInfo.h>
+#include <SkAndroidFrameworkUtils.h>
#include <SkImage.h>
#include <utils/Color.h>
#include <utils/Trace.h>
#include <utils/TraceUtils.h>
#include <vk/GrVkTypes.h>
#include <thread>
+#include "renderthread/RenderThread.h"
+#include "renderthread/VulkanManager.h"
#include "thread/ThreadBase.h"
#include "utils/TimeUtils.h"
@@ -64,13 +64,13 @@ void VkFunctorDrawHandler::draw(const GrBackendDrawableInfo& info) {
SkMatrix44 mat4(mMatrix);
VkFunctorDrawParams params{
- .width = mImageInfo.width(),
- .height = mImageInfo.height(),
- .color_space_ptr = mImageInfo.colorSpace(),
- .clip_left = mClip.fLeft,
- .clip_top = mClip.fTop,
- .clip_right = mClip.fRight,
- .clip_bottom = mClip.fBottom,
+ .width = mImageInfo.width(),
+ .height = mImageInfo.height(),
+ .color_space_ptr = mImageInfo.colorSpace(),
+ .clip_left = mClip.fLeft,
+ .clip_top = mClip.fTop,
+ .clip_right = mClip.fRight,
+ .clip_bottom = mClip.fBottom,
};
mat4.asColMajorf(&params.transform[0]);
params.secondary_command_buffer = vulkan_info.fSecondaryCommandBuffer;
@@ -87,8 +87,7 @@ void VkFunctorDrawHandler::draw(const GrBackendDrawableInfo& info) {
vulkan_info.fDrawBounds->extent.height = mClip.fBottom - mClip.fTop;
}
-VkFunctorDrawable::~VkFunctorDrawable() {
-}
+VkFunctorDrawable::~VkFunctorDrawable() {}
void VkFunctorDrawable::onDraw(SkCanvas* canvas) {
// "canvas" is either SkNWayCanvas created by SkiaPipeline::tryCapture (SKP capture use case) or
@@ -106,9 +105,8 @@ void VkFunctorDrawable::onDraw(SkCanvas* canvas) {
SkCanvas* gpuCanvas = SkAndroidFrameworkUtils::getBaseWrappedCanvas(canvas);
// Enforce "canvas" must be an AlphaFilterCanvas. For GPU canvas, the call should come from
// onSnapGpuDrawHandler.
- LOG_ALWAYS_FATAL_IF(
- gpuCanvas == canvas,
- "VkFunctorDrawable::onDraw() should not be called with a GPU canvas!");
+ LOG_ALWAYS_FATAL_IF(gpuCanvas == canvas,
+ "VkFunctorDrawable::onDraw() should not be called with a GPU canvas!");
// This will invoke onSnapGpuDrawHandler and regular draw flow.
gpuCanvas->drawDrawable(this);
diff --git a/libs/hwui/renderthread/CacheManager.cpp b/libs/hwui/renderthread/CacheManager.cpp
index 8b02c11911ca..a31081c9a451 100644
--- a/libs/hwui/renderthread/CacheManager.cpp
+++ b/libs/hwui/renderthread/CacheManager.cpp
@@ -21,17 +21,16 @@
#include "RenderThread.h"
#include "pipeline/skia/ShaderCache.h"
#include "pipeline/skia/SkiaMemoryTracer.h"
-#include "Properties.h"
#include "renderstate/RenderState.h"
#include "thread/CommonPool.h"
#include <GrContextOptions.h>
#include <SkExecutor.h>
#include <SkGraphics.h>
+#include <SkMathPriv.h>
#include <gui/Surface.h>
#include <math.h>
#include <set>
-#include <SkMathPriv.h>
namespace android {
namespace uirenderer {
@@ -79,14 +78,13 @@ void CacheManager::updateContextCacheSizes() {
class CommonPoolExecutor : public SkExecutor {
public:
- virtual void add(std::function<void(void)> func) override {
- CommonPool::post(std::move(func));
- }
+ virtual void add(std::function<void(void)> func) override { CommonPool::post(std::move(func)); }
};
static CommonPoolExecutor sDefaultExecutor;
-void CacheManager::configureContext(GrContextOptions* contextOptions, const void* identity, ssize_t size) {
+void CacheManager::configureContext(GrContextOptions* contextOptions, const void* identity,
+ ssize_t size) {
contextOptions->fAllowPathMaskCaching = true;
// This sets the maximum size for a single texture atlas in the GPU font cache. If necessary,
@@ -180,7 +178,8 @@ void CacheManager::dumpMemoryUsage(String8& log, const RenderState* renderState)
}
const char* layerType = Properties::getRenderPipelineType() == RenderPipelineType::SkiaGL
- ? "GlLayer" : "VkLayer";
+ ? "GlLayer"
+ : "VkLayer";
size_t layerMemoryTotal = 0;
for (std::set<Layer*>::iterator it = renderState->mActiveLayers.begin();
it != renderState->mActiveLayers.end(); it++) {
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 4808d68b89ab..2957b143a343 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -17,6 +17,7 @@
#include "CanvasContext.h"
#include <GpuMemoryTracker.h>
+#include "../Properties.h"
#include "AnimationContext.h"
#include "EglManager.h"
#include "Frame.h"
@@ -31,7 +32,6 @@
#include "utils/GLUtils.h"
#include "utils/TimeUtils.h"
#include "utils/TraceUtils.h"
-#include "../Properties.h"
#include <cutils/properties.h>
#include <private/hwui/DrawGlInfo.h>
@@ -41,6 +41,7 @@
#include <sys/stat.h>
#include <algorithm>
+#include <cstdint>
#include <cstdlib>
#include <functional>
@@ -153,7 +154,8 @@ void CanvasContext::setSurface(sp<Surface>&& surface) {
}
ColorMode colorMode = mWideColorGamut ? ColorMode::WideColorGamut : ColorMode::SRGB;
- bool hasSurface = mRenderPipeline->setSurface(mNativeSurface.get(), mSwapBehavior, colorMode);
+ bool hasSurface = mRenderPipeline->setSurface(mNativeSurface.get(), mSwapBehavior, colorMode,
+ mRenderAheadDepth);
mFrameNumber = -1;
@@ -298,7 +300,7 @@ void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo, int64_t sy
mAnimationContext->startFrame(info.mode);
mRenderPipeline->onPrepareTree();
- for (const sp<RenderNode> &node : mRenderNodes) {
+ for (const sp<RenderNode>& node : mRenderNodes) {
// Only the primary target node will be drawn full - all other nodes would get drawn in
// real time mode. In case of a window, the primary node is the window content and the other
// node(s) are non client / filler nodes.
@@ -322,7 +324,7 @@ void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo, int64_t sy
if (CC_LIKELY(mSwapHistory.size() && !Properties::forceDrawFrame)) {
nsecs_t latestVsync = mRenderThread.timeLord().latestVsync();
- SwapHistory &lastSwap = mSwapHistory.back();
+ SwapHistory& lastSwap = mSwapHistory.back();
nsecs_t vsyncDelta = std::abs(lastSwap.vsyncTime - latestVsync);
// The slight fudge-factor is to deal with cases where
// the vsync was estimated due to being slow handling the signal.
@@ -405,8 +407,7 @@ void CanvasContext::draw() {
SkRect dirty;
mDamageAccumulator.finish(&dirty);
- if (dirty.isEmpty() && Properties::skipEmptyFrames
- && !surfaceRequiresRedraw()) {
+ if (dirty.isEmpty() && Properties::skipEmptyFrames && !surfaceRequiresRedraw()) {
mCurrentFrameInfo->addFlag(FrameInfoFlags::SkippedFrame);
return;
}
@@ -416,21 +417,21 @@ void CanvasContext::draw() {
Frame frame = mRenderPipeline->getFrame();
SkRect windowDirty = computeDirtyRect(frame, &dirty);
+ if (mRenderAheadDepth) {
+ auto presentTime =
+ mCurrentFrameInfo->get(FrameInfoIndex::Vsync) +
+ (mRenderThread.timeLord().frameIntervalNanos() * (mRenderAheadDepth + 1));
+ native_window_set_buffers_timestamp(mNativeSurface.get(), presentTime);
+ }
bool drew = mRenderPipeline->draw(frame, windowDirty, dirty, mLightGeometry, &mLayerUpdateQueue,
- mContentDrawBounds, mOpaque, mLightInfo,
- mRenderNodes, &(profiler()));
+ mContentDrawBounds, mOpaque, mLightInfo, mRenderNodes,
+ &(profiler()));
int64_t frameCompleteNr = mFrameCompleteCallbacks.size() ? getFrameNumber() : -1;
waitOnFences();
- if (mRenderAheadDepth) {
- auto presentTime = mCurrentFrameInfo->get(FrameInfoIndex::Vsync) +
- (mRenderThread.timeLord().frameIntervalNanos() * (mRenderAheadDepth + 1));
- native_window_set_buffers_timestamp(mNativeSurface.get(), presentTime);
- }
-
bool requireSwap = false;
bool didSwap =
mRenderPipeline->swapBuffers(frame, drew, windowDirty, mCurrentFrameInfo, &requireSwap);
@@ -510,6 +511,17 @@ void CanvasContext::doFrame() {
prepareAndDraw(nullptr);
}
+SkISize CanvasContext::getNextFrameSize() const {
+ ReliableSurface* surface = mNativeSurface.get();
+ if (surface) {
+ SkISize size;
+ surface->query(NATIVE_WINDOW_WIDTH, &size.fWidth);
+ surface->query(NATIVE_WINDOW_HEIGHT, &size.fHeight);
+ return size;
+ }
+ return {INT32_MAX, INT32_MAX};
+}
+
void CanvasContext::prepareAndDraw(RenderNode* node) {
ATRACE_CALL();
@@ -645,21 +657,13 @@ bool CanvasContext::surfaceRequiresRedraw() {
}
void CanvasContext::applyRenderAheadSettings() {
- if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) {
- // TODO: Fix SkiaVulkan's assumptions on buffer counts. And SIGBUS crashes.
- mRenderAheadDepth = 0;
- return;
- }
- if (mNativeSurface) {
- native_window_set_buffer_count(mNativeSurface.get(), 3 + mRenderAheadDepth);
- if (!mRenderAheadDepth) {
- native_window_set_buffers_timestamp(mNativeSurface.get(), NATIVE_WINDOW_TIMESTAMP_AUTO);
- }
+ if (mNativeSurface && !mRenderAheadDepth) {
+ native_window_set_buffers_timestamp(mNativeSurface.get(), NATIVE_WINDOW_TIMESTAMP_AUTO);
}
}
-void CanvasContext::setRenderAheadDepth(int renderAhead) {
- if (renderAhead < 0 || renderAhead > 2 || renderAhead == mRenderAheadDepth) {
+void CanvasContext::setRenderAheadDepth(uint32_t renderAhead) {
+ if (renderAhead > 2 || renderAhead == mRenderAheadDepth || mNativeSurface) {
return;
}
mRenderAheadDepth = renderAhead;
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 4a3119a55c77..912b1257de7b 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -17,30 +17,31 @@
#pragma once
#include "DamageAccumulator.h"
-#include "Lighting.h"
#include "FrameInfo.h"
#include "FrameInfoVisualizer.h"
#include "FrameMetricsReporter.h"
#include "IContextFactory.h"
#include "IRenderPipeline.h"
#include "LayerUpdateQueue.h"
-#include "RenderNode.h"
+#include "Lighting.h"
#include "ReliableSurface.h"
+#include "RenderNode.h"
#include "renderthread/RenderTask.h"
#include "renderthread/RenderThread.h"
#include <EGL/egl.h>
#include <SkBitmap.h>
#include <SkRect.h>
+#include <SkSize.h>
#include <cutils/compiler.h>
#include <gui/Surface.h>
#include <utils/Functor.h>
#include <functional>
+#include <future>
#include <set>
#include <string>
#include <vector>
-#include <future>
namespace android {
namespace uirenderer {
@@ -112,7 +113,7 @@ public:
void setSurface(sp<Surface>&& surface);
bool pauseSurface();
void setStopped(bool stopped);
- bool hasSurface() { return mNativeSurface.get(); }
+ bool hasSurface() const { return mNativeSurface.get(); }
void allocateBuffers();
void setLightAlpha(uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
@@ -187,9 +188,7 @@ public:
mRenderPipeline->setPictureCapturedCallback(callback);
}
- void setForceDark(bool enable) {
- mUseForceDark = enable;
- }
+ void setForceDark(bool enable) { mUseForceDark = enable; }
bool useForceDark() {
// The force-dark override has the highest priority, followed by the disable setting
@@ -204,7 +203,10 @@ public:
return mUseForceDark;
}
- void setRenderAheadDepth(int renderAhead);
+ // Must be called before setSurface
+ void setRenderAheadDepth(uint32_t renderAhead);
+
+ SkISize getNextFrameSize() const;
private:
CanvasContext(RenderThread& thread, bool translucent, RenderNode* rootRenderNode,
@@ -238,7 +240,7 @@ private:
// painted onto its surface.
bool mIsDirty = false;
SwapBehavior mSwapBehavior = SwapBehavior::kSwap_default;
- int mRenderAheadDepth = 0;
+ uint32_t mRenderAheadDepth = 0;
struct SwapHistory {
SkRect damage;
nsecs_t vsyncTime;
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index 51eeab7e46ce..91dc3bc6e603 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -109,9 +109,8 @@ void DrawFrameTask::run() {
// Even if we aren't drawing this vsync pulse the next frame number will still be accurate
if (CC_UNLIKELY(callback)) {
- context->enqueueFrameWork([callback, frameNr = context->getFrameNumber()]() {
- callback(frameNr);
- });
+ context->enqueueFrameWork(
+ [callback, frameNr = context->getFrameNumber()]() { callback(frameNr); });
}
if (CC_LIKELY(canDrawThisFrame)) {
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index 2cc3f362e172..1d553342415c 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -29,10 +29,10 @@
#include <EGL/eglext.h>
#include <GLES/gl.h>
+#include <gui/Surface.h>
+#include <system/window.h>
#include <string>
#include <vector>
-#include <system/window.h>
-#include <gui/Surface.h>
#define GLES_VERSION 2
@@ -171,8 +171,7 @@ EGLConfig EglManager::load8BitsConfig(EGLDisplay display, EglManager::SwapBehavi
EGL_NONE};
EGLConfig config = EGL_NO_CONFIG_KHR;
EGLint numConfigs = 1;
- if (!eglChooseConfig(display, attribs, &config, numConfigs, &numConfigs) ||
- numConfigs != 1) {
+ if (!eglChooseConfig(display, attribs, &config, numConfigs, &numConfigs) || numConfigs != 1) {
return EGL_NO_CONFIG_KHR;
}
return config;
@@ -203,8 +202,7 @@ EGLConfig EglManager::loadFP16Config(EGLDisplay display, SwapBehavior swapBehavi
EGL_NONE};
EGLConfig config = EGL_NO_CONFIG_KHR;
EGLint numConfigs = 1;
- if (!eglChooseConfig(display, attribs, &config, numConfigs, &numConfigs) ||
- numConfigs != 1) {
+ if (!eglChooseConfig(display, attribs, &config, numConfigs, &numConfigs) || numConfigs != 1) {
return EGL_NO_CONFIG_KHR;
}
return config;
@@ -262,7 +260,7 @@ void EglManager::loadConfigs() {
mEglConfigWideGamut = loadFP16Config(mEglDisplay, mSwapBehavior);
if (mEglConfigWideGamut == EGL_NO_CONFIG_KHR) {
ALOGE("Device claims wide gamut support, cannot find matching config, error = %s",
- eglErrorString());
+ eglErrorString());
EglExtensions.pixelFormatFloat = false;
}
} else if (wideColorType == SkColorType::kN32_SkColorType) {
@@ -350,7 +348,7 @@ Result<EGLSurface, EGLint> EglManager::createSurface(EGLNativeWindowType window,
EGLSurface surface = eglCreateWindowSurface(
mEglDisplay, wideColorGamut ? mEglConfigWideGamut : mEglConfig, window, attribs);
if (surface == EGL_NO_SURFACE) {
- return Error<EGLint> { eglGetError() };
+ return Error<EGLint>{eglGetError()};
}
if (mSwapBehavior != SwapBehavior::Preserved) {
@@ -525,12 +523,8 @@ status_t EglManager::fenceWait(sp<Fence>& fence) {
ALOGE("EglManager::fenceWait: error dup'ing fence fd: %d", errno);
return -errno;
}
- EGLint attribs[] = {
- EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd,
- EGL_NONE
- };
- EGLSyncKHR sync = eglCreateSyncKHR(mEglDisplay,
- EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
+ EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd, EGL_NONE};
+ EGLSyncKHR sync = eglCreateSyncKHR(mEglDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
if (sync == EGL_NO_SYNC_KHR) {
close(fenceFd);
ALOGE("EglManager::fenceWait: error creating EGL fence: %#x", eglGetError());
@@ -559,18 +553,16 @@ status_t EglManager::fenceWait(sp<Fence>& fence) {
}
status_t EglManager::createReleaseFence(bool useFenceSync, EGLSyncKHR* eglFence,
- sp<Fence>& nativeFence) {
+ sp<Fence>& nativeFence) {
if (!hasEglContext()) {
ALOGE("EglManager::createReleaseFence: EGLDisplay not initialized");
return INVALID_OPERATION;
}
if (SyncFeatures::getInstance().useNativeFenceSync()) {
- EGLSyncKHR sync = eglCreateSyncKHR(mEglDisplay,
- EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
+ EGLSyncKHR sync = eglCreateSyncKHR(mEglDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
if (sync == EGL_NO_SYNC_KHR) {
- ALOGE("EglManager::createReleaseFence: error creating EGL fence: %#x",
- eglGetError());
+ ALOGE("EglManager::createReleaseFence: error creating EGL fence: %#x", eglGetError());
return UNKNOWN_ERROR;
}
glFlush();
@@ -578,7 +570,8 @@ status_t EglManager::createReleaseFence(bool useFenceSync, EGLSyncKHR* eglFence,
eglDestroySyncKHR(mEglDisplay, sync);
if (fenceFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
ALOGE("EglManager::createReleaseFence: error dup'ing native fence "
- "fd: %#x", eglGetError());
+ "fd: %#x",
+ eglGetError());
return UNKNOWN_ERROR;
}
nativeFence = new Fence(fenceFd);
@@ -592,7 +585,7 @@ status_t EglManager::createReleaseFence(bool useFenceSync, EGLSyncKHR* eglFence,
EGLint result = eglClientWaitSyncKHR(mEglDisplay, *eglFence, 0, 1000000000);
if (result == EGL_FALSE) {
ALOGE("EglManager::createReleaseFence: error waiting for previous fence: %#x",
- eglGetError());
+ eglGetError());
return UNKNOWN_ERROR;
} else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
ALOGE("EglManager::createReleaseFence: timeout waiting for previous fence");
diff --git a/libs/hwui/renderthread/IRenderPipeline.h b/libs/hwui/renderthread/IRenderPipeline.h
index 0502eb88b6a5..3b81014c05e2 100644
--- a/libs/hwui/renderthread/IRenderPipeline.h
+++ b/libs/hwui/renderthread/IRenderPipeline.h
@@ -66,8 +66,8 @@ public:
virtual bool swapBuffers(const Frame& frame, bool drew, const SkRect& screenDirty,
FrameInfo* currentFrameInfo, bool* requireSwap) = 0;
virtual DeferredLayerUpdater* createTextureLayer() = 0;
- virtual bool setSurface(ANativeWindow* window, SwapBehavior swapBehavior,
- ColorMode colorMode) = 0;
+ virtual bool setSurface(ANativeWindow* window, SwapBehavior swapBehavior, ColorMode colorMode,
+ uint32_t extraBuffers) = 0;
virtual void onStop() = 0;
virtual bool isSurfaceReady() = 0;
virtual bool isContextReady() = 0;
diff --git a/libs/hwui/renderthread/ReliableSurface.cpp b/libs/hwui/renderthread/ReliableSurface.cpp
index 6f2b9df918e3..ad1fc4921781 100644
--- a/libs/hwui/renderthread/ReliableSurface.cpp
+++ b/libs/hwui/renderthread/ReliableSurface.cpp
@@ -34,13 +34,13 @@ struct SurfaceExposer : Surface {
// Make warnings happy
SurfaceExposer() = delete;
- using Surface::setBufferCount;
- using Surface::setSwapInterval;
- using Surface::dequeueBuffer;
- using Surface::queueBuffer;
using Surface::cancelBuffer;
+ using Surface::dequeueBuffer;
using Surface::lockBuffer_DEPRECATED;
using Surface::perform;
+ using Surface::queueBuffer;
+ using Surface::setBufferCount;
+ using Surface::setSwapInterval;
};
#define callProtected(surface, func, ...) ((*surface).*&SurfaceExposer::func)(__VA_ARGS__)
@@ -300,17 +300,9 @@ int ReliableSurface::hook_perform(ANativeWindow* window, int operation, ...) {
int result = callProtected(getWrapped(window), perform, operation, args);
va_end(args);
- switch (operation) {
- case NATIVE_WINDOW_SET_BUFFERS_FORMAT:
- case NATIVE_WINDOW_SET_USAGE:
- case NATIVE_WINDOW_SET_USAGE64:
- va_start(args, operation);
- getSelf(window)->perform(operation, args);
- va_end(args);
- break;
- default:
- break;
- }
+ va_start(args, operation);
+ getSelf(window)->perform(operation, args);
+ va_end(args);
return result;
}
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index b58bab1191ed..1a1b9dac37f6 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -84,7 +84,7 @@ void RenderProxy::setName(const char* name) {
void RenderProxy::setSurface(const sp<Surface>& surface) {
mRenderThread.queue().post(
- [ this, surf = surface ]() mutable { mContext->setSurface(std::move(surf)); });
+ [this, surf = surface]() mutable { mContext->setSurface(std::move(surf)); });
}
void RenderProxy::allocateBuffers() {
@@ -251,7 +251,7 @@ void RenderProxy::dumpGraphicsMemory(int fd) {
void RenderProxy::setProcessStatsBuffer(int fd) {
auto& rt = RenderThread::getInstance();
- rt.queue().post([&rt, fd = dup(fd) ]() {
+ rt.queue().post([&rt, fd = dup(fd)]() {
rt.globalProfileData().switchStorageToAshmem(fd);
close(fd);
});
@@ -285,7 +285,7 @@ void RenderProxy::setContentDrawBounds(int left, int top, int right, int bottom)
void RenderProxy::setPictureCapturedCallback(
const std::function<void(sk_sp<SkPicture>&&)>& callback) {
mRenderThread.queue().post(
- [ this, cb = callback ]() { mContext->setPictureCapturedCallback(cb); });
+ [this, cb = callback]() { mContext->setPictureCapturedCallback(cb); });
}
void RenderProxy::setFrameCallback(std::function<void(int64_t)>&& callback) {
@@ -297,13 +297,13 @@ void RenderProxy::setFrameCompleteCallback(std::function<void(int64_t)>&& callba
}
void RenderProxy::addFrameMetricsObserver(FrameMetricsObserver* observerPtr) {
- mRenderThread.queue().post([ this, observer = sp{observerPtr} ]() {
+ mRenderThread.queue().post([this, observer = sp{observerPtr}]() {
mContext->addFrameMetricsObserver(observer.get());
});
}
void RenderProxy::removeFrameMetricsObserver(FrameMetricsObserver* observerPtr) {
- mRenderThread.queue().post([ this, observer = sp{observerPtr} ]() {
+ mRenderThread.queue().post([this, observer = sp{observerPtr}]() {
mContext->removeFrameMetricsObserver(observer.get());
});
}
@@ -313,9 +313,8 @@ void RenderProxy::setForceDark(bool enable) {
}
void RenderProxy::setRenderAheadDepth(int renderAhead) {
- mRenderThread.queue().post([ context = mContext, renderAhead ] {
- context->setRenderAheadDepth(renderAhead);
- });
+ mRenderThread.queue().post(
+ [context = mContext, renderAhead] { context->setRenderAheadDepth(renderAhead); });
}
int RenderProxy::copySurfaceInto(sp<Surface>& surface, int left, int top, int right, int bottom,
@@ -393,9 +392,7 @@ void RenderProxy::releaseVDAtlasEntries() {
void RenderProxy::preload() {
// Create RenderThread object and start the thread. Then preload Vulkan/EGL driver.
auto& thread = RenderThread::getInstance();
- thread.queue().post([&thread]() {
- thread.preload();
- });
+ thread.queue().post([&thread]() { thread.preload(); });
}
} /* namespace renderthread */
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index b76e49ce94a0..eca7d88e4e48 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -16,6 +16,7 @@
#include "RenderThread.h"
+#include "../HardwareBitmapUploader.h"
#include "CanvasContext.h"
#include "DeviceInfo.h"
#include "EglManager.h"
@@ -29,7 +30,6 @@
#include "utils/FatVector.h"
#include "utils/TimeUtils.h"
#include "utils/TraceUtils.h"
-#include "../HardwareBitmapUploader.h"
#ifdef HWUI_GLES_WRAP_ENABLED
#include "debug/GlesDriver.h"
@@ -410,9 +410,7 @@ bool RenderThread::isCurrent() {
void RenderThread::preload() {
// EGL driver is always preloaded only if HWUI renders with GL.
if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaGL) {
- std::thread eglInitThread([]() {
- eglGetDisplay(EGL_DEFAULT_DISPLAY);
- });
+ std::thread eglInitThread([]() { eglGetDisplay(EGL_DEFAULT_DISPLAY); });
eglInitThread.detach();
} else {
requireVkContext();
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index 5f43b488bcf2..6bb26fd6c675 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -22,8 +22,8 @@
#include "../JankTracker.h"
#include "CacheManager.h"
#include "TimeLord.h"
-#include "thread/ThreadBase.h"
#include "WebViewFunctorManager.h"
+#include "thread/ThreadBase.h"
#include "utils/TimeUtils.h"
#include <GrContext.h>
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index 4011329fa2da..5edf3301b2e8 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -29,7 +29,6 @@
#include <GrBackendSurface.h>
#include <GrContext.h>
#include <GrTypes.h>
-#include <GrTypes.h>
#include <vk/GrVkExtensions.h>
#include <vk/GrVkTypes.h>
@@ -43,7 +42,7 @@ static void free_features_extensions_structs(const VkPhysicalDeviceFeatures2& fe
// so we can get access to the pNext for the next struct.
struct CommonVulkanHeader {
VkStructureType sType;
- void* pNext;
+ void* pNext;
};
void* pNext = features.pNext;
@@ -94,13 +93,13 @@ void VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFe
VkResult err;
constexpr VkApplicationInfo app_info = {
- VK_STRUCTURE_TYPE_APPLICATION_INFO, // sType
- nullptr, // pNext
- "android framework", // pApplicationName
- 0, // applicationVersion
- "android framework", // pEngineName
- 0, // engineVerison
- mAPIVersion, // apiVersion
+ VK_STRUCTURE_TYPE_APPLICATION_INFO, // sType
+ nullptr, // pNext
+ "android framework", // pApplicationName
+ 0, // applicationVersion
+ "android framework", // pEngineName
+ 0, // engineVerison
+ mAPIVersion, // apiVersion
};
{
@@ -128,14 +127,14 @@ void VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFe
}
const VkInstanceCreateInfo instance_create = {
- VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, // sType
- nullptr, // pNext
- 0, // flags
- &app_info, // pApplicationInfo
- 0, // enabledLayerNameCount
- nullptr, // ppEnabledLayerNames
- (uint32_t) mInstanceExtensions.size(), // enabledExtensionNameCount
- mInstanceExtensions.data(), // ppEnabledExtensionNames
+ VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, // sType
+ nullptr, // pNext
+ 0, // flags
+ &app_info, // pApplicationInfo
+ 0, // enabledLayerNameCount
+ nullptr, // ppEnabledLayerNames
+ (uint32_t)mInstanceExtensions.size(), // enabledExtensionNameCount
+ mInstanceExtensions.data(), // ppEnabledExtensionNames
};
GET_PROC(CreateInstance);
@@ -200,11 +199,11 @@ void VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFe
{
uint32_t extensionCount = 0;
err = mEnumerateDeviceExtensionProperties(mPhysicalDevice, nullptr, &extensionCount,
- nullptr);
+ nullptr);
LOG_ALWAYS_FATAL_IF(VK_SUCCESS != err);
mDeviceExtensionsOwner.resize(extensionCount);
err = mEnumerateDeviceExtensionProperties(mPhysicalDevice, nullptr, &extensionCount,
- mDeviceExtensionsOwner.data());
+ mDeviceExtensionsOwner.data());
LOG_ALWAYS_FATAL_IF(VK_SUCCESS != err);
bool hasKHRSwapchainExtension = false;
for (const VkExtensionProperties& extension : mDeviceExtensionsOwner) {
@@ -216,7 +215,7 @@ void VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFe
LOG_ALWAYS_FATAL_IF(!hasKHRSwapchainExtension);
}
- auto getProc = [] (const char* proc_name, VkInstance instance, VkDevice device) {
+ auto getProc = [](const char* proc_name, VkInstance instance, VkDevice device) {
if (device != VK_NULL_HANDLE) {
return vkGetDeviceProcAddr(device, proc_name);
}
@@ -224,7 +223,8 @@ void VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFe
};
grExtensions.init(getProc, mInstance, mPhysicalDevice, mInstanceExtensions.size(),
- mInstanceExtensions.data(), mDeviceExtensions.size(), mDeviceExtensions.data());
+ mInstanceExtensions.data(), mDeviceExtensions.size(),
+ mDeviceExtensions.data());
LOG_ALWAYS_FATAL_IF(!grExtensions.hasExtension(VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, 1));
@@ -237,7 +237,7 @@ void VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFe
if (grExtensions.hasExtension(VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME, 2)) {
VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT* blend;
- blend = (VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT*) malloc(
+ blend = (VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT*)malloc(
sizeof(VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT));
LOG_ALWAYS_FATAL_IF(!blend);
blend->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_FEATURES_EXT;
@@ -247,7 +247,7 @@ void VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFe
}
VkPhysicalDeviceSamplerYcbcrConversionFeatures* ycbcrFeature;
- ycbcrFeature = (VkPhysicalDeviceSamplerYcbcrConversionFeatures*) malloc(
+ ycbcrFeature = (VkPhysicalDeviceSamplerYcbcrConversionFeatures*)malloc(
sizeof(VkPhysicalDeviceSamplerYcbcrConversionFeatures));
LOG_ALWAYS_FATAL_IF(!ycbcrFeature);
ycbcrFeature->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES;
@@ -261,17 +261,17 @@ void VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFe
// and we can't depend on it on all platforms
features.features.robustBufferAccess = VK_FALSE;
- float queuePriorities[1] = { 0.0 };
+ float queuePriorities[1] = {0.0};
void* queueNextPtr = nullptr;
VkDeviceQueueGlobalPriorityCreateInfoEXT queuePriorityCreateInfo;
- if (Properties::contextPriority != 0
- && grExtensions.hasExtension(VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME, 2)) {
+ if (Properties::contextPriority != 0 &&
+ grExtensions.hasExtension(VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME, 2)) {
memset(&queuePriorityCreateInfo, 0, sizeof(VkDeviceQueueGlobalPriorityCreateInfoEXT));
queuePriorityCreateInfo.sType =
- VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT;
+ VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT;
queuePriorityCreateInfo.pNext = nullptr;
switch (Properties::contextPriority) {
case EGL_CONTEXT_PRIORITY_LOW_IMG:
@@ -285,41 +285,40 @@ void VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFe
break;
default:
LOG_ALWAYS_FATAL("Unsupported context priority");
- }
- queueNextPtr = &queuePriorityCreateInfo;
+ }
+ queueNextPtr = &queuePriorityCreateInfo;
}
const VkDeviceQueueCreateInfo queueInfo[2] = {
- {
- VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType
- queueNextPtr, // pNext
- 0, // VkDeviceQueueCreateFlags
- mGraphicsQueueIndex, // queueFamilyIndex
- 1, // queueCount
- queuePriorities, // pQueuePriorities
- },
- {
- VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType
- queueNextPtr, // pNext
- 0, // VkDeviceQueueCreateFlags
- mPresentQueueIndex, // queueFamilyIndex
- 1, // queueCount
- queuePriorities, // pQueuePriorities
- }
- };
+ {
+ VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType
+ queueNextPtr, // pNext
+ 0, // VkDeviceQueueCreateFlags
+ mGraphicsQueueIndex, // queueFamilyIndex
+ 1, // queueCount
+ queuePriorities, // pQueuePriorities
+ },
+ {
+ VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType
+ queueNextPtr, // pNext
+ 0, // VkDeviceQueueCreateFlags
+ mPresentQueueIndex, // queueFamilyIndex
+ 1, // queueCount
+ queuePriorities, // pQueuePriorities
+ }};
uint32_t queueInfoCount = (mPresentQueueIndex != mGraphicsQueueIndex) ? 2 : 1;
const VkDeviceCreateInfo deviceInfo = {
- VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // sType
- &features, // pNext
- 0, // VkDeviceCreateFlags
- queueInfoCount, // queueCreateInfoCount
- queueInfo, // pQueueCreateInfos
- 0, // layerCount
- nullptr, // ppEnabledLayerNames
- (uint32_t) mDeviceExtensions.size(), // extensionCount
- mDeviceExtensions.data(), // ppEnabledExtensionNames
- nullptr, // ppEnabledFeatures
+ VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // sType
+ &features, // pNext
+ 0, // VkDeviceCreateFlags
+ queueInfoCount, // queueCreateInfoCount
+ queueInfo, // pQueueCreateInfos
+ 0, // layerCount
+ nullptr, // ppEnabledLayerNames
+ (uint32_t)mDeviceExtensions.size(), // extensionCount
+ mDeviceExtensions.data(), // ppEnabledExtensionNames
+ nullptr, // ppEnabledFeatures
};
LOG_ALWAYS_FATAL_IF(mCreateDevice(mPhysicalDevice, &deviceInfo, nullptr, &mDevice));
@@ -371,8 +370,8 @@ void VulkanManager::initialize() {
// this needs to be on the render queue
commandPoolInfo.queueFamilyIndex = mGraphicsQueueIndex;
commandPoolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
- SkDEBUGCODE(VkResult res =) mCreateCommandPool(mDevice, &commandPoolInfo, nullptr,
- &mCommandPool);
+ SkDEBUGCODE(VkResult res =)
+ mCreateCommandPool(mDevice, &commandPoolInfo, nullptr, &mCommandPool);
SkASSERT(VK_SUCCESS == res);
}
LOG_ALWAYS_FATAL_IF(mCommandPool == VK_NULL_HANDLE);
@@ -391,7 +390,7 @@ void VulkanManager::initialize() {
}
sk_sp<GrContext> VulkanManager::createContext(const GrContextOptions& options) {
- auto getProc = [] (const char* proc_name, VkInstance instance, VkDevice device) {
+ auto getProc = [](const char* proc_name, VkInstance instance, VkDevice device) {
if (device != VK_NULL_HANDLE) {
return vkGetDeviceProcAddr(device, proc_name);
}
@@ -431,7 +430,6 @@ VkFunctorInitParams VulkanManager::getVkFunctorInitParams() const {
}
Frame VulkanManager::dequeueNextBuffer(VulkanSurface* surface) {
-
VulkanSurface::NativeBufferInfo* bufferInfo = surface->dequeueNativeBuffer();
if (bufferInfo == nullptr) {
@@ -480,7 +478,7 @@ Frame VulkanManager::dequeueNextBuffer(VulkanSurface* surface) {
bufferInfo->skSurface->wait(1, &backendSemaphore);
// The following flush blocks the GPU immediately instead of waiting for other
// drawing ops. It seems dequeue_fence is not respected otherwise.
- //TODO: remove the flush after finding why backendSemaphore is not working.
+ // TODO: remove the flush after finding why backendSemaphore is not working.
bufferInfo->skSurface->flush();
}
}
@@ -557,15 +555,15 @@ void VulkanManager::destroySurface(VulkanSurface* surface) {
VulkanSurface* VulkanManager::createSurface(ANativeWindow* window, ColorMode colorMode,
sk_sp<SkColorSpace> surfaceColorSpace,
- SkColorType surfaceColorType,
- GrContext* grContext) {
+ SkColorType surfaceColorType, GrContext* grContext,
+ uint32_t extraBuffers) {
LOG_ALWAYS_FATAL_IF(!hasVkContext(), "Not initialized");
if (!window) {
return nullptr;
}
return VulkanSurface::Create(window, colorMode, surfaceColorType, surfaceColorSpace, grContext,
- *this);
+ *this, extraBuffers);
}
bool VulkanManager::setupDummyCommandBuffer() {
diff --git a/libs/hwui/renderthread/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h
index a7a43cc39a45..1a3a0e485523 100644
--- a/libs/hwui/renderthread/VulkanManager.h
+++ b/libs/hwui/renderthread/VulkanManager.h
@@ -18,16 +18,16 @@
#define VULKANMANAGER_H
#if !defined(VK_USE_PLATFORM_ANDROID_KHR)
-# define VK_USE_PLATFORM_ANDROID_KHR
+#define VK_USE_PLATFORM_ANDROID_KHR
#endif
#include <vulkan/vulkan.h>
#include <GrContextOptions.h>
-#include <vk/GrVkExtensions.h>
#include <SkSurface.h>
#include <ui/Fence.h>
#include <utils/StrongPointer.h>
#include <vk/GrVkBackendContext.h>
+#include <vk/GrVkExtensions.h>
#include "Frame.h"
#include "IRenderPipeline.h"
#include "VulkanSurface.h"
@@ -59,8 +59,8 @@ public:
// Create and destroy functions for wrapping an ANativeWindow in a VulkanSurface
VulkanSurface* createSurface(ANativeWindow* window, ColorMode colorMode,
sk_sp<SkColorSpace> surfaceColorSpace,
- SkColorType surfaceColorType,
- GrContext* grContext);
+ SkColorType surfaceColorType, GrContext* grContext,
+ uint32_t extraBuffers);
void destroySurface(VulkanSurface* surface);
Frame dequeueNextBuffer(VulkanSurface* surface);
diff --git a/libs/hwui/renderthread/VulkanSurface.cpp b/libs/hwui/renderthread/VulkanSurface.cpp
index be78b694f53a..df6b9ed2cdcb 100644
--- a/libs/hwui/renderthread/VulkanSurface.cpp
+++ b/libs/hwui/renderthread/VulkanSurface.cpp
@@ -16,12 +16,12 @@
#include "VulkanSurface.h"
-#include <algorithm>
#include <SkSurface.h>
+#include <algorithm>
#include "VulkanManager.h"
-#include "utils/TraceUtils.h"
#include "utils/Color.h"
+#include "utils/TraceUtils.h"
namespace android {
namespace uirenderer {
@@ -31,10 +31,9 @@ static bool IsTransformSupported(int transform) {
// For now, only support pure rotations, not flip or flip-and-rotate, until we have
// more time to test them and build sample code. As far as I know we never actually
// use anything besides pure rotations anyway.
- return transform == 0
- || transform == NATIVE_WINDOW_TRANSFORM_ROT_90
- || transform == NATIVE_WINDOW_TRANSFORM_ROT_180
- || transform == NATIVE_WINDOW_TRANSFORM_ROT_270;
+ return transform == 0 || transform == NATIVE_WINDOW_TRANSFORM_ROT_90 ||
+ transform == NATIVE_WINDOW_TRANSFORM_ROT_180 ||
+ transform == NATIVE_WINDOW_TRANSFORM_ROT_270;
}
static int InvertTransform(int transform) {
@@ -85,16 +84,16 @@ static SkMatrix GetPreTransformMatrix(SkISize windowSize, int transform) {
}
void VulkanSurface::ComputeWindowSizeAndTransform(WindowInfo* windowInfo, const SkISize& minSize,
- const SkISize& maxSize) {
+ const SkISize& maxSize) {
SkISize& windowSize = windowInfo->size;
// clamp width & height to handle currentExtent of -1 and protect us from broken hints
- if (windowSize.width() < minSize.width() || windowSize.width() > maxSize.width()
- || windowSize.height() < minSize.height() || windowSize.height() > maxSize.height()) {
+ if (windowSize.width() < minSize.width() || windowSize.width() > maxSize.width() ||
+ windowSize.height() < minSize.height() || windowSize.height() > maxSize.height()) {
int width = std::min(maxSize.width(), std::max(minSize.width(), windowSize.width()));
int height = std::min(maxSize.height(), std::max(minSize.height(), windowSize.height()));
- ALOGE("Invalid Window Dimensions [%d, %d]; clamping to [%d, %d]",
- windowSize.width(), windowSize.height(), width, height);
+ ALOGE("Invalid Window Dimensions [%d, %d]; clamping to [%d, %d]", windowSize.width(),
+ windowSize.height(), width, height);
windowSize.set(width, height);
}
@@ -145,12 +144,8 @@ class VkSurfaceAutoDeleter {
public:
VkSurfaceAutoDeleter(VkInstance instance, VkSurfaceKHR surface,
PFN_vkDestroySurfaceKHR destroySurfaceKHR)
- : mInstance(instance)
- , mSurface(surface)
- , mDestroySurfaceKHR(destroySurfaceKHR) {}
- ~VkSurfaceAutoDeleter() {
- destroy();
- }
+ : mInstance(instance), mSurface(surface), mDestroySurfaceKHR(destroySurfaceKHR) {}
+ ~VkSurfaceAutoDeleter() { destroy(); }
void destroy() {
if (mSurface != VK_NULL_HANDLE) {
@@ -166,9 +161,9 @@ private:
};
VulkanSurface* VulkanSurface::Create(ANativeWindow* window, ColorMode colorMode,
- SkColorType colorType, sk_sp<SkColorSpace> colorSpace,
- GrContext* grContext, const VulkanManager& vkManager) {
-
+ SkColorType colorType, sk_sp<SkColorSpace> colorSpace,
+ GrContext* grContext, const VulkanManager& vkManager,
+ uint32_t extraBuffers) {
VkAndroidSurfaceCreateInfoKHR surfaceCreateInfo;
memset(&surfaceCreateInfo, 0, sizeof(VkAndroidSurfaceCreateInfoKHR));
surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR;
@@ -188,10 +183,11 @@ VulkanSurface* VulkanSurface::Create(ANativeWindow* window, ColorMode colorMode,
vkManager.mDestroySurfaceKHR);
SkDEBUGCODE(VkBool32 supported; res = vkManager.mGetPhysicalDeviceSurfaceSupportKHR(
- vkManager.mPhysicalDevice, vkManager.mPresentQueueIndex, vkSurface, &supported);
- // All physical devices and queue families on Android must be capable of
- // presentation with any native window.
- SkASSERT(VK_SUCCESS == res && supported););
+ vkManager.mPhysicalDevice, vkManager.mPresentQueueIndex,
+ vkSurface, &supported);
+ // All physical devices and queue families on Android must be capable of
+ // presentation with any native window.
+ SkASSERT(VK_SUCCESS == res && supported););
// check for capabilities
VkSurfaceCapabilitiesKHR caps;
@@ -225,14 +221,13 @@ VulkanSurface* VulkanSurface::Create(ANativeWindow* window, ColorMode colorMode,
int query_value;
int err = window->query(window, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &query_value);
if (err != 0 || query_value < 0) {
- ALOGE("window->query failed: %s (%d) value=%d", strerror(-err), err,
- query_value);
+ ALOGE("window->query failed: %s (%d) value=%d", strerror(-err), err, query_value);
return nullptr;
}
auto min_undequeued_buffers = static_cast<uint32_t>(query_value);
- windowInfo.bufferCount = min_undequeued_buffers
- + std::max(VulkanSurface::sTargetBufferCount, caps.minImageCount);
+ windowInfo.bufferCount = min_undequeued_buffers +
+ std::max(sTargetBufferCount + extraBuffers, caps.minImageCount);
if (caps.maxImageCount > 0 && windowInfo.bufferCount > caps.maxImageCount) {
// Application must settle for fewer images than desired:
windowInfo.bufferCount = caps.maxImageCount;
@@ -241,8 +236,7 @@ VulkanSurface* VulkanSurface::Create(ANativeWindow* window, ColorMode colorMode,
// Currently Skia requires the images to be color attachments and support all transfer
// operations.
VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
- VK_IMAGE_USAGE_SAMPLED_BIT |
- VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
+ VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
VK_IMAGE_USAGE_TRANSFER_DST_BIT;
LOG_ALWAYS_FATAL_IF((caps.supportedUsageFlags & usageFlags) != usageFlags);
@@ -336,7 +330,8 @@ bool VulkanSurface::UpdateWindow(ANativeWindow* window, const WindowInfo& window
err = native_window_set_buffers_data_space(window, windowInfo.dataspace);
if (err != 0) {
ALOGE("VulkanSurface::UpdateWindow() native_window_set_buffers_data_space(%d) "
- "failed: %s (%d)", windowInfo.dataspace, strerror(-err), err);
+ "failed: %s (%d)",
+ windowInfo.dataspace, strerror(-err), err);
return false;
}
@@ -344,7 +339,8 @@ bool VulkanSurface::UpdateWindow(ANativeWindow* window, const WindowInfo& window
err = native_window_set_buffers_dimensions(window, size.width(), size.height());
if (err != 0) {
ALOGE("VulkanSurface::UpdateWindow() native_window_set_buffers_dimensions(%d,%d) "
- "failed: %s (%d)", size.width(), size.height(), strerror(-err), err);
+ "failed: %s (%d)",
+ size.width(), size.height(), strerror(-err), err);
return false;
}
@@ -357,7 +353,8 @@ bool VulkanSurface::UpdateWindow(ANativeWindow* window, const WindowInfo& window
err = native_window_set_buffers_transform(window, InvertTransform(windowInfo.transform));
if (err != 0) {
ALOGE("VulkanSurface::UpdateWindow() native_window_set_buffers_transform(%d) "
- "failed: %s (%d)", windowInfo.transform, strerror(-err), err);
+ "failed: %s (%d)",
+ windowInfo.transform, strerror(-err), err);
return false;
}
@@ -366,7 +363,8 @@ bool VulkanSurface::UpdateWindow(ANativeWindow* window, const WindowInfo& window
err = native_window_set_scaling_mode(window, NATIVE_WINDOW_SCALING_MODE_FREEZE);
if (err != 0) {
ALOGE("VulkanSurface::UpdateWindow() native_window_set_scaling_mode(SCALE_TO_WINDOW) "
- "failed: %s (%d)", strerror(-err), err);
+ "failed: %s (%d)",
+ strerror(-err), err);
return false;
}
@@ -388,12 +386,12 @@ bool VulkanSurface::UpdateWindow(ANativeWindow* window, const WindowInfo& window
}
VulkanSurface::VulkanSurface(ANativeWindow* window, const WindowInfo& windowInfo,
- SkISize minWindowSize, SkISize maxWindowSize, GrContext* grContext)
+ SkISize minWindowSize, SkISize maxWindowSize, GrContext* grContext)
: mNativeWindow(window)
, mWindowInfo(windowInfo)
, mGrContext(grContext)
, mMinWindowSize(minWindowSize)
- , mMaxWindowSize(maxWindowSize) { }
+ , mMaxWindowSize(maxWindowSize) {}
VulkanSurface::~VulkanSurface() {
releaseBuffers();
@@ -436,8 +434,7 @@ VulkanSurface::NativeBufferInfo* VulkanSurface::dequeueNativeBuffer() {
// value at the end of the function if everything dequeued correctly.
mCurrentBufferInfo = nullptr;
-
- //check if the native window has been resized or rotated and update accordingly
+ // check if the native window has been resized or rotated and update accordingly
SkISize newSize = SkISize::MakeEmpty();
int transformHint = 0;
mNativeWindow->query(mNativeWindow.get(), NATIVE_WINDOW_WIDTH, &newSize.fWidth);
@@ -457,8 +454,8 @@ VulkanSurface::NativeBufferInfo* VulkanSurface::dequeueNativeBuffer() {
newWindowInfo.actualSize.height());
if (err != 0) {
ALOGE("native_window_set_buffers_dimensions(%d,%d) failed: %s (%d)",
- newWindowInfo.actualSize.width(),
- newWindowInfo.actualSize.height(), strerror(-err), err);
+ newWindowInfo.actualSize.width(), newWindowInfo.actualSize.height(),
+ strerror(-err), err);
return nullptr;
}
// reset the NativeBufferInfo (including SkSurface) associated with the old buffers. The
@@ -469,7 +466,7 @@ VulkanSurface::NativeBufferInfo* VulkanSurface::dequeueNativeBuffer() {
if (newWindowInfo.transform != mWindowInfo.transform) {
err = native_window_set_buffers_transform(mNativeWindow.get(),
- InvertTransform(newWindowInfo.transform));
+ InvertTransform(newWindowInfo.transform));
if (err != 0) {
ALOGE("native_window_set_buffers_transform(%d) failed: %s (%d)",
newWindowInfo.transform, strerror(-err), err);
@@ -512,11 +509,9 @@ VulkanSurface::NativeBufferInfo* VulkanSurface::dequeueNativeBuffer() {
VulkanSurface::NativeBufferInfo* bufferInfo = &mNativeBuffers[idx];
if (bufferInfo->skSurface.get() == nullptr) {
- bufferInfo->skSurface =
- SkSurface::MakeFromAHardwareBuffer(mGrContext,
- ANativeWindowBuffer_getHardwareBuffer(bufferInfo->buffer.get()),
- kTopLeft_GrSurfaceOrigin, DataSpaceToColorSpace(mWindowInfo.dataspace),
- nullptr);
+ bufferInfo->skSurface = SkSurface::MakeFromAHardwareBuffer(
+ mGrContext, ANativeWindowBuffer_getHardwareBuffer(bufferInfo->buffer.get()),
+ kTopLeft_GrSurfaceOrigin, DataSpaceToColorSpace(mWindowInfo.dataspace), nullptr);
if (bufferInfo->skSurface.get() == nullptr) {
ALOGE("SkSurface::MakeFromAHardwareBuffer failed");
mNativeWindow->cancelBuffer(mNativeWindow.get(), buffer, fence_fd);
@@ -530,19 +525,19 @@ VulkanSurface::NativeBufferInfo* VulkanSurface::dequeueNativeBuffer() {
bool VulkanSurface::presentCurrentBuffer(const SkRect& dirtyRect, int semaphoreFd) {
if (!dirtyRect.isEmpty()) {
- SkRect transformedRect;
- mWindowInfo.preTransform.mapRect(&transformedRect, dirtyRect);
- SkIRect transformedIRect;
- transformedRect.roundOut(&transformedIRect);
- transformedIRect.intersect(0, 0, mWindowInfo.size.fWidth, mWindowInfo.size.fHeight);
+ // native_window_set_surface_damage takes a rectangle in prerotated space
+ // with a bottom-left origin. That is, top > bottom.
+ // The dirtyRect is also in prerotated space, so we just need to switch it to
+ // a bottom-left origin space.
- // map to bottom-left coordinate system
+ SkIRect irect;
+ dirtyRect.roundOut(&irect);
android_native_rect_t aRect;
- aRect.left = transformedIRect.x();
- aRect.top = mWindowInfo.size.fHeight - (transformedIRect.y() + transformedIRect.height());
- aRect.right = aRect.left + transformedIRect.width();
- aRect.bottom = aRect.top - transformedIRect.height();
+ aRect.left = irect.left();
+ aRect.top = logicalHeight() - irect.top();
+ aRect.right = irect.right();
+ aRect.bottom = logicalHeight() - irect.bottom();
int err = native_window_set_surface_damage(mNativeWindow.get(), &aRect, 1);
ALOGE_IF(err != 0, "native_window_set_surface_damage failed: %s (%d)", strerror(-err), err);
diff --git a/libs/hwui/renderthread/VulkanSurface.h b/libs/hwui/renderthread/VulkanSurface.h
index 305483fce2d5..b7af596ae762 100644
--- a/libs/hwui/renderthread/VulkanSurface.h
+++ b/libs/hwui/renderthread/VulkanSurface.h
@@ -19,8 +19,8 @@
#include <system/window.h>
#include <vulkan/vulkan.h>
-#include <SkSize.h>
#include <SkRefCnt.h>
+#include <SkSize.h>
#include "IRenderPipeline.h"
@@ -34,12 +34,9 @@ class VulkanManager;
class VulkanSurface {
public:
- static VulkanSurface* Create(ANativeWindow* window,
- ColorMode colorMode,
- SkColorType colorType,
- sk_sp<SkColorSpace> colorSpace,
- GrContext* grContext,
- const VulkanManager& vkManager);
+ static VulkanSurface* Create(ANativeWindow* window, ColorMode colorMode, SkColorType colorType,
+ sk_sp<SkColorSpace> colorSpace, GrContext* grContext,
+ const VulkanManager& vkManager, uint32_t extraBuffers);
~VulkanSurface();
sk_sp<SkSurface> getCurrentSkSurface() {
@@ -104,15 +101,10 @@ private:
SkMatrix preTransform;
};
- VulkanSurface(ANativeWindow* window,
- const WindowInfo& windowInfo,
- SkISize minWindowSize,
- SkISize maxWindowSize,
- GrContext* grContext);
- static bool UpdateWindow(ANativeWindow* window,
- const WindowInfo& windowInfo);
- static void ComputeWindowSizeAndTransform(WindowInfo* windowInfo,
- const SkISize& minSize,
+ VulkanSurface(ANativeWindow* window, const WindowInfo& windowInfo, SkISize minWindowSize,
+ SkISize maxWindowSize, GrContext* grContext);
+ static bool UpdateWindow(ANativeWindow* window, const WindowInfo& windowInfo);
+ static void ComputeWindowSizeAndTransform(WindowInfo* windowInfo, const SkISize& minSize,
const SkISize& maxSize);
void releaseBuffers();
diff --git a/libs/hwui/tests/unit/SkiaDisplayListTests.cpp b/libs/hwui/tests/unit/SkiaDisplayListTests.cpp
index 1b4cf7e144bd..6fb164a99ae4 100644
--- a/libs/hwui/tests/unit/SkiaDisplayListTests.cpp
+++ b/libs/hwui/tests/unit/SkiaDisplayListTests.cpp
@@ -23,6 +23,7 @@
#include "pipeline/skia/GLFunctorDrawable.h"
#include "pipeline/skia/SkiaDisplayList.h"
#include "renderthread/CanvasContext.h"
+#include "tests/common/TestContext.h"
#include "tests/common/TestUtils.h"
using namespace android;
@@ -50,13 +51,13 @@ TEST(SkiaDisplayList, reset) {
GLFunctorDrawable functorDrawable(nullptr, nullptr, &dummyCanvas);
skiaDL->mChildFunctors.push_back(&functorDrawable);
skiaDL->mMutableImages.push_back(nullptr);
- skiaDL->mVectorDrawables.push_back(nullptr);
+ skiaDL->appendVD(nullptr);
skiaDL->mProjectionReceiver = &drawable;
ASSERT_FALSE(skiaDL->mChildNodes.empty());
ASSERT_FALSE(skiaDL->mChildFunctors.empty());
ASSERT_FALSE(skiaDL->mMutableImages.empty());
- ASSERT_FALSE(skiaDL->mVectorDrawables.empty());
+ ASSERT_TRUE(skiaDL->hasVectorDrawables());
ASSERT_FALSE(skiaDL->isEmpty());
ASSERT_TRUE(skiaDL->mProjectionReceiver);
@@ -65,7 +66,7 @@ TEST(SkiaDisplayList, reset) {
ASSERT_TRUE(skiaDL->mChildNodes.empty());
ASSERT_TRUE(skiaDL->mChildFunctors.empty());
ASSERT_TRUE(skiaDL->mMutableImages.empty());
- ASSERT_TRUE(skiaDL->mVectorDrawables.empty());
+ ASSERT_FALSE(skiaDL->hasVectorDrawables());
ASSERT_TRUE(skiaDL->isEmpty());
ASSERT_FALSE(skiaDL->mProjectionReceiver);
}
@@ -110,7 +111,7 @@ TEST(SkiaDisplayList, syncContexts) {
SkRect bounds = SkRect::MakeWH(200, 200);
VectorDrawableRoot vectorDrawable(new VectorDrawable::Group());
vectorDrawable.mutateStagingProperties()->setBounds(bounds);
- skiaDL.mVectorDrawables.push_back(&vectorDrawable);
+ skiaDL.appendVD(&vectorDrawable);
// ensure that the functor and vectorDrawable are properly synced
TestUtils::runOnRenderThread([&](auto&) {
@@ -149,9 +150,14 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaDisplayList, prepareListAndChildren) {
SkiaDisplayList skiaDL;
+ // The VectorDrawableRoot needs to have bounds on screen (and therefore not
+ // empty) in order to have PropertyChangeWillBeConsumed set.
+ const auto bounds = SkRect::MakeIWH(100, 100);
+
// prepare with a clean VD
VectorDrawableRoot cleanVD(new VectorDrawable::Group());
- skiaDL.mVectorDrawables.push_back(&cleanVD);
+ cleanVD.mutateProperties()->setBounds(bounds);
+ skiaDL.appendVD(&cleanVD);
cleanVD.getBitmapUpdateIfDirty(); // this clears the dirty bit
ASSERT_FALSE(cleanVD.isDirty());
@@ -159,11 +165,12 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaDisplayList, prepareListAndChildren) {
TestUtils::MockTreeObserver observer;
ASSERT_FALSE(skiaDL.prepareListAndChildren(observer, info, false,
[](RenderNode*, TreeObserver&, TreeInfo&, bool) {}));
- ASSERT_TRUE(cleanVD.getPropertyChangeWillBeConsumed());
+ ASSERT_FALSE(cleanVD.getPropertyChangeWillBeConsumed());
// prepare again this time adding a dirty VD
VectorDrawableRoot dirtyVD(new VectorDrawable::Group());
- skiaDL.mVectorDrawables.push_back(&dirtyVD);
+ dirtyVD.mutateProperties()->setBounds(bounds);
+ skiaDL.appendVD(&dirtyVD);
ASSERT_TRUE(dirtyVD.isDirty());
ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
@@ -191,6 +198,169 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaDisplayList, prepareListAndChildren) {
canvasContext->destroy();
}
+RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaDisplayList, prepareListAndChildren_vdOffscreen) {
+ auto rootNode = TestUtils::createNode(0, 0, 200, 400, nullptr);
+ ContextFactory contextFactory;
+ std::unique_ptr<CanvasContext> canvasContext(
+ CanvasContext::create(renderThread, false, rootNode.get(), &contextFactory));
+
+ // Set up a Surface so that we can position the VectorDrawable offscreen.
+ test::TestContext testContext;
+ testContext.setRenderOffscreen(true);
+ auto surface = testContext.surface();
+ int width, height;
+ surface->query(NATIVE_WINDOW_WIDTH, &width);
+ surface->query(NATIVE_WINDOW_HEIGHT, &height);
+ canvasContext->setSurface(std::move(surface));
+
+ TreeInfo info(TreeInfo::MODE_FULL, *canvasContext.get());
+ DamageAccumulator damageAccumulator;
+ info.damageAccumulator = &damageAccumulator;
+
+ // The VectorDrawableRoot needs to have bounds on screen (and therefore not
+ // empty) in order to have PropertyChangeWillBeConsumed set.
+ const auto bounds = SkRect::MakeIWH(100, 100);
+
+ for (const SkRect b : {bounds.makeOffset(width, 0),
+ bounds.makeOffset(0, height),
+ bounds.makeOffset(-bounds.width(), 0),
+ bounds.makeOffset(0, -bounds.height())}) {
+ SkiaDisplayList skiaDL;
+ VectorDrawableRoot dirtyVD(new VectorDrawable::Group());
+ dirtyVD.mutateProperties()->setBounds(b);
+ skiaDL.appendVD(&dirtyVD);
+
+ ASSERT_TRUE(dirtyVD.isDirty());
+ ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
+
+ TestUtils::MockTreeObserver observer;
+ ASSERT_FALSE(skiaDL.prepareListAndChildren(
+ observer, info, false, [](RenderNode*, TreeObserver&, TreeInfo&, bool) {}));
+ ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
+ }
+
+ // The DamageAccumulator's transform can also result in the
+ // VectorDrawableRoot being offscreen.
+ for (const SkISize translate : { SkISize{width, 0},
+ SkISize{0, height},
+ SkISize{-width, 0},
+ SkISize{0, -height}}) {
+ Matrix4 mat4;
+ mat4.translate(translate.fWidth, translate.fHeight);
+ damageAccumulator.pushTransform(&mat4);
+
+ SkiaDisplayList skiaDL;
+ VectorDrawableRoot dirtyVD(new VectorDrawable::Group());
+ dirtyVD.mutateProperties()->setBounds(bounds);
+ skiaDL.appendVD(&dirtyVD);
+
+ ASSERT_TRUE(dirtyVD.isDirty());
+ ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
+
+ TestUtils::MockTreeObserver observer;
+ ASSERT_FALSE(skiaDL.prepareListAndChildren(
+ observer, info, false, [](RenderNode*, TreeObserver&, TreeInfo&, bool) {}));
+ ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
+ damageAccumulator.popTransform();
+ }
+
+ // Another way to be offscreen: a matrix from the draw call.
+ for (const SkMatrix translate : { SkMatrix::MakeTrans(width, 0),
+ SkMatrix::MakeTrans(0, height),
+ SkMatrix::MakeTrans(-width, 0),
+ SkMatrix::MakeTrans(0, -height)}) {
+ SkiaDisplayList skiaDL;
+ VectorDrawableRoot dirtyVD(new VectorDrawable::Group());
+ dirtyVD.mutateProperties()->setBounds(bounds);
+ skiaDL.appendVD(&dirtyVD, translate);
+
+ ASSERT_TRUE(dirtyVD.isDirty());
+ ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
+
+ TestUtils::MockTreeObserver observer;
+ ASSERT_FALSE(skiaDL.prepareListAndChildren(
+ observer, info, false, [](RenderNode*, TreeObserver&, TreeInfo&, bool) {}));
+ ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
+ }
+
+ // Verify that the matrices are combined in the right order.
+ {
+ // Rotate and then translate, so the VD is offscreen.
+ Matrix4 mat4;
+ mat4.loadRotate(180);
+ damageAccumulator.pushTransform(&mat4);
+
+ SkiaDisplayList skiaDL;
+ VectorDrawableRoot dirtyVD(new VectorDrawable::Group());
+ dirtyVD.mutateProperties()->setBounds(bounds);
+ SkMatrix translate = SkMatrix::MakeTrans(50, 50);
+ skiaDL.appendVD(&dirtyVD, translate);
+
+ ASSERT_TRUE(dirtyVD.isDirty());
+ ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
+
+ TestUtils::MockTreeObserver observer;
+ ASSERT_FALSE(skiaDL.prepareListAndChildren(
+ observer, info, false, [](RenderNode*, TreeObserver&, TreeInfo&, bool) {}));
+ ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
+ damageAccumulator.popTransform();
+ }
+ {
+ // Switch the order of rotate and translate, so it is on screen.
+ Matrix4 mat4;
+ mat4.translate(50, 50);
+ damageAccumulator.pushTransform(&mat4);
+
+ SkiaDisplayList skiaDL;
+ VectorDrawableRoot dirtyVD(new VectorDrawable::Group());
+ dirtyVD.mutateProperties()->setBounds(bounds);
+ SkMatrix rotate;
+ rotate.setRotate(180);
+ skiaDL.appendVD(&dirtyVD, rotate);
+
+ ASSERT_TRUE(dirtyVD.isDirty());
+ ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
+
+ TestUtils::MockTreeObserver observer;
+ ASSERT_TRUE(skiaDL.prepareListAndChildren(
+ observer, info, false, [](RenderNode*, TreeObserver&, TreeInfo&, bool) {}));
+ ASSERT_TRUE(dirtyVD.getPropertyChangeWillBeConsumed());
+ damageAccumulator.popTransform();
+ }
+ {
+ // An AVD that is larger than the screen.
+ SkiaDisplayList skiaDL;
+ VectorDrawableRoot dirtyVD(new VectorDrawable::Group());
+ dirtyVD.mutateProperties()->setBounds(SkRect::MakeLTRB(-1, -1, width + 1, height + 1));
+ skiaDL.appendVD(&dirtyVD);
+
+ ASSERT_TRUE(dirtyVD.isDirty());
+ ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
+
+ TestUtils::MockTreeObserver observer;
+ ASSERT_TRUE(skiaDL.prepareListAndChildren(
+ observer, info, false, [](RenderNode*, TreeObserver&, TreeInfo&, bool) {}));
+ ASSERT_TRUE(dirtyVD.getPropertyChangeWillBeConsumed());
+ }
+ {
+ // An AVD whose bounds are not a rectangle after applying a matrix.
+ SkiaDisplayList skiaDL;
+ VectorDrawableRoot dirtyVD(new VectorDrawable::Group());
+ dirtyVD.mutateProperties()->setBounds(bounds);
+ SkMatrix mat;
+ mat.setRotate(45, 50, 50);
+ skiaDL.appendVD(&dirtyVD, mat);
+
+ ASSERT_TRUE(dirtyVD.isDirty());
+ ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
+
+ TestUtils::MockTreeObserver observer;
+ ASSERT_TRUE(skiaDL.prepareListAndChildren(
+ observer, info, false, [](RenderNode*, TreeObserver&, TreeInfo&, bool) {}));
+ ASSERT_TRUE(dirtyVD.getPropertyChangeWillBeConsumed());
+ }
+}
+
TEST(SkiaDisplayList, updateChildren) {
SkiaDisplayList skiaDL;
diff --git a/libs/hwui/tests/unit/SkiaPipelineTests.cpp b/libs/hwui/tests/unit/SkiaPipelineTests.cpp
index e86cf42fee4d..a671bdada09a 100644
--- a/libs/hwui/tests/unit/SkiaPipelineTests.cpp
+++ b/libs/hwui/tests/unit/SkiaPipelineTests.cpp
@@ -31,6 +31,9 @@
#include "renderthread/CanvasContext.h"
#include "tests/common/TestUtils.h"
+#include <gui/BufferItemConsumer.h>
+#include <gui/Surface.h>
+
using namespace android;
using namespace android::uirenderer;
using namespace android::uirenderer::renderthread;
@@ -421,10 +424,20 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, clip_replace) {
EXPECT_EQ(1, surface->canvas()->mDrawCounter);
}
+static sp<Surface> createDummySurface() {
+ sp<IGraphicBufferProducer> producer;
+ sp<IGraphicBufferConsumer> consumer;
+ BufferQueue::createBufferQueue(&producer, &consumer);
+ producer->setMaxDequeuedBufferCount(1);
+ producer->setAsyncMode(true);
+ return new Surface(producer);
+}
+
RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, context_lost) {
+ auto surface = createDummySurface();
auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
EXPECT_FALSE(pipeline->isSurfaceReady());
- EXPECT_TRUE(pipeline->setSurface((Surface*)0x01, SwapBehavior::kSwap_default, ColorMode::SRGB));
+ EXPECT_TRUE(pipeline->setSurface(surface.get(), SwapBehavior::kSwap_default, ColorMode::SRGB, 0));
EXPECT_TRUE(pipeline->isSurfaceReady());
renderThread.destroyRenderingContext();
EXPECT_FALSE(pipeline->isSurfaceReady());
diff --git a/media/Android.bp b/media/Android.bp
index 8746046c220d..5b7b26cef27a 100644
--- a/media/Android.bp
+++ b/media/Android.bp
@@ -64,7 +64,6 @@ filegroup {
"apex/java/android/media/IMediaSession2Service.aidl",
"apex/java/android/media/MediaConstants.java",
"apex/java/android/media/MediaController2.java",
- "apex/java/android/media/MediaItem2.java",
"apex/java/android/media/MediaSession2.java",
"apex/java/android/media/MediaSession2Service.java",
"apex/java/android/media/Session2Command.java",
diff --git a/media/apex/java/android/media/MediaItem2.java b/media/apex/java/android/media/MediaItem2.java
deleted file mode 100644
index ff0d43e41350..000000000000
--- a/media/apex/java/android/media/MediaItem2.java
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import static android.media.MediaMetadata.METADATA_KEY_MEDIA_ID;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.TextUtils;
-import android.util.Log;
-import android.util.Pair;
-
-import com.android.internal.annotations.GuardedBy;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.Executor;
-
-/**
- * A class with information on a single media item with the metadata information.
- * <p>
- * This API is not generally intended for third party application developers.
- * Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
- * <a href="{@docRoot}reference/androidx/media2/package-summary.html">Media2 Library</a>
- * for consistent behavior across all devices.
- * <p>
- */
-public final class MediaItem2 implements Parcelable {
- private static final String TAG = "MediaItem2";
-
- // intentionally less than long.MAX_VALUE.
- // Declare this first to avoid 'illegal forward reference'.
- static final long LONG_MAX = 0x7ffffffffffffffL;
-
- /**
- * Used when a position is unknown.
- *
- * @see #getEndPosition()
- */
- public static final long POSITION_UNKNOWN = LONG_MAX;
-
- public static final @android.annotation.NonNull Parcelable.Creator<MediaItem2> CREATOR =
- new Parcelable.Creator<MediaItem2>() {
- @Override
- public MediaItem2 createFromParcel(Parcel in) {
- return new MediaItem2(in);
- }
-
- @Override
- public MediaItem2[] newArray(int size) {
- return new MediaItem2[size];
- }
- };
-
- private static final long UNKNOWN_TIME = -1;
-
- private final long mStartPositionMs;
- private final long mEndPositionMs;
-
- private final Object mLock = new Object();
-
- @GuardedBy("mLock")
- private MediaMetadata mMetadata;
- @GuardedBy("mLock")
- private final List<Pair<OnMetadataChangedListener, Executor>> mListeners = new ArrayList<>();
-
- /**
- * Used by {@link MediaItem2.Builder}.
- */
- // Note: Needs to be protected when we want to allow 3rd party player to define customized
- // MediaItem2.
- @SuppressWarnings("WeakerAccess") /* synthetic access */
- MediaItem2(Builder builder) {
- this(builder.mMetadata, builder.mStartPositionMs, builder.mEndPositionMs);
- }
-
- /**
- * Used by Parcelable.Creator.
- */
- // Note: Needs to be protected when we want to allow 3rd party player to define customized
- // MediaItem2.
- @SuppressWarnings("WeakerAccess") /* synthetic access */
- MediaItem2(Parcel in) {
- this(in.readParcelable(MediaItem2.class.getClassLoader()), in.readLong(), in.readLong());
- }
-
- @SuppressWarnings("WeakerAccess") /* synthetic access */
- MediaItem2(MediaItem2 item) {
- this(item.mMetadata, item.mStartPositionMs, item.mEndPositionMs);
- }
-
- @SuppressWarnings("WeakerAccess") /* synthetic access */
- MediaItem2(@Nullable MediaMetadata metadata, long startPositionMs, long endPositionMs) {
- if (startPositionMs > endPositionMs) {
- throw new IllegalArgumentException("Illegal start/end position: "
- + startPositionMs + " : " + endPositionMs);
- }
- if (metadata != null && metadata.containsKey(MediaMetadata.METADATA_KEY_DURATION)) {
- long durationMs = metadata.getLong(MediaMetadata.METADATA_KEY_DURATION);
- if (durationMs != UNKNOWN_TIME && endPositionMs != POSITION_UNKNOWN
- && endPositionMs > durationMs) {
- throw new IllegalArgumentException("endPositionMs shouldn't be greater than"
- + " duration in the metdata, endPositionMs=" + endPositionMs
- + ", durationMs=" + durationMs);
- }
- }
- mMetadata = metadata;
- mStartPositionMs = startPositionMs;
- mEndPositionMs = endPositionMs;
- }
-
- @Override
- public String toString() {
- final StringBuilder sb = new StringBuilder(getClass().getSimpleName());
- synchronized (mLock) {
- sb.append("{mMetadata=").append(mMetadata);
- sb.append(", mStartPositionMs=").append(mStartPositionMs);
- sb.append(", mEndPositionMs=").append(mEndPositionMs);
- sb.append('}');
- }
- return sb.toString();
- }
-
- /**
- * Sets metadata. If the metadata is not {@code null}, its id should be matched with this
- * instance's media id.
- *
- * @param metadata metadata to update
- * @see MediaMetadata#METADATA_KEY_MEDIA_ID
- */
- public void setMetadata(@Nullable MediaMetadata metadata) {
- List<Pair<OnMetadataChangedListener, Executor>> listeners = new ArrayList<>();
- synchronized (mLock) {
- if (mMetadata != null && metadata != null
- && !TextUtils.equals(getMediaId(), metadata.getString(METADATA_KEY_MEDIA_ID))) {
- Log.d(TAG, "MediaItem2's media ID shouldn't be changed");
- return;
- }
- mMetadata = metadata;
- listeners.addAll(mListeners);
- }
-
- for (Pair<OnMetadataChangedListener, Executor> pair : listeners) {
- final OnMetadataChangedListener listener = pair.first;
- pair.second.execute(new Runnable() {
- @Override
- public void run() {
- listener.onMetadataChanged(MediaItem2.this);
- }
- });
- }
- }
-
- /**
- * Gets the metadata of the media.
- *
- * @return metadata from the session
- */
- public @Nullable MediaMetadata getMetadata() {
- synchronized (mLock) {
- return mMetadata;
- }
- }
-
- /**
- * Return the position in milliseconds at which the playback will start.
- * @return the position in milliseconds at which the playback will start
- */
- public long getStartPosition() {
- return mStartPositionMs;
- }
-
- /**
- * Return the position in milliseconds at which the playback will end.
- * {@link #POSITION_UNKNOWN} means ending at the end of source content.
- * @return the position in milliseconds at which the playback will end
- */
- public long getEndPosition() {
- return mEndPositionMs;
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeParcelable(mMetadata, 0);
- dest.writeLong(mStartPositionMs);
- dest.writeLong(mEndPositionMs);
- }
-
- /**
- * Gets the media id for this item. If it's not {@code null}, it's a persistent unique key
- * for the underlying media content.
- *
- * @return media Id from the session
- */
- @Nullable String getMediaId() {
- synchronized (mLock) {
- return mMetadata != null
- ? mMetadata.getString(METADATA_KEY_MEDIA_ID) : null;
- }
- }
-
- void addOnMetadataChangedListener(Executor executor, OnMetadataChangedListener listener) {
- synchronized (mLock) {
- for (Pair<OnMetadataChangedListener, Executor> pair : mListeners) {
- if (pair.first == listener) {
- return;
- }
- }
- mListeners.add(new Pair<>(listener, executor));
- }
- }
-
- void removeOnMetadataChangedListener(OnMetadataChangedListener listener) {
- synchronized (mLock) {
- for (int i = mListeners.size() - 1; i >= 0; i--) {
- if (mListeners.get(i).first == listener) {
- mListeners.remove(i);
- return;
- }
- }
- }
- }
-
- /**
- * Builder for {@link MediaItem2}.
- */
- public static final class Builder {
- @SuppressWarnings("WeakerAccess") /* synthetic access */
- MediaMetadata mMetadata;
- @SuppressWarnings("WeakerAccess") /* synthetic access */
- long mStartPositionMs = 0;
- @SuppressWarnings("WeakerAccess") /* synthetic access */
- long mEndPositionMs = POSITION_UNKNOWN;
-
- /**
- * Set the metadata of this instance. {@code null} for unset.
- *
- * @param metadata metadata
- * @return this instance for chaining
- */
- public @NonNull Builder setMetadata(@Nullable MediaMetadata metadata) {
- mMetadata = metadata;
- return this;
- }
-
- /**
- * Sets the start position in milliseconds at which the playback will start.
- * Any negative number is treated as 0.
- *
- * @param position the start position in milliseconds at which the playback will start
- * @return the same Builder instance.
- */
- public @NonNull Builder setStartPosition(long position) {
- if (position < 0) {
- position = 0;
- }
- mStartPositionMs = position;
- return this;
- }
-
- /**
- * Sets the end position in milliseconds at which the playback will end.
- * Any negative number is treated as maximum length of the media item.
- *
- * @param position the end position in milliseconds at which the playback will end
- * @return the same Builder instance.
- */
- public @NonNull Builder setEndPosition(long position) {
- if (position < 0) {
- position = POSITION_UNKNOWN;
- }
- mEndPositionMs = position;
- return this;
- }
-
- /**
- * Build {@link MediaItem2}.
- *
- * @return a new {@link MediaItem2}.
- */
- public @NonNull MediaItem2 build() {
- return new MediaItem2(this);
- }
- }
-
- interface OnMetadataChangedListener {
- void onMetadataChanged(MediaItem2 item);
- }
-}
diff --git a/media/apex/java/android/media/Session2Command.java b/media/apex/java/android/media/Session2Command.java
index 7f73dc123063..7c752e198f3a 100644
--- a/media/apex/java/android/media/Session2Command.java
+++ b/media/apex/java/android/media/Session2Command.java
@@ -30,7 +30,7 @@ import java.util.Objects;
* <p>
* If {@link #getCommandCode()} isn't {@link #COMMAND_CODE_CUSTOM}), it's predefined command.
* If {@link #getCommandCode()} is {@link #COMMAND_CODE_CUSTOM}), it's custom command and
- * {@link #getCustomCommand()} shouldn't be {@code null}.
+ * {@link #getCustomAction()} shouldn't be {@code null}.
* <p>
* Refer to the
* <a href="{@docRoot}reference/androidx/media2/SessionCommand2.html">AndroidX SessionCommand</a>
@@ -63,8 +63,8 @@ public final class Session2Command implements Parcelable {
private final int mCommandCode;
// Nonnull if it's custom command
- private final String mCustomCommand;
- private final Bundle mExtras;
+ private final String mCustomAction;
+ private final Bundle mCustomExtras;
/**
* Constructor for creating a command predefined in AndroidX media2.
@@ -76,8 +76,8 @@ public final class Session2Command implements Parcelable {
throw new IllegalArgumentException("commandCode shouldn't be COMMAND_CODE_CUSTOM");
}
mCommandCode = commandCode;
- mCustomCommand = null;
- mExtras = null;
+ mCustomAction = null;
+ mCustomExtras = null;
}
/**
@@ -91,8 +91,8 @@ public final class Session2Command implements Parcelable {
throw new IllegalArgumentException("action shouldn't be null");
}
mCommandCode = COMMAND_CODE_CUSTOM;
- mCustomCommand = action;
- mExtras = extras;
+ mCustomAction = action;
+ mCustomExtras = extras;
}
/**
@@ -101,8 +101,8 @@ public final class Session2Command implements Parcelable {
@SuppressWarnings("WeakerAccess") /* synthetic access */
Session2Command(Parcel in) {
mCommandCode = in.readInt();
- mCustomCommand = in.readString();
- mExtras = in.readBundle();
+ mCustomAction = in.readString();
+ mCustomExtras = in.readBundle();
}
/**
@@ -118,8 +118,8 @@ public final class Session2Command implements Parcelable {
* This will return {@code null} for a predefined command.
*/
@Nullable
- public String getCustomCommand() {
- return mCustomCommand;
+ public String getCustomAction() {
+ return mCustomAction;
}
/**
@@ -127,8 +127,8 @@ public final class Session2Command implements Parcelable {
* This will return {@code null} for a predefined command.
*/
@Nullable
- public Bundle getExtras() {
- return mExtras;
+ public Bundle getCustomExtras() {
+ return mCustomExtras;
}
@Override
@@ -142,8 +142,8 @@ public final class Session2Command implements Parcelable {
throw new IllegalArgumentException("parcel shouldn't be null");
}
dest.writeInt(mCommandCode);
- dest.writeString(mCustomCommand);
- dest.writeBundle(mExtras);
+ dest.writeString(mCustomAction);
+ dest.writeBundle(mCustomExtras);
}
@Override
@@ -153,12 +153,12 @@ public final class Session2Command implements Parcelable {
}
Session2Command other = (Session2Command) obj;
return mCommandCode == other.mCommandCode
- && TextUtils.equals(mCustomCommand, other.mCustomCommand);
+ && TextUtils.equals(mCustomAction, other.mCustomAction);
}
@Override
public int hashCode() {
- return Objects.hash(mCustomCommand, mCommandCode);
+ return Objects.hash(mCustomAction, mCommandCode);
}
/**
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index 1ccaa0fe1795..e655460c2ba1 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -535,6 +535,23 @@ public final class AudioAttributes implements Parcelable {
}
/**
+ * Return the capture policy.
+ * @return the capture policy set by {@link Builder#setAllowedCapturePolicy(int)} or
+ * the default if it was not called.
+ */
+ @CapturePolicy
+ public int getAllowedCapturePolicy() {
+ if ((mFlags & FLAG_NO_SYSTEM_CAPTURE) == FLAG_NO_SYSTEM_CAPTURE) {
+ return ALLOW_CAPTURE_BY_NONE;
+ }
+ if ((mFlags & FLAG_NO_MEDIA_PROJECTION) == FLAG_NO_MEDIA_PROJECTION) {
+ return ALLOW_CAPTURE_BY_SYSTEM;
+ }
+ return ALLOW_CAPTURE_BY_ALL;
+ }
+
+
+ /**
* Builder class for {@link AudioAttributes} objects.
* <p> Here is an example where <code>Builder</code> is used to define the
* {@link AudioAttributes} to be used by a new <code>AudioTrack</code> instance:
diff --git a/media/java/android/media/AudioFocusInfo.java b/media/java/android/media/AudioFocusInfo.java
index 3aaa7dfc05d0..ee89509951df 100644
--- a/media/java/android/media/AudioFocusInfo.java
+++ b/media/java/android/media/AudioFocusInfo.java
@@ -18,6 +18,7 @@ package android.media;
import android.annotation.NonNull;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -27,6 +28,7 @@ import java.util.Objects;
* @hide
* A class to encapsulate information about an audio focus owner or request.
*/
+@TestApi
@SystemApi
public final class AudioFocusInfo implements Parcelable {
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 8f699eb9e6fc..d3471378b9d9 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -26,6 +26,7 @@ import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.SystemService;
+import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.app.NotificationManager;
import android.app.PendingIntent;
@@ -1512,7 +1513,22 @@ public class AudioManager {
int result = AudioSystem.setAllowedCapturePolicy(Process.myUid(), flags);
if (result != AudioSystem.AUDIO_STATUS_OK) {
Log.e(TAG, "Could not setAllowedCapturePolicy: " + result);
+ return;
}
+ mCapturePolicy = capturePolicy;
+ }
+
+ @AudioAttributes.CapturePolicy
+ private int mCapturePolicy = AudioAttributes.ALLOW_CAPTURE_BY_ALL;
+
+ /**
+ * Return the capture policy.
+ * @return the capture policy set by {@link #setAllowedCapturePolicy(int)} or
+ * the default if it was not called.
+ */
+ @AudioAttributes.CapturePolicy
+ public int getAllowedCapturePolicy() {
+ return mCapturePolicy;
}
//====================================================================
@@ -3035,6 +3051,7 @@ public class AudioManager {
* @param requestResult the result to the focus request to be passed to the requester
* @param ap a valid registered {@link AudioPolicy} configured as a focus policy.
*/
+ @TestApi
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
public void setFocusRequestResult(@NonNull AudioFocusInfo afi,
@@ -3074,6 +3091,7 @@ public class AudioManager {
* if there was an error sending the request.
* @throws NullPointerException if the {@link AudioFocusInfo} or {@link AudioPolicy} are null.
*/
+ @TestApi
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
public int dispatchAudioFocusChange(@NonNull AudioFocusInfo afi, int focusChange,
@@ -3336,6 +3354,7 @@ public class AudioManager {
* {@link android.Manifest.permission#MODIFY_AUDIO_ROUTING} permission,
* {@link #SUCCESS} otherwise.
*/
+ @TestApi
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
public int registerAudioPolicy(@NonNull AudioPolicy policy) {
@@ -3370,6 +3389,7 @@ public class AudioManager {
* Unregisters an {@link AudioPolicy} asynchronously.
* @param policy the non-null {@link AudioPolicy} to unregister.
*/
+ @TestApi
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
public void unregisterAudioPolicyAsync(@NonNull AudioPolicy policy) {
@@ -3396,6 +3416,7 @@ public class AudioManager {
* associated with mixes of this policy.
* @param policy the non-null {@link AudioPolicy} to unregister.
*/
+ @TestApi
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
public void unregisterAudioPolicy(@NonNull AudioPolicy policy) {
@@ -3410,6 +3431,20 @@ public class AudioManager {
}
}
+ /**
+ * @hide
+ * @return true if an AudioPolicy was previously registered
+ */
+ @TestApi
+ public boolean hasRegisteredDynamicPolicy() {
+ final IAudioService service = getService();
+ try {
+ return service.hasRegisteredDynamicPolicy();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
//====================================================================
// Notification of playback activity & playback configuration
/**
diff --git a/media/java/android/media/AudioPlaybackCaptureConfiguration.java b/media/java/android/media/AudioPlaybackCaptureConfiguration.java
index d61f14c25c7e..fe5005a7cc9a 100644
--- a/media/java/android/media/AudioPlaybackCaptureConfiguration.java
+++ b/media/java/android/media/AudioPlaybackCaptureConfiguration.java
@@ -20,11 +20,14 @@ import android.annotation.NonNull;
import android.media.AudioAttributes.AttributeUsage;
import android.media.audiopolicy.AudioMix;
import android.media.audiopolicy.AudioMixingRule;
+import android.media.audiopolicy.AudioMixingRule.AudioMixMatchCriterion;
import android.media.projection.MediaProjection;
import android.os.RemoteException;
import com.android.internal.util.Preconditions;
+import java.util.function.ToIntFunction;
+
/**
* Configuration for capturing audio played by other apps.
*
@@ -83,6 +86,39 @@ public final class AudioPlaybackCaptureConfiguration {
return mProjection;
}
+ /** @return the usages passed to {@link Builder#addMatchingUsage(int)}. */
+ @AttributeUsage
+ public @NonNull int[] getMatchingUsages() {
+ return getIntPredicates(AudioMixingRule.RULE_MATCH_ATTRIBUTE_USAGE,
+ criterion -> criterion.getAudioAttributes().getUsage());
+ }
+
+ /** @return the UIDs passed to {@link Builder#addMatchingUid(int)}. */
+ public @NonNull int[] getMatchingUids() {
+ return getIntPredicates(AudioMixingRule.RULE_MATCH_UID,
+ criterion -> criterion.getIntProp());
+ }
+
+ /** @return the usages passed to {@link Builder#excludeUsage(int)}. */
+ @AttributeUsage
+ public @NonNull int[] getExcludeUsages() {
+ return getIntPredicates(AudioMixingRule.RULE_EXCLUDE_ATTRIBUTE_USAGE,
+ criterion -> criterion.getAudioAttributes().getUsage());
+ }
+
+ /** @return the UIDs passed to {@link Builder#excludeUid(int)}. */
+ public @NonNull int[] getExcludeUids() {
+ return getIntPredicates(AudioMixingRule.RULE_EXCLUDE_UID,
+ criterion -> criterion.getIntProp());
+ }
+
+ private int[] getIntPredicates(int rule,
+ ToIntFunction<AudioMixMatchCriterion> getPredicate) {
+ return mAudioMixingRule.getCriteria().stream()
+ .filter(criterion -> criterion.getRule() == rule)
+ .mapToInt(getPredicate)
+ .toArray();
+ }
/**
* Returns a mix that routes audio back into the app while still playing it from the speakers.
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 790e189e9109..d9d614f7ead4 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -975,13 +975,9 @@ public class AudioTrack extends PlayerBase
throw new UnsupportedOperationException(
"Offload and low latency modes are incompatible");
}
- if (mAttributes.getUsage() != AudioAttributes.USAGE_MEDIA) {
- throw new UnsupportedOperationException(
- "Cannot create AudioTrack, offload requires USAGE_MEDIA");
- }
if (!AudioSystem.isOffloadSupported(mFormat, mAttributes)) {
throw new UnsupportedOperationException(
- "Cannot create AudioTrack, offload format not supported");
+ "Cannot create AudioTrack, offload format / attributes not supported");
}
}
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index eddbee46252e..85de00a2a989 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -211,6 +211,8 @@ interface IAudioService {
void setVolumePolicy(in VolumePolicy policy);
+ boolean hasRegisteredDynamicPolicy();
+
void registerRecordingCallback(in IRecordingConfigDispatcher rcdb);
oneway void unregisterRecordingCallback(in IRecordingConfigDispatcher rcdb);
diff --git a/media/java/android/media/audiopolicy/AudioMix.java b/media/java/android/media/audiopolicy/AudioMix.java
index 09f17c099609..2f03d26830f2 100644
--- a/media/java/android/media/audiopolicy/AudioMix.java
+++ b/media/java/android/media/audiopolicy/AudioMix.java
@@ -19,6 +19,7 @@ package android.media.audiopolicy;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.media.AudioDeviceInfo;
import android.media.AudioFormat;
@@ -31,6 +32,7 @@ import java.util.Objects;
/**
* @hide
*/
+@TestApi
@SystemApi
public class AudioMix {
diff --git a/media/java/android/media/audiopolicy/AudioMixingRule.java b/media/java/android/media/audiopolicy/AudioMixingRule.java
index 947b06cdf6b2..ed2fdae71fb0 100644
--- a/media/java/android/media/audiopolicy/AudioMixingRule.java
+++ b/media/java/android/media/audiopolicy/AudioMixingRule.java
@@ -18,6 +18,7 @@ package android.media.audiopolicy;
import android.annotation.NonNull;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.media.AudioAttributes;
import android.os.Parcel;
@@ -41,6 +42,7 @@ import java.util.Objects;
* .build();
* </pre>
*/
+@TestApi
@SystemApi
public class AudioMixingRule {
@@ -92,7 +94,8 @@ public class AudioMixingRule {
public static final int RULE_EXCLUDE_UID =
RULE_EXCLUSION_MASK | RULE_MATCH_UID;
- static final class AudioMixMatchCriterion {
+ /** @hide */
+ public static final class AudioMixMatchCriterion {
@UnsupportedAppUsage
final AudioAttributes mAttr;
@UnsupportedAppUsage
@@ -137,6 +140,10 @@ public class AudioMixingRule {
dest.writeInt(-1);
}
}
+
+ public AudioAttributes getAudioAttributes() { return mAttr; }
+ public int getIntProp() { return mIntProp; }
+ public int getRule() { return mRule; }
}
boolean isAffectingUsage(int usage) {
@@ -163,7 +170,8 @@ public class AudioMixingRule {
int getTargetMixType() { return mTargetMixType; }
@UnsupportedAppUsage
private final ArrayList<AudioMixMatchCriterion> mCriteria;
- ArrayList<AudioMixMatchCriterion> getCriteria() { return mCriteria; }
+ /** @hide */
+ public ArrayList<AudioMixMatchCriterion> getCriteria() { return mCriteria; }
@UnsupportedAppUsage
private boolean mAllowPrivilegedPlaybackCapture = false;
diff --git a/media/java/android/media/audiopolicy/AudioPolicy.java b/media/java/android/media/audiopolicy/AudioPolicy.java
index 00f601388164..1cd60f78886e 100644
--- a/media/java/android/media/audiopolicy/AudioPolicy.java
+++ b/media/java/android/media/audiopolicy/AudioPolicy.java
@@ -20,6 +20,7 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.app.ActivityManager;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -55,6 +56,7 @@ import java.util.List;
* @hide
* AudioPolicy provides access to the management of audio routing and audio focus.
*/
+@TestApi
@SystemApi
public class AudioPolicy {
@@ -237,6 +239,7 @@ public class AudioPolicy {
}
/**
+ * @hide
* Test method to declare whether this audio focus policy is for test purposes only.
* Having a test policy registered will disable the current focus policy and replace it
* with this test policy. When unregistered, the previous focus policy will be restored.
@@ -245,6 +248,7 @@ public class AudioPolicy {
* @param isTestFocusPolicy true if the focus policy to register is for testing purposes.
* @return the same Builder instance
*/
+ @TestApi
@NonNull
public Builder setIsTestFocusPolicy(boolean isTestFocusPolicy) {
mIsTestFocusPolicy = isTestFocusPolicy;
diff --git a/packages/SettingsLib/src/com/android/settingslib/graph/ThemedBatteryDrawable.kt b/packages/SettingsLib/src/com/android/settingslib/graph/ThemedBatteryDrawable.kt
index 239b1d464ea3..eff02d24431e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/graph/ThemedBatteryDrawable.kt
+++ b/packages/SettingsLib/src/com/android/settingslib/graph/ThemedBatteryDrawable.kt
@@ -173,6 +173,7 @@ open class ThemedBatteryDrawable(private val context: Context, frameColor: Int)
}
override fun draw(c: Canvas) {
+ c.saveLayer(null, null)
unifiedPath.reset()
levelPath.reset()
levelRect.set(fillRect)
@@ -243,6 +244,7 @@ open class ThemedBatteryDrawable(private val context: Context, frameColor: Int)
// And draw the plus sign on top of the fill
c.drawPath(scaledPlus, errorPaint)
}
+ c.restore()
}
private fun batteryColorForLevel(level: Int): Int {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index fd557083aefd..1d19fecac8c9 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -665,9 +665,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
boolean wasRunning = mFingerprintRunningState == BIOMETRIC_STATE_RUNNING;
boolean isRunning = fingerprintRunningState == BIOMETRIC_STATE_RUNNING;
mFingerprintRunningState = fingerprintRunningState;
- if (DEBUG) Log.v(TAG, "Fingerprint State: " + mFingerprintRunningState);
+ Log.d(TAG, "fingerprintRunningState: " + mFingerprintRunningState);
// Clients of KeyguardUpdateMonitor don't care about the internal state about the
- // asynchronousness of the cancel cycle. So only notify them if the actualy running state
+ // asynchronousness of the cancel cycle. So only notify them if the actually running state
// has changed.
if (wasRunning != isRunning) {
notifyFingerprintRunningStateChanged();
@@ -818,9 +818,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
boolean wasRunning = mFaceRunningState == BIOMETRIC_STATE_RUNNING;
boolean isRunning = faceRunningState == BIOMETRIC_STATE_RUNNING;
mFaceRunningState = faceRunningState;
- if (DEBUG) Log.v(TAG, "Face State: " + mFaceRunningState);
+ Log.d(TAG, "faceRunningState: " + mFaceRunningState);
// Clients of KeyguardUpdateMonitor don't care about the internal state or about the
- // asynchronousness of the cancel cycle. So only notify them if the actualy running state
+ // asynchronousness of the cancel cycle. So only notify them if the actually running state
// has changed.
if (wasRunning != isRunning) {
notifyFaceRunningStateChanged();
@@ -2045,7 +2045,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
*/
public void onKeyguardVisibilityChanged(boolean showing) {
checkIsHandlerThread();
- if (DEBUG) Log.d(TAG, "onKeyguardVisibilityChanged(" + showing + ")");
+ Log.d(TAG, "onKeyguardVisibilityChanged(" + showing + ")");
mKeyguardIsVisible = showing;
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
index 329b001a0a7c..6c1d1f91830f 100644
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
@@ -180,10 +180,6 @@ public class BatteryMeterView extends LinearLayout implements
setClipChildren(false);
setClipToPadding(false);
Dependency.get(ConfigurationController.class).observe(viewAttachLifecycle(this), this);
-
- // Needed for PorderDuff.Mode.CLEAR operations to work properly, but redraws don't happen
- // enough to justify a hardware layer.
- setLayerType(LAYER_TYPE_SOFTWARE, null);
}
private void setupLayoutTransition() {
@@ -405,10 +401,10 @@ public class BatteryMeterView extends LinearLayout implements
|| mShowPercentMode == MODE_ON || mShowPercentMode == MODE_ESTIMATE) {
if (!showing) {
mBatteryPercentView = loadPercentView();
- if (mTextColor != 0) mBatteryPercentView.setTextColor(mTextColor);
if (mPercentageStyleId != 0) { // Only set if specified as attribute
mBatteryPercentView.setTextAppearance(mPercentageStyleId);
}
+ if (mTextColor != 0) mBatteryPercentView.setTextColor(mTextColor);
updatePercentText();
addView(mBatteryPercentView,
new ViewGroup.LayoutParams(
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 72559f56aaa1..56dbe2b2cd99 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -608,6 +608,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
mConnectionCallbacks.add(listener);
listener.onConnectionChanged(mOverviewProxy != null);
listener.onInteractionFlagsChanged(mInteractionFlags);
+ listener.onBackButtonAlphaChanged(mBackButtonAlpha, false);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java
index 907b3ad08c8c..85848cafbfcb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java
@@ -151,7 +151,7 @@ public class NavigationBarController implements Callbacks {
? Dependency.get(AutoHideController.class)
: new AutoHideController(context, mHandler);
navBar.setAutoHideController(autoHideController);
- navBar.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
+ navBar.restoreSystemUiVisibilityState();
mNavigationBars.append(displayId, navBar);
if (result != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
index 4ced702f479e..959342b27b56 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
@@ -141,6 +141,11 @@ public class ButtonDispatcher {
public void setVisibility(int visibility) {
if (mVisibility == visibility) return;
+ if (mFadeAnimator != null) {
+ mFadeAnimator.cancel();
+ mFadeAnimator = null;
+ }
+
mVisibility = visibility;
final int N = mViews.size();
for (int i = 0; i < N; i++) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index 9eecdb924448..4d2b56c5e81a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -123,6 +123,7 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
private static final boolean DEBUG = false;
private static final String EXTRA_DISABLE_STATE = "disabled_state";
private static final String EXTRA_DISABLE2_STATE = "disabled2_state";
+ private static final String EXTRA_SYSTEM_UI_VISIBILITY = "system_ui_visibility";
/** Allow some time inbetween the long press for back and recents. */
private static final int LOCK_TO_APP_GESTURE_TOLERENCE = 200;
@@ -156,7 +157,7 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
private Locale mLocale;
private int mLayoutDirection;
- private int mSystemUiVisibility;
+ private int mSystemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE;
private LightBarController mLightBarController;
private AutoHideController mAutoHideController;
@@ -277,6 +278,7 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
if (savedInstanceState != null) {
mDisabledFlags1 = savedInstanceState.getInt(EXTRA_DISABLE_STATE, 0);
mDisabledFlags2 = savedInstanceState.getInt(EXTRA_DISABLE2_STATE, 0);
+ mSystemUiVisibility = savedInstanceState.getInt(EXTRA_SYSTEM_UI_VISIBILITY, 0);
}
mAccessibilityManagerWrapper.addCallback(mAccessibilityListener);
@@ -363,6 +365,7 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
super.onSaveInstanceState(outState);
outState.putInt(EXTRA_DISABLE_STATE, mDisabledFlags1);
outState.putInt(EXTRA_DISABLE2_STATE, mDisabledFlags2);
+ outState.putInt(EXTRA_SYSTEM_UI_VISIBILITY, mSystemUiVisibility);
if (mNavigationBarView != null) {
mNavigationBarView.getLightTransitionsController().saveState(outState);
}
@@ -492,13 +495,8 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
}
}
- /**
- * Sets System UI flags to {@link NavigationBarFragment}.
- *
- * @see View#setSystemUiVisibility(int)
- */
- public void setSystemUiVisibility(int systemUiVisibility) {
- mSystemUiVisibility = systemUiVisibility;
+ /** Restores the System UI flags saved state to {@link NavigationBarFragment}. */
+ public void restoreSystemUiVisibilityState() {
final int barMode = computeBarMode(0, mSystemUiVisibility);
if (barMode != -1) {
mNavigationBarMode = barMode;
diff --git a/services/accessibility/java/com/android/server/accessibility/MotionEventInjector.java b/services/accessibility/java/com/android/server/accessibility/MotionEventInjector.java
index 46e3226bb751..7b6a12822faa 100644
--- a/services/accessibility/java/com/android/server/accessibility/MotionEventInjector.java
+++ b/services/accessibility/java/com/android/server/accessibility/MotionEventInjector.java
@@ -111,6 +111,15 @@ public class MotionEventInjector extends BaseEventStreamTransformation implement
@Override
public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
+ // MotionEventInjector would cancel any injected gesture when any MotionEvent arrives.
+ // For user using an external device to control the pointer movement, it's almost
+ // impossible to perform the gestures. Any slightly unintended movement results in the
+ // cancellation of the gesture.
+ if ((event.isFromSource(InputDevice.SOURCE_MOUSE)
+ && event.getActionMasked() == MotionEvent.ACTION_HOVER_MOVE)
+ && mOpenGesturesInProgress.get(EVENT_SOURCE, false)) {
+ return;
+ }
cancelAnyPendingInjectedEvents();
sendMotionEventToNext(event, rawEvent, policyFlags);
}
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
index 757c2dc7f6f1..7f411d83b34b 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
@@ -60,8 +60,8 @@ import android.util.SparseBooleanArray;
import android.view.contentcapture.ContentCaptureCondition;
import android.view.contentcapture.ContentCaptureHelper;
import android.view.contentcapture.ContentCaptureManager;
+import android.view.contentcapture.DataRemovalRequest;
import android.view.contentcapture.IContentCaptureManager;
-import android.view.contentcapture.UserDataRemovalRequest;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.infra.AbstractRemoteService;
@@ -583,14 +583,14 @@ public final class ContentCaptureManagerService extends
}
@Override
- public void removeUserData(@NonNull UserDataRemovalRequest request) {
+ public void removeData(@NonNull DataRemovalRequest request) {
Preconditions.checkNotNull(request);
assertCalledByPackageOwner(request.getPackageName());
final int userId = UserHandle.getCallingUserId();
synchronized (mLock) {
final ContentCapturePerUserService service = getServiceForUserLocked(userId);
- service.removeUserDataLocked(request);
+ service.removeDataLocked(request);
}
}
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
index 564952697250..b4a1f381f7ff 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
@@ -57,7 +57,7 @@ import android.util.ArraySet;
import android.util.Slog;
import android.util.SparseArray;
import android.view.contentcapture.ContentCaptureCondition;
-import android.view.contentcapture.UserDataRemovalRequest;
+import android.view.contentcapture.DataRemovalRequest;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.infra.WhitelistHelper;
@@ -343,12 +343,12 @@ final class ContentCapturePerUserService
}
@GuardedBy("mLock")
- public void removeUserDataLocked(@NonNull UserDataRemovalRequest request) {
+ public void removeDataLocked(@NonNull DataRemovalRequest request) {
if (!isEnabledLocked()) {
return;
}
assertCallerLocked(request.getPackageName());
- mRemoteService.onUserDataRemovalRequest(request);
+ mRemoteService.onDataRemovalRequest(request);
}
@GuardedBy("mLock")
diff --git a/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java b/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java
index 3fa3fdf6d36e..2171033c5a28 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java
@@ -29,7 +29,7 @@ import android.service.contentcapture.IContentCaptureServiceCallback;
import android.service.contentcapture.SnapshotData;
import android.util.Slog;
import android.view.contentcapture.ContentCaptureContext;
-import android.view.contentcapture.UserDataRemovalRequest;
+import android.view.contentcapture.DataRemovalRequest;
import com.android.internal.infra.AbstractMultiplePendingRequestsRemoteService;
import com.android.internal.os.IResultReceiver;
@@ -120,10 +120,10 @@ final class RemoteContentCaptureService
}
/**
- * Called by {@link ContentCaptureServerSession} to request removal of user data.
+ * Called by {@link ContentCaptureServerSession} to request removal of content capture data.
*/
- public void onUserDataRemovalRequest(@NonNull UserDataRemovalRequest request) {
- scheduleAsyncRequest((s) -> s.onUserDataRemovalRequest(request));
+ public void onDataRemovalRequest(@NonNull DataRemovalRequest request) {
+ scheduleAsyncRequest((s) -> s.onDataRemovalRequest(request));
}
/**
diff --git a/services/core/java/com/android/server/BluetoothService.java b/services/core/java/com/android/server/BluetoothService.java
index 6018f008054c..5c5b477352b1 100644
--- a/services/core/java/com/android/server/BluetoothService.java
+++ b/services/core/java/com/android/server/BluetoothService.java
@@ -18,11 +18,10 @@ package com.android.server;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
-import android.os.SystemProperties;
-class BluetoothService extends SystemService {
- private static final String HEADLESS_SYSTEM_USER = "android.car.systemuser.headless";
+import com.android.internal.os.RoSystemProperties;
+class BluetoothService extends SystemService {
private BluetoothManagerService mBluetoothManagerService;
private boolean mInitialized = false;
@@ -48,7 +47,7 @@ class BluetoothService extends SystemService {
publishBinderService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE,
mBluetoothManagerService);
} else if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY &&
- !SystemProperties.getBoolean(HEADLESS_SYSTEM_USER, false)) {
+ !RoSystemProperties.MULTIUSER_HEADLESS_SYSTEM_USER) {
initialize();
}
}
diff --git a/services/core/java/com/android/server/attention/AttentionManagerService.java b/services/core/java/com/android/server/attention/AttentionManagerService.java
index 3dbea0d1978e..411dd794d1bd 100644
--- a/services/core/java/com/android/server/attention/AttentionManagerService.java
+++ b/services/core/java/com/android/server/attention/AttentionManagerService.java
@@ -17,7 +17,6 @@
package com.android.server.attention;
import static android.provider.DeviceConfig.NAMESPACE_ATTENTION_MANAGER_SERVICE;
-import static android.provider.Settings.System.ADAPTIVE_SLEEP;
import static android.service.attention.AttentionService.ATTENTION_FAILURE_CANCELLED;
import static android.service.attention.AttentionService.ATTENTION_FAILURE_UNKNOWN;
@@ -47,7 +46,6 @@ import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.DeviceConfig;
-import android.provider.Settings;
import android.service.attention.AttentionService;
import android.service.attention.AttentionService.AttentionFailureCodes;
import android.service.attention.AttentionService.AttentionSuccessCodes;
@@ -275,19 +273,6 @@ public class AttentionManagerService extends SystemService {
}
}
- /** Disables service dependants. */
- private void disableSelf() {
- final long identity = Binder.clearCallingIdentity();
- try {
- if (DEBUG) {
- Slog.d(LOG_TAG, "Disabling self.");
- }
- Settings.System.putInt(mContext.getContentResolver(), ADAPTIVE_SLEEP, 0);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
-
@GuardedBy("mLock")
private void freeIfInactiveLocked() {
// If we are called here, it means someone used the API again - reset the timer then.
@@ -418,11 +403,6 @@ public class AttentionManagerService extends SystemService {
public void cancelAttentionCheck(AttentionCallbackInternal callbackInternal) {
AttentionManagerService.this.cancelAttentionCheck(callbackInternal);
}
-
- @Override
- public void disableSelf() {
- AttentionManagerService.this.disableSelf();
- }
}
private static final class AttentionCheckCache {
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index b7746477f0f8..44c1715cfed5 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -406,6 +406,10 @@ import java.util.ArrayList;
mAudioService.checkVolumeCecOnHdmiConnection(state, caller);
}
+ /*package*/ boolean hasAudioFocusUsers() {
+ return mAudioService.hasAudioFocusUsers();
+ }
+
//---------------------------------------------------------------------
// Message handling on behalf of helper classes
/*package*/ void postBroadcastScoConnectionState(int state) {
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index 7750bfefae05..91b51b4989d8 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -819,11 +819,12 @@ public final class AudioDeviceInventory {
if (((device == musicDevice) || mDeviceBroker.isInCommunication())
&& (device == devices) && !mDeviceBroker.hasMediaDynamicPolicy()
&& ((musicDevice & AudioSystem.DEVICE_OUT_REMOTE_SUBMIX) == 0)) {
- if (!AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0 /*not looking in past*/)) {
+ if (!AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0 /*not looking in past*/)
+ && !mDeviceBroker.hasAudioFocusUsers()) {
// no media playback, not a "becoming noisy" situation, otherwise it could cause
// the pausing of some apps that are playing remotely
AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent(
- "dropping ACTION_AUDIO_BECOMING_NOISY, no media playback")).printLog(TAG));
+ "dropping ACTION_AUDIO_BECOMING_NOISY")).printLog(TAG));
return 0;
}
mDeviceBroker.postBroadcastBecomingNoisy();
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 77472ed288c3..aee08bb09401 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -1523,9 +1523,11 @@ public class AudioService extends IAudioService.Stub
+ ", flags=" + flags + ", caller=" + caller
+ ", volControlStream=" + mVolumeControlStream
+ ", userSelect=" + mUserSelectedVolumeControlStream);
- sVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_ADJUST_SUGG_VOL, suggestedStreamType,
- direction/*val1*/, flags/*val2*/, new StringBuilder(callingPackage)
- .append("/").append(caller).append(" uid:").append(uid).toString()));
+ if (direction != AudioManager.ADJUST_SAME) {
+ sVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_ADJUST_SUGG_VOL, suggestedStreamType,
+ direction/*val1*/, flags/*val2*/, new StringBuilder(callingPackage)
+ .append("/").append(caller).append(" uid:").append(uid).toString()));
+ }
final int streamType;
synchronized (mForceControlStreamLock) {
// Request lock in case mVolumeControlStream is changed by other thread.
@@ -5578,6 +5580,10 @@ public class AudioService extends IAudioService.Stub
return mMediaFocusControl.getFocusRampTimeMs(focusGain, attr);
}
+ /*package*/ boolean hasAudioFocusUsers() {
+ return mMediaFocusControl.hasAudioFocusUsers();
+ }
+
//==========================================================================================
private boolean readCameraSoundForced() {
return SystemProperties.getBoolean("audio.camerasound.force", false) ||
@@ -6320,6 +6326,11 @@ public class AudioService extends IAudioService.Stub
@Override
public void adjustStreamVolumeForUid(int streamType, int direction, int flags,
String callingPackage, int uid) {
+ if (direction != AudioManager.ADJUST_SAME) {
+ sVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_ADJUST_VOL_UID, streamType,
+ direction/*val1*/, flags/*val2*/, new StringBuilder(callingPackage)
+ .append(" uid:").append(uid).toString()));
+ }
adjustStreamVolume(streamType, direction, flags, callingPackage,
callingPackage, uid);
}
@@ -6660,6 +6671,13 @@ public class AudioService extends IAudioService.Stub
return AudioManager.SUCCESS;
}
+ /** see AudioManager.hasRegisteredDynamicPolicy */
+ public boolean hasRegisteredDynamicPolicy() {
+ synchronized (mAudioPolicies) {
+ return !mAudioPolicies.isEmpty();
+ }
+ }
+
private final Object mExtVolumeControllerLock = new Object();
private IAudioPolicyCallback mExtVolumeController;
private void setExtVolumeController(IAudioPolicyCallback apc) {
diff --git a/services/core/java/com/android/server/audio/AudioServiceEvents.java b/services/core/java/com/android/server/audio/AudioServiceEvents.java
index 7ccb45e97912..d999217bf29b 100644
--- a/services/core/java/com/android/server/audio/AudioServiceEvents.java
+++ b/services/core/java/com/android/server/audio/AudioServiceEvents.java
@@ -94,6 +94,7 @@ public class AudioServiceEvents {
static final int VOL_SET_STREAM_VOL = 2;
static final int VOL_SET_HEARING_AID_VOL = 3;
static final int VOL_SET_AVRCP_VOL = 4;
+ static final int VOL_ADJUST_VOL_UID = 5;
final int mOp;
final int mStream;
@@ -160,6 +161,13 @@ public class AudioServiceEvents {
return new StringBuilder("setAvrcpVolume:")
.append(" index:").append(mVal1)
.toString();
+ case VOL_ADJUST_VOL_UID:
+ return new StringBuilder("adjustStreamVolumeForUid(stream:")
+ .append(AudioSystem.streamToString(mStream))
+ .append(" dir:").append(AudioManager.adjustToString(mVal1))
+ .append(" flags:0x").append(Integer.toHexString(mVal2))
+ .append(") from ").append(mCaller)
+ .toString();
default: return new StringBuilder("FIXME invalid op:").append(mOp).toString();
}
}
diff --git a/services/core/java/com/android/server/audio/MediaFocusControl.java b/services/core/java/com/android/server/audio/MediaFocusControl.java
index 1e58b454a15b..5c93071fd551 100644
--- a/services/core/java/com/android/server/audio/MediaFocusControl.java
+++ b/services/core/java/com/android/server/audio/MediaFocusControl.java
@@ -162,6 +162,12 @@ public class MediaFocusControl implements PlayerFocusEnforcer {
}
}
+ /*package*/ boolean hasAudioFocusUsers() {
+ synchronized (mAudioFocusLock) {
+ return !mFocusStack.empty();
+ }
+ }
+
/**
* Discard the current audio focus owner.
* Notify top of audio focus stack that it lost focus (regardless of possibility to reassign
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index e88d62f58507..3c97c39f70a0 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -4710,10 +4710,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
@ShellCommandResult
private int handleShellCommandEnableDisableInputMethod(
@NonNull ShellCommand shellCommand, boolean enabled) {
+ final int userIdToBeResolved = handleOptionsForCommandsThatOnlyHaveUserOption(shellCommand);
final String imeId = shellCommand.getNextArgRequired();
final PrintWriter out = shellCommand.getOutPrintWriter();
final PrintWriter error = shellCommand.getErrPrintWriter();
- final int userIdToBeResolved = handleOptionsForCommandsThatOnlyHaveUserOption(shellCommand);
synchronized (mMethodMap) {
final int[] userIds = InputMethodUtils.resolveUserId(userIdToBeResolved,
mSettings.getCurrentUserId(), shellCommand.getErrPrintWriter());
@@ -4733,6 +4733,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
*
* <p>You cannot use this helper method if the command has other options.</p>
*
+ * <p>CAVEAT: This method must be called only once before any other
+ * {@link ShellCommand#getNextArg()} and {@link ShellCommand#getNextArgRequired()} for the
+ * main arguments.</p>
+ *
* @param shellCommand {@link ShellCommand} from which options should be obtained.
* @return User ID to be resolved. {@link UserHandle#CURRENT} if not specified.
*/
@@ -4819,10 +4823,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
@BinderThread
@ShellCommandResult
private int handleShellCommandSetInputMethod(@NonNull ShellCommand shellCommand) {
+ final int userIdToBeResolved = handleOptionsForCommandsThatOnlyHaveUserOption(shellCommand);
final String imeId = shellCommand.getNextArgRequired();
final PrintWriter out = shellCommand.getOutPrintWriter();
final PrintWriter error = shellCommand.getErrPrintWriter();
- final int userIdToBeResolved = handleOptionsForCommandsThatOnlyHaveUserOption(shellCommand);
synchronized (mMethodMap) {
final int[] userIds = InputMethodUtils.resolveUserId(userIdToBeResolved,
mSettings.getCurrentUserId(), shellCommand.getErrPrintWriter());
@@ -4864,7 +4868,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
out.print("Input method ");
out.print(imeId);
out.print(" selected for user #");
- error.println(userId);
+ out.println(userId);
}
}
}
diff --git a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
index a2515c8bb8cc..580150ed887e 100644
--- a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
@@ -1228,6 +1228,24 @@ public final class MultiClientInputMethodManagerService {
public boolean isUidAllowedOnDisplay(int displayId, int uid) {
return mIWindowManagerInternal.isUidAllowedOnDisplay(displayId, uid);
}
+
+ @BinderThread
+ @Override
+ public void setActive(int clientId, boolean active) {
+ synchronized (mPerUserData.mLock) {
+ final InputMethodClientInfo clientInfo =
+ mPerUserData.getClientFromIdLocked(clientId);
+ if (clientInfo == null) {
+ Slog.e(TAG, "Unknown clientId=" + clientId);
+ return;
+ }
+ try {
+ clientInfo.mClient.setActive(active, false /* fullscreen */);
+ } catch (RemoteException e) {
+ return;
+ }
+ }
+ }
}
/**
diff --git a/services/core/java/com/android/server/locksettings/PasswordSlotManager.java b/services/core/java/com/android/server/locksettings/PasswordSlotManager.java
index 686ae2bbaede..5cbd237a0722 100644
--- a/services/core/java/com/android/server/locksettings/PasswordSlotManager.java
+++ b/services/core/java/com/android/server/locksettings/PasswordSlotManager.java
@@ -52,10 +52,12 @@ public class PasswordSlotManager {
// This maps each used password slot to the OS image that created it. Password slots are
// integer keys/indices into secure storage. The OS image is recorded as a string. The factory
// image is "host" and GSIs are "gsi<N>" where N >= 1.
- private final Map<Integer, String> mSlotMap;
+ private Map<Integer, String> mSlotMap;
+
+ // Cache the active slots until loadSlotMap() is called.
+ private Set<Integer> mActiveSlots;
public PasswordSlotManager() {
- mSlotMap = loadSlotMap();
}
@VisibleForTesting
@@ -74,6 +76,11 @@ public class PasswordSlotManager {
* @throws RuntimeException
*/
public void refreshActiveSlots(Set<Integer> activeSlots) throws RuntimeException {
+ if (mSlotMap == null) {
+ mActiveSlots = new HashSet<Integer>(activeSlots);
+ return;
+ }
+
// Update which slots are owned by the current image.
final HashSet<Integer> slotsToDelete = new HashSet<Integer>();
for (Map.Entry<Integer, String> entry : mSlotMap.entrySet()) {
@@ -100,6 +107,7 @@ public class PasswordSlotManager {
* @throws RuntimeException
*/
public void markSlotInUse(int slot) throws RuntimeException {
+ ensureSlotMapLoaded();
if (mSlotMap.containsKey(slot) && !mSlotMap.get(slot).equals(getMode())) {
throw new RuntimeException("password slot " + slot + " is not available");
}
@@ -113,6 +121,7 @@ public class PasswordSlotManager {
* @throws RuntimeException
*/
public void markSlotDeleted(int slot) throws RuntimeException {
+ ensureSlotMapLoaded();
if (mSlotMap.containsKey(slot) && mSlotMap.get(slot) != getMode()) {
throw new RuntimeException("password slot " + slot + " cannot be deleted");
}
@@ -126,6 +135,7 @@ public class PasswordSlotManager {
* @return Integer set of all used slots.
*/
public Set<Integer> getUsedSlots() {
+ ensureSlotMapLoaded();
return Collections.unmodifiableSet(mSlotMap.keySet());
}
@@ -167,8 +177,21 @@ public class PasswordSlotManager {
return new HashMap<Integer, String>();
}
+ private void ensureSlotMapLoaded() {
+ if (mSlotMap == null) {
+ mSlotMap = loadSlotMap();
+ if (mActiveSlots != null) {
+ refreshActiveSlots(mActiveSlots);
+ mActiveSlots = null;
+ }
+ }
+ }
+
@VisibleForTesting
protected void saveSlotMap(OutputStream stream) throws IOException {
+ if (mSlotMap == null) {
+ return;
+ }
final Properties props = new Properties();
for (Map.Entry<Integer, String> entry : mSlotMap.entrySet()) {
props.setProperty(entry.getKey().toString(), entry.getValue());
@@ -177,6 +200,9 @@ public class PasswordSlotManager {
}
private void saveSlotMap() {
+ if (mSlotMap == null) {
+ return;
+ }
if (!getSlotMapFile().getParentFile().exists()) {
Slog.w(TAG, "Not saving slot map, " + getSlotMapDir() + " does not exist");
return;
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index ee2e4f573fb9..7f1b25ca3ca3 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -455,7 +455,6 @@ public class NotificationManagerService extends SystemService {
private int mAutoGroupAtCount;
private boolean mIsTelevision;
private boolean mIsAutomotive;
- private boolean mNotificationEffectsEnabledForAutomotive;
private MetricsLogger mMetricsLogger;
private TriPredicate<String, Integer, String> mAllowedManagedServicePackages;
@@ -1687,8 +1686,6 @@ public class NotificationManagerService extends SystemService {
mIsAutomotive =
mPackageManagerClient.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0);
- mNotificationEffectsEnabledForAutomotive =
- resources.getBoolean(R.bool.config_enableServerNotificationEffectsForAutomotive);
mPreferencesHelper.lockChannelsForOEM(getContext().getResources().getStringArray(
com.android.internal.R.array.config_nonBlockableNotificationPackages));
@@ -5563,9 +5560,6 @@ public class NotificationManagerService extends SystemService {
@VisibleForTesting
@GuardedBy("mNotificationLock")
void buzzBeepBlinkLocked(NotificationRecord record) {
- if (mIsAutomotive && !mNotificationEffectsEnabledForAutomotive) {
- return;
- }
boolean buzz = false;
boolean beep = false;
boolean blink = false;
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index c1587dc9f86f..c12ee03fb86d 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -19151,22 +19151,22 @@ public class PackageManagerService extends IPackageManager.Stub
final UserHandle user = action.user;
final int flags = action.flags;
final boolean systemApp = isSystemApp(ps);
- synchronized (mPackages) {
- if (ps.parentPackageName != null
- && (!systemApp || (flags & PackageManager.DELETE_SYSTEM_APP) != 0)) {
- if (DEBUG_REMOVE) {
- Slog.d(TAG, "Uninstalled child package:" + packageName + " for user:"
- + ((user == null) ? UserHandle.USER_ALL : user));
- }
- final int removedUserId = (user != null) ? user.getIdentifier()
- : UserHandle.USER_ALL;
+ if (ps.parentPackageName != null
+ && (!systemApp || (flags & PackageManager.DELETE_SYSTEM_APP) != 0)) {
+ if (DEBUG_REMOVE) {
+ Slog.d(TAG, "Uninstalled child package:" + packageName + " for user:"
+ + ((user == null) ? UserHandle.USER_ALL : user));
+ }
+ final int removedUserId = (user != null) ? user.getIdentifier()
+ : UserHandle.USER_ALL;
- clearPackageStateForUserLIF(ps, removedUserId, outInfo, flags);
+ clearPackageStateForUserLIF(ps, removedUserId, outInfo, flags);
+ synchronized (mPackages) {
markPackageUninstalledForUserLPw(ps, user);
scheduleWritePackageRestrictionsLocked(user);
- return;
}
+ return;
}
final int userId = user == null ? UserHandle.USER_ALL : user.getIdentifier();
@@ -19180,6 +19180,7 @@ public class PackageManagerService extends IPackageManager.Stub
// its data. If this is a system app, we only allow this to happen if
// they have set the special DELETE_SYSTEM_APP which requests different
// semantics than normal for uninstalling system apps.
+ final boolean clearPackageStateAndReturn;
synchronized (mPackages) {
markPackageUninstalledForUserLPw(ps, user);
if (!systemApp) {
@@ -19190,15 +19191,14 @@ public class PackageManagerService extends IPackageManager.Stub
// we need to do is clear this user's data and save that
// it is uninstalled.
if (DEBUG_REMOVE) Slog.d(TAG, "Still installed by other users");
- clearPackageStateForUserLIF(ps, userId, outInfo, flags);
- scheduleWritePackageRestrictionsLocked(user);
- return;
+ clearPackageStateAndReturn = true;
} else {
// We need to set it back to 'installed' so the uninstall
// broadcasts will be sent correctly.
if (DEBUG_REMOVE) Slog.d(TAG, "Not installed by other users, full delete");
ps.setInstalled(true, userId);
mSettings.writeKernelMappingLPr(ps);
+ clearPackageStateAndReturn = false;
}
} else {
// This is a system app, so we assume that the
@@ -19206,10 +19206,15 @@ public class PackageManagerService extends IPackageManager.Stub
// we need to do is clear this user's data and save that
// it is uninstalled.
if (DEBUG_REMOVE) Slog.d(TAG, "Deleting system app");
- clearPackageStateForUserLIF(ps, userId, outInfo, flags);
+ clearPackageStateAndReturn = true;
+ }
+ }
+ if (clearPackageStateAndReturn) {
+ clearPackageStateForUserLIF(ps, userId, outInfo, flags);
+ synchronized (mPackages) {
scheduleWritePackageRestrictionsLocked(user);
- return;
}
+ return;
}
}
@@ -20027,7 +20032,7 @@ public class PackageManagerService extends IPackageManager.Stub
PreferredActivity pa = removed.get(j);
pir.removeFilter(pa);
}
- outUserChanged.setValueAt(thisUserId, true);
+ outUserChanged.put(thisUserId, true);
}
}
}
@@ -20747,8 +20752,16 @@ public class PackageManagerService extends IPackageManager.Stub
}
@Override
- public String getAttentionServicePackageName() {
- return mContext.getString(R.string.config_defaultAttentionService);
+ public @Nullable String getAttentionServicePackageName() {
+ final String flattenedComponentName =
+ mContext.getString(R.string.config_defaultAttentionService);
+ if (flattenedComponentName != null) {
+ ComponentName componentName = ComponentName.unflattenFromString(flattenedComponentName);
+ if (componentName != null && componentName.getPackageName() != null) {
+ return componentName.getPackageName();
+ }
+ }
+ return null;
}
private @Nullable String getDocumenterPackageName() {
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 72d543862c58..803ab2d299e2 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -261,13 +261,13 @@ public class StagingManager {
if (storageManager.supportsCheckpoint()) {
storageManager.startCheckpoint(1 /* numRetries */);
}
- } catch (RemoteException e) {
+ } catch (Exception e) { // TODO(b/130190815) make a RemoteException again
// While StorageManager lives in the same process, the native implementation
// it calls through lives in 'vold'; so, this call can fail if 'vold' isn't
// reachable.
// Since we can live without filesystem checkpointing, just warn in this case
// and continue.
- Slog.w(TAG, "Could not start filesystem checkpoint.");
+ Slog.w(TAG, "Could not start filesystem checkpoint:", e);
}
session.setStagedSessionReady();
diff --git a/services/core/java/com/android/server/power/AttentionDetector.java b/services/core/java/com/android/server/power/AttentionDetector.java
index d9d21babe210..5e829b2d6067 100644
--- a/services/core/java/com/android/server/power/AttentionDetector.java
+++ b/services/core/java/com/android/server/power/AttentionDetector.java
@@ -16,9 +16,14 @@
package com.android.server.power;
+import static android.provider.Settings.System.ADAPTIVE_SLEEP;
+
+import android.Manifest;
import android.attention.AttentionManagerInternal;
import android.attention.AttentionManagerInternal.AttentionCallbackInternal;
+import android.content.ContentResolver;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.database.ContentObserver;
import android.os.Handler;
import android.os.PowerManager;
@@ -83,6 +88,12 @@ public class AttentionDetector {
@VisibleForTesting
protected AttentionManagerInternal mAttentionManager;
+ @VisibleForTesting
+ protected PackageManager mPackageManager;
+
+ @VisibleForTesting
+ protected ContentResolver mContentResolver;
+
/**
* Current wakefulness of the device. {@see PowerManagerInternal}
*/
@@ -137,6 +148,8 @@ public class AttentionDetector {
public void systemReady(Context context) {
updateEnabledFromSettings(context);
+ mPackageManager = context.getPackageManager();
+ mContentResolver = context.getContentResolver();
mAttentionManager = LocalServices.getService(AttentionManagerInternal.class);
mMaximumExtensionMillis = context.getResources().getInteger(
com.android.internal.R.integer.config_attentionMaximumExtension);
@@ -162,6 +175,11 @@ public class AttentionDetector {
return nextScreenDimming;
}
+ if (!serviceHasSufficientPermissions()) {
+ Settings.System.putInt(mContentResolver, ADAPTIVE_SLEEP, 0);
+ return nextScreenDimming;
+ }
+
final long now = SystemClock.uptimeMillis();
final long whenToCheck = nextScreenDimming - getAttentionTimeout();
final long whenToStopExtending = mLastUserActivityTime + mMaximumExtensionMillis;
@@ -263,6 +281,18 @@ public class AttentionDetector {
return mAttentionManager != null && mAttentionManager.isAttentionServiceSupported();
}
+ /**
+ * Returns {@code true} if the attention service has sufficient permissions, disables the
+ * depending features otherwise.
+ */
+ @VisibleForTesting
+ boolean serviceHasSufficientPermissions() {
+ final String attentionPackage = mPackageManager.getAttentionServicePackageName();
+ return attentionPackage != null && mPackageManager.checkPermission(
+ Manifest.permission.CAMERA, attentionPackage)
+ == PackageManager.PERMISSION_GRANTED;
+ }
+
public void dump(PrintWriter pw) {
pw.print("AttentionDetector:");
pw.print(" mMaximumExtensionMillis=" + mMaximumExtensionMillis);
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index 10ed88f49231..44ed070fda23 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -2084,6 +2084,9 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
e.writeBoolean(Settings.Secure.getIntForUser(mContext.getContentResolver(),
Settings.Secure.FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION, 0,
userId) != 0);
+ e.writeBoolean(Settings.Secure.getIntForUser(mContext.getContentResolver(),
+ Settings.Secure.FACE_UNLOCK_DIVERSITY_REQUIRED, 1,
+ userId) != 0);
pulledData.add(e);
}
diff --git a/services/core/java/com/android/server/wm/ActivityStartController.java b/services/core/java/com/android/server/wm/ActivityStartController.java
index b287a0b011e7..7eac07c47741 100644
--- a/services/core/java/com/android/server/wm/ActivityStartController.java
+++ b/services/core/java/com/android/server/wm/ActivityStartController.java
@@ -457,7 +457,7 @@ public class ActivityStartController {
"pendingActivityLaunch");
try {
starter.startResolvedActivity(pal.r, pal.sourceRecord, null, null, pal.startFlags,
- resume, pal.r.pendingOptions, null, null /* outRecords */);
+ resume, pal.r.pendingOptions, null);
} catch (Exception e) {
Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
pal.sendErrorResult(e.getMessage());
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 473a8757f09f..ea9477f7bbc4 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -544,11 +544,17 @@ class ActivityStarter {
*/
int startResolvedActivity(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
- int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
- ActivityRecord[] outActivity) {
+ int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
try {
- return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
- doResume, options, inTask, outActivity);
+ mSupervisor.getActivityMetricsLogger().notifyActivityLaunching(r.intent);
+ mLastStartReason = "startResolvedActivity";
+ mLastStartActivityTimeMs = System.currentTimeMillis();
+ mLastStartActivityRecord[0] = r;
+ mLastStartActivityResult = startActivity(r, sourceRecord, voiceSession, voiceInteractor,
+ startFlags, doResume, options, inTask, mLastStartActivityRecord);
+ mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(mLastStartActivityResult,
+ mLastStartActivityRecord[0]);
+ return mLastStartActivityResult;
} finally {
onExecutionComplete();
}
@@ -937,7 +943,7 @@ class ActivityStarter {
|| callingUid == Process.NFC_UID) {
return false;
}
- // don't abort if the callingUid is in the foreground or is a persistent system process
+ // don't abort if the callingUid has a visible window or is a persistent system process
final int callingUidProcState = mService.getUidState(callingUid);
final boolean callingUidHasAnyVisibleWindow =
mService.mWindowManager.mRoot.isAnyNonToastWindowVisibleForUid(callingUid);
@@ -946,7 +952,7 @@ class ActivityStarter {
|| callingUidProcState == ActivityManager.PROCESS_STATE_BOUND_TOP;
final boolean isCallingUidPersistentSystemProcess = (callingUid == Process.SYSTEM_UID)
|| callingUidProcState <= ActivityManager.PROCESS_STATE_PERSISTENT_UI;
- if (isCallingUidForeground || isCallingUidPersistentSystemProcess) {
+ if (callingUidHasAnyVisibleWindow || isCallingUidPersistentSystemProcess) {
return false;
}
// take realCallingUid into consideration
@@ -965,8 +971,8 @@ class ActivityStarter {
: (realCallingUid == Process.SYSTEM_UID)
|| realCallingUidProcState <= ActivityManager.PROCESS_STATE_PERSISTENT_UI;
if (realCallingUid != callingUid) {
- // don't abort if the realCallingUid is in the foreground and callingUid isn't
- if (isRealCallingUidForeground) {
+ // don't abort if the realCallingUid has a visible window
+ if (realCallingUidHasAnyVisibleWindow) {
return false;
}
// if the realCallingUid is a persistent system process, abort if the IntentSender
@@ -980,35 +986,6 @@ class ActivityStarter {
return false;
}
}
- // If we don't have callerApp at this point, no caller was provided to startActivity().
- // That's the case for PendingIntent-based starts, since the creator's process might not be
- // up and alive. If that's the case, we retrieve the WindowProcessController for the send()
- // caller, so that we can make the decision based on its foreground/whitelisted state.
- if (callerApp == null) {
- callerApp = mService.getProcessController(realCallingPid, realCallingUid);
- }
- if (callerApp != null) {
- // don't abort if the callerApp has any visible activity
- if (callerApp.hasForegroundActivities()) {
- return false;
- }
- // don't abort if the callerApp is instrumenting with background activity starts privs
- if (callerApp.isInstrumentingWithBackgroundActivityStartPrivileges()) {
- return false;
- }
- // don't abort if the caller is currently temporarily whitelisted
- if (callerApp.areBackgroundActivityStartsAllowed()) {
- return false;
- }
- // don't abort if the caller has an activity in any foreground task
- if (callerApp.hasActivityInVisibleTask()) {
- return false;
- }
- // don't abort if the caller is bound by a UID that's currently foreground
- if (isBoundByForegroundUid(callerApp)) {
- return false;
- }
- }
// don't abort if the callingUid has START_ACTIVITIES_FROM_BACKGROUND permission
if (mService.checkPermission(START_ACTIVITIES_FROM_BACKGROUND, callingPid, callingUid)
== PERMISSION_GRANTED) {
@@ -1033,6 +1010,33 @@ class ActivityStarter {
+ " temporarily whitelisted. This will not be supported in future Q builds.");
return false;
}
+ // If we don't have callerApp at this point, no caller was provided to startActivity().
+ // That's the case for PendingIntent-based starts, since the creator's process might not be
+ // up and alive. If that's the case, we retrieve the WindowProcessController for the send()
+ // caller, so that we can make the decision based on its foreground/whitelisted state.
+ int callerAppUid = callingUid;
+ if (callerApp == null) {
+ callerApp = mService.getProcessController(realCallingPid, realCallingUid);
+ callerAppUid = realCallingUid;
+ }
+ // don't abort if the callerApp or other processes of that uid are whitelisted in any way
+ if (callerApp != null) {
+ // first check the original calling process
+ if (callerApp.areBackgroundActivityStartsAllowed()) {
+ return false;
+ }
+ // only if that one wasn't whitelisted, check the other ones
+ final ArraySet<WindowProcessController> uidProcesses =
+ mService.mProcessMap.getProcesses(callerAppUid);
+ if (uidProcesses != null) {
+ for (int i = uidProcesses.size() - 1; i >= 0; i--) {
+ final WindowProcessController proc = uidProcesses.valueAt(i);
+ if (proc != callerApp && proc.areBackgroundActivityStartsAllowed()) {
+ return false;
+ }
+ }
+ }
+ }
// anything that has fallen through would currently be aborted
Slog.w(TAG, "Background activity start [callingPackage: " + callingPackage
+ "; callingUid: " + callingUid
@@ -1057,18 +1061,6 @@ class ActivityStarter {
return true;
}
- private boolean isBoundByForegroundUid(WindowProcessController callerApp) {
- final ArraySet<Integer> boundClientUids = callerApp.getBoundClientUids();
- for (int i = boundClientUids.size() - 1; i >= 0; --i) {
- final int uid = boundClientUids.valueAt(i);
- if (mService.mWindowManager.mRoot.isAnyNonToastWindowVisibleForUid(uid)
- || mService.getUidState(uid) == ActivityManager.PROCESS_STATE_TOP) {
- return true;
- }
- }
- return false;
- }
-
// TODO: remove this toast after feature development is done
void showBackgroundActivityBlockedToast(boolean abort, String callingPackage) {
final Resources res = mService.mContext.getResources();
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
index 7d25466bf348..48aee200ccc0 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
@@ -503,7 +503,7 @@ public abstract class ActivityTaskManagerInternal {
public abstract ActivityManager.TaskSnapshot getTaskSnapshot(int taskId,
boolean reducedResolution);
- /** Returns true if uid has a visible window or its process is in a top state. */
+ /** Returns true if uid is considered foreground for activity start purposes. */
public abstract boolean isUidForeground(int uid);
/**
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index b4249046c1b5..3fa026873953 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -373,8 +373,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
private final SparseArray<String> mPendingTempWhitelist = new SparseArray<>();
/** All processes currently running that might have a window organized by name. */
final ProcessMap<WindowProcessController> mProcessNames = new ProcessMap<>();
- /** All processes we currently have running mapped by pid */
- final SparseArray<WindowProcessController> mPidMap = new SparseArray<>();
+ /** All processes we currently have running mapped by pid and uid */
+ final WindowProcessControllerMap mProcessMap = new WindowProcessControllerMap();
/** This is the process holding what we currently consider to be the "home" activity. */
WindowProcessController mHomeProcess;
/** The currently running heavy-weight process, if any. */
@@ -913,7 +913,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
return getGlobalConfiguration();
}
synchronized (mGlobalLock) {
- final WindowProcessController app = mPidMap.get(pid);
+ final WindowProcessController app = mProcessMap.getProcess(pid);
return app != null ? app.getConfiguration() : getGlobalConfiguration();
}
}
@@ -4640,7 +4640,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
enforceSystemHasVrFeature();
synchronized (mGlobalLock) {
final int pid = Binder.getCallingPid();
- final WindowProcessController wpc = mPidMap.get(pid);
+ final WindowProcessController wpc = mProcessMap.getProcess(pid);
mVrController.setVrThreadLocked(tid, pid, wpc);
}
}
@@ -4659,7 +4659,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
enforceSystemHasVrFeature();
synchronized (mGlobalLock) {
final int pid = Binder.getCallingPid();
- final WindowProcessController proc = mPidMap.get(pid);
+ final WindowProcessController proc = mProcessMap.getProcess(pid);
mVrController.setPersistentVrThreadLocked(tid, pid, proc);
}
}
@@ -5204,9 +5204,10 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
mH.sendMessage(msg);
}
- for (int i = mPidMap.size() - 1; i >= 0; i--) {
- final int pid = mPidMap.keyAt(i);
- final WindowProcessController app = mPidMap.get(pid);
+ SparseArray<WindowProcessController> pidMap = mProcessMap.getPidMap();
+ for (int i = pidMap.size() - 1; i >= 0; i--) {
+ final int pid = pidMap.keyAt(i);
+ final WindowProcessController app = pidMap.get(pid);
if (DEBUG_CONFIGURATION) {
Slog.v(TAG_CONFIGURATION, "Update process config of "
+ app.mName + " to new config " + configCopy);
@@ -5859,7 +5860,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
WindowProcessController getProcessController(int pid, int uid) {
- final WindowProcessController proc = mPidMap.get(pid);
+ final WindowProcessController proc = mProcessMap.getProcess(pid);
if (proc == null) return null;
if (UserHandle.isApp(uid) && proc.mUid == uid) {
return proc;
@@ -5872,8 +5873,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
boolean isUidForeground(int uid) {
- return (getUidState(uid) == ActivityManager.PROCESS_STATE_TOP)
- || mWindowManager.mRoot.isAnyNonToastWindowVisibleForUid(uid);
+ // A uid is considered to be foreground if it has a visible non-toast window.
+ return mWindowManager.mRoot.isAnyNonToastWindowVisibleForUid(uid);
}
boolean isDeviceOwner(int uid) {
@@ -6423,14 +6424,14 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
@Override
public void onProcessMapped(int pid, WindowProcessController proc) {
synchronized (mGlobalLock) {
- mPidMap.put(pid, proc);
+ mProcessMap.put(pid, proc);
}
}
@Override
public void onProcessUnMapped(int pid) {
synchronized (mGlobalLock) {
- mPidMap.remove(pid);
+ mProcessMap.remove(pid);
}
}
@@ -6480,9 +6481,10 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
*/
@Override
public void onImeWindowSetOnDisplay(final int pid, final int displayId) {
- // Update display configuration for IME process only when Single-client IME window
- // moving to another display.
- if (!InputMethodSystemProperty.MULTI_CLIENT_IME_ENABLED) return;
+ // Don't update process-level configuration for Multi-Client IME process since other
+ // IMEs on other displays will also receive this configuration change due to IME
+ // services use the same application config/context.
+ if (InputMethodSystemProperty.MULTI_CLIENT_IME_ENABLED) return;
if (pid == MY_PID || pid < 0) {
if (DEBUG_CONFIGURATION) {
@@ -6502,7 +6504,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
return;
}
- final WindowProcessController process = mPidMap.get(pid);
+ final WindowProcessController process = mProcessMap.getProcess(pid);
if (process == null) {
if (DEBUG_CONFIGURATION) {
Slog.w(TAG, "Trying to update display configuration for invalid "
@@ -6695,7 +6697,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
// Only allow this from foreground processes, so that background
// applications can't abuse it to prevent system UI from being shown.
if (uid >= FIRST_APPLICATION_UID) {
- final WindowProcessController proc = mPidMap.get(pid);
+ final WindowProcessController proc = mProcessMap.getProcess(pid);
if (!proc.isPerceptible()) {
Slog.w(TAG, "Ignoring closeSystemDialogs " + reason
+ " from background process " + proc);
diff --git a/services/core/java/com/android/server/wm/CompatModePackages.java b/services/core/java/com/android/server/wm/CompatModePackages.java
index c8f8e82bdb18..104805fba308 100644
--- a/services/core/java/com/android/server/wm/CompatModePackages.java
+++ b/services/core/java/com/android/server/wm/CompatModePackages.java
@@ -48,6 +48,7 @@ import android.os.Message;
import android.os.RemoteException;
import android.util.AtomicFile;
import android.util.Slog;
+import android.util.SparseArray;
import android.util.Xml;
public final class CompatModePackages {
@@ -324,8 +325,9 @@ public final class CompatModePackages {
ActivityRecord starting = stack.restartPackage(packageName);
// Tell all processes that loaded this package about the change.
- for (int i = mService.mPidMap.size() - 1; i >= 0; i--) {
- final WindowProcessController app = mService.mPidMap.valueAt(i);
+ SparseArray<WindowProcessController> pidMap = mService.mProcessMap.getPidMap();
+ for (int i = pidMap.size() - 1; i >= 0; i--) {
+ final WindowProcessController app = pidMap.valueAt(i);
if (!app.mPkgList.contains(packageName)) {
continue;
}
diff --git a/services/core/java/com/android/server/wm/Dimmer.java b/services/core/java/com/android/server/wm/Dimmer.java
index 4bd8cab05700..a7a793fa8d34 100644
--- a/services/core/java/com/android/server/wm/Dimmer.java
+++ b/services/core/java/com/android/server/wm/Dimmer.java
@@ -41,7 +41,7 @@ class Dimmer {
private static final int DEFAULT_DIM_ANIM_DURATION = 200;
private class DimAnimatable implements SurfaceAnimator.Animatable {
- private final SurfaceControl mDimLayer;
+ private SurfaceControl mDimLayer;
private DimAnimatable(SurfaceControl dimLayer) {
mDimLayer = dimLayer;
@@ -100,6 +100,11 @@ class Dimmer {
// See getSurfaceWidth() above for explanation.
return mHost.getSurfaceHeight();
}
+
+ void removeSurface() {
+ getPendingTransaction().remove(mDimLayer);
+ mDimLayer = null;
+ }
}
@VisibleForTesting
@@ -129,8 +134,7 @@ class Dimmer {
final DimAnimatable dimAnimatable = new DimAnimatable(dimLayer);
mSurfaceAnimator = new SurfaceAnimator(dimAnimatable, () -> {
if (!mDimming) {
- dimAnimatable.getPendingTransaction().remove(mDimLayer);
- mDimLayer = null;
+ dimAnimatable.removeSurface();
}
}, mHost.mWmService);
}
diff --git a/services/core/java/com/android/server/wm/ImmersiveModeConfirmation.java b/services/core/java/com/android/server/wm/ImmersiveModeConfirmation.java
index 3d20501222b6..d774dc3fd2f1 100644
--- a/services/core/java/com/android/server/wm/ImmersiveModeConfirmation.java
+++ b/services/core/java/com/android/server/wm/ImmersiveModeConfirmation.java
@@ -90,8 +90,6 @@ public class ImmersiveModeConfirmation {
mShowDelayMs = getNavBarExitDuration() * 3;
mPanicThresholdMs = context.getResources()
.getInteger(R.integer.config_immersive_mode_confirmation_panic);
- mWindowManager = (WindowManager)
- mContext.getSystemService(Context.WINDOW_SERVICE);
mVrModeEnabled = vrModeEnabled;
}
@@ -177,7 +175,7 @@ public class ImmersiveModeConfirmation {
private void handleHide() {
if (mClingWindow != null) {
if (DEBUG) Slog.d(TAG, "Hiding immersive mode confirmation");
- mWindowManager.removeView(mClingWindow);
+ getWindowManager().removeView(mClingWindow);
mClingWindow = null;
}
}
@@ -275,7 +273,7 @@ public class ImmersiveModeConfirmation {
super.onAttachedToWindow();
DisplayMetrics metrics = new DisplayMetrics();
- mWindowManager.getDefaultDisplay().getMetrics(metrics);
+ getWindowManager().getDefaultDisplay().getMetrics(metrics);
float density = metrics.density;
getViewTreeObserver().addOnComputeInternalInsetsListener(mInsetsListener);
@@ -341,6 +339,19 @@ public class ImmersiveModeConfirmation {
}
}
+ /**
+ * DO HOLD THE WINDOW MANAGER LOCK WHEN CALLING THIS METHOD
+ * The reason why we add this method is to avoid the deadlock of WMG->WMS and WMS->WMG
+ * when ImmersiveModeConfirmation object is created.
+ */
+ private WindowManager getWindowManager() {
+ if (mWindowManager == null) {
+ mWindowManager = (WindowManager)
+ mContext.getSystemService(Context.WINDOW_SERVICE);
+ }
+ return mWindowManager;
+ }
+
private void handleShow() {
if (DEBUG) Slog.d(TAG, "Showing immersive mode confirmation");
@@ -352,7 +363,7 @@ public class ImmersiveModeConfirmation {
// show the confirmation
WindowManager.LayoutParams lp = getClingWindowLayoutParams();
- mWindowManager.addView(mClingWindow, lp);
+ getWindowManager().addView(mClingWindow, lp);
}
private final Runnable mConfirm = new Runnable() {
diff --git a/services/core/java/com/android/server/wm/RecentTasks.java b/services/core/java/com/android/server/wm/RecentTasks.java
index d6c7b21e16b2..7dcbedf811c2 100644
--- a/services/core/java/com/android/server/wm/RecentTasks.java
+++ b/services/core/java/com/android/server/wm/RecentTasks.java
@@ -60,7 +60,6 @@ import android.os.Bundle;
import android.os.Environment;
import android.os.IBinder;
import android.os.RemoteException;
-import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.text.TextUtils;
@@ -185,7 +184,6 @@ class RecentTasks {
// front. Newly created tasks, or tasks that are removed from the list will continue to change
// the list. This does not affect affiliated tasks.
private boolean mFreezeTaskListReordering;
- private long mFreezeTaskListReorderingTime;
private long mFreezeTaskListTimeoutMs = FREEZE_TASK_LIST_TIMEOUT_MS;
// Mainly to avoid object recreation on multiple calls.
@@ -220,6 +218,9 @@ class RecentTasks {
}
};
+ private final Runnable mResetFreezeTaskListOnTimeoutRunnable =
+ this::resetFreezeTaskListReorderingOnTimeout;
+
@VisibleForTesting
RecentTasks(ActivityTaskManagerService service, TaskPersister taskPersister) {
mService = service;
@@ -255,8 +256,7 @@ class RecentTasks {
}
@VisibleForTesting
- void setFreezeTaskListTimeoutParams(long reorderingTime, long timeoutMs) {
- mFreezeTaskListReorderingTime = reorderingTime;
+ void setFreezeTaskListTimeout(long timeoutMs) {
mFreezeTaskListTimeoutMs = timeoutMs;
}
@@ -272,7 +272,8 @@ class RecentTasks {
// Always update the reordering time when this is called to ensure that the timeout
// is reset
mFreezeTaskListReordering = true;
- mFreezeTaskListReorderingTime = SystemClock.elapsedRealtime();
+ mService.mH.removeCallbacks(mResetFreezeTaskListOnTimeoutRunnable);
+ mService.mH.postDelayed(mResetFreezeTaskListOnTimeoutRunnable, mFreezeTaskListTimeoutMs);
}
/**
@@ -286,6 +287,7 @@ class RecentTasks {
// Once we end freezing the task list, reset the existing task order to the stable state
mFreezeTaskListReordering = false;
+ mService.mH.removeCallbacks(mResetFreezeTaskListOnTimeoutRunnable);
// If the top task is provided, then restore the top task to the front of the list
if (topTask != null) {
@@ -295,6 +297,8 @@ class RecentTasks {
// Resume trimming tasks
trimInactiveRecentTasks();
+
+ mService.getTaskChangeNotificationController().notifyTaskStackChanged();
}
/**
@@ -302,13 +306,8 @@ class RecentTasks {
* before we need to iterate the task list in order (either for purposes of returning the list
* to SystemUI or if we need to trim tasks in order)
*/
+ @VisibleForTesting
void resetFreezeTaskListReorderingOnTimeout() {
- // Unfreeze the recent task list if the time heuristic has passed
- if (mFreezeTaskListReorderingTime
- > (SystemClock.elapsedRealtime() - mFreezeTaskListTimeoutMs)) {
- return;
- }
-
final ActivityStack focusedStack = mService.getTopDisplayFocusedStack();
final TaskRecord topTask = focusedStack != null
? focusedStack.topTask()
@@ -875,9 +874,6 @@ class RecentTasks {
final Set<Integer> includedUsers = getProfileIds(userId);
includedUsers.add(Integer.valueOf(userId));
- // Check if the frozen task list has timed out
- resetFreezeTaskListReorderingOnTimeout();
-
final ArrayList<ActivityManager.RecentTaskInfo> res = new ArrayList<>();
final int size = mTasks.size();
int numVisibleTasks = 0;
@@ -1654,8 +1650,8 @@ class RecentTasks {
pw.println("mRecentsUid=" + mRecentsUid);
pw.println("mRecentsComponent=" + mRecentsComponent);
pw.println("mFreezeTaskListReordering=" + mFreezeTaskListReordering);
- pw.println("mFreezeTaskListReorderingTime (time since)="
- + (SystemClock.elapsedRealtime() - mFreezeTaskListReorderingTime) + "ms");
+ pw.println("mFreezeTaskListReorderingPendingTimeout="
+ + mService.mH.hasCallbacks(mResetFreezeTaskListOnTimeoutRunnable));
if (mTasks.isEmpty()) {
return;
}
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 1ca31f127b0d..f9fd54178ca7 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -314,9 +314,10 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
* Returns true if the callingUid has any non-toast window currently visible to the user.
*/
boolean isAnyNonToastWindowVisibleForUid(int callingUid) {
- return forAllWindows(w -> {
- return w.getOwningUid() == callingUid && w.isVisible() && w.mAttrs.type != TYPE_TOAST;
- }, true /* traverseTopToBottom */);
+ return forAllWindows(w ->
+ w.getOwningUid() == callingUid && w.mAttrs.type != TYPE_TOAST
+ && w.isVisibleNow(),
+ true /* traverseTopToBottom */);
}
/**
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimator.java b/services/core/java/com/android/server/wm/SurfaceAnimator.java
index 33d952e80a6b..b3b41b733cdb 100644
--- a/services/core/java/com/android/server/wm/SurfaceAnimator.java
+++ b/services/core/java/com/android/server/wm/SurfaceAnimator.java
@@ -286,8 +286,12 @@ class SurfaceAnimator {
final boolean destroy = mLeash != null && surface != null && parent != null;
if (destroy) {
if (DEBUG_ANIM) Slog.i(TAG, "Reparenting to original parent");
- t.reparent(surface, parent);
- scheduleAnim = true;
+ // We shouldn't really need these isValid checks but we do
+ // b/130364451
+ if (surface.isValid() && parent.isValid()) {
+ t.reparent(surface, parent);
+ scheduleAnim = true;
+ }
}
mService.mAnimationTransferMap.remove(mAnimation);
if (mLeash != null && destroyLeash) {
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 4ca35f7d427b..eb919eb00f0c 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -372,16 +372,37 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
mAllowBackgroundActivityStarts = allowBackgroundActivityStarts;
}
- public boolean areBackgroundActivityStartsAllowed() {
- return mAllowBackgroundActivityStarts;
+ boolean areBackgroundActivityStartsAllowed() {
+ // allow if the whitelisting flag was explicitly set
+ if (mAllowBackgroundActivityStarts) {
+ return true;
+ }
+ // allow if the proc is instrumenting with background activity starts privs
+ if (mInstrumentingWithBackgroundActivityStartPrivileges) {
+ return true;
+ }
+ // allow if the caller has an activity in any foreground task
+ if (hasActivityInVisibleTask()) {
+ return true;
+ }
+ // allow if the caller is bound by a UID that's currently foreground
+ if (isBoundByForegroundUid()) {
+ return true;
+ }
+ return false;
}
- public void setBoundClientUids(ArraySet<Integer> boundClientUids) {
- mBoundClientUids = boundClientUids;
+ private boolean isBoundByForegroundUid() {
+ for (int i = mBoundClientUids.size() - 1; i >= 0; --i) {
+ if (mAtm.isUidForeground(mBoundClientUids.valueAt(i))) {
+ return true;
+ }
+ }
+ return false;
}
- public ArraySet<Integer> getBoundClientUids() {
- return mBoundClientUids;
+ public void setBoundClientUids(ArraySet<Integer> boundClientUids) {
+ mBoundClientUids = boundClientUids;
}
public void setInstrumenting(boolean instrumenting,
@@ -394,14 +415,6 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
return mInstrumenting;
}
- /**
- * @return true if the instrumentation was started by a holder of
- * START_ACTIVITIES_FROM_BACKGROUND permission
- */
- boolean isInstrumentingWithBackgroundActivityStartPrivileges() {
- return mInstrumentingWithBackgroundActivityStartPrivileges;
- }
-
public void setPerceptible(boolean perceptible) {
mPerceptible = perceptible;
}
@@ -487,7 +500,7 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
}
}
- boolean hasActivityInVisibleTask() {
+ private boolean hasActivityInVisibleTask() {
for (int i = mActivities.size() - 1; i >= 0; --i) {
TaskRecord task = mActivities.get(i).getTaskRecord();
if (task == null) {
diff --git a/services/core/java/com/android/server/wm/WindowProcessControllerMap.java b/services/core/java/com/android/server/wm/WindowProcessControllerMap.java
new file mode 100644
index 000000000000..2767972f7ea0
--- /dev/null
+++ b/services/core/java/com/android/server/wm/WindowProcessControllerMap.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import android.util.ArraySet;
+import android.util.SparseArray;
+
+import java.util.Map;
+import java.util.HashMap;
+
+final class WindowProcessControllerMap {
+
+ /** All processes we currently have running mapped by pid */
+ private final SparseArray<WindowProcessController> mPidMap = new SparseArray<>();
+ /** All processes we currently have running mapped by uid */
+ private final Map<Integer, ArraySet<WindowProcessController>> mUidMap = new HashMap<>();
+
+ /** Retrieves a currently running process for pid. */
+ WindowProcessController getProcess(int pid) {
+ return mPidMap.get(pid);
+ }
+
+ /** Retrieves all currently running processes for uid. */
+ ArraySet<WindowProcessController> getProcesses(int uid) {
+ return mUidMap.get(uid);
+ }
+
+ SparseArray<WindowProcessController> getPidMap() {
+ return mPidMap;
+ }
+
+ void put(int pid, WindowProcessController proc) {
+ // if there is a process for this pid already in mPidMap it'll get replaced automagically,
+ // but we actually need to remove it from mUidMap too before adding the new one
+ final WindowProcessController prevProc = mPidMap.get(pid);
+ if (prevProc != null) {
+ removeProcessFromUidMap(prevProc);
+ }
+ // put process into mPidMap
+ mPidMap.put(pid, proc);
+ // put process into mUidMap
+ final int uid = proc.mUid;
+ ArraySet<WindowProcessController> procSet = mUidMap.getOrDefault(uid,
+ new ArraySet<WindowProcessController>());
+ procSet.add(proc);
+ mUidMap.put(uid, procSet);
+ }
+
+ void remove(int pid) {
+ final WindowProcessController proc = mPidMap.get(pid);
+ if (proc != null) {
+ // remove process from mPidMap
+ mPidMap.remove(pid);
+ // remove process from mUidMap
+ removeProcessFromUidMap(proc);
+ }
+ }
+
+ private void removeProcessFromUidMap(WindowProcessController proc) {
+ if (proc == null) {
+ return;
+ }
+ final int uid = proc.mUid;
+ ArraySet<WindowProcessController> procSet = mUidMap.get(uid);
+ if (procSet != null) {
+ procSet.remove(proc);
+ if (procSet.isEmpty()) {
+ mUidMap.remove(uid);
+ }
+ }
+ }
+}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/AbUpdateInstaller.java b/services/devicepolicy/java/com/android/server/devicepolicy/AbUpdateInstaller.java
index d5cfab960171..5acf83aeb890 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/AbUpdateInstaller.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/AbUpdateInstaller.java
@@ -194,8 +194,17 @@ class AbUpdateInstaller extends UpdateInstaller {
}
UpdateEngine updateEngine = buildBoundUpdateEngine();
- updateEngine.applyPayload(
- updatePath, mOffsetForUpdate, mSizeForUpdate, headerKeyValuePairs);
+ try {
+ updateEngine.applyPayload(
+ updatePath, mOffsetForUpdate, mSizeForUpdate, headerKeyValuePairs);
+ } catch (Exception e) {
+ // Prevent an automatic restart when an update is already being processed
+ // (http://b/124106342).
+ Log.w(UpdateInstaller.TAG, "Failed to install update from file.", e);
+ notifyCallbackOnError(
+ InstallSystemUpdateCallback.UPDATE_ERROR_UNKNOWN,
+ "Failed to install update from file.");
+ }
}
private boolean updateStateForPayload() throws IOException {
diff --git a/services/tests/mockingservicestests/AndroidManifest.xml b/services/tests/mockingservicestests/AndroidManifest.xml
index c9aa63153a5d..32d7d026ff10 100644
--- a/services/tests/mockingservicestests/AndroidManifest.xml
+++ b/services/tests/mockingservicestests/AndroidManifest.xml
@@ -17,6 +17,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.frameworks.mockingservicestests">
+ <uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />
+ <uses-permission android:name="android.permission.HARDWARE_TEST"/>
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
<application android:testOnly="true"
diff --git a/services/tests/servicestests/src/com/android/server/display/color/DisplayTransformManagerTest.java b/services/tests/mockingservicestests/src/com/android/server/display/color/DisplayTransformManagerTest.java
index fc74c972ed83..73b3b8b1ce3c 100644
--- a/services/tests/servicestests/src/com/android/server/display/color/DisplayTransformManagerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/color/DisplayTransformManagerTest.java
@@ -16,87 +16,119 @@
package com.android.server.display.color;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyString;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
import static com.android.server.display.color.DisplayTransformManager.LEVEL_COLOR_MATRIX_NIGHT_DISPLAY;
import static com.android.server.display.color.DisplayTransformManager.PERSISTENT_PROPERTY_DISPLAY_COLOR;
import static com.android.server.display.color.DisplayTransformManager.PERSISTENT_PROPERTY_SATURATION;
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+
import android.hardware.display.ColorDisplayManager;
import android.os.SystemProperties;
import androidx.test.runner.AndroidJUnit4;
+import com.android.dx.mockito.inline.extended.ExtendedMockito;
+
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.MockitoSession;
+import org.mockito.quality.Strictness;
+import org.mockito.stubbing.Answer;
+
+import java.util.HashMap;
@RunWith(AndroidJUnit4.class)
public class DisplayTransformManagerTest {
+ private MockitoSession mSession;
private DisplayTransformManager mDtm;
private float[] mNightDisplayMatrix;
+ private HashMap<String, String> mSystemProperties;
@Before
public void setUp() {
mDtm = new DisplayTransformManager();
mNightDisplayMatrix = mDtm.getColorMatrix(LEVEL_COLOR_MATRIX_NIGHT_DISPLAY);
- SystemProperties.set(PERSISTENT_PROPERTY_DISPLAY_COLOR, null);
- SystemProperties.set(PERSISTENT_PROPERTY_SATURATION, null);
+ mSession = ExtendedMockito.mockitoSession()
+ .initMocks(this)
+ .strictness(Strictness.LENIENT)
+ .spyStatic(SystemProperties.class)
+ .startMocking();
+ mSystemProperties = new HashMap<>();
+
+ doAnswer((Answer<Void>) invocationOnMock -> {
+ mSystemProperties.put(invocationOnMock.getArgument(0),
+ invocationOnMock.getArgument(1));
+ return null;
+ }
+ ).when(() -> SystemProperties.set(anyString(), any()));
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ mSession.finishMocking();
+ mSystemProperties.clear();
}
@Test
public void setColorMode_natural() {
mDtm.setColorMode(ColorDisplayManager.COLOR_MODE_NATURAL, mNightDisplayMatrix);
- assertThat(SystemProperties.get(PERSISTENT_PROPERTY_DISPLAY_COLOR, null))
+ assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_DISPLAY_COLOR))
.isEqualTo("0" /* managed */);
- assertThat(SystemProperties.get(PERSISTENT_PROPERTY_SATURATION, null))
+ assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_SATURATION))
.isEqualTo("1.0" /* natural */);
}
@Test
public void setColorMode_boosted() {
mDtm.setColorMode(ColorDisplayManager.COLOR_MODE_BOOSTED, mNightDisplayMatrix);
- assertThat(SystemProperties.get(PERSISTENT_PROPERTY_DISPLAY_COLOR, null))
+
+ assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_DISPLAY_COLOR))
.isEqualTo("0" /* managed */);
- assertThat(SystemProperties.get(PERSISTENT_PROPERTY_SATURATION, null))
+ assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_SATURATION))
.isEqualTo("1.1" /* boosted */);
}
@Test
public void setColorMode_saturated() {
mDtm.setColorMode(ColorDisplayManager.COLOR_MODE_SATURATED, mNightDisplayMatrix);
- assertThat(SystemProperties.get(PERSISTENT_PROPERTY_DISPLAY_COLOR, null))
+ assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_DISPLAY_COLOR))
.isEqualTo("1" /* unmanaged */);
- assertThat(SystemProperties.get(PERSISTENT_PROPERTY_SATURATION, null))
+ assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_SATURATION))
.isEqualTo("1.0" /* natural */);
}
@Test
public void setColorMode_automatic() {
mDtm.setColorMode(ColorDisplayManager.COLOR_MODE_AUTOMATIC, mNightDisplayMatrix);
- assertThat(SystemProperties.get(PERSISTENT_PROPERTY_DISPLAY_COLOR, null))
+ assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_DISPLAY_COLOR))
.isEqualTo("2" /* enhanced */);
- assertThat(SystemProperties.get(PERSISTENT_PROPERTY_SATURATION, null))
+ assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_SATURATION))
.isEqualTo("1.0" /* natural */);
}
@Test
public void setColorMode_vendor() {
mDtm.setColorMode(0x100, mNightDisplayMatrix);
- assertThat(SystemProperties.get(PERSISTENT_PROPERTY_DISPLAY_COLOR, null))
+ assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_DISPLAY_COLOR))
.isEqualTo(Integer.toString(0x100) /* pass-through */);
- assertThat(SystemProperties.get(PERSISTENT_PROPERTY_SATURATION, null))
- .isEqualTo("1.0" /* default */);
+ assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_SATURATION))
+ .isEqualTo("1.0" /* natural */);
}
@Test
public void setColorMode_outOfBounds() {
mDtm.setColorMode(0x50, mNightDisplayMatrix);
- assertThat(SystemProperties.get(PERSISTENT_PROPERTY_DISPLAY_COLOR, null))
- .isEqualTo("" /* default */);
- assertThat(SystemProperties.get(PERSISTENT_PROPERTY_SATURATION, null))
- .isEqualTo("" /* default */);
+ assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_DISPLAY_COLOR))
+ .isEqualTo(null);
+ assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_SATURATION))
+ .isEqualTo(null);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java b/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java
index 2cba9d022866..2977414fb302 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java
@@ -17,6 +17,7 @@
package com.android.server.accessibility;
import static android.view.MotionEvent.ACTION_DOWN;
+import static android.view.MotionEvent.ACTION_HOVER_MOVE;
import static android.view.MotionEvent.ACTION_UP;
import static android.view.WindowManagerPolicyConstants.FLAG_PASS_TO_USER;
@@ -116,6 +117,7 @@ public class MotionEventInjectorTest {
MotionEvent mClickDownEvent;
MotionEvent mClickUpEvent;
+ MotionEvent mHoverMoveEvent;
ArgumentCaptor<MotionEvent> mCaptor1 = ArgumentCaptor.forClass(MotionEvent.class);
ArgumentCaptor<MotionEvent> mCaptor2 = ArgumentCaptor.forClass(MotionEvent.class);
@@ -152,6 +154,10 @@ public class MotionEventInjectorTest {
CLICK_POINT.y, 0);
mClickUpEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN);
+ mHoverMoveEvent = MotionEvent.obtain(0, 0, ACTION_HOVER_MOVE, CLICK_POINT.x, CLICK_POINT.y,
+ 0);
+ mHoverMoveEvent.setSource(InputDevice.SOURCE_MOUSE);
+
mIsLineStart = allOf(IS_ACTION_DOWN, isAtPoint(LINE_START), hasStandardInitialization(),
hasTimeFromDown(0));
mIsLineMiddle = allOf(IS_ACTION_MOVE, isAtPoint(LINE_END), hasStandardInitialization(),
@@ -301,6 +307,23 @@ public class MotionEventInjectorTest {
}
@Test
+ public void
+ testOnMotionEvents_fromMouseWithInjectedGestureInProgress_shouldNotCancelAndPassReal()
+ throws RemoteException {
+ EventStreamTransformation next = attachMockNext(mMotionEventInjector);
+ injectEventsSync(mLineList, mServiceInterface, LINE_SEQUENCE);
+ mMessageCapturingHandler.sendOneMessage(); // Send a motion event
+ mMotionEventInjector.onMotionEvent(mHoverMoveEvent, mHoverMoveEvent, 0);
+ mMessageCapturingHandler.sendAllMessages();
+
+ verify(next, times(3)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
+ assertThat(mCaptor1.getAllValues().get(0), mIsLineStart);
+ assertThat(mCaptor1.getAllValues().get(1), mIsLineMiddle);
+ assertThat(mCaptor1.getAllValues().get(2), mIsLineEnd);
+ verify(mServiceInterface).onPerformGestureResult(LINE_SEQUENCE, true);
+ }
+
+ @Test
public void testOnMotionEvents_closedInjectedGestureInProgress_shouldOnlyNotifyAndPassReal()
throws RemoteException {
EventStreamTransformation next = attachMockNext(mMotionEventInjector);
diff --git a/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java b/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java
index 5de41ea5e7d1..4de00f7b5565 100644
--- a/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java
@@ -29,6 +29,7 @@ import static org.mockito.Mockito.when;
import android.attention.AttentionManagerInternal;
import android.attention.AttentionManagerInternal.AttentionCallbackInternal;
+import android.content.pm.PackageManager;
import android.os.PowerManager;
import android.os.PowerManagerInternal;
import android.os.SystemClock;
@@ -49,6 +50,8 @@ import org.mockito.MockitoAnnotations;
public class AttentionDetectorTest extends AndroidTestCase {
@Mock
+ private PackageManager mPackageManager;
+ @Mock
private AttentionManagerInternal mAttentionManagerInternal;
@Mock
private Runnable mOnUserAttention;
@@ -60,6 +63,9 @@ public class AttentionDetectorTest extends AndroidTestCase {
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
+ when(mPackageManager.getAttentionServicePackageName()).thenReturn("com.google.android.as");
+ when(mPackageManager.checkPermission(any(), any())).thenReturn(
+ PackageManager.PERMISSION_GRANTED);
when(mAttentionManagerInternal.checkAttention(anyLong(), any()))
.thenReturn(true);
mAttentionDetector = new TestableAttentionDetector();
@@ -108,6 +114,27 @@ public class AttentionDetectorTest extends AndroidTestCase {
}
@Test
+ public void testOnUserActivity_doesntCheckIfNotSufficientPermissions() {
+ when(mPackageManager.checkPermission(any(), any())).thenReturn(
+ PackageManager.PERMISSION_DENIED);
+
+ long when = registerAttention();
+ verify(mAttentionManagerInternal, never()).checkAttention(anyLong(), any());
+ assertThat(mNextDimming).isEqualTo(when);
+ }
+
+ @Test
+ public void testOnUserActivity_disablesSettingIfNotSufficientPermissions() {
+ when(mPackageManager.checkPermission(any(), any())).thenReturn(
+ PackageManager.PERMISSION_DENIED);
+
+ registerAttention();
+ boolean enabled = Settings.System.getIntForUser(getContext().getContentResolver(),
+ Settings.System.ADAPTIVE_SLEEP, 0, UserHandle.USER_CURRENT) == 1;
+ assertFalse(enabled);
+ }
+
+ @Test
public void testOnUserActivity_doesntCrashIfNoAttentionService() {
mAttentionManagerInternal = null;
registerAttention();
@@ -211,6 +238,8 @@ public class AttentionDetectorTest extends AndroidTestCase {
TestableAttentionDetector() {
super(AttentionDetectorTest.this.mOnUserAttention, new Object());
mAttentionManager = mAttentionManagerInternal;
+ mPackageManager = AttentionDetectorTest.this.mPackageManager;
+ mContentResolver = getContext().getContentResolver();
mMaximumExtensionMillis = 10000L;
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
index 49ee8b3bba19..6be2c2e8c59e 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
@@ -48,8 +48,8 @@ import android.app.Notification;
import android.app.Notification.Builder;
import android.app.NotificationChannel;
import android.app.NotificationManager;
+import android.content.Context;
import android.content.pm.PackageManager;
-import android.content.res.Resources;
import android.graphics.Color;
import android.media.AudioAttributes;
import android.media.AudioManager;
@@ -63,7 +63,6 @@ import android.provider.Settings;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.test.suitebuilder.annotation.SmallTest;
-import android.testing.TestableContext;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.IAccessibilityManager;
@@ -71,7 +70,6 @@ import android.view.accessibility.IAccessibilityManagerClient;
import androidx.test.runner.AndroidJUnit4;
-import com.android.internal.R;
import com.android.internal.util.IntPair;
import com.android.server.UiServiceTestCase;
import com.android.server.lights.Light;
@@ -88,7 +86,6 @@ import org.mockito.MockitoAnnotations;
@RunWith(AndroidJUnit4.class)
public class BuzzBeepBlinkTest extends UiServiceTestCase {
- private TestableContext mContext = spy(getContext());
@Mock AudioManager mAudioManager;
@Mock Vibrator mVibrator;
@Mock android.media.IRingtonePlayer mRingtonePlayer;
@@ -99,8 +96,6 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase {
NotificationUsageStats mUsageStats;
@Mock
IAccessibilityManager mAccessibilityService;
- @Mock
- Resources mResources;
private NotificationManagerService mService;
private String mPkg = "com.android.server.notification";
@@ -150,7 +145,7 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase {
verify(mAccessibilityService).addClient(any(IAccessibilityManagerClient.class), anyInt());
assertTrue(accessibilityManager.isEnabled());
- mService = spy(new NotificationManagerService(mContext));
+ mService = spy(new NotificationManagerService(getContext()));
mService.setAudioManager(mAudioManager);
mService.setVibrator(mVibrator);
mService.setSystemReady(true);
@@ -280,7 +275,7 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase {
boolean isLeanback) {
NotificationChannel channel =
new NotificationChannel("test", "test", IMPORTANCE_HIGH);
- final Builder builder = new Builder(mContext)
+ final Builder builder = new Builder(getContext())
.setContentTitle("foo")
.setSmallIcon(android.R.drawable.sym_def_app_icon)
.setPriority(Notification.PRIORITY_HIGH)
@@ -326,14 +321,15 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase {
n.flags |= Notification.FLAG_INSISTENT;
}
- PackageManager packageManager = spy(mContext.getPackageManager());
- when(mContext.getPackageManager()).thenReturn(packageManager);
+ Context context = spy(getContext());
+ PackageManager packageManager = spy(context.getPackageManager());
+ when(context.getPackageManager()).thenReturn(packageManager);
when(packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK))
.thenReturn(isLeanback);
StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, id, mTag, mUid,
mPid, n, mUser, null, System.currentTimeMillis());
- NotificationRecord r = new NotificationRecord(mContext, sbn, channel);
+ NotificationRecord r = new NotificationRecord(context, sbn, channel);
mService.addNotification(r);
return r;
}
@@ -459,25 +455,7 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase {
}
@Test
- public void testNoBeepForAutomotiveIfEffectsDisabled() throws Exception {
- when(mContext.getResources()).thenReturn(mResources);
- when(mResources.getBoolean(R.bool.config_enableServerNotificationEffectsForAutomotive))
- .thenReturn(false);
- mService.setIsAutomotive(true);
-
- NotificationRecord r = getBeepyNotification();
-
- mService.buzzBeepBlinkLocked(r);
-
- verifyNeverBeep();
- assertFalse(r.isInterruptive());
- }
-
- @Test
- public void testNoBeepForImportanceDefaultInAutomotiveIfEffectsEnabled() throws Exception {
- when(mContext.getResources()).thenReturn(mResources);
- when(mResources.getBoolean(R.bool.config_enableServerNotificationEffectsForAutomotive))
- .thenReturn(true);
+ public void testNoBeepForImportanceDefaultInAutomotive() throws Exception {
mService.setIsAutomotive(true);
NotificationRecord r = getBeepyNotification();
@@ -490,10 +468,7 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase {
}
@Test
- public void testBeepForImportanceHighInAutomotiveIfEffectsEnabled() throws Exception {
- when(mContext.getResources()).thenReturn(mResources);
- when(mResources.getBoolean(R.bool.config_enableServerNotificationEffectsForAutomotive))
- .thenReturn(true);
+ public void testBeepForImportanceHighInAutomotive() throws Exception {
mService.setIsAutomotive(true);
NotificationRecord r = getBeepyNotification();
@@ -1040,12 +1015,12 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase {
public void testEmptyUriSoundTreatedAsNoSound() throws Exception {
NotificationChannel channel = new NotificationChannel("test", "test", IMPORTANCE_HIGH);
channel.setSound(Uri.EMPTY, null);
- final Notification n = new Builder(mContext, "test")
+ final Notification n = new Builder(getContext(), "test")
.setSmallIcon(android.R.drawable.sym_def_app_icon).build();
StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, 0, mTag, mUid,
mPid, n, mUser, null, System.currentTimeMillis());
- NotificationRecord r = new NotificationRecord(mContext, sbn, channel);
+ NotificationRecord r = new NotificationRecord(getContext(), sbn, channel);
mService.addNotification(r);
mService.buzzBeepBlinkLocked(r);
@@ -1094,13 +1069,13 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase {
@Test
public void testCrossUserSoundMuted() throws Exception {
- final Notification n = new Builder(mContext, "test")
+ final Notification n = new Builder(getContext(), "test")
.setSmallIcon(android.R.drawable.sym_def_app_icon).build();
int userId = mUser.getIdentifier() + 1;
StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, 0, mTag, mUid,
mPid, n, UserHandle.of(userId), null, System.currentTimeMillis());
- NotificationRecord r = new NotificationRecord(mContext, sbn,
+ NotificationRecord r = new NotificationRecord(getContext(), sbn,
new NotificationChannel("test", "test", IMPORTANCE_HIGH));
mService.buzzBeepBlinkLocked(r);
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 96db38b14ad5..a7bbe6e4cf02 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStartControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStartControllerTests.java
@@ -87,7 +87,7 @@ public class ActivityStartControllerTests extends ActivityTestsBase {
mController.doPendingActivityLaunches(resume);
verify(mStarter, times(1)).startResolvedActivity(eq(activity), eq(source), eq(null),
- eq(null), eq(startFlags), eq(resume), eq(null), eq(null), eq(null));
+ eq(null), eq(startFlags), eq(resume), eq(null), eq(null));
}
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 44aa55d07133..45d52195c5fd 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -577,12 +577,27 @@ public class ActivityStarterTests extends ActivityTestsBase {
UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1,
UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
false, false, false, false, false, false);
+ runAndVerifyBackgroundActivityStartsSubtest(
+ "disallowed_callingUidProcessStateTop_aborted", true,
+ UNIMPORTANT_UID, false, PROCESS_STATE_TOP,
+ UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
+ false, false, false, false, false, false);
+ runAndVerifyBackgroundActivityStartsSubtest(
+ "disallowed_realCallingUidProcessStateTop_aborted", true,
+ UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1,
+ UNIMPORTANT_UID2, false, PROCESS_STATE_TOP,
+ false, false, false, false, false, false);
+ runAndVerifyBackgroundActivityStartsSubtest(
+ "disallowed_hasForegroundActivities_aborted", true,
+ UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1,
+ UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
+ true, false, false, false, false, false);
}
/**
* This test ensures that supported usecases aren't aborted when background starts are
* disallowed.
- * The scenarios each have only one condidion that makes them supported.
+ * The scenarios each have only one condition that makes them supported.
*/
@Test
public void testBackgroundActivityStartsDisallowed_supportedStartsNotAborted() {
@@ -606,26 +621,11 @@ public class ActivityStarterTests extends ActivityTestsBase {
UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
false, false, false, false, false, false);
runAndVerifyBackgroundActivityStartsSubtest(
- "disallowed_callingUidProcessStateTop_notAborted", false,
- UNIMPORTANT_UID, false, PROCESS_STATE_TOP,
- UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
- false, false, false, false, false, false);
- runAndVerifyBackgroundActivityStartsSubtest(
"disallowed_realCallingUidHasVisibleWindow_notAborted", false,
UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1,
UNIMPORTANT_UID2, true, PROCESS_STATE_TOP + 1,
false, false, false, false, false, false);
runAndVerifyBackgroundActivityStartsSubtest(
- "disallowed_realCallingUidProcessStateTop_notAborted", false,
- UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1,
- UNIMPORTANT_UID2, false, PROCESS_STATE_TOP,
- false, false, false, false, false, false);
- runAndVerifyBackgroundActivityStartsSubtest(
- "disallowed_hasForegroundActivities_notAborted", false,
- UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1,
- UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
- true, false, false, false, false, false);
- runAndVerifyBackgroundActivityStartsSubtest(
"disallowed_callerIsRecents_notAborted", false,
UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1,
UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
index c4009df27c1f..ca3f6846f74d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -52,6 +52,7 @@ import android.view.Display;
import android.view.Surface;
import android.view.WindowManager;
+import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
import org.junit.Before;
@@ -383,6 +384,7 @@ public class AppWindowTokenTests extends WindowTestsBase {
}
@Test
+ @FlakyTest(bugId = 130392471)
public void testAddRemoveRace() {
// There was once a race condition between adding and removing starting windows
for (int i = 0; i < 1000; i++) {
diff --git a/services/tests/wmtests/src/com/android/server/wm/AssistDataRequesterTest.java b/services/tests/wmtests/src/com/android/server/wm/AssistDataRequesterTest.java
index 329af952c07a..bb574ceed4e0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AssistDataRequesterTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AssistDataRequesterTest.java
@@ -48,6 +48,7 @@ import android.platform.test.annotations.Presubmit;
import android.util.Log;
import android.view.IWindowManager;
+import androidx.test.filters.FlakyTest;
import androidx.test.filters.MediumTest;
import com.android.server.am.AssistDataRequester;
@@ -150,6 +151,7 @@ public class AssistDataRequesterTest extends ActivityTestsBase {
}
@Test
+ @FlakyTest(bugId = 130388718)
public void testRequestData() throws Exception {
setupMocks(CURRENT_ACTIVITY_ASSIST_ALLOWED, CALLER_ASSIST_STRUCTURE_ALLOWED,
CALLER_ASSIST_SCREENSHOT_ALLOWED);
@@ -250,6 +252,7 @@ public class AssistDataRequesterTest extends ActivityTestsBase {
}
@Test
+ @FlakyTest(bugId = 130388718)
public void testNoFetchScreenshots_expectNoScreenshotCallbacks() throws Exception {
setupMocks(CURRENT_ACTIVITY_ASSIST_ALLOWED, CALLER_ASSIST_STRUCTURE_ALLOWED,
CALLER_ASSIST_SCREENSHOT_ALLOWED);
@@ -260,6 +263,7 @@ public class AssistDataRequesterTest extends ActivityTestsBase {
}
@Test
+ @FlakyTest(bugId = 130388718)
public void testDisallowAssistScreenshot_expectNullScreenshotCallback() throws Exception {
setupMocks(CURRENT_ACTIVITY_ASSIST_ALLOWED, CALLER_ASSIST_STRUCTURE_ALLOWED,
!CALLER_ASSIST_SCREENSHOT_ALLOWED);
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
index af048586b425..3392bc43e568 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
@@ -712,7 +712,6 @@ public class RecentTasksTest extends ActivityTestsBase {
mRecentTasks.add(mTasks.get(4));
// Freeze the list
- long freezeTime = SystemClock.elapsedRealtime();
mRecentTasks.setFreezeTaskListReordering();
assertTrue(mRecentTasks.isFreezeTaskListReorderingSet());
@@ -720,13 +719,11 @@ public class RecentTasksTest extends ActivityTestsBase {
mRecentTasks.add(mTasks.get(2));
mRecentTasks.add(mTasks.get(1));
- // Override the freeze timeout params to simulate the timeout (simulate the freeze at 100ms
- // ago with a timeout of 1ms)
- mRecentTasks.setFreezeTaskListTimeoutParams(freezeTime - 100, 1);
-
ActivityStack stack = mTasks.get(2).getStack();
stack.moveToFront("", mTasks.get(2));
doReturn(stack).when(mTestService.mRootActivityContainer).getTopDisplayFocusedStack();
+
+ // Simulate the reset from the timeout
mRecentTasks.resetFreezeTaskListReorderingOnTimeout();
assertFalse(mRecentTasks.isFreezeTaskListReorderingSet());
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
index 35a8ec37c758..263f6501bbf6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
@@ -50,8 +50,8 @@ public class RootWindowContainerTests extends WindowTestsBase {
toastyToast.mHasSurface = true;
app.mHasSurface = true;
- assertTrue(toastyToast.isVisible());
- assertTrue(app.isVisible());
+ assertTrue(toastyToast.isVisibleNow());
+ assertTrue(app.isVisibleNow());
assertTrue(mWm.mRoot.isAnyNonToastWindowVisibleForUid(FAKE_CALLING_UID));
}
@@ -60,7 +60,7 @@ public class RootWindowContainerTests extends WindowTestsBase {
final WindowState toastyToast = createWindow(null, TYPE_TOAST, "toast", FAKE_CALLING_UID);
toastyToast.mHasSurface = true;
- assertTrue(toastyToast.isVisible());
+ assertTrue(toastyToast.isVisibleNow());
assertFalse(mWm.mRoot.isAnyNonToastWindowVisibleForUid(FAKE_CALLING_UID));
}
@@ -69,8 +69,8 @@ public class RootWindowContainerTests extends WindowTestsBase {
final WindowState topBar = createWindow(null, TYPE_STATUS_BAR, "topBar", FAKE_CALLING_UID);
final WindowState app = createWindow(null, TYPE_APPLICATION, "app", FAKE_CALLING_UID);
- assertFalse(topBar.isVisible());
- assertFalse(app.isVisible());
+ assertFalse(topBar.isVisibleNow());
+ assertFalse(app.isVisibleNow());
assertFalse(mWm.mRoot.isAnyNonToastWindowVisibleForUid(FAKE_CALLING_UID));
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java
index 9722d2ccce99..62247d889485 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java
@@ -39,6 +39,7 @@ import android.platform.test.annotations.Presubmit;
import android.support.test.uiautomator.UiDevice;
import android.text.TextUtils;
+import androidx.test.filters.FlakyTest;
import androidx.test.filters.MediumTest;
import com.android.internal.annotations.GuardedBy;
@@ -78,6 +79,7 @@ public class TaskStackChangedListenerTest {
@Test
@Presubmit
+ @FlakyTest(bugId = 130388819)
public void testTaskStackChanged_afterFinish() throws Exception {
registerTaskStackChangedListener(new TaskStackListener() {
@Override
@@ -159,6 +161,7 @@ public class TaskStackChangedListenerTest {
*/
@Test
@Presubmit
+ @FlakyTest(bugId = 130388819)
public void testTaskChangeCallBacks() throws Exception {
final Object[] params = new Object[2];
final CountDownLatch taskCreatedLaunchLatch = new CountDownLatch(1);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
index 78fca0f2e6ef..06bcdf8fcadf 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
@@ -36,6 +36,7 @@ import android.view.Gravity;
import android.view.IWindow;
import android.view.WindowManager;
+import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
import com.android.server.wm.utils.WmDisplayCutout;
@@ -323,6 +324,7 @@ public class WindowFrameTests extends WindowTestsBase {
}
@Test
+ @FlakyTest(bugId = 130388666)
public void testCalculatePolicyCrop() {
final FrameTestWindowState w = createWindow(MATCH_PARENT, MATCH_PARENT);
w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
@@ -423,6 +425,7 @@ public class WindowFrameTests extends WindowTestsBase {
}
@Test
+ @FlakyTest(bugId = 130388666)
public void testDisplayCutout() {
// Regular fullscreen task and window
WindowState w = createWindow(MATCH_PARENT, MATCH_PARENT);
@@ -446,6 +449,7 @@ public class WindowFrameTests extends WindowTestsBase {
}
@Test
+ @FlakyTest(bugId = 130388666)
public void testDisplayCutout_tempDisplayedBounds() {
// Regular fullscreen task and window
WindowState w = createWindow(MATCH_PARENT, MATCH_PARENT);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerMapTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerMapTests.java
new file mode 100644
index 000000000000..cb7bff3a4f15
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerMapTests.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.wm;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import android.os.UserHandle;
+import android.platform.test.annotations.Presubmit;
+import android.util.ArraySet;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests for the {@link WindowProcessControllerMap} class.
+ *
+ * Build/Install/Run:
+ * atest WmTests:WindowProcessControllerMapTests
+ */
+@SmallTest
+@Presubmit
+public class WindowProcessControllerMapTests extends ActivityTestsBase {
+
+ private static final int FAKE_UID1 = 666;
+ private static final int FAKE_UID2 = 667;
+ private static final int FAKE_PID1 = 668;
+ private static final int FAKE_PID2 = 669;
+ private static final int FAKE_PID3 = 670;
+ private static final int FAKE_PID4 = 671;
+
+ private WindowProcessControllerMap mProcessMap;
+ private WindowProcessController pid1uid1;
+ private WindowProcessController pid1uid2;
+ private WindowProcessController pid2uid1;
+ private WindowProcessController pid3uid1;
+ private WindowProcessController pid4uid2;
+
+ @Before
+ public void setUp() throws Exception {
+ mProcessMap = new WindowProcessControllerMap();
+ pid1uid1 = new WindowProcessController(
+ mService, mService.mContext.getApplicationInfo(), "fakepid1fakeuid1", FAKE_UID1,
+ UserHandle.getUserId(12345), mock(Object.class), mock(WindowProcessListener.class));
+ pid1uid1.setPid(FAKE_PID1);
+ pid1uid2 = new WindowProcessController(
+ mService, mService.mContext.getApplicationInfo(), "fakepid1fakeuid2", FAKE_UID2,
+ UserHandle.getUserId(12345), mock(Object.class), mock(WindowProcessListener.class));
+ pid1uid2.setPid(FAKE_PID1);
+ pid2uid1 = new WindowProcessController(
+ mService, mService.mContext.getApplicationInfo(), "fakepid2fakeuid1", FAKE_UID1,
+ UserHandle.getUserId(12345), mock(Object.class), mock(WindowProcessListener.class));
+ pid2uid1.setPid(FAKE_PID2);
+ pid3uid1 = new WindowProcessController(
+ mService, mService.mContext.getApplicationInfo(), "fakepid3fakeuid1", FAKE_UID1,
+ UserHandle.getUserId(12345), mock(Object.class), mock(WindowProcessListener.class));
+ pid3uid1.setPid(FAKE_PID3);
+ pid4uid2 = new WindowProcessController(
+ mService, mService.mContext.getApplicationInfo(), "fakepid4fakeuid2", FAKE_UID2,
+ UserHandle.getUserId(12345), mock(Object.class), mock(WindowProcessListener.class));
+ pid4uid2.setPid(FAKE_PID4);
+ }
+
+ @Test
+ public void testAdditionsAndRemovals() {
+ // test various additions and removals
+ mProcessMap.put(FAKE_PID1, pid1uid1);
+ mProcessMap.put(FAKE_PID2, pid2uid1);
+ assertEquals(pid1uid1, mProcessMap.getProcess(FAKE_PID1));
+ assertEquals(pid2uid1, mProcessMap.getProcess(FAKE_PID2));
+ ArraySet<WindowProcessController> uid1processes = mProcessMap.getProcesses(FAKE_UID1);
+ assertTrue(uid1processes.contains(pid1uid1));
+ assertTrue(uid1processes.contains(pid2uid1));
+ assertEquals(uid1processes.size(), 2);
+
+ mProcessMap.remove(FAKE_PID2);
+ mProcessMap.put(FAKE_PID3, pid3uid1);
+ uid1processes = mProcessMap.getProcesses(FAKE_UID1);
+ assertTrue(uid1processes.contains(pid1uid1));
+ assertFalse(uid1processes.contains(pid2uid1));
+ assertTrue(uid1processes.contains(pid3uid1));
+ assertEquals(uid1processes.size(), 2);
+
+ mProcessMap.put(FAKE_PID4, pid4uid2);
+ ArraySet<WindowProcessController> uid2processes = mProcessMap.getProcesses(FAKE_UID2);
+ assertTrue(uid2processes.contains(pid4uid2));
+ assertEquals(uid2processes.size(), 1);
+
+ mProcessMap.remove(FAKE_PID1);
+ mProcessMap.remove(FAKE_PID3);
+ assertNull(mProcessMap.getProcesses(FAKE_UID1));
+ assertEquals(mProcessMap.getProcess(FAKE_PID4), pid4uid2);
+ }
+
+ @Test
+ public void testReplacement() {
+ // test that replacing a process is handled correctly
+ mProcessMap.put(FAKE_PID1, pid1uid1);
+ ArraySet<WindowProcessController> uid1processes = mProcessMap.getProcesses(FAKE_UID1);
+ assertTrue(uid1processes.contains(pid1uid1));
+ assertEquals(uid1processes.size(), 1);
+
+ mProcessMap.put(FAKE_PID1, pid1uid2);
+ assertNull(mProcessMap.getProcesses(FAKE_UID1));
+ ArraySet<WindowProcessController> uid2processes = mProcessMap.getProcesses(FAKE_UID2);
+ assertTrue(uid2processes.contains(pid1uid2));
+ assertEquals(uid2processes.size(), 1);
+ assertEquals(mProcessMap.getProcess(FAKE_PID1), pid1uid2);
+ }
+}
diff --git a/telecomm/java/android/telecom/InCallService.java b/telecomm/java/android/telecom/InCallService.java
index cbcd40f15583..ebfa3a15639a 100644
--- a/telecomm/java/android/telecom/InCallService.java
+++ b/telecomm/java/android/telecom/InCallService.java
@@ -41,26 +41,12 @@ import java.util.List;
/**
* This service is implemented by an app that wishes to provide functionality for managing
* phone calls.
- * <p>
- * There are three types of apps which Telecom can bind to when there exists a live (active or
- * incoming) call:
- * <ol>
- * <li>Default Dialer/Phone app - the default dialer/phone app is one which provides the
- * in-call user interface while the device is in a call. A device is bundled with a system
- * provided default dialer/phone app. The user may choose a single app to take over this role
- * from the system app.</li>
- * <li>Default Car-mode Dialer/Phone app - the default car-mode dialer/phone app is one which
- * provides the in-call user interface while the device is in a call and the device is in car
- * mode. The user may choose a single app to fill this role.</li>
- * <li>Call Companion app - a call companion app is one which provides no user interface itself,
- * but exposes call information to another display surface, such as a wearable device. The
- * user may choose multiple apps to fill this role.</li>
- * </ol>
- * <p>
- * Apps which wish to fulfill one of the above roles use the {@link android.app.role.RoleManager}
- * to request that they fill the desired role.
- *
* <h2>Becoming the Default Phone App</h2>
+ * The default dialer/phone app is one which provides the in-call user interface while the device is
+ * in a call. A device is bundled with a system provided default dialer/phone app. The user may
+ * choose a single app to take over this role from the system app. An app which wishes to fulfill
+ * one this role uses the {@code android.app.role.RoleManager} to request that they fill the role.
+ * <p>
* An app filling the role of the default phone app provides a user interface while the device is in
* a call, and the device is not in car mode.
* <p>
@@ -193,47 +179,6 @@ import java.util.List;
* notificationManager.notify(YOUR_CHANNEL_ID, YOUR_TAG, YOUR_ID, builder.build());
* }</pre>
* <p>
- * <h2>Becoming the Default Car-mode Phone App</h2>
- * An app filling the role of the default car-mode dialer/phone app provides a user interface while
- * the device is in a call, and in car mode. See
- * {@link android.app.UiModeManager#ACTION_ENTER_CAR_MODE} for more information about car mode.
- * When the device is in car mode, Telecom binds to the default car-mode dialer/phone app instead
- * of the usual dialer/phone app.
- * <p>
- * Similar to the requirements for becoming the default dialer/phone app, your app must declare a
- * manifest entry for its {@link InCallService} implementation. Your manifest entry should ensure
- * the following conditions are met:
- * <ul>
- * <li>Do NOT declare the {@link TelecomManager#METADATA_IN_CALL_SERVICE_UI} metadata.</li>
- * <li>Set the {@link TelecomManager#METADATA_IN_CALL_SERVICE_CAR_MODE_UI} metadata to
- * {@code true}<li>
- * <li>Your app must request the permission
- * {@link android.Manifest.permission.CALL_COMPANION_APP}.</li>
- * </ul>
- * <p>
- * Your app should request to fill the role {@code android.app.role.CAR_MODE_DIALER} in order to
- * become the default (see <a href="#requestRole">above</a> for how to request your app fills this
- * role).
- *
- * <h2>Becoming a Call Companion App</h2>
- * An app which fills the companion app role does not directly provide a user interface while the
- * device is in a call. Instead, it is typically used to relay information about calls to another
- * display surface, such as a wearable device.
- * <p>
- * Similar to the requirements for becoming the default dialer/phone app, your app must declare a
- * manifest entry for its {@link InCallService} implementation. Your manifest entry should
- * ensure the following conditions are met:
- * <ul>
- * <li>Do NOT declare the {@link TelecomManager#METADATA_IN_CALL_SERVICE_UI} metadata.</li>
- * <li>Do NOT declare the {@link TelecomManager#METADATA_IN_CALL_SERVICE_CAR_MODE_UI}
- * metadata.</li>
- * <li>Your app must request the permission
- * {@link android.Manifest.permission.CALL_COMPANION_APP}.</li>
- * </ul>
- * <p>
- * Your app should request to fill the role {@code android.app.role.CALL_COMPANION} in order to
- * become a call companion app (see <a href="#requestRole">above</a> for how to request your app
- * fills this role).
*/
public abstract class InCallService extends Service {
diff --git a/telecomm/java/android/telecom/PhoneAccountHandle.java b/telecomm/java/android/telecom/PhoneAccountHandle.java
index 71a28b575394..eb568e04ebf3 100644
--- a/telecomm/java/android/telecom/PhoneAccountHandle.java
+++ b/telecomm/java/android/telecom/PhoneAccountHandle.java
@@ -17,6 +17,7 @@
package android.telecom;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.os.Build;
@@ -174,4 +175,21 @@ public final class PhoneAccountHandle implements Parcelable {
in.readString(),
UserHandle.CREATOR.createFromParcel(in));
}
+
+ /**
+ * Determines if two {@link PhoneAccountHandle}s are from the same package.
+ *
+ * @param a Phone account handle to check for same {@link ConnectionService} package.
+ * @param b Other phone account handle to check for same {@link ConnectionService} package.
+ * @return {@code true} if the two {@link PhoneAccountHandle}s passed in belong to the same
+ * {@link ConnectionService} / package, {@code false} otherwise. Note: {@code null} phone
+ * account handles are considered equivalent to other {@code null} phone account handles.
+ * @hide
+ */
+ public static boolean areFromSamePackage(@Nullable PhoneAccountHandle a,
+ @Nullable PhoneAccountHandle b) {
+ String aPackageName = a != null ? a.getComponentName().getPackageName() : null;
+ String bPackageName = b != null ? b.getComponentName().getPackageName() : null;
+ return Objects.equals(aPackageName, bPackageName);
+ }
}
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 391d788cfe72..db6319871540 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -16,7 +16,6 @@ package android.telecom;
import android.Manifest;
import android.annotation.IntDef;
-import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SuppressAutoDoc;
@@ -497,6 +496,9 @@ public class TelecomManager {
* Dialer implementations (see {@link #getDefaultDialerPackage()}) which would also like to
* override the system provided ringing should set this meta-data to {@code true} in the
* manifest registration of their {@link InCallService}.
+ * <p>
+ * When {@code true}, it is the {@link InCallService}'s responsibility to play a ringtone for
+ * all incoming calls.
*/
public static final String METADATA_IN_CALL_SERVICE_RINGING =
"android.telecom.IN_CALL_SERVICE_RINGING";
@@ -1495,8 +1497,21 @@ public class TelecomManager {
/**
* Silences the ringer if a ringing call exists.
- *
- * Requires permission: {@link android.Manifest.permission#MODIFY_PHONE_STATE}
+ * <p>
+ * This method can only be relied upon to stop the ringtone for a call if the ringtone has
+ * already started playing. It is intended to handle use-cases such as silencing a ringing call
+ * when the user presses the volume button during ringing.
+ * <p>
+ * If this method is called prior to when the ringtone begins playing, the ringtone will not be
+ * silenced. As such it is not intended as a means to avoid playing of a ringtone.
+ * <p>
+ * A dialer app which wants to have more control over ringtone playing should declare
+ * {@link TelecomManager#METADATA_IN_CALL_SERVICE_RINGING} in the manifest entry for their
+ * {@link InCallService} implementation to indicate that the app wants to be responsible for
+ * playing the ringtone for all incoming calls.
+ * <p>
+ * Requires permission: {@link android.Manifest.permission#MODIFY_PHONE_STATE} or that the
+ * app fills the dialer role (see {@link #getDefaultDialerPackage()}).
*/
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public void silenceRinger() {
diff --git a/telephony/java/android/provider/Telephony.java b/telephony/java/android/provider/Telephony.java
index 2d8a8cbae59f..037e47520c94 100644
--- a/telephony/java/android/provider/Telephony.java
+++ b/telephony/java/android/provider/Telephony.java
@@ -3394,6 +3394,7 @@ public final class Telephony {
* {@link SubscriptionManager#getDefaultSubscriptionId()}. To specify subId for MSIM,
* use {@link Uri#withAppendedPath(Uri, String)} to append with subscription id.
*/
+ @NonNull
public static final Uri CONTENT_URI = Uri.parse("content://telephony/carriers");
/**
@@ -3406,6 +3407,7 @@ public final class Telephony {
* {@link SubscriptionManager#getDefaultSubscriptionId()}. To specify subId for MSIM,
* use {@link Uri#withAppendedPath(Uri, String)} to append with subscription id.
*/
+ @NonNull
public static final Uri SIM_APN_URI = Uri.parse(
"content://telephony/carriers/sim_apn_list");
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 9f6528bc4709..d2f88bbda654 100755
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -2804,7 +2804,7 @@ public class CarrierConfigManager {
* @hide
*/
public static final String KEY_SUBSCRIPTION_GROUP_UUID_STRING =
- "key_subscription_group_uuid_string";
+ "subscription_group_uuid_string";
/**
* A boolean property indicating whether this subscription should be managed as an opportunistic
@@ -2819,7 +2819,7 @@ public class CarrierConfigManager {
* @hide
*/
public static final String KEY_IS_OPPORTUNISTIC_SUBSCRIPTION_BOOL =
- "key_is_opportunistic_subscription_bool";
+ "is_opportunistic_subscription_bool";
/**
* A list of 4 GSM RSSI thresholds above which a signal level is considered POOR,
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index cf15b92ae640..c57f9e63f9db 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -39,6 +39,7 @@ import android.util.DisplayMetrics;
import android.util.Log;
import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
import java.util.Objects;
@@ -123,6 +124,16 @@ public class SubscriptionInfo implements Parcelable {
private String mMnc;
/**
+ * EHPLMNs associated with the subscription
+ */
+ private String[] mEhplmns;
+
+ /**
+ * HPLMNs associated with the subscription
+ */
+ private String[] mHplmns;
+
+ /**
* ISO Country code for the subscription's provider
*/
private String mCountryIso;
@@ -316,6 +327,14 @@ public class SubscriptionInfo implements Parcelable {
}
/**
+ * @hide
+ */
+ public void setAssociatedPlmns(String[] ehplmns, String[] hplmns) {
+ mEhplmns = ehplmns;
+ mHplmns = hplmns;
+ }
+
+ /**
* Creates and returns an icon {@code Bitmap} to represent this {@code SubscriptionInfo} in a
* user interface.
*
@@ -467,6 +486,20 @@ public class SubscriptionInfo implements Parcelable {
}
/**
+ * @hide
+ */
+ public List<String> getEhplmns() {
+ return mEhplmns == null ? Collections.emptyList() : Arrays.asList(mEhplmns);
+ }
+
+ /**
+ * @hide
+ */
+ public List<String> getHplmns() {
+ return mHplmns == null ? Collections.emptyList() : Arrays.asList(mHplmns);
+ }
+
+ /**
* @return the profile class of this subscription.
* @hide
*/
@@ -600,7 +633,7 @@ public class SubscriptionInfo implements Parcelable {
String mcc = source.readString();
String mnc = source.readString();
String countryIso = source.readString();
- Bitmap iconBitmap = Bitmap.CREATOR.createFromParcel(source);
+ Bitmap iconBitmap = source.readParcelable(Bitmap.class.getClassLoader());
boolean isEmbedded = source.readBoolean();
UiccAccessRule[] accessRules = source.createTypedArray(UiccAccessRule.CREATOR);
String cardString = source.readString();
@@ -611,11 +644,15 @@ public class SubscriptionInfo implements Parcelable {
int carrierid = source.readInt();
int profileClass = source.readInt();
int subType = source.readInt();
-
- return new SubscriptionInfo(id, iccId, simSlotIndex, displayName, carrierName,
- nameSource, iconTint, number, dataRoaming, iconBitmap, mcc, mnc, countryIso,
- isEmbedded, accessRules, cardString, cardId, isOpportunistic, groupUUID,
- isGroupDisabled, carrierid, profileClass, subType);
+ String[] ehplmns = source.readStringArray();
+ String[] hplmns = source.readStringArray();
+
+ SubscriptionInfo info = new SubscriptionInfo(id, iccId, simSlotIndex, displayName,
+ carrierName, nameSource, iconTint, number, dataRoaming, iconBitmap, mcc, mnc,
+ countryIso, isEmbedded, accessRules, cardString, cardId, isOpportunistic,
+ groupUUID, isGroupDisabled, carrierid, profileClass, subType);
+ info.setAssociatedPlmns(ehplmns, hplmns);
+ return info;
}
@Override
@@ -638,7 +675,7 @@ public class SubscriptionInfo implements Parcelable {
dest.writeString(mMcc);
dest.writeString(mMnc);
dest.writeString(mCountryIso);
- mIconBitmap.writeToParcel(dest, flags);
+ dest.writeParcelable(mIconBitmap, flags);
dest.writeBoolean(mIsEmbedded);
dest.writeTypedArray(mAccessRules, flags);
dest.writeString(mCardString);
@@ -649,6 +686,8 @@ public class SubscriptionInfo implements Parcelable {
dest.writeInt(mCarrierId);
dest.writeInt(mProfileClass);
dest.writeInt(mSubscriptionType);
+ dest.writeStringArray(mEhplmns);
+ dest.writeStringArray(mHplmns);
}
@Override
@@ -686,6 +725,8 @@ public class SubscriptionInfo implements Parcelable {
+ " isOpportunistic " + mIsOpportunistic + " mGroupUUID=" + mGroupUUID
+ " mIsGroupDisabled=" + mIsGroupDisabled
+ " profileClass=" + mProfileClass
+ + " ehplmns = " + Arrays.toString(mEhplmns)
+ + " hplmns = " + Arrays.toString(mHplmns)
+ " subscriptionType=" + mSubscriptionType + "}";
}
@@ -729,6 +770,8 @@ public class SubscriptionInfo implements Parcelable {
&& TextUtils.equals(mDisplayName, toCompare.mDisplayName)
&& TextUtils.equals(mCarrierName, toCompare.mCarrierName)
&& Arrays.equals(mAccessRules, toCompare.mAccessRules)
- && mProfileClass == toCompare.mProfileClass;
+ && mProfileClass == toCompare.mProfileClass
+ && Arrays.equals(mEhplmns, toCompare.mEhplmns)
+ && Arrays.equals(mHplmns, toCompare.mHplmns);
}
}
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 0c6341111029..0808adf26aef 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -458,6 +458,18 @@ public class SubscriptionManager {
public static final String CARRIER_ID = "carrier_id";
/**
+ * @hide A comma-separated list of EHPLMNs associated with the subscription
+ * <P>Type: TEXT (String)</P>
+ */
+ public static final String EHPLMNS = "ehplmns";
+
+ /**
+ * @hide A comma-separated list of HPLMNs associated with the subscription
+ * <P>Type: TEXT (String)</P>
+ */
+ public static final String HPLMNS = "hplmns";
+
+ /**
* TelephonyProvider column name for the MCC associated with a SIM, stored as a string.
* <P>Type: TEXT (String)</P>
* @hide
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 0d3bc1db831f..2bd4f8f336fd 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -10376,10 +10376,10 @@ public class TelephonyManager {
* <p>Requires permission {@link android.Manifest.permission#READ_PHONE_STATE} or the calling
* app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
- * @return Map including the key as the active subscription ID (Note: if there is no active
+ * @return Map including the keys as the active subscription IDs (Note: if there is no active
* subscription, the key is {@link SubscriptionManager#getDefaultSubscriptionId}) and the value
- * as the list of {@link EmergencyNumber}; null if this information is not available; or throw
- * a SecurityException if the caller does not have the permission.
+ * as the list of {@link EmergencyNumber}; empty Map if this information is not available;
+ * or throw a SecurityException if the caller does not have the permission.
*/
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
@NonNull
@@ -10429,10 +10429,10 @@ public class TelephonyManager {
* <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_MIEC} </li>
* <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_AIEC} </li>
* </ol>
- * @return Map including the key as the active subscription ID (Note: if there is no active
+ * @return Map including the keys as the active subscription IDs (Note: if there is no active
* subscription, the key is {@link SubscriptionManager#getDefaultSubscriptionId}) and the value
- * as the list of {@link EmergencyNumber}; null if this information is not available; or throw
- * a SecurityException if the caller does not have the permission.
+ * as the list of {@link EmergencyNumber}; empty Map if this information is not available;
+ * or throw a SecurityException if the caller does not have the permission.
*/
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
@NonNull